差别

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

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
steptrainingboardddsacode [2020/03/23 18:31]
gongyu
steptrainingboardddsacode [2021/02/02 12:38] (当前版本)
gongyusu
行 1: 行 1:
-##​用于小脚丫FPGA综合技能训练板的DDS培训代码+##​用于小脚丫FPGA综合技能训练板的DDS代码
  
-### Main Code+### DDS主程序
 <code verilog> <code verilog>
 module dds_main(clk_in,​led,​dac_data,​pwm_out);​ module dds_main(clk_in,​led,​dac_data,​pwm_out);​
-input clk_in; ​   //12MHz +input clk_in; ​                ​// 小脚丫FPGA的外部时钟频率位12MHz 
-output led; +                              // 内部可以通过PLL产生12MHz整数倍的高速时钟 
-output [9:0] dac_data; +                              // 比如96MHz、108MHz、120MHz...216MHz 
-output pwm_out;+output led;                   // 用以指示状态或帮助调试的LED 
 +                              // 小脚丫模块上有8个单色LED和2个三色LED,可选择其一 
 +output [9:0] dac_data; ​       // 10位数据输出送给外部的R-2R节点 
 +output pwm_out; ​              // 用以产生PWM波形,进而可以产生直流或任意波形,取决于外接的低通滤波器的参数
  
-reg [23:0] cnt;                 ​//??????? +reg [23:0] cnt;               ​// 自由运行的计数器,共计24位,最低频率为cnt[23]的12MHz/​2^24= 0.7Hz 
-always@(posedge clk_in) ​ cnt <= cnt +1'​b1;​ +always@(posedge clk_in) ​ cnt <= cnt + 1'​b1;​ 
-assign led= cnt[22]; ​     //12MHz/2^21 6Hz+assign led= cnt[22]; ​         //12MHz/2^23 1.5Hz, 接近心跳频率
  
  
-wire clk_96m; +//​通过同时改变所有的数据位从0-->​1--0来产生方波 
-CLK_96M u5(.CLKI(clk_in),​ .CLKOP(clk_96m));+//wire cnt_tap = cnt[2]     // 从计数器中取出其中的一位(这的bit7 = 第8位) 
 +//assign dac_data = {10{cnt_tap}}  // 复制10次,给每一位赋同样的值,产生一个10-bits DAC值 ​
  
 +//assign dac_data = cnt[9:​0]; ​ //​锯齿波,​ 频率 = Fclk/2^10
 +//assign dac_data = cnt[10] ? ~cnt[9:0] : cnt[9:​0]; ​ // 三角波形,频率 = Fclk/2^11
  
