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

相关推荐
ThreeYear_s3 小时前
基于FPGA 的4位密码锁 矩阵键盘 数码管显示 报警仿真
fpga开发·矩阵·计算机外设
Anin蓝天(北京太速科技-陈)9 小时前
252-8路SATAII 6U VPX高速存储模块
fpga开发
如何学会学习?12 小时前
2. FPGA基础了解--全局网络
fpga开发
Anin蓝天(北京太速科技-陈)12 小时前
271-基于XC7V690T的12路光纤PCIe接口卡
嵌入式硬件·fpga开发
碎碎思16 小时前
FPGA新闻速览-WiMi开发基于FPGA的数字量子计算机验证技术
fpga开发·量子计算
hi941 天前
Vivado - 远程调试 + 远程综合实现 + vmWare网络配置 + NFS 文件共享 + 使用 VIO 核
嵌入式硬件·fpga开发·vivado 远程开发·vmware网络配置
乘风~&1 天前
基于发FPGA 练手智能小车顶层文件
fpga开发
_Hello_Panda_2 天前
高云GW5AT系列FPGA在接口扩展和桥接领域的应用方向探讨分享
fpga开发·高云·gw5at
aningxiaoxixi2 天前
音频接口:PDM TDM128 TDM256
fpga开发·pcm
希言自然也2 天前
赛灵思ZYNQ系列的启动过程分析
嵌入式硬件·fpga开发