使用软件: Vivado

DDS信号发生器

  • 基本原理
    • DDS基本原理
    • DDS模块
    • ROM IP的使用
    • 波形数据存储器
  • 代码及仿真
    • verilog代码
    • 仿真代码(Fword有值,Pword=0时)
    • 仿真结果及分析
    • 增加Pword(相位控制字之后)仿真代码
    • 运行结果

基本原理

DDS基本原理

[百度] DDS信号发生器采用直接数字频率合成(Direct Digital Synthesis,简称DDS)技术,把信号发生器的频率稳定度、准确度提高到与基准频率相同的水平,并且可以在很宽的频率范围内进行精细的频率调节。采用这种方法设计的信号源可工作于调制状态,可对输出电平进行调节,也可输出各种波形。
DDS基本结构图:

由图可以看出,DDS 主要由相位累加器、相位调制器、波形数据表以及 D/A转换器构成。
其中相位累加器由 N 位加法器与 N 位寄存器构成。每个时钟周期的时钟上升沿,加法器就将频率控制字与累加寄存器输出的相位数据相加,相加的结果又反馈至累加寄存器的数据输入端,以使加法器在下一个时钟脉冲的作用下继续与频率控制字相加。这样,相位累加器在时钟作用下,不断对频率控制字进行线性相位累加。即在每一个时钟脉冲输入时,相位累加器便把频率控制字累加一次。
相位累加器输出的数据就是合成信号的相位。相位累加器的溢出频率,就是DDS 输出的信号频率,相位累加器输出的数据,作为波形存储器的相位采样地址,这样就可以把存储在波形存储器里的波形采样值经查表找出,完成相位到幅度的转换。波形存储器的输出数据送到 D/A 转换器,由 D/A 转换器将数字信号转换成模拟信号输出。
DDS信号流程示意图如下:

这里相位累加器位数为 N 位(N 的取值范围实际应用中一般为 24~32),相
当于把正弦信号在相位上的精度定义为 N 位,所以其分辨率为1/2N
若DDS的时钟频率为Fcl,频率控制字fword=B,则输出频率Fout=BxFclk/2N

因此理论上由以上三个参数就可以得出任意的Fout输出频率。且可得出频率分辨率由时钟频率和累加器的位数决定的结论。当参考时钟频率越高,累加器位数越高,输出频率分辨率就越高。
为了合理控制ROM的容量,此处选取ROM查询的地址时,可以采用截断式,即只取32位累加器的高M位。这里相位寄存器输出的位数一般取10~16位。

DDS模块

在本设计中参考时钟Fclk 频率为50 MHz,相位累加器位数 N 取32 位,频率控制字位数 M 取 12 位。经过以上的分析,可以得出 DDS 模块的端口模块如下图所示:

端口功能描述:

ROM IP的使用

单击 IP Catalog,在右边窗口 Search 位置输入rom,在Memories &Storage Elements 下可以看到有两个与 ROM 相关的 IP,一个是 Distributed Memory Generator,另一个是Block Memory Generator,先简单说说两个的差别,两者最主要的差别是生成的 Core所占用的 FPGA 资源不一样,从 Distributed Memory Generator 生成的 ROM/RAM Core 占用的资源是 LUT(查找表,查找表本质就是一个小的 RAM);从 Block Memory Generator 生成的 ROM/RAM Core 占用的资源是 Block Memory(嵌入式的硬件 RAM)

在 IP Catalog 窗口选择 Distributed Memory Generator 并双击。
进入IP配置界面,如下。


(1)Documentation:IP 相关文档入口,点击后出现如下内容
(2)IP Location:生成 IP 的存放路径,可以通过点击 … 设置更换存放路径,默认是存放在工程路径下的 bin_counter.srcs\ sources_1\ ip,我这里就保持默认。
(3)Switch to Default:点击后所有的设置恢复到默认值
(4)Component Name:设置生成 IP Core 的名称,我这里将名字设置为 dist_mem_rom_ip;
(5)Depth:设置 ROM 深度,我这里设置 256;
(6)Data Width:设置数据位宽,我这里设置 8;
(7)Memory Type:选择存储类型,这里选择 ROM


