DDS(Direct Digital Synthesizer)即数字合成器,是一种新型的频率合成技术,具有相对带宽大,频率转换时间短、分辨率高和相位连续性好等优点。较容易实现频率、相位以及幅度的数控调制,广泛应用于通信领域。

        DDS的基本结构框图如下所示:

     

       由图可以看出,DDS 主要由相位累加器、相位调制器、波形数据表以及D/A 转换器构成。本次实验仅在VIVADO平台上完成DDS的仿真,故设计流程不需要D/A转换器,在PC端完成仿真设计即可。若需要结合FPGA开发板使用,则需要再外接一个D/A转换模块,将产生的数字信号转换为模拟信号即可。

       其中相位累加器由 N 位加法器与 N 位寄存器构成。每个时钟周期的时钟上升沿,加法器就将频率控制字与累加寄存器输出的相位数据相加,相加的结果又反馈至累加寄存器的数据输入端,以使加法器在下一个时钟脉冲的作用下继续与频率控制字相加。这样,相位累加器在时钟作用下,不断对频率控制字进行线性相位累加。即在每一个时钟脉冲输入时,相位累加器便把频率控制字累加一次。相位累加器输出的数据就是合成信号的相位。相位累加器输出的数据,作为波形存储器的相位采样地址,这样就可以把存储在波形存储器里的波形采样值经查表找出,完成相位到幅度的转换。波形存储器的输出数据送到 D/A 转换器,由 D/A 转换器将数字信号转换成模拟信号输出。

        DDS 信号流程示意图如下: 

       这里相位累加器位数为 N 位(N 的取值范围实际应用中一般为 24~32),相当于把正弦信号在相位上的精度定义为 N 位,所以其分辨率为1⁄2^N。 若 DDS 的时钟频率为Fclk,频率控制字 fword 为 1,则输出频率为Fout = Fclk/2^N ,这个频率相当于“基频”。若 fword 为 B,则输出频率为Fout = B × Fclk /2^N 。

       因此理论上由以上三个参数就可以得出任意的Fout输出频率。且可得出频率分辨率由时钟频率和累加器的位数决定的结论。当参考时钟频率越高,累加器位数越高,输出频率分辨率就越高。

       从上式分析可得,当系统输入时钟频率Fclk不变时,输出信号频率由频率控制字 B 所决定。其中 B 为频率字且只能取整数。为了合理控制 ROM 的容量,此处选取 ROM 查询的地址时,可以采用截断式,即只取 32 位累加器的高 M 位。这里相位寄存器输出的位数一般取 10~16 位。

       故按照一定的时钟,产生顺序的相位值,将该值作为ROM查找表的地址,即可顺序读出存储的正弦波表数据,作为数据输出,同样的,为了产生其他不同类型的波形,只需要改变波表数据即可。

       为了实现频率的改变,只需要加入一个频率控制字,按照一定的规则取地址即可(比如三点取一点、五点取一点),这样依然能输出完整的波形,只不过取的点数变了,导致频率改变。

      为了实现相位的改变,只需要加入一个相位控制字,根据该值选择起始的地址点即可,实现波形的移动,相位的改变。

      为了实现幅值的改变,只需要加入一个幅度控制字,按照一定比例将该值与产生数据相乘,即可改变输出数据的大小,实现幅度的改变。

      在此设计了四种波形的幅频相可调的波形发生器,可以产生一定频率范围内的波形数据。根据不同的输入产生不同的输出波形。

     基于FPGA编写的DDS信号波形发生器,通过波表查找的方式生成正弦波。设置系统的时钟为50MHz,输出数据位宽为10位,从0-1023。可以输入波形控制字、频率控制字、相位控制字及幅度控制字来控制所生成波形的形式。该DDS模块可以产生正弦波、方波、三角波与锯齿波,频率范围为1KHz-5MHz,相位0-360°,幅度为0-1023的波形数据。其中设定D/A模块为10位的D/A转换器,产生的波形幅值为0-5V,因此根据不同的输出数据将转换为0-5V的电压值输出。

 

      其中各端口定义如下:

clk:系统时钟输入

rst:复位信号

wave[3:0]:波形选择输入,00 正弦波,01 方波,10 三角波,11 锯齿波

Fword[9:0]:频率控制字,选择输出频率

