3. 数字下变频(DDC):NCO原理、CORDIC算法、混频器实现、多级抽取滤波
好,咱们今天聊聊数字下变频,也就是DDC。这玩意儿在通信芯片里,基本就是个标配。说白了,就是把天线收到的高频信号,搬到一个我们能轻松处理的低频上来。我当年刚入行时,觉得这不就是个乘法器加个滤波器嘛,有啥难的?后来真做项目了,才发现坑多着呢。
3.1 NCO原理:怎么产生那个本振信号?
DDC的第一步,就是需要一个本地的正弦波和余弦波,去跟输入信号做乘法。这个产生本地信号的家伙,就叫NCO(数控振荡器)。
NCO的核心思想,其实特别简单。你想想看,一个正弦波,不就是个圆上的点在转嘛。我们用一个累加器,每个时钟周期加一个步进值,这个累加器的输出就代表相位。然后查一个正弦表,就能得到对应的幅度值。
关键参数:
- 频率控制字(FCW): 决定了步进大小,也就决定了输出频率。公式是:
F_out = (FCW * F_clk) / 2^N,N是累加器位宽。 - 相位累加器位宽: 决定了频率分辨率。位宽越大,能调出来的频率就越精细。我个人习惯至少用32位,不然有些窄带信号你根本对不准。
- 查找表深度: 决定了输出波形的SFDR(无杂散动态范围)。
我在项目中遇到过一个问题:NCO输出的杂散太大,导致接收机灵敏度怎么也上不去。查了半天,发现是查找表只存了1/4周期的数据,压缩比太高,引入了量化噪声。后来改成存半周期,SFDR立马好了10个dB。
3.2 CORDIC算法:不用查表也能算正余弦
查表法虽然直观,但有个毛病:表太大,占ROM。尤其是你需要高精度的时候,表深度指数级增长。这时候,CORDIC算法就登场了。
CORDIC,全称是“坐标旋转数字计算机”。说白了,它就是用一堆简单的移位和加法,迭代地去逼近一个旋转角度。你给它一个角度,它就能给你算出这个角度的正弦和余弦值。
为什么这玩意儿在芯片里受欢迎?因为它只有加法和移位,没有乘法器。面积小,频率还能跑得高。
我的经验:
CORDIC的迭代次数一般取12到16次就够用了。再多了,精度提升有限,但延迟和面积都上去了。我曾经试过20次迭代,结果综合出来时序都跑不过,得不偿失。
代码实现上,核心就是个迭代循环。每次迭代判断当前角度是正还是负,决定是顺时针转还是逆时针转。嗯,这里要注意,CORDIC的输入角度范围最好先归一化到[-π, π]之间,不然迭代会不收敛。
// 伪代码:CORDIC 核心迭代
for (i = 0; i < N; i++) {
if (z >= 0) {
x_new = x - (y >> i);
y_new = y + (x >> i);
z_new = z - atan_table[i];
} else {
x_new = x + (y >> i);
y_new = y - (x >> i);
z_new = z + atan_table[i];
}
x = x_new; y = y_new; z = z_new;
}
3.3 混频器实现:乘法器没那么简单
有了NCO产生的本振信号,下一步就是跟输入信号做乘法。这就是混频器。
理论上,就是个乘法器。但在数字芯片里,你得考虑位宽。输入信号是12位,NCO输出也是12位,乘出来就是24位。你直接往下扔给滤波器?那面积和功耗都受不了。
所以,混频器后面通常紧跟着一个截位操作。截位怎么截?直接截掉低位?那会引入量化噪声。我建议的做法是:先做饱和处理,防止溢出,然后再四舍五入截位。
避坑指南:
我曾经犯过一个错:混频器输出直接截位,没做饱和。结果信号稍微大一点,就发生了溢出,整个星座图都乱了。后来加了饱和逻辑,问题才解决。记住,饱和比截位重要得多。
另外,混频器可以用复数乘法器来实现。如果你做的是正交下变频,那就是I路和Q路分别乘,然后加减。公式很简单:
I_out = I_in * cos(wt) + Q_in * sin(wt)
Q_out = Q_in * cos(wt) - I_in * sin(wt)
3.4 多级抽取滤波:降采样是个技术活
混频之后,信号带宽变窄了。这时候再用高速ADC采样的速率去处理,纯属浪费。所以我们要降采样,也就是抽取。
但直接抽取会带来一个问题:频谱混叠。你想想看,降采样相当于降低了采样率,如果信号带宽超过了新的奈奎斯特频率,高频分量就会折叠到低频,把信号搞坏。
所以,抽取之前必须先做滤波。这个滤波器叫抗混叠滤波器。
为什么用多级?因为单级滤波器阶数太高,硬件实现不了。比如你要做64倍降采样,单级滤波器可能需要上千阶。但分成三级:4倍、4倍、4倍,每级只需要几十阶。总面积小得多,功耗也低。
| 级数 | 抽取倍数 | 滤波器阶数 | 工作频率 |
|---|---|---|---|
| 第一级 | 4 | 32 | Fs |
| 第二级 | 4 | 48 | Fs/4 |
| 第三级 | 4 | 64 | Fs/16 |
你看,第一级工作在最高频率,所以阶数要尽量低。后面几级频率降下来了,阶数可以适当高一些,把带外抑制做干净。
我的习惯:
第一级我通常用CIC滤波器(级联积分梳状滤波器)。它没有乘法器,全是加法器,面积极小,非常适合高速场景。后面几级再用FIR滤波器来补偿CIC的带内衰减。这种组合,我在三个项目里都用过,效果很稳定。
好了,DDC的核心就是这些。NCO产生本振,CORDIC可以替代查表,混频器要注意截位和饱和,多级抽取滤波要合理分配每一级的指标。你把这些搞明白了,一个能用的DDC基本就能搭出来了。