差别
这里会显示出您选择的修订版和当前版本之间的差别。
| 两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
|
dds_verilog [2023/03/11 13:36] gongyu |
dds_verilog [2023/03/20 16:33] (当前版本) gongyu [4. “任意”信号生成] |
||
|---|---|---|---|
| 行 2: | 行 2: | ||
| [[DDS]]是一种用于通过单个固定频率的参考时钟信号生成任意波形的频率合成器,被广泛用于测试测量仪表和通信系统中。也是学习[[FPGA]]、[[大学生电子设计竞赛]]备赛必学的原理性技能,在这里我们通过FPGA [[Verilog]]代码编程示例一步步让大家理解一下DDS的基本概念、构成以及各项指标的含义。 | [[DDS]]是一种用于通过单个固定频率的参考时钟信号生成任意波形的频率合成器,被广泛用于测试测量仪表和通信系统中。也是学习[[FPGA]]、[[大学生电子设计竞赛]]备赛必学的原理性技能,在这里我们通过FPGA [[Verilog]]代码编程示例一步步让大家理解一下DDS的基本概念、构成以及各项指标的含义。 | ||
| - | ### 1. 用以学习和体验DDS的开源平台 | + | ### 1. 平台介绍 |
| - | 硬禾学堂专门设计了一款通过小脚丫FPGA来学习数字系统应用的平台: | + | 本案例使用[[analog_circuit_learning_kit|模拟电路学习套件]]中的信号产生部分为例: |
| - | {{ :alk1.png? 600 |3D效果图}} | + | {{ :alk1.png? |}}<WRAP centeralign> 模拟电路学习套件 </WRAP> |
| - | + | {{ :dds_sch.png? |}}<WRAP centeralign> 信号产生部分的原理图 </WRAP> | |
| - | {{ :fpgatrainingboard.png |}} | + | |
| - | {{ :howtouse_traingingboard.png?800 |}}<WRAP centeralign> 基于小脚丫FPGA的综合训练口袋实验系统沟通 </WRAP> | + | |
| 以及一款针对高校电子设计竞赛的训练平台: | 以及一款针对高校电子设计竞赛的训练平台: | ||
| 行 15: | 行 13: | ||
| <WRAP centeralign> 基于小脚丫FPGA的电赛训练平台 </WRAP> | <WRAP centeralign> 基于小脚丫FPGA的电赛训练平台 </WRAP> | ||
| - | 这两款平台可以支持任意一款的[[stepfpga|小脚丫FPGA核心板]],第一款平台的[[DAC]]部分都是由R-2R网络构成的,第二款平台上使用通用的高速DAC IC,它们的代码基本上是一致的,只是通用的高速DAC IC会需要转换时钟进行同步,而R-2R只需要数据线,无需时钟。 | + | 这两款平台可以支持任意一款的[[stepfpga|小脚丫FPGA核心板]],这两款平台的[[DAC]]部分都是使用通用的高速DAC IC - ADI的AD9740或3Peaks的3PD5651,。 |
| - | 它们都能通过FPGA中的Verilog逻辑编程实现以下的功能并能达到相应的性能: | + | 通过FPGA中的Verilog逻辑编程可以实现以下的功能并能达到相应的性能: |
| * DDS的主时钟选择为12M(案例中前面的例子)和120MHz(案例中后面的例子,由小脚丫外部的12MHz输入时钟,通过内部[[PLL]]倍频到120MHz),使用120MHz的时钟能够生成0 - 15MHz(用8个点构成一个周期波形),甚至更高频率的正弦波波形,输出的信号波形可以是正弦波、三角波、锯齿波、方波等; | * DDS的主时钟选择为12M(案例中前面的例子)和120MHz(案例中后面的例子,由小脚丫外部的12MHz输入时钟,通过内部[[PLL]]倍频到120MHz),使用120MHz的时钟能够生成0 - 15MHz(用8个点构成一个周期波形),甚至更高频率的正弦波波形,输出的信号波形可以是正弦波、三角波、锯齿波、方波等; | ||
| - | * 由于R-2R后面的运算放大器的性能限制,为保证在不同的频率上实现恒定的信号幅度 ,这两款板子的最高输出频率做了一定的限制 - 第一款平台的输出信号带宽保证到2MHz,信号幅度为0.5-3V,电赛训练板的输出信号带宽可以达到15MHz,信号幅度为2Vpp。 | + | * 由于适用Web IDE时FPGA无法使用PLL,只能使用12MHz的时钟频率,第1款平台的输出信号带宽保证到5MHz,由DAC输出的信号幅度为最高2Vpp,电赛训练板的输出信号带宽可以达到15MHz,信号幅度为2Vpp。 |
| - | * 第一款板子都可以通过[[UART]]同PC连接,通过PC上的软件(比如LabView或用QT等自编)对FPGA中的参数进行设置,进而调节DDS输出信号的波形、频率、幅度和直流偏移等。 | + | |
| 下面我们来看看在这两款平台上通过DDS能够实现的任意波形及实现方法、相关的Verilog代码。 | 下面我们来看看在这两款平台上通过DDS能够实现的任意波形及实现方法、相关的Verilog代码。 | ||
| 行 47: | 行 44: | ||
| 无论采用任何一款DAC,第一步就是要验证从FPGA的逻辑到DAC是否正常工作(尤其是FPGA和R-2R网络连接时管脚的分配),最简单的就是输出固定的数字,看输出的直流电压是否是你换算出来应该得到的模拟量,如下图所示: | 无论采用任何一款DAC,第一步就是要验证从FPGA的逻辑到DAC是否正常工作(尤其是FPGA和R-2R网络连接时管脚的分配),最简单的就是输出固定的数字,看输出的直流电压是否是你换算出来应该得到的模拟量,如下图所示: | ||
| - | {{ ::DDS_Training_DC.png?800 |}} <WRAP centeralign> 产生直流电压用来验证FPGA到DAC的链路是否能够正常工作</WRAP> | + | {{drawio>ACDLK_DDS_DC.png}} <WRAP centeralign> 产生直流电压用来验证FPGA到DAC的链路是否能够正常工作</WRAP> |
| - | 细心的朋友可能观察到了,上面的图中用到了反向放大器且为单电源供电的结构。 | + | <code verilog> |
| + | module dds_main(clk, dac_data, dac_clk); | ||
| + | input clk; //12MHz的外部时钟送给FPGA; | ||
| + | output [9:0] dac_data; //10位的并行数据输出到DAC; | ||
| + | output dac_clk; //输出给DAC的并行时钟,在R-2R的DAC中不需要这个时钟信号 | ||
| + | |||
| + | assign dac_data = 10’d511; // 0-1023对应于输出模拟信号的最小值和最大值,511对应于0V | ||
| + | assign dac_clk= clk; | ||
| + | |||
| + | endmodule | ||
| + | </code> | ||
| FPGA到DAC的连接工作正常,下一步就可以开始各种波形的输出了。 | FPGA到DAC的连接工作正常,下一步就可以开始各种波形的输出了。 | ||
| 行 58: | 行 65: | ||
| ##### 3.1 生成方波 | ##### 3.1 生成方波 | ||
| - | {{ ::DDS_Training_Square.png?800 |}} | + | {{drawio>ACDLK_DDA_Squre.png}} |
| DDS常被用来产生周期性的信号,第一步我们先看看如何产生一个方波信号,下面是代码: | DDS常被用来产生周期性的信号,第一步我们先看看如何产生一个方波信号,下面是代码: | ||
| <code verilog> | <code verilog> | ||
| module dds_main(clk, dac_data, dac_clk); | module dds_main(clk, dac_data, dac_clk); | ||
| input clk; //12MHz的外部时钟送给FPGA; | input clk; //12MHz的外部时钟送给FPGA; | ||
| - | output [9:0] dac_data; //10位的并行数据输出到R-2R DAC; | + | output [9:0] dac_data; //10位的并行数据输出到DAC; |
| - | output dac_clk; //输出给DAC的并行时钟,在R-2R的DAC中不需要这个时钟信号 | + | output dac_clk; //输出给DAC的并行时钟,在R-2R的DAC中不需要这个时钟信号 |
| //创建一个24位的自由运行的二进制计数器,方便取出最高位(0.7秒一个周期)送给LED用作心跳灯指示用, 在此程序中不列出LED的部分 | //创建一个24位的自由运行的二进制计数器,方便取出最高位(0.7秒一个周期)送给LED用作心跳灯指示用, 在此程序中不列出LED的部分 | ||
| 行 86: | 行 93: | ||
| ##### 3.2 生成锯齿波 | ##### 3.2 生成锯齿波 | ||
| - | {{ ::DDS_Training_Sawtooth.png?800 |}} | + | {{drawio>ACDLK_DDA_SAWTOOTH.png}} |
| 我们再看看锯齿波是如何轻松实现的,只需要将上面的代码的最后两行更换成这样: | 我们再看看锯齿波是如何轻松实现的,只需要将上面的代码的最后两行更换成这样: | ||
| 行 99: | 行 106: | ||
| 根据下面的图示方法实现三角波也不难: | 根据下面的图示方法实现三角波也不难: | ||
| - | {{ ::DDS_Training_Triangle.png?800 |}} | + | {{drawio>ACDLK_DDA_Triangle.png}} |
| <code verilog> | <code verilog> | ||
| 行 125: | 行 132: | ||
| {{ :heartwave.jpeg |}}<WRAP centeralign> 用查找表的方式生成的心型模拟信号波形 </WRAP> | {{ :heartwave.jpeg |}}<WRAP centeralign> 用查找表的方式生成的心型模拟信号波形 </WRAP> | ||
| - | 参见[[steptrainingboardddsacode|用于小脚丫FPGA综合技能训练板的DDS培训代码]],在这个页面中有一段lookup table的代码,示例中使用的为8位地址波表(出于演示的方便,采用了更少的位数)、10位精度的DAC。基于正弦波的对称性,在这个波表中我们只保存了1/4个周期的波形,其它3个1/4周期的波形可以基于对称性来实现,周期的选择采用地址的高两位 - 示例中的phase[7:6]。 | + | 参见[[https://www.eetree.cn/wiki/steptrainingboardddsacode|用于小脚丫FPGA综合技能训练板的DDS培训代码]],在这个页面中有一段lookup table的代码,示例中使用的为8位地址波表(出于演示的方便,采用了更少的位数)、10位精度的DAC。基于正弦波的对称性,在这个波表中我们只保存了1/4个周期的波形,其它3个1/4周期的波形可以基于对称性来实现,周期的选择采用地址的高两位 - 示例中的phase[7:6]。 |
| <code verilog> | <code verilog> | ||