DDS信号生成模块的Verilog实现

描述

直接数字频率合成器(Direct Digital Synthesizer,DDS),是一种频率合成技术,具有相对带宽大、频率转换速度快、相位分辨率高、连续性好等优点,在数字信号处理中常用于调制信号的生成,模块设计较为简单,频率、相位容易控制,多用于无线通信领域。

DDS发生器的组成原理精髓在于对“模板”信号在单个周期内的采样,在系统工作频率一定的情况下,输出信号频率和周期内的取样点数有着直接的关系,举个栗子,假设基波信号 U(t)=sin(2pift+θ )=sin( 2pit ) ,* 在0~2Π

等分周期,在相同的系统时钟下采用不同的抽样点数进行抽样,如下图所示:

频率合成器

以*Π/4 *为步进在单个周期内抽样

频率合成器

以*Π/8 *为步进在单个周期内抽样

频率合成器

可以很明显看出,相同系统时钟下使用不同的抽样点数,可以得到不同的输出频率;基本组成架构如下,系统时钟驱动频率控制字(抽样间隔)逐次累加生成存储着基波数据ROM的对应抽样地址,相位控制字主要用来决定基波的起始相位;

频率合成器

在FPGA中开辟一块Block RAM用于存储对应的“模板”信号,也就是要输周期信号的一个完整周期,输出数据位数决定采样波形存储ROM的宽度,数据深度与采样精度有关,累加器用于按频率控制字步长控制等间隔采样精度,相位寄存器用于锁定波形发生起始的位置,生成的周期数列作为ROM表的驱动地址,完成对"模板"信号不同频率的抽样;

频率合成器

模块设计前需要先准备ROM初始化文件“ .coe ”,生成方式可以使用工具或者MATLAB,下面是个人使用的一个基于MATLAB的coe文件生成代码;

clc;clear;close all;  
width = 10;  
depth = 2048;  
t = linspace(0,2*pi,depth);  
sin_val = sin(t);  
% %cos_val = cos(t); 
plot(t,sin_val,'--');
 sin_val = fix(sin_val*(2^width-1)/2 + 0.5); %四舍五入  
% %cos_val = fix(cos_val*(2^width-1)/2 + 0.5);


sin_val(find(sin_val< 0))=sin_val(find(sin_val< 0)) + 2^width; %求补码 
addr = [0:depth - 1];  
file = fopen('sin1024.coe','wt');  
fprintf(file,'MEMORY_INITIALIZATION_RADIX=10;n);
fprintf(file,'MEMORY_INITIALIZATION_VECTOR=n');


for i=1:depth  
    fprintf(file,'%04X : %04X;n',addr(i), sin_val(i)); 

end  
fprintf(file,'END;n');  
fclose(file);

模块设计为便于修改添加部分参数定义,在有不同位宽需求时可以只修改参数和ROM模块IP即可实现;频率计算公式不在推到,直接给出:

频率合成器

其中K为频率控制字,N为相位累加器位宽,f0为模块输出频率,fC为系统时钟频率;举个例子,设系统时钟为50Mhz,相位宽度10Bit,要输出1Mhz的信号,则K=(2^101)/50; *设计代码如下,使用时只需添加ROM模块的IP,然后就可以例化工程使用:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: nhike
// Engineer: chenyivi
// 
// Create Date: 2019/11/03 19:25:35
// Design Name:DDS_ROM_IP 
// Module Name: DDS_ROM
// Project Name: DDS_ROM_IP
// Target Devices: zynq7010
// Tool Versions:1.0 
// Description: WaveFrom
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////




module DDS_ROM(
    clk,          //系统时钟
    rst_n,        //系统复位
    Freword,      //频率控制参数
    Phaword,      //初始相位控制参数
    WaveDataOut    //输出信号
  );

  parameter   FrequencyBitWidth = 32;       
  parameter   PhaseBitWidth =10;
  parameter   DataOutBitWidth= 10;

  input clk;
  input rst_n;
  input   [FrequencyBitWidth-1:0] Freword;
  input   [PhaseBitWidth-1:0]    Phaword;
  output   [DataOutBitWidth-1:0]   WaveDataOut;

  reg   [FrequencyBitWidth-1:0]  Freword_temp;
  reg   [PhaseBitWidth-1:0]    Phaword_temp;
  wire   [PhaseBitWidth-1:0]    WaveAddData;

  always@(posedge clk or negedge rst_n)begin    //data latch.
    if(!rst_n)begin
      Freword_temp <= 32'b0;
      Phaword_temp <= 10'b0;
      end
    else begin
      Freword_temp <= Freword;
      Phaword_temp <= Phaword;  
      end
  end

  reg [FrequencyBitWidth-1:0] cnt;

  always @(posedge clk or negedge rst_n)begin    //Sampling control.
    if(!rst_n)
      cnt <= 0;
    else
      cnt <= cnt + Freword_temp;
  end

  assign WaveAddData = cnt[FrequencyBitWidth-1:FrequencyBitWidth-(DataOutBitWidth + 1)] + Phaword_temp;   //Data precision interception

  WaveRom WaveRomBase (
    .clka(clk),   
    .addra(WaveAddData),  
    .douta(WaveDataOut)  
  );

endmodule

下面是仿真结果和RTL:

频率合成器

频率合成器

以上实现均在Vivado中验证,Quartus使用方法与上述一致;

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分