FPGA入门必懂--DDS(Direct Digital Synthesizer)直接数字频率合成器,从原理到实战全解析

DDS(Direct Digital Synthesizer)即数字合成器,是近年来发展起来的一种新的频率合成技术,其主要优点是相对带宽很大,频率转换时间极短(可小于20 ns),频率分辨率很高,全数字化结构便于集成,输出相位连续可调,且频率、相位和幅度均可实现程控。随着FPGA技术的不断发展,该技术得到愈加成熟的应用。借助 FPGA 平台开发的高性能的 DDS 发生器与基于 DDS 芯片设计的信号发生器相比,具有成本更低,操作更加灵活,而且还能根据要求在线更新配置等诸多优点。同时,整个系统开发流程更趋于软件化、自定义化,开发周期更短,调试过程更加简单。

我会用“在坐标纸上画正弦波”的类比,把DDS的核心模块、工作流程拆解得明明白白。

一、先搞懂:DDS到底是个啥?

DDS的全称是“Direct Digital Synthesizer”,直译就是“直接数字频率合成器”。核心定义可以总结为:用纯数字的方式,生成稳定、可控的模拟信号

DDS 是如何实现控制发生信号的呢?如果想生成一个质量较好的 DDS 发生信号,无非是对波形、频率、相位这几个关键要素进行控制和搭配组合。下面是其中一种常用的 DDS 控制信号发生器的实现方案原理图。
image

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

初学者不用记复杂概念,只需记住DDS的3个核心优势:

  • 频率灵活:想改输出频率,改个数字参数就行,不用动硬件;

  • 相位可控:正弦波想从0°开始,还是从90°开始,自由设定;

  • 波形多样:存不同的波形数据,就能输出正弦波、方波、三角波。

举个实际场景:你做一个信号发生器项目,需要输出1MHz、相位偏移30°的正弦波,以及500kHz的方波——用DDS只需改3个参数,不用换任何硬件,这就是它的强大之处。

二、核心目标:DDS要解决什么问题?

传统模拟信号发生器(比如用晶振+分频器)有个大问题:想改频率就得换晶振或调整复杂电路,而且频率精度低、相位没法灵活控制。

DDS的核心目标就是解决这些痛点,实现“数字编程控制模拟信号”:

  1. 控制频率:输出信号的频率精准可调(比如从1Hz到100MHz);

  2. 控制相位:信号的起始相位可设(0°~360°任意偏移);

  3. 控制波形:支持多种波形输出(正弦、方波、三角波等);

  4. 高稳定性:输出信号的频率、幅度都很稳定,不受温度等环境影响。

三、用“画正弦波”理解DDS核心模块

DDS的硬件结构不复杂,核心是“相位控制→查表取幅度→数模转换”的流程。我们把整个过程类比成“在坐标纸上画正弦波”,每个模块对应画波形的一个步骤,瞬间就懂了。

先明确“画波形”的核心要素:

  • 横坐标:相位(对应波形的周期进度,0°~360°为一个完整周期);

  • 纵坐标:幅度(对应波形的高低,比如正弦波0°时幅度0,90°时幅度最大);

  • 节拍器:系统时钟(每响一次,画笔就移动一次,控制画画的速度)。

下面结合DDS的经典结构,逐个拆解模块的作用:

1. 系统时钟(CLOCK):画波形的“节拍器”

系统时钟是整个DDS的“节奏指挥家”——每来一个时钟脉冲,整个画波形的流程就推进一次

比如我们用50MHz的系统时钟(周期20ns),就相当于“节拍器每20ns响一次,画笔每20ns移动一次”。时钟频率越高,画笔移动的节拍越快,理论上能生成的信号频率也越高。

核心作用:给DDS所有模块提供统一的工作节奏,确保数据传输和计算同步。

2. 频率控制字(FWORD):画笔的“每拍移动距离”

image

频率控制字是控制输出信号频率的核心,没有它,DDS就没法调频率。我们把它类比成“画笔每拍在横坐标(相位)上移动的距离”:

  • 移动距离大:每拍走10个刻度,画完一个周期(360°)用的节拍少,输出频率高;

  • 移动距离小:每拍走2个刻度,画完一个周期用的节拍多,输出频率低。

