基于FPGA的DDS设计及仿真

一、DDS的基本概念

        DDS(Direct Digital Synthesizer),直接数字频率合成器,是一项关键的数字化技术。与传统的频率合成技术相比,其具有低成本、低功耗、高分辨率以及相位连续性好等优点,被广泛的应用于通信领域。利用DDS可以合成相位、频率以及幅度可控的信号波形。

二、DDS原理

        上图为DDS的基本结构图,可以看出,DDS主要由相位累加器、相位加法器、波形查找表以及D/A转换等构成。

        波形查找表一般是一个ROM,里边存放了信号的采样值,本次存放的是正弦信号,但其也支持方波以及三角波等信号的波形。对于波形查找表,给定一个地址,便可以读出该地址对应的波形数据,而这一系列离散的数据便形成了目标波形,然后再进行数模转换,就可以得到连续的波形。

        假设相位累加器的位数为N位(本次实验N=32),那么相当于把正弦信号的相位分为了2^{N}份,其分辨率便为1/2^{N}

        频率控制字fword,它用来控制行为控制字每次自增的步长,当其为1时,每个时钟周期相位加1,输出频率F_{out}=F_{clk}/2^{N},若fword=B时,那每个时钟周期的相位自加步长为B,其输出频率为F_{out}=B*F_{clk}/2^{N},这里的B必须是整数。

        在相位控制字pword为0的情况下,通过在相位累加器中将频率控制字fword累加起来,便可以获得波形查找表ROM的地址,然后再取出这个地址对应的值,便可以得到输出波形数据。但为了相位的可控,我们在相位累加器的输出结果上再直接加上相位控制字pword的值,相当于对ROM的地址整体做了一个偏移,这样便完成了相位的改变。

        而在实际应用中,为了合理的控制ROM的容量,在将相位累加器与相位控制字相加的结果转化为ROM的查询地址时,我们采用截断式,只采用32位相位累加器的高M位,在本次实验中,M=32。即ROM的地址为16位,其深度为2^{16}=65536

三、DDS的设计

        在清晰了DDS的构成之后,我们照图施工,便可以完成DDS的硬件描述。

        首先是频率控制字的同步寄存器,我们使用一个寄存器将频率控制字fword的值保存一个时钟周期;接下来是相位累加器,这里也是一个寄存器,每次让相位累加器的结果加上频率控制字的值即可;相位控制字的同步寄存器与前者相同,将其结果加在相位累加器的输出结果上,就可以实现初相的改变,即对ROM的查询地址做出了偏移;最后将相位累加器结果的高16位与相位累加器求和,作为ROM的地址,将该地址送给ROM便可以输出响应的目标波形。

     

`timescale 1ns / 1ps

module DDS(
//input
    clk  ,
    rst_n,
    fword,
    pword,
    hword,
//output
    wave_out,
    read_addr

    );
    
input          clk  ;
input          rst_n;
input  [31:0]  fword;
input  [15:0]  pword;
input  [1:0 ]  hword;    

output reg signed [15:0] wave_out;
output [15:0] read_addr;


//幅度定义:1,1/2,1/4,1/8,
parameter h1 = 2'b00 ;
parameter h2 = 2'b01 ;
parameter h3 = 2'b10 ;
parameter h4 = 2'b11 ;

    
//频率控制字同步寄存器    
reg [31:0] fword_r;
always@(posedge clk or negedge rst_n)
    if(!rst_n)
        fword_r <= 32'd0;
    else
        fword_r <= fword; 
        
//相位控制字同步寄存器    
reg [15:0] pword_r;
always@(posedge clk or negedge rst_n)
    if(!rst_n)
        pword_r <= 16'd0;
    else
        pword_r <= pword; 
        
//相位累加器
reg [31:0] p_sum;
always@(posedge clk or negedge rst_n)
    if(!rst_n)
        p_sum <= 16'd0;
    else 
        p_sum <= p_sum + fword_r;
        
//波形查找表ROM的地址
reg [15:0] read_addr;
always@(posedge clk or negedge rst_n)
    if(!rst_n)
        read_addr <= 16'd0;
    else 
        read_addr <= p_sum[31:16] + pword_r;
        
wire [15:0] wave;
 blk_mem_gen_0  blk_mem_gen_0(
  .clka (clk),
  .ena  (rst_n),
  .addra(read_addr),
  .douta(wave)
);
always@(posedge clk or negedge rst_n)
    if(!rst_n)
        wave_out <= 16'd0;
    else
        case(hword)
            h1:wave_out = wave - 16'd32767 ;
            h2:wave_out = (wave - 16'd32767)/2;
            h3:wave_out = (wave - 16'd32767)/4;
            h4:wave_out = (wave - 16'd32767)/8;
            default:wave_out = wave - 16'd32767;    
        endcase
 
    
    
endmodule

        ROM的配置如下:

        ROM的初始化文件为正弦波形,可以使用工具生成,也可以直接使用我使用的文件。(6条消息) ROM的初始化文件,正弦波形资源-CSDN文库icon-default.png?t=N4P3https://download.csdn.net/download/qq_57541474/87886533

 四、仿真

Fclk=50MHZFo=B*Fclk/2^32,ROMwidth=16,depth=65536=2^16

1. fword =2048=2^11,pword=0,T=41.94304ms,=>f=23.84185 Fo = Fclk /2^21=23.8418579.
2. fword =8192=2^13,pword=0,T=10.48576ms,=>f=95.3674 Fo = Fclk /2^19=95.3674.
3. fword =16384=2^14,pword=0,T=5.22428ms,=>f=190.7377 Fo = Fclk /2^18=190.7377.

对三种不同的频率进行仿真,结果符合预期。

 

1.waveA:fword=8192=2^13,pword=0°,T=10.48576msf=95.3674,Fo=Fclk/2^19=95.3674

2.waveB: fword=8192=2^13,pword1=16384=90°fword2=32768=180°,T=10.48576msf=95.3674,Fo=Fclk/2^19=95.3674

信号AB频率相同,A路的相位不变,B路的信号相位先为1/4的深度,即90°,之后再变为1/2的深度,即180°,从仿真结果可看出相差正确,频率与上边第二次相同。

猜你喜欢

转载自blog.csdn.net/qq_57541474/article/details/131127335