差别

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

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
任意波形产生 [2016/05/26 16:32]
gongyu [代码实现]
任意波形产生 [2020/10/09 01:31] (当前版本)
gongyu
行 8: 行 8:
   * 信号流程中的时序及各级时钟产生   * 信号流程中的时序及各级时钟产生
   * 通过[[示波器]]、[[频谱仪]]观察信号的构成及质量   * 通过[[示波器]]、[[频谱仪]]观察信号的构成及质量
 +
 +{{drawio>​simpledds}}
  
 ====项目要求==== ====项目要求====
 {{ :​stepfpga_dds.png |}} {{ :​stepfpga_dds.png |}}
 +<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以内的信号。具体要求如下: 本项目采用[[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个按键,用于控制输出信号的波形以及频率选择
行 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
  
 ====代码实现==== ====代码实现====
-<​code ​C+ 
-module ​MAX548A ​(CLOCK, DAC_SCLK, DAC_DIN, DAC_CS, DAC_LD, ​DATA_BYTE_A,​ DATA_BYTE_B, RESET); + 
-input CLOCK; ​                  // 96MHz system clock +===通过SPI控制DAC的Verilog代码=== 
-input RESET; ​                  // system reset +本参考代码是控制Max548 - 双通道8位串行DAC,其SPI接口模式和内部控制寄存器都不相同,但设计思路一致 
-input [7:0]    DATA_BYTE_A,​DATA_BYTE_B             // Data Byte Register+<​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_SCLK; ​              // 6MHz Serial Clock
行 56: 行 76:
 output DAC_LD; ​                // DAC Load output output DAC_LD; ​                // DAC Load output
  
-// DAC input for 2 channels, ​data_reg is used for buffer ​address and data +// data_reg is used for buffer address and data 
-reg [31:​0] data_reg;​+reg [15:​0] data_reg;​
  
 // Create 6MHz clock from system clock // Create 6MHz clock from system clock
行 63: 行 83:
 wire clk6mhz; wire clk6mhz;
  
-always @ (posedge CLOCK or posedge RESET)+always @(posedge CLOCK or posedge RESET)
 begin begin
    if (RESET)    if (RESET)
行 74: 行 94:
  
 // Detect changing of control byte and data byte // Detect changing of control byte and data byte
-reg [15:0] comp_reg;+reg [7:0] comp_reg;
 reg data_chg; reg data_chg;
  
行 81: 行 101:
  if (RESET) {comp_reg,​ data_chg} <= 0;  if (RESET) {comp_reg,​ data_chg} <= 0;
    ​ else begin    ​ else begin
- comp_reg <= {DATA_BYTE_A,​ DATA_BYTE_B}+ comp_reg <= DATA_BYTE
-      if (comp_reg != {DATA_BYTE_A,​ DATA_BYTE_B}) data_chg <= 1;+      if (comp_reg != DATA_BYTE) data_chg <= 1;
       else  data_chg <= 0;       else  data_chg <= 0;
    end    end
行 88: 行 108:
  
 // Shift data_reg ​ // Shift data_reg ​
-reg [5:0] cnt32;+reg [4:0] cnt16;
 reg DAC_CS; reg DAC_CS;
  
-always @ (posedge clk6mhz or posedge RESET)+always @(posedge clk6mhz or posedge RESET)
 begin begin
  if (RESET) begin  if (RESET) begin
  DAC_CS <= 1;  DAC_CS <= 1;
- cnt32 <=  0; + cnt16 <=  0; 
- data_reg <={32'h0};+ data_reg <={16'h0};
  end  end
  else if (data_chg) begin  else if (data_chg) begin
  DAC_CS <​=0;  ​  DAC_CS <​=0;  ​
- cnt32 <= 0; + cnt16 <= 0; 
- data_reg <​={8'​h0a,​DATA_BYTE_A,​8'​h09,​DATA_BYTE_B};+ data_reg <​={8'​h0a,​DATA_BYTE};
  end  end
  else  else
-    if(cnt32 31) begin +    if(cnt16 15) begin 
- cnt32 <= cnt32 + 1;+ cnt16 <= cnt16 + 1;
  data_reg <= data_reg <<1;  data_reg <= data_reg <<1;
  end  end
行 116: 行 136:
  
 assign DAC_LD = 1'b1; assign DAC_LD = 1'b1;
-assign DAC_DIN = data_reg[31];+assign DAC_DIN = data_reg[15];
  
 reg DAC_SCLK; reg DAC_SCLK;
-always @ (negedge clk12mhz or posedge RESET)+always @(negedge clk12mhz or posedge RESET)
 begin begin
- if (RESET) DAC_SCLK <= 0;+ if (RESET) DAC_SCLK <= 0;
  else if (!DAC_CS) DAC_SCLK <= !DAC_SCLK ;  else if (!DAC_CS) DAC_SCLK <= !DAC_SCLK ;
 end end
 endmodule endmodule
  
-/* +</​code>​
-</​code ​C>+
  
 ====结果及资源报告==== ====结果及资源报告====
- 
  
 ====参考资料==== ====参考资料====