DDS Compiler
设计原理
一个正弦波 的幅度不是随时间 线性变化的,但是相位 是时间 的线性函数。因此可以考虑用一个线性递增的变量存储相位,再将相位转换成相应的正弦波幅度。

首先存储一个周期的正弦波,然后将相位 用 比特量化,即平均分成 份,以 的频率每始终周期转动 ,则可以得到输出频率为 的信号,
可以看出,输出频率 是参考时钟频率 、相位量化位宽 、和相位增量(频率控制字) 的函数。增加频率控制字,将得到更高频率的信号。
根据奈奎斯特采样定律,为了使波形不失真,需要满足 ,则有
始终小于 ,不妨将其看成是一个分频器,通过修改频率控制字分频参考时钟 ,获得所需要的频率。
组成结构

如图,直接式数字频率合成器(Direct Digital Synthesizer,DDS)主要由 相位累加器、波形查找表、数模转换器和低通滤波器 等部分组成。
其中的核心部分是相位累加器,由一个 位累加器和 位寄存器构成,在每个参考时钟上升沿,累加器将频率控制字与累加寄存器的输出相加,结果作为寄存器新的输入。如此反复, 当累加器累加满时, 就会发生溢出,完成一个周期, 即 DDS 合成信号的一个频率周期。
波形查找表(Lookup Table,LUT)中存储了正弦波的数字幅度信息,每个地址对应一个相位点,每个相位点对应正弦波的一个幅度值。将相位累加寄存器的输出与相位控制字相加,作为波形查找表的输入地址,地址映射为正弦波幅度,输出到 D/A 转换器。
D/A 转换器将数字信号转换成模拟信号,再经低通滤波器滤除不需要的取样分量,最终得到所需信号。
量化性能
理想的 DDS 应满足:
相位累加器的输出相位为 ,周期 ,则波形查找表输出的幅度序列为
经过 D/A 转换器后
令 ,是 的理想采样信号,令 。
则有 的频谱是 的频谱以 为周期的延拓,得到 的频谱即理想的 DDS 输出频谱为
由输出频谱的表达式可以看出,它的谱线分布在 处,即 DDS 输出信号频谱的镜像分量总是在参考频率 的附近。因此,理想条件下,在 MATLAB 绘制的 的功率谱密度图像中不应该存在其它的频率分量,如图(左)所示

DDS 的量化性能分析
DDS 的幅度量化误差
相位对应的幅度值是小数时,波形查找表不能够精确的存储,导致幅度的量化误差,DDS 输出的信号是周期性的,这种误差也具有周期性,体现在频谱上是周期性的频率分量。
为探究 DDS 幅度的量化误差对载波信号的影响,设定采样频率为 160MHz,载波频率为 21MHz,幅度的量化位数分别为 8 位和 16 位,得到的载波功率谱密度如上图(左、右)所示,右图对应的量化位数为 8 位,量化误差较大,因此存在很多高频分量,左图对应的量化位数为 16 位,精度较高,几乎没有高频分量。
DDS 的相位截断误差
频率分辨率 不可能无穷小, 可能是小数,用二进整数表示时小数位要被去掉,造成误差;波形查找表的位数有限,会带来幅度量化误差;相位累加器的位数有限,则相位值会被截断,导致相位不连续和周期性误差,会在输出频谱中产生杂散。
控制变量“幅度的量化位数”8 位不变,改变相位量化位宽,得到功率谱密度图像如图所示,上图对应的相位量化位宽为 16 位,右图对应的相位量化位宽为 32 位。

DDS 的量化性能分析
DDS 的配置中用二进制整数表示频率控制字。由频率控制字的计算公式 可知,当参考频率为 ,输出频率为 ,相位量化位宽数为 16 或 32 时,需要的频率控制字不是整数,因此会带来相位截断误差。体现在频谱上,是信号频谱的杂散分量,随着相位量化位数增加,频率分辨率和相位精度提高,减少了因为相位截断造成的上图的杂散谱线
与 PLL 相比:
DDS 的频率分辨率高,可以生成多种波形;在高频段由较多的杂散分量
PLL 输出频率更稳定,相位噪声更低
MATLAB 仿真
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| close all; clear; clc;
tic;
fs = 160e3; f_out = 10e3; phase_width = 16; N = 2 ^ phase_width; output_width = 16; phase_offset = 0; phase_increment = f_out * N / fs;
n = 0 : 1/N : 1/4 - 1/N; cos_rom = cos(2 * pi * n); len_lut = length(cos_rom);
figure; stem(cos_rom(1:len_lut)); xlabel("Points"); ylabel("Amplitude"); xlim([0, len_lut]); ylim([0, 1]); title("Look-up Table (1/4 cos)"); grid on;
t_total = 1; t = 0 : 1/fs : t_total - 1/fs; dds_dout_len = length(t);
dds_dout = zeros(1, dds_dout_len); phase_acc = phase_offset;
for i = 1:dds_dout_len idx = floor(mod(phase_acc, N)); if idx == 0 dds_dout(i) = 1; elseif idx > 0 && idx <= len_lut idx_new = idx; dds_dout(i) = 1 * cos_rom(idx_new); elseif idx > len_lut && idx <= len_lut * 2 idx_new = 2 * len_lut + 1 - idx; dds_dout(i) = -1 * cos_rom(idx_new); elseif idx > len_lut * 2 && idx <= len_lut * 3 idx_new = idx - 2 * len_lut; dds_dout(i) = -1 * cos_rom(idx_new); else idx_new = 4 * len_lut + 1 - idx; dds_dout(i) = 1 * cos_rom(idx_new); end phase_acc = phase_acc + phase_increment; end
dds_dout = floor(dds_dout / max(dds_dout) * 2 ^ (output_width - 1));
figure; subplot(2, 1, 1); plot(t(1:2048), dds_dout(1:2048)); xlabel('Time (s)'); ylabel('Amplitude'); title('DDS Generated Signal'); grid on; subplot(2, 1, 2); pwelch(dds_dout);
sgtitle("Simulation of the Quantization Performance of DDS");
toc;
|
IP Catalog 配置
详见 Euler0525@Wiki/zynq/DDS Compiler
参考资料