**这是本文档旧的修订版!**
在电赛训练板上实现DDS的功能
关于用FPGA实现DDS的过程可以参考文档:DDS生成任意波形的方法及Verilog代码实例
顶层模块
DDS核心模块
// -------------------------------------------------------------------- // >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<< // -------------------------------------------------------------------- // Module: dds // // Author: Step // // Description: dds // // Web: www.stepfapga.com // // -------------------------------------------------------------------- // Code Revision History : // -------------------------------------------------------------------- // Version: |Mod. Date: |Changes Made: // V1.0 |2021.11.27 |Initial ver // -------------------------------------------------------------------- module dds(clk_in,rst_n,O_pulse,L_pulse,R_pulse,dac_data,wave,WaveFreq);// localparam SIN = 2'b00, SAW = 2'b01, TRI = 2'b10, SQU = 2'b11; input clk_in; // 小脚丫FPGA的外部时钟频率为12MHz input rst_n; input wire O_pulse,L_pulse,R_pulse; output reg [9:0] dac_data; // 10位数据输出送给外部的DAC output reg [1:0] wave; output reg [26:0] WaveFreq; reg [23:0] phase_acc; //增加相位累加器位数使得分辨率提高 wire [23:0] phase; reg [23:0] f_inc; assign phase=phase_acc; always @(posedge clk_in) phase_acc <= phase_acc + f_inc; //f_inc=24'd27962;主时钟为12MHz,则产生20KHz的正弦波信号 wire [9:0] sin_dat; //正弦波 wire [9:0] saw_dat = phase[23:14]; //锯齿波 wire [9:0] tri_dat = phase[23]? (~phase[22:13]) : phase[22:13]; //三角波 wire [9:0] squ_dat = phase[23]? 10'h3ff : 10'h000; //方波 always @(*) begin case(wave) 2'b00: dac_data = sin_dat; //正弦波 2'b01: dac_data = saw_dat; //锯齿波 2'b10: dac_data = tri_dat; //三角波 2'b11: dac_data = squ_dat; //方波 default: dac_data = sin_dat; //正弦波 endcase end lookup_tables u_lookup_tables(.phase(phase_acc[23:16]), .sin_out(sin_dat)); //波形输出选择 always @(posedge clk_in or negedge rst_n) begin if(!rst_n) wave <= SIN; else if(O_pulse)begin case(wave) SIN: wave <= SAW; SAW: wave <= TRI; TRI: wave <= SQU; SQU: wave <= SIN; default: wave <= SIN; endcase end else wave <= wave; end //频率控制 always@(posedge clk_in or negedge rst_n) begin if(!rst_n) begin f_inc <= 24'h22222; WaveFreq<=1_000_000; end else if(L_pulse==1'b1) begin if(f_inc <= 24'h369d) f_inc <= f_inc; else begin f_inc <= f_inc - 24'h369d; WaveFreq<=WaveFreq-100000; end end else if(R_pulse==1'b1) begin if(f_inc >= 24'h155554) f_inc <= f_inc; else begin f_inc <= f_inc + 24'h369d; WaveFreq<=WaveFreq+100000; end end else f_inc <= f_inc; end endmodule //dds时钟频率给定后,输出信号的频率取决于频率控制字, // 频率分辨率取决于累加器位数, // 相位分辨率取决于ROM的地址线位数, // 幅度量化噪声取决于ROM的数据位字长和D/A转换器位数