(8)Input Options:设置是否对输入的地址增加一级寄存器,这里设置选择 Registered,对输入的地址增加一级寄存器(也可以选择 Non Registered,不增加寄存器)。
(9)Output Option:设置是否对输出的地址增加一级寄存器,这里设置选择 Both,对输出数据信号 spo 和增加一级寄存器后的输出数据信号 qspo 都从端口引出。下面还有个Single Port Output CE 可选配,当勾选后,ROM Core 就会多出一个 qspo_ce 的端口,这个信号是用来控制使能输出寄存器的时钟。这里没有用这个功能,不勾选该项。

(10)Pipeline Stages:流水线级数,在生成 ROM 模式下,不可配。

(11)添加 COE 文件位置,可以通过选择路径添加已有的 COE文件,软件会通过 COE 文件生成 ROM 初始化文件 MIF 文件。关于如何创建 COE 文件看下一步骤。
(12) 编辑按钮,当(11)中未加载 COE 文件时,点击这里按钮,会弹出提示框,点击YES 可进入到创建 COE 文件的流程,这里点击 YES。
(13)COE Options:设置 ROM 中初始化数据没有覆盖的区域的数值,比如 ROM 深度 256,添加的 COE 文件中仅初始化了200 个数据,这里就是统一设置剩下的 56 个数据的数值。
(14)Reset Options:添加输出寄存器复位信号,可添加同步复位或异步复位,这里就不勾选添加复位信号。
(15)ce overrides 设置
CE Overrides Sync Controls:在选择了输出寄存器同步复位和时钟使能才能启用,启用后,同步控制由时钟使能限定。
Sync Controls Overrides CE:在选择了输出寄存器同步复位和时钟使能才能启用,
启用后,同步控制信号会工作,不受时钟使能限定。
前面未勾选时钟使能信号 CE,这里就不可设置,保持默认即可。ROM IP 的各种参数设置完后点击 OK。


选择 COE 文件存放的路径位置和设置好 COE 文件名,点击 Save。


出现如上图弹窗,点击 Generate。
等 IP 生成完成后,出现如下图弹窗,点击 OK。

波形数据存储器

为了能产生相应的波形,我们需要创建 ROM 来分别存储正弦波、方波、三角波的波形数据。其中单端口的 ROM 主要配置数据如下图所示,其初始化文件选为已经生成的相应波形的 coe 文件。此处 coe 位宽为 14,深度为 4096。

关于生成 coe 文件需要注意的是,由于本次设计使用的是 Xilinx 出品的芯
片,所以在使用 Mif 精灵生成该文件时,应选择 Xilinx,同时 maxi 中数据应改
为 16383,其余设置如下图所示:

Mif精灵文件生成器网站:http://www.corecourse.cn/forum.php?mod=viewthread&tid=28374

选择sine wave生成正弦波数据。

然后载入生成的正弦波数据如下所示:

点击ok,保存生成即可。

代码及仿真

verilog代码

