一、DDS工作原理

  • 以正弦信号为例,DDS大概就是将M个点的一个周期的正弦序列存入ROM中,序列数据的地址就是正弦信号的相位;
  • 通过修改频率控制字(Fword)来改变每隔多少个地址取ROM里的数据进行输出。频率控制字越大,从ROM取出的数据点就越少,点数越少,输出一个周期信号的时间就越短,从而改变了输出信号的频率;
  • 通过修改相位控制字(Pword)来改变读取ROM里的数据的初地址(就是给ROM地址增加偏移量),从而改变输出信号的初相。
    DDS的基本结构图如下图所示:
    DDS结构的FPGA实现
    输出信号的频率的公式为:DDS结构的FPGA实现
    其中\(F_{CLK}\)为模块的时钟频率,\(F_{Word}\)为频率控制字,N为频率控制字的位宽。

二、模块代码

关于ROM的配置可以点击此处。

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: GDUT
// Engineer: Lclone
// 
// Create Date: 2023/01/30 19:11:43
// Design Name: DDS_Base
// Module Name: DDS_Base
// Project Name: DDS_Base
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////
module DDS_Base(
       input               Clk,
       input               Rst_n,
       input       [31:0]  Fword,
       input       [11:0]  Pword,
       output      [ 7:0]  Signal_data
   );
   reg [31:0]  Fword_r;
   always @(posedge Clk or negedge Rst_n) begin
       if(Rst_n == 0)
           Fword_r <= 0;
       else
           Fword_r <= Fword_r + Fword;
   end
   reg [11:0]  ROM_addr;
   always @(posedge Clk or negedge Rst_n) begin
       if(Rst_n == 0)
           ROM_addr <= 0;
       else
           ROM_addr <= Fword_r[31:20] + Pword + 1'b1;
   end
   ROM_Sinwave     ROM_Sinwave_inst(
       .clka                (Clk),
       .addra               (ROM_addr),
       .douta               (Signal_data)
);
endmodule

三、仿真

1、仿真代码

在分析频率的时候例化一个该模块分析就行,在分析相位时候例化两个模块进行对比即可
下面给出分析相位时候的仿真文件:

`timescale 1ns / 1ps
module DDS_Base_tb();
reg clk_50m;
initial clk_50m <= 0;
always #10 clk_50m <= ~clk_50m;
reg rst_n;
initial begin
    rst_n <= 0;
    #200
    rst_n <= 1;
end
reg [31:0]  FwordA;
reg [11:0]  PwordA;
wire[ 7:0]  Signal_dataA;
reg [31:0]  FwordB;
reg [11:0]  PwordB;
wire[ 7:0]  Signal_dataB;
initial begin
    FwordA <= 0;
    PwordA <= 0;
    FwordB <= 0;
    PwordB <= 0;
    #300
    FwordA <= 1024*1024*2; //情况1
    PwordA <= 0;
    FwordB <= 1024*1024*2;
    PwordB <= 4096/4 - 1; //相移90°
    #163840
    FwordA <= 1024*1024*4; //情况2
    PwordA <= 0;
    FwordB <= 1024*1024*4;
    PwordB <= 4096/2 - 1; //相移180°
    #163840
    FwordA <= 1024*1024*0.5;//情况3
    PwordA <= 0;    
    FwordB <= 1024*1024*0.5;
    PwordB <= 4096/2 - 1; //相移180°
    #163840
    #100
    $stop;
end
DDS_Base    DDS_Base_A(
        .Clk                (clk_50m),
        .Rst_n              (rst_n),
        .Fword              (FwordA),
        .Pword              (PwordA),
        .Signal_data        (Signal_dataA)
    );
DDS_Base    DDS_Base_B(
        .Clk                (clk_50m),
        .Rst_n              (rst_n),
        .Fword              (FwordB),
        .Pword              (PwordB),
        .Signal_data        (Signal_dataB)
    );
endmodule

3、仿真分析

频率分析

整体波形如下图所示:
DDS结构的FPGA实现
情况1:
DDS结构的FPGA实现
此时频率控制字设置为102410242,根据公式算得频率为24,414Hz,周期为40.96us,与仿真结果41us相近。
情况2:
DDS结构的FPGA实现
此时频率控制字设置为102410244,根据公式算得频率为48,828.125Hz,周期为20.48us,与仿真20.4889us结果相近。
情况3:
DDS结构的FPGA实现
此时频率控制字设置为102410240.5,根据公式算得频率为6,103.51Hz,周期为163.84us,与仿真163.8405us结果相近。

相位分析

DDS结构的FPGA实现
结论:仿真通过,该DDS模块能够调节输出信号的频率和初相。

四、参考资料

[1]【零基础轻松学习FPGA】小梅哥Xilinx FPGA基础入门到项目应用培训教程

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。