FPGA之简易DDS信号发生器设计
文章目录
- 前言
- 一、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信号发生器设计相关推荐
- 基于FPGA的简易DDS信号发生器的设计与验证
基于FPGA的简易DDS信号发生器的设计与验证 一,理论介绍 补充:举例理解 二,代码实现 1,实验目标 2,MATLAB代码 3,verilog代码及实现思路 一,理论介绍 DDS 是直接数字式频率 ...
- 基于FPGA的简易DDS信号发生器的设计(一)
写这篇文章的本意不是为了探讨AD9767怎么使用,因为9767的控制实在是太简单了,准备好数据直接输出即可,和网上大多数的并行DA输出基本上一模一样,更麻烦的反而是硬件方面.发文的原因是最近一位很细心 ...
- 基于FPGA的简易 DDS 信号发生器的设计
文章目录 前言 一.pandas是什么? 二.ROM 内波形数据写入 1.MIF 2.DDS 模块参考代码 波形仿真 前言 DDS 是直接数字式频率合成器(Direct Digital Synthes ...
- 【FPGA实例】基于FPGA的DDS信号发生器设计
原文链接来源:www.runoob.com 基于FPGA的DDS信号发生器设计 DDS 原理 ------DDS(直接频率合成) 技术是根据奈奎斯特抽样定理及数字处理技术,把一系列的模拟信号进行不失真 ...
- 简易DDS信号发生器记录
简易DDS信号发生器 学习资料:野火 升腾Pro<FPGA Verilog开发实战指南--基于Xilinx Artix7>2021.11.16 1. 理论知识 DDS 是直接数字式频率合成 ...
- 基于 FPGA 的便携式 DDS 信号发生器与示波器
基于 FPGA 的便携式 DDS 信号发生器与示波器 项目来源:2019年第三届全国大学生FPGA创新设计竞赛 一.设计概述 1.1 设计目的 利用赛灵思公司 A7 系列板卡 EG01.AD9226 ...
- c语言中如何用sqar函数,简易函数信号发生器设计_毕业论文.doc
简易函数信号发生器设计 PAGE PAGE 2 简易函数信号发生器设计 摘要:信号发生器又称信号源或振荡器,在生产实践和科技领域中有着广泛的应用.这次的设计分为五个模块:单片机控制及显示模块.数模转换 ...
- DDS信号发生器设计matlab,基于DDS的LFM信号发生器
内容简介: 毕业论文 基于DDS的LFM信号发生器,共32页,12745字 摘要:信号发生器作为现代电子产品中的重要一员,必须满足高精度.高速度.高分辨率等要求.而采用DDS方案实现的信号发生器正好有 ...
- 基于FPGA的双通道DDS信号发生器
硬件:FPGA开发板 ,AD9767双通道DA转换器 软件:ISE,Matlab,Modelsim 最终效果:输出方波,正弦波,三角波以及锯齿波,可以通过按键改变输出波形的频率,频率在1Hz-1MHz ...
最新文章
- Java 抽象方法和抽象类基础知识
- linux搜索文件为1kb,Linux常用命令
- linux下面的查找
- 一篇搞懂mysql中的索引(大白话版)
- Java中反射获取成员变量、构造方法、成员方法及类名
- 用EZBOOT制作多个gho文件的安装盘
- window8服务器
- 计算机启动硬盘引导过程,如何重建mbr|硬盘重建主引导记录(mbr)步骤
- 基于FPGA卡拉ok系统的设计--反馈抑制
- 全球公认最搞笑的15则冷笑话
- 什么是“荷花定律”?
- 联想thinkbook14+2023款和2022款区别对比评测
- php药膳 源码,5款药膳方治疗关节炎
- 在Unity中创建基于Node节点的编辑器 (二) 窗口序列化
- java SE小练习
- Pycharm专业版下载、安装、与Anaconda配置、中文化及字体设置、Cracking(自行翻译)方法
- 谷歌高质量外链怎么做?Google网站买英文外链可行吗?
- WiFi路由器存在226个漏洞
- 人脸表情系列——人脸表情识别(Facial Expression Recognization/FER)
- 怎么实现用户登录功能,提交表单呢?
热门文章
- 网阔MZ200A设备常见问题定位与解决
- Python网络爬虫实战:抓取和分析天猫胸罩销售数据
- 2022年最新内测分发内测托管、上架App Store教程
- LeetCode 416 分割等和子集
- flash做一个时钟程序
- Java图片添加水印功能
- 最新金蝶K3 wise15.1 金蝶K3 15.0 最新金蝶K3 V15.1 金蝶K3 15.1 WISE15.1 金蝶ERP K3行政事业15.1 K3行政事业12.1 金蝶医疗HRP 金蝶SHR
- 【云计算小知识】什么是云计算?云计算特点是什么?
- 一心多用多线程-阻塞队列(7)-CyclicBarrier
- 「津津乐道播客」#231. 串台:跟『新世相』聊聊被刷屏的『沈老师』