`timescale 1ns / 1ps
//
// Module Name: DDS_Moudle
//
//module DDS_Moudle(clk,Reset_n,Fword_i,        //频率控制字Pword,   //相位控制字Data //输出);input clk;input Reset_n;input[31:0] Fword_i;input[11:0] Pword;output[13:0] Data; //输出14位?4096//频率控制字同步寄存器reg[31:0] Fword_r;always@(posedge clk) beginFword_r <= Fword_i;end//相位控制字同步寄存器reg[11:0] Pword_r;always@(posedge clk)Pword_r <= Pword;//相位累加器reg[31:0] Freq_ACC;always@(posedge clk or negedge Reset_n) beginif(!Reset_n)Freq_ACC <= 0;elseFreq_ACC <= Fword_r + Freq_ACC;end//相位累加器与相位控制字的结果输出 //wire[31:0] Freq_ACC_out;//assign Freq_ACC_out <= Freq_ACC+Pword_r;//波形数据表地址wire[11:0] Rom_Addr;/*为什么是取ROM高12位地址因为频率控制器就是12位,所以取高12位 Freq_ACC_out[31:20]B=2^20*/assign Rom_Addr = Freq_ACC[31:20]+Pword_r;rom rom(.clka(clk),.addra(Rom_Addr),.douta(Data));endmodule

仿真代码(Fword有值,Pword=0时)

`timescale 1ns / 1ps
//
// Module Name: sim_DDS_Moudle
// Revision 0.01 - File Created
// Additional Comments:
//
//module sim_DDS_Moudle();reg clk;reg reset_n;reg[31:0] Fword;reg[11:0] Pword;wire[13:0] Data;DDS_Moudle uut(clk,reset_n,Fword,Pword,Data);initial clk=1;always #10 clk=~clk; //时钟周期20ns,仿真50M Hzinitial beginreset_n=0;Fword=65536;Pword=0;#201;reset_n=1;#2000000;Fword=65536*1024;#2000000;Fword=65536*32;#2000000;$stop;end
endmodule

仿真结果及分析

点击下图按钮,获得10ms长的仿真结果

鼠标右键Data,找到[Waveform style],选择[Analog],查看模拟波形

经过调整缩放之后波形如下所示:

计算周期:
找到波形最高点然后点击Add marker键

找到另一个最高点,点击Add marker键

由上图可以看到,此时周期为1310.72μs
可以由此算出此时的频率:762.9394513125 Hz

从代码中可以看到此时Fword为65536=216

根据公式:Fout=BxFclk/2N
B=Fword=65536=216
Fclk = 50M
N=32
所以Fout=Fclk/216=762.939453125

同理可以算出Fword为其他值的时候的Fout输出值,与预期结果一致。

增加Pword(相位控制字之后)仿真代码

因为生成正弦信号数据总数为4096个,Pword=1024是它的1/4,与Pword=0相差90度;Pword=2048与Pword=0相差180度。
令PwordA=0;PwordB为1024和2048,从仿真结果中查看相位变化