Pword[9:0]:相位控制字,选择输出相位

Aword[9:0]:幅度控制字,选择输出幅度

clkout:输出同步时钟,此处与输入时钟一致

dataout[9:0]:波形数据输出

     代码如下:

//DDS数字信号发生器
//波形控制字:
//wave: 00:正弦波 01:方波 10:三角波 11: 锯齿波
//频率控制字:
//fout=fclk*Fword/2^(N) N:相位累加器的位数 ,Fword:频率控制字,当Fword=2^(32(位宽)-N)时 达到基频
//设置基频为50KHz,对于正弦波、三角波、锯齿波、方波的Fword为4194304,Fword变大,频率变大,Fword变小,频率变小
//此时 fout=fclk/2^(N)
//频率分辨率=fclk/2^32(位宽)=0.01164Hz
//想获得任意频率,Fword=f/0.01164,一般大于0,小于fclk/2
//fout=fclk*Fword/2^(32)选用不同的Fword,得到不同的fout
//相位控制字:
//Pword:从0-1024,对应0-2pi
//幅度控制字:
//Aword:从0-1024,设定对于模拟输出0-5V,初始为1023,对应5V
module DDS(
    input clk,
    input rst,
    input [1:0]wave,
    input [31:0]Fword,
    input [9:0]Pword,
    input [9:0]Aword,
    output clkout,
    output [9:0]dataout
);

//波形数据:
reg [9:0] wavedata;
//波形信号:
wire [9:0] sindata;
wire [9:0] squdata;
wire [9:0] tridata;
wire [9:0] sawdata;
assign clkout = clk;
//正弦波形产生:
//相位寄存器:
reg [31:0]frechange; 
 
always @(posedge clk or negedge rst) begin
   if(!rst)
       frechange <= 32'd0; 
   else
       frechange <= frechange + Fword;
end

//相位累加器:
reg [9:0]romaddr;

always @(posedge clk or negedge rst) begin
   if(!rst)
       romaddr <= 10'd0;
   else
       romaddr <= frechange[31:22] + Pword;
end

//正弦波表:
rom_sin romsin (
  .clka(clk),       // input wire clka
  .addra(romaddr),  // input wire [9 : 0] addra
  .douta(sindata)      // output wire [9 : 0] douta
);

//其他波形产生器:
reg [31:0] phaseacc;
always @(posedge clk or negedge rst) begin
	if(!rst) 
	   phaseacc <= 32'b0;
	else 
	   phaseacc <= phaseacc+Fword;
end

wire [31:0] phase=phaseacc+Pword;

//方波:
assign squdata = phase[31] ? 10'd1023:10'd0;
//三角波:
assign tridata = phase[31]? (~phase[30:21]): phase[30:21];
//锯齿波:
assign sawdata = phase[31:22];

//波形选择:
always @(*) begin
	case(wave)
		2'b00: wavedata<= sindata;	
		2'b01: wavedata<= squdata;	
		2'b10: wavedata<= tridata;	
		2'b11: wavedata<= sawdata;	
		default: wavedata<= sindata;
	endcase
end

//调幅:
wire [9:0] data;
assign data = wavedata;
reg [19:0] AMdata;
always@(posedge clk)
   if(!rst)
       AMdata<=1'd0;
   else
       AMdata<=data*Aword;
assign dataout = AMdata[19:10];

endmodule

       正弦波波表数据 存储在ROM里,这里调用了VIVADO的IP核,波表数据的coe文件可以利用MATLAB或者相关的软件生成,这里不再赘述,需要可以在附件中下载。

