差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
任意波形产生 [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>​
 +
 +====结果及资源报告====
  
 ====参考资料==== ====参考资料====