彻底理解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°

相关推荐
175063319454 小时前
Vivado Zynq7020 生成正弦波(查表法) + 行为级仿真
fpga开发
Terasic友晶科技4 小时前
4-DE10-Nano的HDMI方块移动案例——I2C通信协议
fpga开发·i2c·hdmi·de10-nano·i2c通信协议
云雾J视界15 小时前
FPGA在AI时代的角色重塑:硬件可重构性与异构计算的完美结合
fpga开发·边缘计算·gpu·vitis·ai推理·azure云·异构编程
s09071361 天前
FPGA中CIC设计注意事项
算法·fpga开发·cic滤波器
Aaron15882 天前
RFSOC+VU13P在无线信道模拟中的技术应用分析
数据结构·人工智能·算法·fpga开发·硬件架构·硬件工程·射频工程
碎碎思2 天前
BerkeleyLab Bedrock:为 FPGA 与加速计算打造的开源基石
fpga开发·开源
zidan14122 天前
xilinx常用文档说明
fpga开发
ShiMetaPi2 天前
GM-3568JHF丨ARM+FPGA异构开发板系列教程:外设教程 04 WIFI
网络·arm开发·fpga开发·智能路由器·fpga
FPGA_小田老师2 天前
FPGA基础知识(二十):Xilinx Block Memory IP核(5)--ROM 详解
fpga开发·rom·coe文件格式·导入coe·block memory
FPGA_无线通信2 天前
压缩解压缩算法 BFP-8bit
fpga开发