-//square wave generated by toggling all data bits from 0-->​1--0 +reg [23:0] phase_acc
-//wire cnt_tap = cnt[2]; ​    // we take one bit out of the counter (here bit 7 = the 8th bit) +always @(posedge ​clk_inphase_acc ​<= phase_acc + 24'​d27962 //主时钟为12MHz,产生20KHz的正弦波信号 
-//assign dac_data = {10{cnt_tap}}; ​  // and we duplicate it 10 times to create the 10-bits DAC value  +lookup_tables u_lookup_tables(.phase(phase_acc[23:​16]), .sine_data(dac_data));
- +
-//assign dac_data = cnt[9:​0]; ​ //Sawtooth waveform, frenquency = Fclk/2^10 +
- +
-// Triangle waveform, frequency = Fclk/2^11 +
-//assign dac_data = cnt[10] ? ~cnt[9:0] : cnt[9:​0]; ​ // Triangle waveform, frenquency = Fclk/2^11 +
- +
-wire   ​ [23:​0] next_phase;​ +
-wire   ​ [7:​0] phase; +
-reg     [23:0] accumulator; +
- +
-assign next_phase = 24'​H0DA7 + accumulator;​ +
- +
-always @(posedge ​clk_96m +
-      accumulator ​<= #1 next_phase; +
- +
-assign phase = accumulator[23:​16]; ​   // phase is the high 8 bits +
- +
-wire [9:0] sine_data;​ +
- +
-//lookup_tables u_lookup_tables(clk_96m, ​phase, sine_data);​ +
- +
-LUT_sine_table U_lut_sine_table(.Clock(~clk_96m), .ClkEn(1'b1), .Reset(1'​b0), .Theta(phase),​ .Sine(sine_data));​ +
-assign dac_data = sine_data[9:​0] + 10'​h1ff ​;+
  
 wire [9:0] PWM_in; wire [9:0] PWM_in;
-//assign PWM_in = 8'​d38;​ +//assign PWM_in = 8'​d38; ​          // 产生直流电压 
-assign PWM_in = dac_data[9:​0];​+assign PWM_in = dac_data[9:​0]; ​    // 变化的数据产生变化的PWM占空比,从而产生变化的输出波形
  
 reg [10:0] PWM_DDS_accumulator;​ reg [10:0] PWM_DDS_accumulator;​
  
-always @(posedge ​clk_96m) PWM_DDS_accumulator <= PWM_DDS_accumulator[9:​0] + PWM_in;+always @(posedge ​clk_in) PWM_DDS_accumulator <= PWM_DDS_accumulator[9:​0] + PWM_in;
  
 assign pwm_out = PWM_DDS_accumulator[10];​ assign pwm_out = PWM_DDS_accumulator[10];​
 +
 +// 可以通过内部PLL产生更高频率的时钟信号,比如120MHz,如下面的例子,只需要将上述代码中的clk_in都改为PLL产生的时钟,比如clk_120m就可以了
 +//wire clk_120m; ​                              // 内部高倍时钟的名字
 +//CLK_PLL u5(.CLKI(clk_in),​ .CLKOP(clk_120m));​ // 以Lattice的IPCore为例产生高速内部时钟
 +                                               // 从12MHz产生120MHz,用以内部的逻辑以及DAC转换
  
  
行 60: 行 48:
 </​code>​ </​code>​
  
-### lookup table code+### 波表部分的代码
 <code verilog> <code verilog>
 /* lookup_tables.v */ /* lookup_tables.v */
  
-module lookup_tables(clk, phase, sin_out);+module lookup_tables(phase,​ sin_out);
 input  [7:0] phase; input  [7:0] phase;
 output [9:0] sin_out; output [9:0] sin_out;
行 76: 行 64:
 reg     ​[9:​0] ​  ​sine_onecycle_amp;​ reg     ​[9:​0] ​  ​sine_onecycle_amp;​
  
-//assign sin_out = {4'b0, sine_onecycle_amp[9:​4]} + 9'hff;+//assign sin_out = {4'b0, sine_onecycle_amp[9:​4]} + 9'​hff; ​ // 可以调节输出信号的幅度
 assign sin_out = sine_onecycle_amp[9:​0];​ assign sin_out = sine_onecycle_amp[9:​0];​
  
  assign sel = phase[7:6];  assign sel = phase[7:6];
  
-//   ​ sin_table u_sin_table(address,​sine_table_out);​ 
    ​ sin_table u_sin_table(address,​sine_table_out);​    ​ sin_table u_sin_table(address,​sine_table_out);​
-sine_table u_sine_table(.Clock(clk),​ .ClkEn(1'​b1),​ .Reset(1'​b0),​ .Theta(phase),​ .Sine(sin_out));​+
 always @(sel or sine_table_out) always @(sel or sine_table_out)
 begin begin
行 108: 行 95:
 endmodule endmodule
  
-/ 
 module sin_table(address,​sin);​ module sin_table(address,​sin);​
 output [8:0] sin; output [8:0] sin;
行 188: 行 174:
 </​code>​ </​code>​
  
 +### 10位地址、12位分辨率的正弦波表数据参考
 +  * [[sine_tables|10位地址、12位分辨率的正弦波表Verilog代码]]
 +  * {{:​sinetable.xlsx|10位地址、14位分辨率/​10位地址、12位分辨率/​10位地址、10位分辨率/​8位地址、10位分辨率的正弦波表xls格式的文件}}