文章目录

  • 前言
  • 一、DDS信号发生器
    • 1.DDS是什么
    • 2.DDS工作原理
  • 二、模块代码
    • 1.调用rom模块储存波形图
    • 2.按键控制模块
    • 2.按键消抖模块
    • 3.DDS生成模块
    • 4.顶层模块
    • 5.RTL视图
  • 三、仿真测试模块
    • 1.仿真测试代码
    • 2.仿真波形图
  • 总结

前言

设计一个能产生频率可变、相位可调的能产生正弦波、三角波、方波、锯齿波的信号发生器。


一、DDS信号发生器

1.DDS是什么

DDS 是直接数字式频率合成器(Direct Digital Synthesizer)的英文缩写,是一项关键的数字化技术。与传统的频率合成器相比,DDS 具有低成本、低功耗、高分辨率和快速转换时间等优点,广泛使用在电信与电子仪器领域,是实现设备全数字化的一个关键技术。作为设计人员,我们习惯称它为信号发生器,一般用它产生正弦、锯齿、方波等不同波形或不同频率的信号波形,在电子设计和测试中得到广泛应用。

注:图片摘自《FPGA Verliog开发实战指南》
图中主要包括相位累加器、相位调制器、波形存储器、数模转换器四大结构。

2.DDS工作原理

频率字K,数值大小控制输出信号的频率大小,数值越大输出信号频率越高,反之越小。

相位字P,数值大小控制输出信号的相位偏移,主要用于相位的信号调制。

相位累加器输入为频率字输入K表示相位增量,设其位宽为N,满足等式K=2^N*fout/fclk,其在输入相位累加器之前,在系统时钟同步下做数据寄存,数据改变时不会干扰相位累加器的正常工作。

波形数据表 ROM 中存有一个完整周期的正弦波信号。假设波形数据 ROM 的地址位宽为 12 位,存储数据位宽为 8 位,即 ROM 有 212 = 4096 个存储空间,每个存储空间可存储 1字节数据。将一个周期的正弦波信号,沿横轴等间隔采样 212 = 4096 次,每次采集的信号幅度用 1 字节数据表示,最大值为 255,最小值为 0。将 4096 次采样结果按顺序写入 ROM的 4096 个存储单元,一个完整周期正弦波的数字幅度信号写入了波形数据表 ROM 中。波形数据表 ROM 以相位调制器传入的相位码为 ROM 读地址,将地址对应存储单元中的电压幅值数字量输出。

D/A 转 换 器 将 输 入 的 电 压 幅 值 数 字 量 转 换 为 模 拟 量 输 出 , 就 得 到 输 出 信 号CLK_OUT。

输出信号 CLK_OUT 的信号频率 fOUT = K * fCLK / 2N。当 K = 1 时,可得 DDS 最小分辨率为:fOUT = fCLK / 2N,此时输出信号频率最低。根据采样定理,K 的最大值应小于 2N / 2。

相位累加器每计数 2N 次,对应一个正弦周期。而相位累加器 1 秒钟计数 fCLK次,在 k=1 时,DDS 输出的时钟频率就是频率分辨率。频率控制字 K 增加时,相位累加器溢出的频率增加,对应 DDS 输出信号 CLK_OUT 频率变为 K 倍的 DDS 频率分辨率。

DAC:自波形数据表 ROM 输出的波形数据传入 D/A 转换器转换为模拟信号。D/A 转换器即数/模转换器,简称 DAC(Digital to Analog Conver),是指将数字信号转换为模拟信号的电子元件或电路。

DAC使用外部挂载的高速AD/DA板卡。

二、模块代码

1.调用rom模块储存波形图

首先使用matlab产生四种波形的mif文件,深度为4096*4,matlab代码见另一篇文章。

2.按键控制模块

