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

相关推荐
tju新生代魔迷1 天前
Verilog HDL 学习笔记(十)| 第10章 时序和延迟
笔记·学习·fpga开发
aprilaaaaa1 天前
(TC397 学习笔记)二、ICU和TIM的时钟计算
笔记·学习·fpga开发
X_xcccc1 天前
2026高端FPGA开发平台权威评测与选型指南
fpga开发
威嵌神州1 天前
军工加固计算机七大核心特性解析|国产化、宽温、强加固工程实现
嵌入式硬件·计算机网络·fpga开发
FPGA小迷弟1 天前
高云半导体深度解读:国产FPGA车规赛道的领跑者
fpga开发
努力搬砖的小H1 天前
FPGA应用技巧之Block Design基本使用方法
功能测试·fpga开发·zynq·block design
ALINX技术博客2 天前
【黑金云课堂】FPGA技术教程FPGA 基础:HDMI视频输入与环路输出实验
fpga开发·音视频
hahaha60162 天前
HLS高层次综合设计--axi之burst纠偏
开发语言·算法·fpga开发·c#
珞光电子USRP SDR软件无线电平台2 天前
国产嵌入式SDR平台LW-E320-G详解:射频、FPGA、ARM架构与应用选型
arm开发·fpga开发·架构
FPGA小迷弟2 天前
【硬核通俗】FPGA实现SDR软件无线电完整技术解析(原理+架构+实战)
fpga开发·dsp开发·sdr·无线电