差别
这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
任意波形产生 [2016/05/26 17:50] gongyu [代码实现] |
— (当前版本) | ||
---|---|---|---|
行 1: | 行 1: | ||
- | ====学习目标==== | ||
- | 在这个项目中,我们将通过[[FPGA]]+[[串行DAC]]构成一个简单的任意波形发生器,从而学习信号合成的基本原理以及如何用FPGA内部的SRAM构成存储波表的ROM,通过产生能够访问这些波表的地址指针达到调整输出信号频率的目的。在本项目训练中需要掌握的知识点: | ||
- | * 按键输入及防抖处理 | ||
- | * [[DDS]]的基本原理及[[FPGA]]实现 | ||
- | * FPGA内部软核的调用及[[ROM]]构成 | ||
- | * 信号的频谱变化 | ||
- | * 串行DAC的工作原理及数据/控制接口 | ||
- | * 信号流程中的时序及各级时钟产生 | ||
- | * 通过[[示波器]]、[[频谱仪]]观察信号的构成及质量 | ||
- | ====项目要求==== | ||
- | {{ :stepfpga_dds.png |}} | ||
- | 本项目采用[[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个按键,用于控制输出信号的波形以及频率选择 | ||
- | * 时钟:25MHz晶振,FPGA内如需更高频率的时钟可以通过FPGA内置的PLL电路来实现 | ||
- | * 输出波形可调:正弦波、三角波、阶梯波、方波、白噪声 | ||
- | * 频率可调:可以输出频率从5Hz-200KHz的波形,调节精度达到1Hz | ||
- | * 输出信号的幅度为0-3.3V | ||
- | |||
- | ====硬件构成==== | ||
- | ===小脚丫FPGA=== | ||
- | ===5个按键=== | ||
- | ===DAC - AD5601:=== | ||
- | * 2.7 V至5.5 V,在本系统中工作电压为3.3V,其DAC转换用参考电压也为3.3V | ||
- | * 工作电流小于100µA | ||
- | * 8位nanoDAC®,由于本项目只是掌握原理,不追求更高的性能,因此采用了8位的器件,如需更高的性能可以选用管脚兼容的其它器件 | ||
- | * SPI接口 | ||
- | * 采用LFCSP和SC70封装 | ||
- | {{ :ad5601block.png |}} | ||
- | {{ :ad5601timing.png |}} | ||
- | |||
- | ===逻辑架构=== | ||
- | {{ :dds_block.png |DDS的构成框图}} | ||
- | |||
- | {{ :dds_spectrum.png |通过DDS产生的信号频谱}} | ||
- | |||
- | {{ :dds_antialias.png |DDS系统中的抗混叠滤波器的使用}} | ||
- | |||
- | ===核心代码=== | ||
- | * top.v: 系统的顶层文件 | ||
- | * keyin.v: 按键输入控制,选择波形以及调整频率,需要防抖处理 | ||
- | * dds.v: 根据频率控制字能够改变的相位累加器 | ||
- | * rom.v: Lattice Diamond软核构成的波表存储器,可以配置成宽度8位、深度256Byte的ROM,如果要存储多个波形方便切换,可以生成对应于不同波形的ROM文件 | ||
- | * 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> | ||
- | |||
- | ====结果及资源报告==== | ||
- | |||
- | |||
- | ====参考资料==== | ||
- | * [[http://www.analog.com/cn/search.html?q=AD5601|AD5601产品页面]] | ||
- | * [[http://www.analog.com/media/en/technical-documentation/data-sheets/AD5601_5611_5621.pdf|AD5601数据手册]] | ||
- | * {{:dds_pll.pdf|采用DDS构成PLL}} | ||
- | * {{:signal_generator_fundamentals-_tektronix.pdf|Tektronix公司关于信号发生器的基本原理介绍文档}} | ||
- | * {{:awg_basic.pdf|Agilent公司关于任意波形发生器产生的原理介绍}} | ||
- | * {{:dds_basic.pdf|Analog Devices公司关于直接数字合成技术的综述文章}} |