4、数字下变频(DDC):NCO原理、混频器实现、CIC与FIR滤波器设计

数字下变频,简称DDC,是雷达接收机里最核心的模块之一。说白了,就是把天线收到的高频信号,搬到一个我们能处理的低频基带上来。我刚开始接触雷达时,总觉得这玩意儿不就是个数学公式嘛,后来真上了硬件才发现,里面的坑一个接一个。

今天咱们就掰开揉碎了聊聊DDC的四个关键部分:NCO怎么产生本振信号、混频器怎么搭、CIC和FIR滤波器又该怎么设计。嗯,这些都是我这些年调板子、抓波形、跟FPGA死磕出来的经验。

4.1 NCO原理:数字本振是怎么来的

NCO,全称是数控振荡器。它的任务很简单——产生一个频率可调的正弦波和余弦波。你想想看,雷达信号进来,我们得用本振信号去跟它相乘,才能把频谱搬下来。这个本振信号,就是NCO给的。

NCO的核心结构其实就三样东西:

  • 相位累加器:一个不断累加的计数器
  • 相位-幅度查找表:存着正弦波的一个周期的采样值
  • 频率控制字:决定累加器每次加多少

频率控制字越大,相位累加器跑得越快,输出的频率就越高。公式很简单:

f_out = (Fcw * f_clk) / 2^N

其中Fcw是频率控制字,f_clk是系统时钟,N是累加器位宽。举个例子,我用100MHz时钟,32位累加器,想要输出10MHz,那Fcw就是:

Fcw = (10e6 * 2^32) / 100e6 ≈ 429496730

我个人习惯把NCO的位宽做到至少24位以上。为什么?因为位宽不够,频率分辨率就太粗了。我在一个项目中遇到过,用16位累加器,想调个几百赫兹的频率都调不准,最后只能换芯片重做板子,教训深刻。

小技巧: 查找表不用存整个周期,存1/4周期就够了,通过象限映射可以恢复出完整波形。这样能省3/4的存储资源。

4.2 混频器实现:乘法器与正交下变频

混频器,就是做乘法。把输入信号跟NCO产生的本振信号乘在一起。但这里有个关键点——我们做的是正交下变频

为什么要正交?因为单路混频会把正负频率混在一起,分不清。正交下变频用两路:I路(同相)和Q路(正交),分别跟cos和sin相乘,这样就能保留信号的相位信息。

混频器的实现,在FPGA里就是调用DSP48乘法器。我建议直接用Xilinx或Altera的IP核,别自己手写乘法器。为什么?因为IP核经过了充分优化,时序、延迟、资源都给你算好了。

不过有一点要注意——混频后的信号频率是f_in ± f_lo。我们想要的是差频f_in - f_lo,那个和频f_in + f_lo是高频分量,后面要靠低通滤波器滤掉。

注意: 混频器输出一定要做截位处理。两个N位数据相乘,结果是2N位。如果不截位,后面滤波器位宽会爆炸。我曾经因为没做截位,导致滤波器资源用了原来的4倍,时序还跑不过。

4.3 CIC滤波器:抽取与抗混叠

混频之后,信号采样率通常很高。比如ADC采样率是100MHz,混频后还是100MHz。但基带信号带宽可能只有几兆赫兹,没必要用这么高的采样率。这时候就需要抽取——降低采样率。

CIC滤波器就是专门干这个的。它的好处是:不需要乘法器,只用加法器和减法器,资源极省。特别适合做高倍率抽取。

CIC滤波器的结构分三部分:

  1. 积分器:累加输入数据
  2. 抽取器:每隔R个点取一个
  3. 梳状器:做差分运算

级联数N决定了滤波器的阻带衰减。N越大,衰减越陡,但通带衰减也越大。我一般用3到5级,再高就有点得不偿失了。

CIC有个致命问题——通带滚降。它的幅频响应像sinc函数,在通带内不是平的。所以后面通常要接一个FIR滤波器来做补偿。

// CIC滤波器参数示例
// 抽取因子 R = 16
// 级联数 N = 4
// 差分延迟 M = 1

// 积分器部分(伪代码)
for i = 0 to N-1:
    integrator[i] = integrator[i] + input

// 抽取
if sample_count % R == 0:
    temp = integrator[N-1]

// 梳状器部分
for i = 0 to N-1:
    output = temp - comb_delay[i]
    comb_delay[i] = temp
    temp = output
关键点: CIC滤波器的增益是(R * M)^N。如果R=16,M=1,N=4,增益就是16^4=65536。输出位宽必须留够余量,否则数据会溢出。我一般会在CIC后面做一次右移截位。

4.4 FIR滤波器:补偿与成形

CIC之后,信号已经降到了较低的采样率。但CIC的通带不平坦,而且阻带衰减可能不够。这时候就需要FIR滤波器来补偿成形

FIR滤波器的设计,我推荐用MATLAB的Filter Designer工具。你只需要告诉它:通带频率、阻带频率、通带纹波、阻带衰减,它就能帮你算出系数。

设计时要注意几个参数:

参数 说明 我的建议
阶数 滤波器抽头数量 阶数越高,过渡带越陡,但延迟越大
通带纹波 通带内幅度的波动 一般0.1dB以内,雷达要求高的话0.01dB
阻带衰减 阻带内信号的抑制程度 至少60dB,我习惯做到80dB以上

在FPGA里实现FIR,有几种方式:

  • 直接型:最直观,但资源消耗大
  • 转置型:时序更好,适合高速设计
  • 对称型:利用系数对称性,省一半乘法器
  • 多相分解:适合多倍率抽取或插值

我个人偏爱对称型+转置型的组合。既省资源,时序又容易收敛。不过要注意,对称型要求系数严格对称,如果系数有微小不对称,滤波效果会变差。

避坑指南: 我曾经在FIR系数量化时吃了大亏。MATLAB算出来的是浮点数,转成定点数时,如果位宽不够,滤波器的幅频响应会严重变形。我建议系数量化至少做到16位,关键场合用18位或24位。

4.5 完整的DDC链路设计

好了,现在我们把所有模块串起来,看看完整的DDC链路长什么样:

ADC输入 → 混频器(I/Q) → CIC抽取 → FIR补偿 → 基带输出
                ↑
              NCO

这个链路里,每一步的位宽都要精心设计。我一般这样分配:

  1. ADC输出:12-16位
  2. 混频后:24-32位(乘法结果)
  3. CIC输出:根据增益计算,通常比输入多log2(R^N)位
  4. FIR输出:根据系数位宽和阶数,通常16-24位

最后输出的基带数据,就是I和Q两路,采样率已经降到了合适的水平。后面就可以做脉冲压缩、MTI、CFAR等处理了。

重要提醒: 整个DDC链路一定要做仿真验证。我习惯先用MATLAB搭一个浮点模型,跟FPGA的定点模型做对比。如果两者的输出误差在1个LSB以内,基本就稳了。如果误差大了,八成是截位策略有问题。

嗯,DDC这块内容就聊到这儿。说白了,NCO、混频器、CIC、FIR这四个模块,每个单独拿出来都不难,但串在一起时,位宽、时序、资源、性能这些因素都要权衡。我这些年调过的DDC,少说也有几十个版本了,每次都能学到新东西。希望今天的分享能帮你少走些弯路。