旁边的“同步寄存器”作用很简单:暂存这个“移动距离”,避免它突然变化导致画出来的波形“断档”。比如你正在画1MHz的正弦波,频率控制字突然跳变,波形就会出现毛刺,同步寄存器能让变化“平稳过渡”。
image

3. 相位累加器+相位寄存器:记录画笔的“当前位置”

image

这是DDS的灵魂模块,相当于“实时记录画笔在横坐标(相位)上的位置”,也是DDS能精准控制频率的关键。

工作逻辑很简单:每来一个系统时钟(节拍器响一次),就把“频率控制字(每拍移动距离)”加到当前的“横坐标位置”上,得到新的位置;相位寄存器则负责暂存这个新位置,确保下一次计算的起点准确。

举个具体例子帮你理解:

假设相位累加器是32位的(可以理解为把0°~360°的横坐标分成了2³²个小刻度,精度极高),系统时钟频率f_c=50MHz,频率控制字FWORD=1073741824(约2³²的1/4)。

  1. 每拍移动距离:1073741824个刻度;

  2. 每4拍移动的总刻度:4×1073741824=4294967296=2³²个刻度(刚好走完一个周期360°);

  3. 输出频率:50MHz ÷ 4 = 12.5MHz(每4个时钟周期输出一个波形周期)。

这就引出了DDS的核心频率计算公式(记不住也没关系,工具能自动算):

image

其中:fo是输出信号频率,FWORD是频率控制字,f_c是系统时钟频率,N是相位累加器的位数(常用32位)。

关键特性:当累加器的值超过2³²时,会自动“溢出”(相当于横坐标走完一个周期,回到起点重新开始),溢出的频率就是我们要的输出频率。

4. 相位控制字(PWORD):画笔的“起始位置”

image

想让正弦波从0°开始画,还是从90°开始画?这就靠相位控制字了——它相当于“画笔的起始横坐标”,负责控制信号的相位偏移。

比如:

  • 相位控制字对应0°:画笔从横坐标起点开始画,输出标准正弦波;

  • 相位控制字对应90°:画笔从横坐标的90°位置开始画,输出的正弦波就变成了余弦波(相位偏移90°)。

和频率控制字一样,它也配有同步寄存器,确保相位偏移的变化平稳,不会导致波形突变。

5. 加法器:确定画笔的“最终位置”

image

这个模块的作用很直接:把“相位累加器的当前位置”和“相位控制字的起始位置”相加,得到画笔当前实际要画的横坐标。

比如:起始位置是30°(相位控制字),当前累加的位置是60°(相位累加器),那么最终横坐标就是90°——对应正弦波90°位置的幅度值(最大幅度)。

6. 波形数据表ROM:正弦波的“幅度模板”

image

ROM(只读存储器)里存的是“横坐标→纵坐标”的对应表,相当于“画波形的模板”。比如我们要画正弦波,就把0°~360°每个相位对应的幅度值提前存到ROM里。

举个简化例子(实际用10位或12位精度,这里用8位方便理解):

相位(横坐标) 正弦波幅度(纵坐标) 8位数字值(ROM存储值)
0 128(中间值,对应0V)
30° 0.5×最大幅度 192
90° 最大幅度 255
180° 0 128
270° 最小幅度 0

当加法器给出“最终横坐标”(比如90°),ROM就会根据这个地址,输出对应的“数字幅度值”(255)——这一步就是“查表取幅度”。

灵活之处:想输出方波?只需把ROM里的“正弦波幅度表”换成“方波幅度表”(比如0°180°存255,180°360°存0),不用改任何其他模块。

7. D/A转换器:把“数字幅度”变成“模拟波形”

image

ROM输出的是“数字信号”(比如8位的0255),但我们最终需要的是“模拟电压信号”(比如03.3V的正弦波)——这就需要D/A转换器(数模转换器)来“翻译”。

