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

参考资料