仿真部分:

       利用设计的DDS模块,可以在VIVADO平台上仿真得到波形,此处编写testbench以后,仿真显示了多种波形和调幅、频、相后的结果。

       例化四个DDS模块,生成1.56MHz,幅值为1024单位的四种不同类型的波形信号,仿真结果如下所示:

       图中产生了四种不同类型的波形,按照不同的波形控制字得到不同的输出,波形的频率为1.56MHz,此处只测量了正弦波的频率,其他波形的频率也一样。由图中数据可知T=649us,故f约等于1.56MHz。

      例化四个DDS模块,生成1.56MHz,幅值为1024单位的四个不同相位的正弦波,分别为0°,90°,180°,270°,实现调相功能,仿真结果如下所示:

 

       以绿色波形为0°基准,四个波形各相差90°,完成功能实现。

      例化四个DDS模块,生成1.56MHz,相位为0°,幅值大小不同的四个正弦波,分别为1024、512、256、128(如DA部分生成电压为0-5V,则分别对应电压幅值为5V、2.5V、1.25V、0.625V),仿真结果如下所示:

        由各波形的输出峰值大小可以看出,四个波形的数字输出各有不同,经过D/A以后输出的模拟波形幅值就是不一样的,实现了调幅功能。

       例化四个DDS模块,生成相位为0°,幅值为1024单位,频率大小不同的四个正弦波,分别为1.56MHz、780KHz、390KHz、195KHz,仿真结果如下所示:

        由波形图可知,按照设定的数值,实现了不同频率波形的产生,此处为2分频的结果,频率测量只测量了1.56MHz的波形,由数据可知T=640us,故频率f约为1.56MHz,其余波形就不再显示。 

        仿真部分代码(多波形发生可自行例化):

`timescale 1ns / 1ps

module DDS_tb();
reg clk;
reg rst;
reg [1:0]wave1;
reg [31:0]Fword1;
reg [9:0]Pword1;
reg [9:0]Aword1;
wire clkout1;
wire [9:0]dataout1;

reg [1:0]wave2;
reg [31:0]Fword2;
reg [9:0]Pword2;
reg [9:0]Aword2;
wire clkout2;
wire [9:0]dataout2;

reg [1:0]wave3;
reg [31:0]Fword3;
reg [9:0]Pword3;
reg [9:0]Aword3;
wire clkout3;
wire [9:0]dataout3;

reg [1:0]wave4;
reg [31:0]Fword4;
reg [9:0]Pword4;
reg [9:0]Aword4;
wire clkout4;
wire [9:0]dataout4;

parameter frequence = 50000000;//50MHz 系统

always # 10 clk=~clk;

DDS dds1(
    .clk(clk),
    .rst(rst),
    .wave(wave1),
    .Fword(Fword1),
    .Pword(Pword1),
    .Aword(Aword1),
    .clkout(clkout1),
    .dataout(dataout1)
);

DDS dds2(
    .clk(clk),
    .rst(rst),
    .wave(wave2),
    .Fword(Fword2),
    .Pword(Pword2),
    .Aword(Aword2),
    .clkout(clkout2),
    .dataout(dataout2)
);

DDS dds3(
    .clk(clk),
    .rst(rst),
    .wave(wave3),
    .Fword(Fword3),
    .Pword(Pword3),
    .Aword(Aword3),
    .clkout(clkout3),
    .dataout(dataout3)
);

DDS dds4(
    .clk(clk),
    .rst(rst),
    .wave(wave4),
    .Fword(Fword4),
    .Pword(Pword4),
    .Aword(Aword4),
    .clkout(clkout4),
    .dataout(dataout4)
);
initial begin
     rst<= 1'b0;
     clk<=1'b0;
     //一路信号:
     Fword1 <= 32'd1;
     Pword1 <= 10'd0;    
     Aword1 <= 10'd1023; 
     wave1 <= 2'b00;
     //二路信号:
     Fword2 <= 32'd1;
     Pword2 <= 10'd0;    
     Aword2 <= 10'd1023; 
     wave2 <= 2'b00;
      //三路信号:
     Fword3 <= 32'd1;
     Pword3 <= 10'd0;    
     Aword3 <= 10'd1023; 
     wave3 <= 2'b00;
      //四路信号:
     Fword4 <= 32'd1;
     Pword4 <= 10'd0;    
     Aword4 <= 10'd1023; 
     wave4 <= 2'b00;
     #500
     rst <= 1'b1;
     #500
     //基频 50KHz,Fword=4194304: 
     // 1.56MHz: Fword <= 32'd134217728;
     Fword1 <= 32'd134217728;
     Fword2 <= 32'd134217728;
     Fword3 <= 32'd134217728;
     Fword4 <= 32'd134217728;
     wave2<=2'b01;
     wave3<=2'b10;
     wave4<=2'b11;
     #10000000000
     $stop;

end

endmodule

      波表数据地址:https://download.csdn.net/download/qq_46132759/77509190

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