它的工作原理很简单:把数字幅度值按比例转换成模拟电压。比如8位D/A的参考电压是3.3V,那么数字值255对应3.3V,128对应1.65V,0对应0V——这样一来,数字幅度值就变成了连续变化的模拟电压,也就是我们想要的正弦波。

注意:D/A的位数决定了波形的“精度”,比如12位D/A比8位D/A的幅度台阶更细,输出的波形更平滑,没有“锯齿感”。

四、完整流程

把上面的模块串起来,我们用“生成12.5MHz正弦波”的例子,看DDS的完整工作流程(系统时钟50MHz,32位相位累加器,频率控制字1073741824):
image

  1. 初始化:相位控制字设为0°(从起点开始画),频率控制字设为1073741824(每拍移动1/4周期);

  2. 节拍触发:50MHz时钟每20ns来一个脉冲(节拍器响);

  3. 相位更新:相位累加器把“当前位置+频率控制字”,得到新位置(每拍移动1/4周期);

  4. 相位校准:加法器把“新位置+相位控制字(0°)”,得到最终横坐标;

  5. 查表取幅度:根据最终横坐标,从ROM中读出对应的数字幅度值;

  6. 数模转换:D/A把数字幅度值转换成模拟电压;

  7. 循环重复:每来一个时钟脉冲,重复步骤3~6,最终输出连续的12.5MHz正弦波。

关键观察:每4个时钟周期,相位累加器刚好走完一个周期(360°),所以输出频率=50MHz÷4=12.5MHz,和我们预期的一致。

五、DDS的核心设计思路

学完模块和流程,你会发现DDS的灵活度来自“全数字可编程”,核心思路可以总结为3点:

  1. 频率由“相位步进”控制:不用改硬件,只需改频率控制字(每拍移动距离),就能精准调频率;

  2. 相位由“起始位置”控制:改相位控制字(起始横坐标),就能实现任意相位偏移;

  3. 波形由“ROM表”控制:换ROM里的波形数据,就能输出不同波形,实现“一器多用”。

这也是DDS在FPGA中特别受欢迎的原因——所有参数都能通过代码编程控制,适配各种场景。

六、从原理到上手

懂了原理,下一步就是动手实践。给初学者3个关键tips,帮你快速用FPGA实现DDS:

1. 波形ROM的实现(最常用操作)

FPGA中不用外接ROM,直接用“Block Memory Generator”IP核生成内置ROM:

  • 用Matlab生成波形数据(比如1024点的正弦波,12位精度),保存为.coe文件;

  • 在Vivado中调用IP核,选择“ROM”模式,导入.coe文件,生成波形ROM;

  • 把相位累加器的输出作为ROM的地址,就能读出对应的幅度值。

2. 频率控制字的计算(不用死算)

直接用公式算频率控制字容易出错,推荐两个方法:

  • 在线计算器:搜“DDS频率控制字计算器”,输入系统时钟、输出频率、累加器位数,直接出结果;

  • 代码自动算:在Verilog中用参数定义,比如“parameter FWORD = (输出频率 << 32) / 系统时钟频率;”,编译时自动计算。

3. D/A选型的关键指标

D/A是连接数字和模拟的桥梁,初学者选D/A时重点看两个指标:

  • 位数:8位~16位,位数越高,波形越平滑;

  • 转换速率:必须大于2倍的输出信号频率( Nyquist准则),比如输出100MHz信号,选转换速率≥200MSPS的D/A。

七、总结:DDS的核心就是“数字控相位”

看到这里,你应该彻底明白DDS的原理了——它没有复杂的模拟电路,核心就是“用数字逻辑控制相位的变化,再通过查表和数模转换,把相位变化变成模拟波形”。

记住这个核心逻辑,不管是改频率、调相位,还是换波形,都能对应到具体的模块参数:

  • 改频率 → 调频率控制字;

  • 改相位 → 调相位控制字;

  • 改波形 → 换ROM数据表。

如果在实践中遇到问题,欢迎在评论区交流~

posted @ 2025-12-18 15:19  lzx_拿命学fpga  阅读(19)  评论(0)    收藏  举报