DDS Compiler

设计原理

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

首先存储一个周期的正弦波,然后将相位 比特量化,即平均分成 份,以 的频率每始终周期转动 ,则可以得到输出频率为 的信号,

可以看出,输出频率 是参考时钟频率 、相位量化位宽 、和相位增量(频率控制字) 的函数。增加频率控制字,将得到更高频率的信号。

根据奈奎斯特采样定律,为了使波形不失真,需要满足 ,则有

始终小于 ,不妨将其看成是一个分频器,通过修改频率控制字分频参考时钟 ,获得所需要的频率。

组成结构

如图,直接式数字频率合成器(Direct Digital Synthesizer,DDS)主要由 相位累加器波形查找表数模转换器和低通滤波器 等部分组成。

其中的核心部分是相位累加器,由一个 位累加器和 位寄存器构成,在每个参考时钟上升沿,累加器将频率控制字与累加寄存器的输出相加,结果作为寄存器新的输入。如此反复, 当累加器累加满时, 就会发生溢出,完成一个周期, 即 DDS 合成信号的一个频率周期。

波形查找表(Lookup Table,LUT)中存储了正弦波的数字幅度信息,每个地址对应一个相位点,每个相位点对应正弦波的一个幅度值。将相位累加寄存器的输出与相位控制字相加,作为波形查找表的输入地址,地址映射为正弦波幅度,输出到 D/A 转换器。

D/A 转换器将数字信号转换成模拟信号,再经低通滤波器滤除不需要的取样分量,最终得到所需信号。

量化性能

理想的 DDS 应满足:

  • 稳定的参考时钟

  • 波形查找表地址的位数等于相位累加器的位数;

  • 相位累加器位宽无限大,且都输出到查找表,没有截断;

  • 波形查找表幅度无量化误差,即幅值位数为

  • D/A 转换器无误差、低通滤波器是理想的;

相位累加器的输出相位为 ,周期 ,则波形查找表输出的幅度序列为

经过 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;

% FIXME System Parameters
fs = 160e3;
f_out = 10e3; % f_out < 80e3
phase_width = 16; N = 2 ^ phase_width; % Phase width quantization (frequency resolution = fs / N;)
output_width = 16; % Magnitude quantization
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

参考资料