差别
这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
任意波形产生 [2016/05/26 15:22] gongyu |
任意波形产生 [2020/10/09 01:31] (当前版本) gongyu |
||
---|---|---|---|
行 8: | 行 8: | ||
* 信号流程中的时序及各级时钟产生 | * 信号流程中的时序及各级时钟产生 | ||
* 通过[[示波器]]、[[频谱仪]]观察信号的构成及质量 | * 通过[[示波器]]、[[频谱仪]]观察信号的构成及质量 | ||
+ | |||
+ | {{drawio>simpledds}} | ||
====项目要求==== | ====项目要求==== | ||
{{ :stepfpga_dds.png |}} | {{ :stepfpga_dds.png |}} | ||
- | 本项目采用Analog Devices公司的8位串行DAC芯片AD5601,小脚丫FPGA模块通过SPI总线与AD5601连接,AD5601输出模拟信号,通过一个RC低通滤波器进行抗混叠绿波,得到最高频率为200KHz以内的信号。具体要求如下: | + | <WRAP centeralign> **图1. 小脚丫FPGA同串行DAC构成的任意信号发生器** </WRAP> |
+ | |||
+ | 本项目采用[[http://www.analog.com|Analog Devices]]公司的8位串行DAC芯片[[http://www.analog.com/cn/search.html?q=ad5601|AD5601]],小脚丫FPGA模块通过SPI总线与AD5601连接,AD5601输出模拟信号,通过一个RC低通滤波器进行抗混叠滤波,得到最高频率为200KHz以内的信号。具体要求如下: | ||
* 输入:5个按键,用于控制输出信号的波形以及频率选择 | * 输入:5个按键,用于控制输出信号的波形以及频率选择 | ||
* 时钟:25MHz晶振,FPGA内如需更高频率的时钟可以通过FPGA内置的PLL电路来实现 | * 时钟:25MHz晶振,FPGA内如需更高频率的时钟可以通过FPGA内置的PLL电路来实现 | ||
行 28: | 行 32: | ||
* 采用LFCSP和SC70封装 | * 采用LFCSP和SC70封装 | ||
{{ :ad5601block.png |}} | {{ :ad5601block.png |}} | ||
+ | |||
+ | <WRAP centeralign>**图2 AD5601的内部功能框图** </WRAP> | ||
+ | |||
{{ :ad5601timing.png |}} | {{ :ad5601timing.png |}} | ||
+ | <WRAP centeralign> **图3 AD5601数据接口时序**</WRAP> | ||
===逻辑架构=== | ===逻辑架构=== | ||
{{ :dds_block.png |DDS的构成框图}} | {{ :dds_block.png |DDS的构成框图}} | ||
+ | <WRAP centeralign> **图4 DDS的构成框图**</WRAP> | ||
{{ :dds_spectrum.png |通过DDS产生的信号频谱}} | {{ :dds_spectrum.png |通过DDS产生的信号频谱}} | ||
+ | <WRAP centeralign> **图5 通过DDS产生的信号频谱**</WRAP> | ||
{{ :dds_antialias.png |DDS系统中的抗混叠滤波器的使用}} | {{ :dds_antialias.png |DDS系统中的抗混叠滤波器的使用}} | ||
+ | <WRAP centeralign> **图6 DDS系统中的抗混叠滤波器的使用**</WRAP> | ||
+ | |||
+ | **调试过程:**由于这是一个相对复杂的系统,我们采用分段实现的方式进行系统实现和分阶段调试: | ||
+ | - DAC产生直流电压:通过[[SPI]]串行总线的低速数模变换器[[DAC]]得到需要的直流电压,按键更改数字参数能够改变输出直流电压的值 | ||
+ | - DAC生成正弦波:通过[[FPGA]]内部寄存器或调用内部IP核将内嵌的块RAM配置成256深度,位宽为8位的[[ROM]]存储一个周期的正弦波波形信号,逻辑控制将波形表中的每个点通过DAC输出,生成模拟的正弦波信号 | ||
+ | - DAC生成任意波形,并且可以调整频率 | ||
===核心代码=== | ===核心代码=== | ||
行 41: | 行 57: | ||
* keyin.v: 按键输入控制,选择波形以及调整频率,需要防抖处理 | * keyin.v: 按键输入控制,选择波形以及调整频率,需要防抖处理 | ||
* dds.v: 根据频率控制字能够改变的相位累加器 | * dds.v: 根据频率控制字能够改变的相位累加器 | ||
- | * rom.v: Lattice Diamond软核构成的波表存储器,可以配置成宽度8位、深度256Byte的ROM,如果要存储多个波形方便切换,可以生成对应于不同波形的ROM文件 | + | * rom.v: [[Lattice Diamond]]系统自带软核构成的波表存储器,可以配置成宽度8位、深度256Byte的[[ROM]],如果要存储多个波形方便切换,可以生成对应于不同波形的ROM文件 |
* spidac.v: 通过SPI总线协议将ROM表中的数据串行发送給AD5601 | * spidac.v: 通过SPI总线协议将ROM表中的数据串行发送給AD5601 | ||
====代码实现==== | ====代码实现==== | ||
- | ====结果及资源报告==== | ||
+ | ===通过SPI控制DAC的Verilog代码=== | ||
+ | 本参考代码是控制Max548 - 双通道8位串行DAC,其SPI接口模式和内部控制寄存器都不相同,但设计思路一致 | ||
+ | <code verilog> | ||
+ | module SPIDAC(CLOCK, DAC_SCLK, DAC_DIN, DAC_CS, DAC_LD, DATA_BYTE, RESET); | ||
+ | input CLOCK; // 96MHz system clock | ||
+ | input RESET; // system reset | ||
+ | input [7:0] DATA_BYTE_A; // Data Byte Register | ||
+ | |||
+ | output DAC_SCLK; // 6MHz Serial Clock | ||
+ | output DAC_DIN; // Serial Data output | ||
+ | output DAC_CS; // Serial Interface Select | ||
+ | output DAC_LD; // DAC Load output | ||
+ | |||
+ | // data_reg is used for buffer address and data | ||
+ | reg [15:0] data_reg; | ||
+ | |||
+ | // Create 6MHz clock from system clock | ||
+ | reg [3:0] cnt6; | ||
+ | wire clk6mhz; | ||
+ | |||
+ | always @(posedge CLOCK or posedge RESET) | ||
+ | begin | ||
+ | if (RESET) | ||
+ | cnt6 <= 0; | ||
+ | else | ||
+ | cnt6 <= cnt6 + 1; | ||
+ | end | ||
+ | |||
+ | assign clk6mhz = cnt6[3]; | ||
+ | |||
+ | // Detect changing of control byte and data byte | ||
+ | reg [7:0] comp_reg; | ||
+ | reg data_chg; | ||
+ | |||
+ | always @ (negedge clk6mhz or posedge RESET) | ||
+ | begin | ||
+ | if (RESET) {comp_reg, data_chg} <= 0; | ||
+ | else begin | ||
+ | comp_reg <= DATA_BYTE; | ||
+ | if (comp_reg != DATA_BYTE) data_chg <= 1; | ||
+ | else data_chg <= 0; | ||
+ | end | ||
+ | end | ||
+ | |||
+ | // Shift data_reg | ||
+ | reg [4:0] cnt16; | ||
+ | reg DAC_CS; | ||
+ | |||
+ | always @(posedge clk6mhz or posedge RESET) | ||
+ | begin | ||
+ | if (RESET) begin | ||
+ | DAC_CS <= 1; | ||
+ | cnt16 <= 0; | ||
+ | data_reg <={16'h0}; | ||
+ | end | ||
+ | else if (data_chg) begin | ||
+ | DAC_CS <=0; | ||
+ | cnt16 <= 0; | ||
+ | data_reg <={8'h0a,DATA_BYTE}; | ||
+ | end | ||
+ | else | ||
+ | if(cnt16 < 15) begin | ||
+ | cnt16 <= cnt16 + 1; | ||
+ | data_reg <= data_reg <<1; | ||
+ | end | ||
+ | else | ||
+ | DAC_CS <= 1; | ||
+ | end | ||
+ | |||
+ | wire clk12mhz; | ||
+ | assign clk12mhz = cnt6[2]; | ||
+ | |||
+ | assign DAC_LD = 1'b1; | ||
+ | assign DAC_DIN = data_reg[15]; | ||
+ | |||
+ | reg DAC_SCLK; | ||
+ | always @(negedge clk12mhz or posedge RESET) | ||
+ | begin | ||
+ | if (RESET) DAC_SCLK <= 0; | ||
+ | else if (!DAC_CS) DAC_SCLK <= !DAC_SCLK ; | ||
+ | end | ||
+ | endmodule | ||
+ | |||
+ | </code> | ||
+ | |||
+ | ====结果及资源报告==== | ||
====参考资料==== | ====参考资料==== |