module key_ctrl(input wire clk,input wire rst_n,input wire [3:0]key,output reg [3:0]wave_select
);wire key0;wire key1;wire key2;wire key3;parameter sin_wave=4'b0001, //正弦波squ_wave=4'b0010,    //方波tri_wave=4'b0100, //三角波saw_wave=4'b1000;    //锯齿波key_filter key_filter0(.clk(clk),.rst_n(rst_n),.key_in(key[0]),.key_flag(key0));key_filter key_filter1(.clk(clk),.rst_n(rst_n),.key_in(key[1]),.key_flag(key1));key_filter key_filter2(.clk(clk),.rst_n(rst_n),.key_in(key[2]),.key_flag(key2));key_filter key_filter3(.clk(clk),.rst_n(rst_n),.key_in(key[3]),.key_flag(key3));always @(posedge clk or negedge rst_n)if(!rst_n)wave_select<=4'b0000;else if(key0)wave_select<=sin_wave;else if(key1)wave_select<=squ_wave;else if(key2)wave_select<=tri_wave;else if(key3)wave_select<=saw_wave;elsewave_select<=wave_select;endmodule

按下四个按键分别生成四种波形

2.按键消抖模块

module key_filter
#(parameter CNT_MAX=999_999)
(input wire clk,input wire rst_n,input wire key_in,output reg key_flag);reg [19:0]cnt_20;always @(posedge clk or negedge rst_n)if(!rst_n)cnt_20<=1'b0;else if(key_in==1'b1)cnt_20<=1'b0;else if(cnt_20==CNT_MAX &&  key_in==1'b0)cnt_20<=cnt_20;elsecnt_20<=cnt_20+1'b1;always @(posedge clk or negedge rst_n)if(!rst_n)key_flag<=1'b0;else if(cnt_20==CNT_MAX-1'b1)key_flag<=1'b1;else key_flag<=1'b0;endmodule

3.DDS生成模块

module dds(input wire clk,input wire rst_n,input wire [3:0]wave_select,output wire [7:0]data_out
);parameter sin_wave=4'b0001, //正弦波squ_wave=4'b0010,    //方波tri_wave=4'b0100, //三角波saw_wave=4'b1000;    //锯齿波
//本实验,我们希望输出一个频率为 500Hz,初相位为π/2 的正弦波信号。
//计算参数 FREQ_CTRL,即频率输入字 K。
//FREQ_CTRL = K = 2N * fOUT / fCLK,其中 N = 32(相位累加器输出值 fre_add 的位宽)、 fOUT = 500Hz,
//fCLK = 50MHz,带入公式,FREQ_CTRL = K = 42949.67296 ,取整数部分为42949;
//PHASE_CTRL = P =  / (2π / 2M),其中 M =12(输入 ROM 地址位宽)、 = π / 2,带入公式,
//PHASE_CTRL = P = 1024。
//计算参数 PHASE_CTRL,即相位输入字 P。parameter FREQ_CTRL=32'd42949,//相位累加器单次累加值,PHASE_CTRL=12'd1024;//相位偏移量reg [31:0]fre_add;   //相位累加器reg [11:0]rom_addr_reg;  //相位调制后的相位码reg [13:0]rom_addr;  //ROM读地址//相位累加器always @(posedge clk or negedge rst_n)if(!rst_n)fre_add<=1'b0;elsefre_add<=fre_add+FREQ_CTRL;always @(posedge clk or negedge rst_n)if(!rst_n)beginrom_addr<=1'b0;rom_addr_reg<=1'b0;endelsecase(wave_select)sin_wave:beginrom_addr_reg<=fre_add[31:20]+PHASE_CTRL;rom_addr<=rom_addr_reg;endsqu_wave:beginrom_addr_reg<=fre_add[31:20]+PHASE_CTRL;rom_addr<=rom_addr_reg+14'd4096;endtri_wave:beginrom_addr_reg<=fre_add[31:20]+PHASE_CTRL;rom_addr<=rom_addr_reg+14'd8192;endsaw_wave:beginrom_addr_reg<=fre_add[31:20]+PHASE_CTRL;rom_addr<=rom_addr_reg+14'd12288;enddefault:beginrom_addr_reg<=fre_add[31:20]+PHASE_CTRL;rom_addr<=rom_addr_reg;endendcasewave_ip wave_ip0(.address(rom_addr),.clock(clk),.q(data_out));endmodule

4.顶层模块

module dds_top(input wire clk,input wire rst_n,input wire [3:0]key,output wire dac_clk,  //输出DAC模块时钟output wire [7:0]dac_data
);wire [3:0]wave_select;assign dac_clk=~clk;dds dds0(.clk(clk),.rst_n(rst_n),.wave_select(wave_select),.data_out(dac_data));key_ctrl key_ctrl0(.clk(clk),.rst_n(rst_n),.key(key),.wave_select(wave_select));
endmodule

5.RTL视图

三、仿真测试模块

1.仿真测试代码

`timescale 1ns/1ns
`define clk_period 20module dds_top_tb;reg clk;reg rst_n;reg [3:0]key;wire dac_clk;    //输出DAC模块时钟wire [7:0]dac_data;reg [21:0]tb_cnt;reg key_in;reg [1:0]cnt_key;defparam dds_top_inst.key_ctrl0.key_filter0.CNT_MAX=24,dds_top_inst.key_ctrl0.key_filter1.CNT_MAX=24,dds_top_inst.key_ctrl0.key_filter2.CNT_MAX=24,dds_top_inst.key_ctrl0.key_filter3.CNT_MAX=24;parameter   CNT_1MS = 20'd19000 ,CNT_11MS = 21'd69000 ,CNT_41MS = 22'd149000 ,CNT_51MS = 22'd199000 ,CNT_60MS = 22'd249000 ;dds_top dds_top_inst(.clk(clk),.rst_n(rst_n),.key(key),.dac_clk(dac_clk), //输出DAC模块时钟.dac_data(dac_data));initial clk=1'b1;always #(`clk_period/2) clk=~clk;initial beginrst_n=1'b0;#(`clk_period*20+1);rst_n=1'b1;end//tb_cnt:按键过程计数器,通过该计数器的计数时间来模拟按键的抖动过程always@(posedge clk or negedge rst_n)if(rst_n == 1'b0)tb_cnt <= 22'b0;else if(tb_cnt == CNT_60MS)tb_cnt <= 22'b0;else tb_cnt <= tb_cnt + 1'b1;//key_in:产生输入随机数,模拟按键的输入情况always@(posedge clk or negedge rst_n)if(rst_n == 1'b0)key_in <= 1'b1;else if((tb_cnt >= CNT_1MS && tb_cnt <= CNT_11MS) || (tb_cnt >= CNT_41MS && tb_cnt <= CNT_51MS))key_in <= {$random} % 2;else if(tb_cnt >= CNT_11MS && tb_cnt <= CNT_41MS)key_in <= 1'b0;elsekey_in <= 1'b1;always@(posedge clk or negedge rst_n)if(rst_n == 1'b0)cnt_key <= 2'd0;else if(tb_cnt == CNT_60MS)cnt_key <= cnt_key + 1'b1;elsecnt_key <= cnt_key;always@(posedge clk or negedge rst_n)if(rst_n == 1'b0)key <= 4'b1111;elsecase(cnt_key)0: key <= {3'b111,key_in};1: key <= {2'b11,key_in,1'b1};2: key <= {1'b1,key_in,2'b11};3: key <= {key_in,3'b111};default:key <= 4'b1111;endcase
endmodule

2.仿真波形图


可以看到,第一部分波形为正弦波,第二部分为方波,第三部分为三角波,第四部分为锯齿波,设计成功。


总结

可以通过dds代码中频率字与相位字的改变来实现更多的波形变化。

FPGA之简易DDS信号发生器设计相关推荐

  1. 基于FPGA的简易DDS信号发生器的设计与验证

    基于FPGA的简易DDS信号发生器的设计与验证 一,理论介绍 补充:举例理解 二,代码实现 1,实验目标 2,MATLAB代码 3,verilog代码及实现思路 一,理论介绍 DDS 是直接数字式频率 ...

  2. 基于FPGA的简易DDS信号发生器的设计(一)

    写这篇文章的本意不是为了探讨AD9767怎么使用,因为9767的控制实在是太简单了,准备好数据直接输出即可,和网上大多数的并行DA输出基本上一模一样,更麻烦的反而是硬件方面.发文的原因是最近一位很细心 ...

  3. 基于FPGA的简易 DDS 信号发生器的设计

    文章目录 前言 一.pandas是什么? 二.ROM 内波形数据写入 1.MIF 2.DDS 模块参考代码 波形仿真 前言 DDS 是直接数字式频率合成器(Direct Digital Synthes ...

  4. 【FPGA实例】基于FPGA的DDS信号发生器设计

    原文链接来源:www.runoob.com 基于FPGA的DDS信号发生器设计 DDS 原理 ------DDS(直接频率合成) 技术是根据奈奎斯特抽样定理及数字处理技术,把一系列的模拟信号进行不失真 ...

  5. 简易DDS信号发生器记录

    简易DDS信号发生器 学习资料:野火 升腾Pro<FPGA Verilog开发实战指南--基于Xilinx Artix7>2021.11.16 1. 理论知识 DDS 是直接数字式频率合成 ...

  6. 基于 FPGA 的便携式 DDS 信号发生器与示波器

    基于 FPGA 的便携式 DDS 信号发生器与示波器 项目来源:2019年第三届全国大学生FPGA创新设计竞赛 一.设计概述 1.1 设计目的 利用赛灵思公司 A7 系列板卡 EG01.AD9226 ...

  7. c语言中如何用sqar函数,简易函数信号发生器设计_毕业论文.doc

    简易函数信号发生器设计 PAGE PAGE 2 简易函数信号发生器设计 摘要:信号发生器又称信号源或振荡器,在生产实践和科技领域中有着广泛的应用.这次的设计分为五个模块:单片机控制及显示模块.数模转换 ...

  8. DDS信号发生器设计matlab,基于DDS的LFM信号发生器

    内容简介: 毕业论文 基于DDS的LFM信号发生器,共32页,12745字 摘要:信号发生器作为现代电子产品中的重要一员,必须满足高精度.高速度.高分辨率等要求.而采用DDS方案实现的信号发生器正好有 ...

  9. 基于FPGA的双通道DDS信号发生器

    硬件:FPGA开发板 ,AD9767双通道DA转换器 软件:ISE,Matlab,Modelsim 最终效果:输出方波,正弦波,三角波以及锯齿波,可以通过按键改变输出波形的频率,频率在1Hz-1MHz ...

最新文章

  1. Java 抽象方法和抽象类基础知识
  2. linux搜索文件为1kb,Linux常用命令
  3. linux下面的查找
  4. 一篇搞懂mysql中的索引(大白话版)
  5. Java中反射获取成员变量、构造方法、成员方法及类名
  6. 用EZBOOT制作多个gho文件的安装盘
  7. window8服务器
  8. 计算机启动硬盘引导过程,如何重建mbr|硬盘重建主引导记录(mbr)步骤
  9. 基于FPGA卡拉ok系统的设计--反馈抑制
  10. 全球公认最搞笑的15则冷笑话
  11. 什么是“荷花定律”?
  12. 联想thinkbook14+2023款和2022款区别对比评测
  13. php药膳 源码,5款药膳方治疗关节炎
  14. 在Unity中创建基于Node节点的编辑器 (二) 窗口序列化
  15. java SE小练习
  16. Pycharm专业版下载、安装、与Anaconda配置、中文化及字体设置、Cracking(自行翻译)方法
  17. 谷歌高质量外链怎么做?Google网站买英文外链可行吗?
  18. WiFi路由器存在226个漏洞
  19. 人脸表情系列——人脸表情识别(Facial Expression Recognization/FER)
  20. 怎么实现用户登录功能,提交表单呢?

热门文章

  1. 网阔MZ200A设备常见问题定位与解决
  2. Python网络爬虫实战:抓取和分析天猫胸罩销售数据
  3. 2022年最新内测分发内测托管、上架App Store教程
  4. LeetCode 416 分割等和子集
  5. flash做一个时钟程序
  6. Java图片添加水印功能
  7. 最新金蝶K3 wise15.1 金蝶K3 15.0 最新金蝶K3 V15.1 金蝶K3 15.1 WISE15.1 金蝶ERP K3行政事业15.1 K3行政事业12.1 金蝶医疗HRP 金蝶SHR
  8. 【云计算小知识】什么是云计算?云计算特点是什么?
  9. 一心多用多线程-阻塞队列(7)-CyclicBarrier
  10. 「津津乐道播客」#231. 串台:跟『新世相』聊聊被刷屏的『沈老师』