差别

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

到此差别页面的链接

后一修订版
前一修订版
steptrainingboardddsacode [2020/03/23 18:28]
gongyu 创建
steptrainingboardddsacode [2021/02/02 12:38] (当前版本)
gongyusu
行 1: 行 1:
 +##​用于小脚丫FPGA综合技能训练板的DDS代码
 +
 +### 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--+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_in) phase_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+wire [9:0] PWM_in; 
 +//​assign ​PWM_in ​8'​d38; ​          // 产生直流电压 
 +assign PWM_in = dac_data[9:​0]; ​    ​// 变化的数据产生变化的PWM占空比,从而产生变化的输出波形
  
-// Triangle waveform, frequency = Fclk/2^11 +reg [10:​0] ​PWM_DDS_accumulator;
-//assign dac_data = cnt[10] ? ~cnt[9:0] : cnt[9:0];  // Triangle waveform, frenquency = Fclk/2^11+
  
-wire    [23:0]  next_phase;​ +always @(posedge clk_in) PWM_DDS_accumulator <= PWM_DDS_accumulator[9:0] + PWM_in;
-wire   ​ [7:​0] phase; +
-reg    [23:0] accumulator;+
  
-assign ​next_phase ​24'​H0DA7 + accumulator;+assign ​pwm_out ​PWM_DDS_accumulator[10];
  
