基于FPGA的DDS开发和实现,可修改输出正弦的频率和相位,包含testbench

发布时间 2023-06-23 23:14:32作者: 我爱C编程

1.算法仿真效果

vivado2019.2仿真结果如下:

 

输出2个不同频率的正弦信号:

 

 修改相位,得到如下所示。

 

2.算法涉及理论知识概要

     直接数字频率合成技术 (Direct Digital Synthesis)完全不同于我们己经熟悉的直接频率合成技术和锁相环频率合成技术。直接数字频率合成技术(简称DDS)的理论早在七十年代就被提出。它的基本原理就是利用采样定理,通过查表法产生波形,由于硬件技术的限制,DDS技术当时没能得到广泛应用。随着大规模集成电路技术的飞速发展,DDS技术的优越性己逐步显现出来。不少学者认为,DDS是产生信号和频率的一种理想方法,发展前景十分广阔。与其他频率合成方法相比较,直接数字频率合成技术的主要优点是易于程控,相位连续,输出频率稳定度高,分辨率高。其频率分辨率可以达到10-3。而且频率转换速度快,可小于100ns,特别适宜用在跳频无线通信系统。其相位噪声主要决定于参考时钟振荡器。

 

       DDS(Direct Digital frequency Synthesis)即直接数字频率合成器,是一种新型的频率合成技术,具有较高的频率分辨率,快速的频率切换,稳定性好,可灵活产生多种信号的优点。因此,在现代电子系统及设备的频率源设计中,尤其在通信领域,直接数字频率合成器的应用越来越广泛。在数字化的调制解调模块中。DDS取代了VCO(模拟的压控振荡器),被大量应用。这种合成技术是一种利用数字技术来控制信号的相位增量的技术,它采用插值取样的方式,将要合成的正弦波波形用若干个采样点的取值来代替,然后依次等时间间隔输出这些取值,每个采样点的值由预先存储的数字值经D/A转换后得到。

 

       DDS工作原理框图如图1所示。其基本结构包括:相位累加器PA、波形查询表ROM、数模转换器DAC及低通滤波器。

 

       DDS的工作过程为:在参考时钟fc的作用下,相位累加器对频率控制字FCW(Frequency Control Word)进行线性累加,将其高W位作为地址码通过波形查值表ROM变换,产生D位对应信号波形的数字序列,再由数模转换器DAC将其转化为阶梯模拟电压波形后由具有内插作用的低通滤波器LPF将其平滑为连续的正弦波形作为输出。

 

       一个N位的相位累加器对应相位圆2N上个相位点,其最低相位分辨率为θmin=Δθ=2π/2N。在图2N4,则有16个相位值和16个幅度码相对应。该幅度存储于波形存储器中,在频率控制字FCW的作用下,相位累加器给出不同的相位码,对波形存储器寻址,完成相位--幅度变换,经DAC变成阶梯正弦波信号,再通过低通滤波器平滑,便得到模拟正弦波输出。

 

       自第一部正弦波发生器问世以来,函数发生器的设计已经发生了多次演进,在当前数字领域中,大多数新型函数发生器都在采用直接数字频率合成技术。DDS在大部分操作中使用数字电路,从而提供了数字操作拥有的许多优势。

 

第一,输出信号的频率精度可以达到作为发生器参考信号使用的晶体控制振荡器的水平。如果想实现更高的精度,也可以采用函数发生器本身的温度补偿晶体振荡器产生。

 

第二,DDS信号发生器的数字电路可以实现与数字电路相同的频率精度。

 

第三,如果拥有RAM波形存储器,那么DDS函数发生器可以重现几乎任何波形。因此,函数发生器现在的功能要远远超过传统函数发生器。对称性可变的波形现在已经是标配功能,另外还可以内置各种不常见的波形,如指数上升和下降型波形或正弦脉冲型波形等。但由于DDS的全数字结构,使得直接数字频率合成器不可避免的拥有以下两个缺点。

 

第一,其杂散分量丰富。这些杂散分量主要由相位舍位、幅度量化和DAC的非理想特性所引起。

 

第二,输出频带受限。由于DDS内部DACROM的工作速度限制,使得DDS输出的最高频率受到极大的限制。

 

3.Verilog核心程序

 

`timescale 1ns / 1ps
 
module TEST_tops;
 reg i_clk;
 reg i_rst;
 reg[15:0] i_Fre1;
 reg[15:0] i_phase1; 
  reg[15:0] i_Fre2;
 reg[15:0] i_phase2; 
 wire[15:0] o_sin1; 
 wire[15:0] o_sin2; 
 
 
tops tops_u(
.i_clk    (i_clk),
.i_rst    (i_rst),
.i_Fre1    (i_Fre1),
.i_phase1    (i_phase1),
.i_Fre2    (i_Fre2),
.i_phase2    (i_phase2),
.o_sin1   (o_sin1),
.o_sin2   (o_sin2) 
);
 
initial
begin
i_clk  = 1'b1;
i_rst   = 1'b1;
i_Fre1=16'd0;
i_phase1=16'd0;
i_Fre2=16'd0;
i_phase2=16'd6000;
#100
i_rst   = 1'b0;
i_Fre1=16'd32;
 i_phase1=16'd0;
 i_Fre2=16'd64;
 i_phase2=16'd32000;
end
always #5 i_clk=~i_clk;
endmodule