彻底理解DDS(信号发生器)的fpga实现(verilog设计代码)
作者:互联网
DDS(Direct Digital Synthesis)是一种把一系列数字信号通过D/A转换器转换成模拟信号的数字合成技术。
它有查表法和计算法两种基本合成方法。在这里主要记录DDS查表法的fpga实现。
查表法:由于ROM查询法结构简单,只需要在ROM中存放不同相位对应的幅度序列,然后通过相位累加器的输出对其寻址,经过数/模转换和低通滤波(LPF)输出便可以得到所需要的模拟信号。
查表法示意图:
设计:
输入:频率控制字f,相位控制字,系统时钟Fclk,复位信号reset
输出:幅度数据dout。
关系:Tout = M * Tclk 即 Fout = Fclk / M 。其中,M为一个波形的离散点数。
简单解释一下:比如我们把一个正弦波形分为16个点,而ROM容量为8,那么我们的点数间隔就要取16 / 8 = 2 ,即频率控制字为 2 。
细节:由于在设计时点数间隔不一定为1,即相位累加器的值可能大于ROM容量,所以我们要取它的高位到ROM中取相位对应的幅度点。如:频率控制字=4,则相位累加器的值为:0(00000),4(00100),8(01000),12(010100) ....... 也就是说因为步进4(100),后两位将一直保持不变,高位每次加1(1个4),可以类比十进制理解:每次加10:000,010,020,030...最后一位不变。
代码实现:
module DDS_Module( clk , reset , f_ctrl , p_ctrl , dout ); input clk ; input reset ; input [2:0]f_ctrl ;//(取值限制为2的倍数) input [9:0]p_ctrl ; output [9:0]dout ; //频率控制字寄存器(频率)(大于1的时候,后面相位累加器输出到实时相位时要砍掉它的位宽) reg [2:0]f_regist ;//(取值限制为2的倍数) always @ (posedge clk) f_regist <= f_ctrl ; //相位累加器 (f * t) reg [12:0]p_add ; always@(posedge clk or negedge reset ) if(!reset ) p_add <= 0 ; else p_add <= p_add + f_regist ; //相位控制字寄存器(初始相位)(相位偏移量) reg [9:0]p_regist ; always @ (posedge clk) p_regist <= p_ctrl ; //实时相位 reg [9:0]p_now ; always@(posedge clk or negedge reset ) if(!reset ) p_now <= 0 ; else p_now <= p_add[12:3] + p_regist ; //取相位累加器的前10位,因为f每次+4,后三位是不变的 DDS_ROM DDS_ROM( .clka(clk), .addra(p_now), .douta(dout) ); endmodule
这里是需要引用ROM的IP核的,上节内容。
`timescale 1ns / 1ps module DDS_tb( ); reg clk ; reg reset ; reg [2:0]f_ctrl1 ; reg [2:0]f_ctrl2 ; reg [9:0]p_ctrl1 ; reg [9:0]p_ctrl2 ; wire [9:0]dout1 ; wire [9:0]dout2 ; DDS_Module DDS_Module1( .clk(clk) , .reset(reset) , .f_ctrl(f_ctrl1) , .p_ctrl(p_ctrl1) , .dout(dout1) ); DDS_Module DDS_Module2( .clk(clk) , .reset(reset) , .f_ctrl(f_ctrl2) , .p_ctrl(p_ctrl2) , .dout(dout2) ); initial clk = 1 ; always #10 clk = !clk ; initial begin reset = 0 ; f_ctrl1 = 0 ; p_ctrl1 = 0 ; f_ctrl2 = 0 ; p_ctrl2 = 0 ; #201 ; reset = 1 ; #201 ; f_ctrl1 = 3'd4; p_ctrl1 = 10'd0 ; f_ctrl2 = 3'd4; p_ctrl2 = 10'd0 ; #90000 ; #90000 ; #90000 ; #90000 ; f_ctrl1 = 3'd4; p_ctrl1 = 10'd0 ; f_ctrl2 = 3'd4; p_ctrl2 = 10'd256 ; #90000 ; #90000 ; #90000 ; f_ctrl1 = 3'd4; p_ctrl1 = 10'd0 ; f_ctrl2 = 3'd4; p_ctrl2 = 10'd512 ; #90000 ; #90000 ; #90000 ; $stop; end endmodule
效果:分别是相位差 0° ,90 °,180°
标签:reset,fpga,clk,DDS,90000,verilog,ctrl1,ctrl2 来源: https://www.cnblogs.com/fbur/p/16476683.html