-always @(posedge clk_96m +// 可以通过内部PLL产生更高频率的时钟信号,比如120MHz,如下面的例子,只需要将上述代码中的clk_in都改为PLL产生的时钟,比如clk_120m就可以了 
-      accumulator <= #1 next_phase;+//wire clk_120m; ​                              // 内部高倍时钟的名字 
 +//CLK_PLL u5(.CLKI(clk_in),​ .CLKOP(clk_120m)); // 以Lattice的IPCore为例产生高速内部时钟 
 +                                               // 从12MHz产生120MHz,用以内部的逻辑以及DAC转换
  
-assign phase = accumulator[23:​16]; ​   // phase is the high 8 bits 
  
-wire [9:0] sine_data;+endmodule
  
-//​lookup_tables u_lookup_tables(clk_96m,​ phase, sine_data);+</code>
  
-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 ;+<code verilog>​ 
 +/* lookup_tables.v */
  
-wire [9:0] PWM_in; +module lookup_tables(phase,​ sin_out); 
-//assign PWM_in = 8'd38+input  [7:0]  phase
-assign PWM_in = dac_data[9:0];+output [9:0]  sin_out;
  
-reg [10:0] PWM_DDS_accumulator;+wire     [9:0]   sin_out;
  
-always @(posedge clk_96m) PWM_DDS_accumulator <= PWM_DDS_accumulator[9:0] + PWM_in;+reg    [5:0]  address; 
 +wire   ​ [1:​0] sel; 
 +wire   ​ [8:​0] sine_table_out;
  
-assign ​pwm_out ​PWM_DDS_accumulator[10];+reg     ​[9:​0] ​  ​sine_onecycle_amp;​ 
 + 
 +//assign ​sin_out ​{4'b0, sine_onecycle_amp[9:​4]} + 9'​hff; ​ // 可以调节输出信号的幅度 
 +assign sin_out = sine_onecycle_amp[9:​0];​ 
 + 
 + assign sel = phase[7:​6];​ 
 + 
 +   ​ sin_table u_sin_table(address,​sine_table_out);​ 
 + 
 +always @(sel or sine_table_out) 
 +begin 
 + case(sel) 
 + 2'​b00:​ begin 
 + sine_onecycle_amp = 9'h1ff + sine_table_out[8:​0];​ 
 + address = phase[5:​0];​ 
 +      ​ end 
 +  2'​b01:​ begin 
 + sine_onecycle_amp = 9'h1ff + sine_table_out[8:​0];​ 
 + address = ~phase[5:​0];​ 
 +      ​ end 
 +  2'​b10:​ begin 
 + sine_onecycle_amp = 9'h1ff - sine_table_out[8:​0];​ 
 + address = phase[5:​0];​ 
 +     ​ end 
 +  2'​b11:​ begin 
 + sine_onecycle_amp = 9'h1ff - sine_table_out[8:​0];​ 
 + address = ~ phase[5:​0];​ 
 +     ​ end 
 + endcase 
 +end 
 + 
 +endmodule 
 + 
 +module sin_table(address,​sin);​ 
 +output [8:0] sin; 
 +input  ​[5:0address;
  
 +reg    [8:0] sin;
  
 +always @(address)
 + begin
 +                  case(address)
 +                      6'h0: sin=9'​h0;​
 +                      6'h1: sin=9'​hC;​
 +                      6'h2: sin=9'​h19;​
 +                      6'h3: sin=9'​h25;​
 +                      6'h4: sin=9'​h32;​
 +                      6'h5: sin=9'​h3E;​
 +                      6'h6: sin=9'​h4B;​
 +                      6'h7: sin=9'​h57;​
 +                      6'h8: sin=9'​h63;​
 +                      6'h9: sin=9'​h70;​
 +                      6'ha: sin=9'​h7C;​
 +                      6'hb: sin=9'​h88;​
 +                      6'hc: sin=9'​h94;​
 +                      6'hd: sin=9'​hA0;​
 +                      6'he: sin=9'​hAC;​
 +                      6'hf: sin=9'​hB8;​
 +                      6'h10: sin=9'​hC3;​
 +                      6'h11: sin=9'​hCF;​
 +                      6'h12: sin=9'​hDA;​
 +                      6'h13: sin=9'​hE6;​
 +                      6'h14: sin=9'​hF1;​
 +                      6'h15: sin=9'​hFC;​
 +                      6'h16: sin=9'​h107;​
 +                      6'h17: sin=9'​h111;​
 +                      6'h18: sin=9'​h11C;​
 +                      6'h19: sin=9'​h126;​
 +                      6'h1a: sin=9'​h130;​
 +                      6'h1b: sin=9'​h13A;​
 +                      6'h1c: sin=9'​h144;​
 +                      6'h1d: sin=9'​h14E;​
 +                      6'h1e: sin=9'​h157;​
 +                      6'h1f: sin=9'​h161;​
 +                      6'h20: sin=9'​h16A;​
 +                      6'h21: sin=9'​h172;​
 +                      6'h22: sin=9'​h17B;​
 +                      6'h23: sin=9'​h183;​
 +                      6'h24: sin=9'​h18B;​
 +                      6'h25: sin=9'​h193;​
 +                      6'h26: sin=9'​h19B;​
 +                      6'h27: sin=9'​h1A2;​
 +                      6'h28: sin=9'​h1A9;​
 +                      6'h29: sin=9'​h1B0;​
 +                      6'h2a: sin=9'​h1B7;​
 +                      6'h2b: sin=9'​h1BD;​
 +                      6'h2c: sin=9'​h1C3;​
 +                      6'h2d: sin=9'​h1C9;​
 +                      6'h2e: sin=9'​h1CE;​
 +                      6'h2f: sin=9'​h1D4;​
 +                      6'h30: sin=9'​h1D9;​
 +                      6'h31: sin=9'​h1DD;​
 +                      6'h32: sin=9'​h1E2;​
 +                      6'h33: sin=9'​h1E6;​
 +                      6'h34: sin=9'​h1E9;​
 +                      6'h35: sin=9'​h1ED;​
 +                      6'h36: sin=9'​h1F0;​
 +                      6'h37: sin=9'​h1F3;​
 +                      6'h38: sin=9'​h1F6;​
 +                      6'h39: sin=9'​h1F8;​
 +                      6'h3a: sin=9'​h1FA;​
 +                      6'h3b: sin=9'​h1FC;​
 +                      6'h3c: sin=9'​h1FD;​
 +                      6'h3d: sin=9'​h1FE;​
 +                      6'h3e: sin=9'​h1FF;​
 +                      6'h3f: sin=9'​h1FF;​
 +                   ​endcase
 +              end
 endmodule endmodule
  
 </​code>​ </​code>​
  
 +### 10位地址、12位分辨率的正弦波表数据参考
 +  * [[sine_tables|10位地址、12位分辨率的正弦波表Verilog代码]]
 +  * {{:​sinetable.xlsx|10位地址、14位分辨率/​10位地址、12位分辨率/​10位地址、10位分辨率/​8位地址、10位分辨率的正弦波表xls格式的文件}}