`timescale 1ns / 1ps
//
// Create Date: 2022/10/16 19:06:41
// Design Name:
// Module Name: sim_DDS_Moudle
// Revision 0.01 - File Created
// Additional Comments:
//
//module sim_DDS_Moudle();reg clk;reg reset_n;reg[31:0] FwordA,FwordB;reg[11:0] PwordA,PwordB;wire[13:0] DataA,DataB;DDS_Moudle DDS_ModuleA(clk,reset_n,FwordA,PwordA,DataA);DDS_Moudle DDS_Moduleb(clk,reset_n,FwordB,PwordB,DataB);initial clk=1;always #10 clk=~clk; //时钟周期20ns,仿真50M Hzinitial beginreset_n=0;FwordA=65536;PwordA=0;FwordB=65536;PwordB=1024;//因为数据一共4096个,取1/4个,相位相差90度#201;reset_n=1;#5000000;FwordA=65536*1024;FwordB=65536*1024;PwordA=0;PwordB=2048; //与A相位相差180度#1000000;$stop;end
endmodule

运行结果

从下图中可以看出前5ms结果中,DataA和DataB波形明显相差90度

从下图中可以看出前5ms结果中,DataA和DataB波形明显相差180度

FPGA—DDS信号发生器笔记相关推荐

  1. Matlab与FPGA数字信号处理系列——DDS信号发生器——Quartus ii 原理图法利用 ROM 存储波形实现DDS(1)

    MATLAB 与 FPGA无线通信.图像处理.数字信号处理系列 系统框图 基于FPGA的DDS信号发生器系统框图如下图所示,采取查表法. (1)对一个完整周期的波形进行采样,将采样点存在ROM中: ( ...

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

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

  3. 基于FPGA的DDS信号发生器

    基于FPGA的DDS信号发生器     两个礼拜前就像写这个文档了,但是一直鸽到现在,主要是人摆了.还有个技术上的原因是,我想用串口屏显示波形,在串口调试助手上返回的数据是对的,但是发到串口屏上啥反应 ...

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

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

  5. 国产紫光FPGA实现DDS信号发生器

    前言 随着信息技术的迅速发展,FPGA作为半定制电路具有可重复编程.计算能力强等优势,进入人们的视野,并在未来将发挥出越来越重要的作用. 作为电子专业的大三学生,我们小组在老师的带领下对现有国产FPG ...

  6. 【FPGA Verilog】手把手教你实现一个DDS信号发生器

    信号发⽣器的设计与实现 1.输出波形:⽅波(占空⽐50%).锯⻮波.三⻆波.脉冲信号(占空⽐连续可调).正弦波.任意波等 2.输出频率:100KHz 3.波形选择:使⽤拨码开关选择 思路: 使用FPG ...

  7. FPGA之简易DDS信号发生器设计

    文章目录 前言 一.DDS信号发生器 1.DDS是什么 2.DDS工作原理 二.模块代码 1.调用rom模块储存波形图 2.按键控制模块 2.按键消抖模块 3.DDS生成模块 4.顶层模块 5.RTL ...

  8. CASE_05 基于FPGA的DDS信号发生器

             该系类博客序言和资源简介可浏览该博客:PREFACE FPGA经典案例序言 快速了解该系列博客的内容与可用 资源. 目录 1 简介 2 DDS原理与方案 2.1 方案一:基于CORD ...

  9. 国产紫光FPGA实现DDS信号发生器(ModelSim仿真)

    简介 本文主要根据利用紫光同创软件联合ModelSim对DDS信号发生器进行仿真.前序步骤(DDS实现过程)见 国产紫光FPGA实现DDS信号发生器_窃听龙吟的博客-CSDN博客 该博客. 一.创建仿 ...

最新文章

  1. Linux 播号上网
  2. java 越来越慢_浅析Java语言慢的原因
  3. 计算机机房门内开还是外开,卫生间的门是朝内开还是朝外开好?原来这样开,入住才方便!...
  4. left join 后边的on条件 小记
  5. 商业 - 业务领先模型介绍(BLM)
  6. Flutter之Container 简单分析
  7. bootstrap 复选框及单选按钮
  8. .net GridView绑定数据、编辑、更新、删除(弹出确认对话框)、取消、根据条件隐藏或显示按钮操作
  9. 2021-09-07冒泡排序
  10. nuxt.js局部引入js获取ip地址
  11. freemarker
  12. 你被优衣库遭到******与英特尔漏洞刷屏了吗?
  13. 穷举算法——奶牛碑文(cow)
  14. 一道[CSCCTF 2019 Qual]FlaskLight的详解再遇SSTI
  15. TechSmith Camtasia2022屏幕视频录像
  16. 常见深度学习模型集成方法
  17. 膜蛋白分子动力学模拟流程
  18. 《炬丰科技-半导体工艺》 碳化硅技术优于传统硅技术
  19. 阿里旺旺调用谷歌Chrome浏览器打不开网页崩溃了显示错误代码 RESULT_CODE_MISSING_DATA-完美解决
  20. 游戏盾是否可以连同网站一起防护

热门文章

  1. JVM命令之 jstat:查看JVM统计信息
  2. win10 + Ubuntu 18.04.1 LTS (Bionic Beaver) 双系统的安装配置
  3. Java异常(漂亮简洁的思维导图)
  4. web前端CSS选择符:表示要定义样式的对象
  5. 加法链POJ2248
  6. VB全面控制Excel方法大汇总
  7. hread first html5,科学网—Time to read: 谨以此短文,献给那些失去父、母的成年人(Feb 8,2019) - 虞左俊的博文...
  8. Malcolm的新书:Outliers
  9. 产品定位,什么是产品?什么是产品定位?
  10. 【计算机动画】复习笔记 ( ゚∀゚) ノ♡