ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

CIC滤波器通带下垂补偿:firceqrip FIR设计与工程实践

CIC滤波器通带下垂补偿:firceqrip FIR设计与工程实践

1. 先搞清楚问题:CIC 的通带为什么会"塌"下去

几年前接手一个宽带数字接收通道的抽取链,前级为了省资源,用的是最经典的多级 CIC 抽取。资源确实省下来了,综合报告干干净净,但联调时发现问题:整个通道的通带边缘比中心低了将近 4 dB,扫频一画出来就是一条明显的下坡。当时第一反应是"加个增益补一下不就完了",加完之后下坡是抬上去了,但带内平坦度变成了一条起伏的波浪线,相邻信道的功率估计全歪了。

这就是 CIC 滤波器通带补偿这件事的起点:CIC 的结构决定了它的幅频响应天然是一个 sinc 形状的下坡,而绝大多数实际系统需要的是平坦通带。想把它拉平,光靠一个常数增益没用,必须用一条频率相关的曲线去对冲。基于 firceqrip 的 FIR 滤波器设计,就是把这根"反向曲线"做出来的主流手段之一。

这篇内容面向的是已经知道 CIC 是什么、正在做抽取链预算、或者被通带平坦度指标卡住的人。我会把下垂量的手算、补偿滤波器的规格推导、firceqrip 的实际调用、定点化和硬件结构的坑,一条线串下来,中间给出可以直接抄的参数和代码。刚接触多速率信号处理的读者也能看,只是前面几节建议慢一点。

1.1 CIC 频响的解析式和下垂量手算

先把公式摆出来,不然后面所有参数都是拍脑袋。N 级级联、微分延迟 M、抽取因子 R 的 CIC 抽取滤波器,其幅频响应(归一化到直流增益为 1)是:

|H(f)| = [ sin(π·f·R·M/fs) / (R·M·sin(π·f/fs)) ]^N

其中 fs 是 CIC 的输入采样率,f 是从直流算起的绝对频率。注意这个公式里的分母有个 R·M,是为了把直流增益归一到 1;不归一的话直流增益是 (R·M)^N,这个数在定点实现里很关键,先记着。

这个式子的形状就是一个 sinc 函数被抬到了 N 次方。sinc 在 0 附近是 1,越往高频越小,取 N 次方之后衰减被放大 N 倍,所以级数越多,通带下垂越厉害。这就是为什么高抽取比、多级数的 CIC 一定要补偿,而 R=2、N=1 这种几乎不用管。

手算的时候有个近似很好用。当 f 远小于 fs/(R·M) 时:

|H(f)| ≈ 1 - N·(π·f·R·M/fs)²/6

换成 dB,下垂量约等于:

droop_dB ≈ -8.686 · N · (π·f·R·M/fs)² / 6

这个近似在归一化频率 0.5 以内误差很小,可以拿来快速判断"到底要不要补、补多少"。我一般在 Excel 里拉一张表,把通带边缘的几个候选值代进去看一眼,几十秒就能决定设计方向。

1.2 下垂量到底有多严重:两组参数对比

光说公式没有感觉,直接上两组数。假设输入采样率 fs = 100 MHz,抽取因子 R = 8,输出采样率 12.5 MHz,Nyquist 就是 6.25 MHz。

第一组:N = 5,M = 1,通带边缘取 3 MHz。

x = π·f·R·M/fs = π × 3e6 × 8 / 1e8 = 0.754 sin(x)/x = sin(0.754)/0.754 = 0.6846/0.754 = 0.9080 |H| = 0.9080^5 = 0.618 droop = 20·log10(0.618) = -4.18 dB

第二组:同样的 N 和 M,通带边缘放宽到 4 MHz。

x = π × 4e6 × 8 / 1e8 = 1.005 sin(x)/x = 0.8445/1.005 = 0.8403 |H| = 0.8403^5 = 0.4186 droop = 20·log10(0.4186) = -7.56 dB

看出来没有,通带边缘从 3 MHz 挪到 4 MHz,下垂从 4.2 dB 跳到 7.6 dB。因为下垂随频率是平方关系,越靠近输出 Nyquist,恶化速度越快。这也解释了为什么很多人设计时把通带定在 0.4×Nyquist 附近,那是一个下垂量还压得住的甜点区。

再看一组:通带 3 MHz 不变,把级数从 5 降到 3。

|H| = 0.9080^3 = 0.7488,droop = -2.51 dB。

4.18 dB 和 2.51 dB 的差别,决定了你后面补偿滤波器要做多高增益、要多少阶。所以我个人的习惯是:在系统预算允许的前提下,宁可多花一点前级资源把 CIC 的级数或通带比例选得保守一些,也别把压力全甩给补偿滤波器。补偿滤波器要做出 +4 dB 以上的峰值增益,定点实现时动态范围会很难受。

1.3 为什么不能靠简单加个增益解决问题

经常看到一种做法:在 CIC 后面乘一个 1/|H(fpass)| 的常数,把通带边缘抬到 0 dB。这么做的问题在于,它把整条曲线整体抬起来,中心频率变成了正增益,带内依然是弯的。

举个具体数字:3 MHz 处下垂 4.18 dB,通带中间 1.5 MHz 处算一下。

x = π × 1.5e6 × 8 / 1e8 = 0.377 sin(x)/x = 0.3680/0.377 = 0.9761 |H| = 0.9761^5 = 0.8862,droop = -1.05 dB

常数增益补偿 +4.18 dB 之后,中心变成 +3.13 dB,边缘是 0 dB。整条通带从 0 到 3 dB 之间来回摆,比原来的 0 到 -4.18 dB 好一点,但摆动的幅度仍然有 3 dB 以上。如果系统要求的是 ±0.2 dB 的带内平坦度,这个方案直接出局。

更麻烦的是,常数增益会让整个通道的绝对增益标定失效,除非你在后面再做一次归一化。所以正确的思路只有一条:用一条形状和 CIC 下垂曲线相反的传输函数去级联,让两者相乘接近常数。这条反向曲线,就是一个补偿滤波器。

2. 补偿方案选型:为什么最后落到 firceqrip 上

把 CIC 的下垂拉平,能走的路不止一条。我在不同项目里试过四种,各有各的适用边界,先说清楚取舍逻辑,再说为什么 FIR 补偿是我的默认选择。

2.1 四条可选路线与取舍

第一条是模拟域补偿。在 ADC 之后、数字链路之前加一级模拟均衡网络。优点是完全不占数字资源,缺点是电阻电容精度差、温漂大,而且模拟均衡器很难做到陡峭的形状,做 4 dB 的斜率补偿通常还要牺牲噪声性能。我的看法是除非整条链路已经没有数字余量,否则不在模拟侧折腾。

第二条是 IIR 逆向补偿。用几个极点零点去逼近 1/sinc^N 的形状。阶数低、资源省,但相位是非线性的,会破坏通道的群延迟一致性,而且对定点量化的敏感度比 FIR 高一个档次。如果系统只关心幅度不关心相位(比如某些功率检测场景),IIR 是可行的;如果后端要做相干解调或波束形成,IIR 就得慎用。

第三条是多项式补偿,也叫 ISOP 一类的低成本方案。用一阶或二阶的整系数多项式近似逆 sinc 曲线,本质上是一个只有 3 到 5 个抽头的极短滤波器。资源几乎可以忽略,但补偿精度有限,一般只能把 2 dB 以内的下垂压到 0.3 dB 左右。我在一个资源极其紧张的通道里用过,够用,但心里不踏实。

第四条就是 FIR 逆向补偿。线性相位、形状可控、精度高、定点行为可预测。代价是阶数可能不小,尤其是通带边缘比较靠外的时候。这也是我为什么默认选它——多速率链路里的滤波器,相位线性这条几乎是一票通过项。

四条路线的对比如下:

方案资源占用补偿精度相位特性定点友好度典型适用场景
模拟均衡无数字资源中视电路而定不涉及数字资源已耗尽
IIR 逆补偿低中高非线性一般只看幅度不看相位
多项式补偿极低低到中准线性好资源极端受限
FIR 逆补偿中高严格线性好通用首选

2.2 firceqrip 的定位:给定阶数下的等波纹最优解

确定了用 FIR,接下来的问题是:系数怎么算。方法有好几种,窗函数法、频率采样法、最小二乘、等波纹优化。firceqrip 属于最后这一类。

它解决的问题是:给定滤波器阶数 n、通带边缘归一化频率 wo、通带允许偏差 dp、阻带允许偏差 ds,找出一个使通带和阻带误差都达到等波纹状态(也就是最大误差最小化)的线性相位 FIR。这是切比雪夫意义下的最优解,同样阶数下,等波纹设计的过渡带最窄。

firceqrip 跟 firpm 的最大区别在于它内置了曲线模板。firpm 的名字里带 P 和 M,也就是 Parks-McClellan,它默认你要的是平坦通带加零阻带。要做 CIC 补偿,你得自己构造一个非平坦的期望增益向量再喂进去,还得调权重,麻烦。

firceqrip 支持一个'invsinc'选项,直接把"通带响应应该是 1/sinc^C 的形状"这个模板给你做好。这就省掉了整个"构造期望响应—调权重—迭代收敛"的过程。这也是我在 CIC 补偿这件事上首选它的核心原因——不是因为它在数学上比 firpm 强,而是因为这个场景的组合刚好被它覆盖了。

2.3 与 firpm、firls 的实际差别

我把三个函数的差异列一下,方便你在别的场景里做判断。

firls做的是最小二乘拟合,最小化误差平方和。它的特点是整体误差小,但可能出现局部大误差,尤其是在通带边缘。做 CIC 补偿的时候,边缘恰恰是最需要精确的地方,所以 firls 在这件事上不占优。

firpm是等波纹,性能上跟 firceqrip 同源,但模板要自己搭。如果你的补偿曲线不是标准的 sinc 幂次形状——比如 CIC 前面还串了一级模拟低通,整体下垂曲线被改过了——那 firpm 反而更灵活。

firceqrip的接口是"给指标,出系数",最省事,但灵活性差一点,因为期望形状被限定在 sinc 幂次的家族里。

我个人的使用顺序是:先试 firceqrip,看级联响应能不能压到指标以内;压不住再退回 firpm 手工构造;firls 基本不用在这个场景。

还有一点值得提:如果用的是较新版本的设计工具箱,fdesign.ciccomp这个设计对象会更省事——你把 CIC 的级数、微分延迟、抽取因子和通带阻带指标一次性交给它,它内部会自动算出下垂量并调用合适的算法。我通常用它做快速估算,确定大致阶数,然后再用 firceqrip 手工精调,因为手工调参时对 dp、ds 的控制更直接。

3. 参数怎么定:从系统指标倒推滤波器规格

这一节是整篇里最容易出错的地方。参数写错一个,设计出来的滤波器看着像那么回事,级联一测就不对。我按我自己的推导顺序讲。

3.1 通带边缘与归一化频率的换算

firceqrip 的频率参数 wo 是归一化到 Nyquist 的,也就是 1 对应 fs/2。这里的 fs 是补偿滤波器自己的采样率,也就是 CIC 抽取之后的速率,不是原始输入速率。这一点非常容易搞混。

接前面的例子:输入 100 MHz,R = 8,输出 12.5 MHz,补偿滤波器工作在 12.5 MHz 上,Nyquist 是 6.25 MHz。通带边缘 3 MHz,那么:

wo = 3 / 6.25 = 0.48

如果误用了输入速率算,会得到 3/50 = 0.06,设计出来的滤波器通带极窄,级联之后补偿完全不起作用。这个错误我见过不止一次,尤其是在多人协作的项目里,一个人算 CIC 参数、一个人算补偿滤波器参数,中间的速率定义没对齐。

我的做法是代码里把速率链写死成变量,所有归一化都从变量推,绝不手写数字:

fs_in = 100e6; R = 8; fs_out = fs_in / R; fpass = 3e6; wo = fpass / (fs_out/2);

这样改任何一个参数,后面自动跟着变,不会出现局部失配。

3.2 阶数与过渡带的博弈

firceqrip 的参数里,阶数 n 和阻带指标 ds 是绑定关系。你把 n 定死,ds 定死,过渡带的宽度就由算法决定了,你没法直接指定"阻带必须从 5 MHz 开始"。

实际设计时,一般是先定阻带起点 fstop,然后反推阶数。经验公式(等波纹低通的常见估算)大致是:

n ≈ (-10·log10(dp·ds) - 13) / (14.6 · Δf_norm)

其中 Δf_norm 是过渡带宽度归一化到 Nyquist 的值。这个公式只能用来估个数量级,最终还是要迭代。所以我的实际流程是:

  1. 按公式估一个 n;
  2. 用这个 n 和给定的 dp、ds 跑一次 firceqrip;
  3. 用 freqz 看 -ds 对应的频率点落在哪;
  4. 如果落在 fstop 之外,n 减一点;落在之内,n 加一点;
  5. 重复两三次基本就收敛了。

举个实例:fpass = 3 MHz,fstop = 5 MHz,Nyquist = 6.25 MHz。Δf_norm = (5-3)/6.25 = 0.32。dp = 0.01(约 ±0.086 dB),ds = 0.001(-60 dB)。

按公式:(-10·log10(1e-5) - 13) / (14.6 × 0.32) = (50 - 13) / 4.672 = 7.9。

这个结果明显偏小,因为公式假设的是平坦通带,而 invsinc 模板会吃掉一部分设计自由度。实际跑下来,n 大概要 50 到 70 才能达标。这就是为什么我一直强调"公式估个数量级就行,别当真"。

3.3 波纹指标与残余平坦度的换算

dp 和 ds 都是线性幅度偏差,不是 dB。这个转换必须记牢,我看到过有人直接把 0.1 dB 填进去,结果设计出来的通带波纹大得离谱。

换算关系:

dp_linear = 10^(Ap_dB/20) - 1 ds_linear = 10^(-As_dB/20)

比如要求通带残余波纹 ±0.1 dB,那 Ap 换成峰值偏差是 0.2 dB 峰峰值,对应 dp = 10^(0.1/20) - 1 = 0.0116。要求阻带 60 dB,ds = 10^(-3) = 0.001。

这里有个容易忽略的点:这个 dp 是相对于 invsinc 目标曲线的偏差,不是相对于平坦响应的偏差。也就是说,补偿滤波器的实际响应会在 1/sinc^C 这条曲线上下摆动,摆幅由 dp 决定。级联之后,残余的下垂波动就是这个摆幅。

所以系统指标如果是"带内平坦度 ±0.15 dB",你不能把整个预算都给补偿滤波器。我的分配习惯是:补偿滤波器拿走一半,剩下的一半留给 CIC 本身的残余、后级半带滤波器的波纹、以及定点量化引入的误差。这样 dp 大致取 0.005 到 0.01 之间。

3.4 抽取因子、级数、微分延迟三者的敏感性

这三个参数对补偿滤波器的影响不是线性的,值得单独说。

抽取因子 R 变大,输出速率降低,归一化通带 wo 变大(同样的绝对带宽占 Nyquist 的比例更高),同时 CIC 下垂也变大。两个效应叠加,补偿滤波器的阶数会显著上升。

级数 N 变大,下垂按 N 倍放大,但 CIC 的归一化形状不变。所以补偿滤波器的阶数需求主要是被"下垂深度"推高的,因为深的下垂需要更高的峰值增益,而高增益曲线用 FIR 逼近时,边缘的斜率更陡。

微分延迟 M 的影响等价于把 R 乘上 M。所以 M 从 1 改成 2,效果跟抽取因子翻倍类似。很多设计里 M 取 1 就是为了减轻补偿压力,代价是 CIC 的阻带零点位置变化,需要重新核算混叠抑制。

我做参数扫描时的习惯是固定 R 和 M,只扫 N,看补偿阶数怎么变。这条曲线通常在 N 超过 4 之后开始陡峭上升,那是一个很好的参考点。

4. 动手做:一条完整的设计链路

前面讲的都是推导,这一节是能直接跑的代码和能对得上的数字。

4.1 环境与函数签名核对

先提醒一句:firceqrip 在不同版本的设计工具箱里,参数顺序和可选参数有过调整。网上抄来的老代码经常跑不通。动手之前先help firceqrip扫一眼签名。

我用的是这种形式:

b = firceqrip(n, wo, dp, ds, 'invsinc', C);

n 是阶数(滤波器长度是 n+1),wo 是归一化通带边缘,dp、ds 是线性偏差,'invsinc'后面跟的 C 是 sinc 的幂次。

C 怎么填?CIC 的等效形状是 sinc 的 N·M 次方,所以 M=1 的时候 C 就等于级数 N。如果各级的微分延迟不一样,可以传一个向量,每个元素对应一级的幂次。我一般先用标量 N 试,级联曲线对不上再考虑向量。

如果版本不认这个写法,退一步用fdesign.ciccomp构造设计对象再 design,或者用 firpm 手工搭模板。三条路都能到终点,只是费劲程度不同。

4.2 设计代码与频响验证

把前面所有参数串起来,完整的一段是这样:

fs_in = 100e6; R = 8; N = 5; M = 1; fs_out = fs_in / R; fpass = 3e6; fstop = 5e6; wo = fpass / (fs_out/2); dp = 0.01; % 约 ±0.086 dB 的残余波纹 ds = 0.001; % 约 -60 dB 阻带 % 先看 CIC 在通带边缘的下垂量 fchk = [0 fpass]; Hcic = abs((sin(pi*fchk*R*M/fs_in) ./ (R*M*sin(pi*fchk/fs_in))).^N); droop = 20*log10(Hcic(end)); fprintf('CIC 通带边缘下垂: %.2f dB\n', droop); % 设计补偿 FIR n = 64; b = firceqrip(n, wo, dp, ds, 'invsinc', N); % 看补偿器自己的幅频 [Hc, f] = freqz(b, 1, 8192, fs_out); figure; subplot(2,1,1); plot(f/1e6, 20*log10(abs(Hc))); grid on; xlabel('频率 (MHz)'); ylabel('幅度 (dB)'); title('补偿滤波器幅频响应'); subplot(2,1,2); plot(f/1e6, unwrap(angle(Hc))); grid on; xlabel('频率 (MHz)'); ylabel('相位 (rad)');

跑出来的补偿器幅频,直流处应该在 0 dB 附近,往通带边缘单调上升,到 3 MHz 处应该接近 +4.18 dB,也就是前面算出来的下垂量。如果这个峰值对不上,说明 C 填错了或者 wo 算错了。

4.3 级联频响、残余下垂与群延迟对齐

补偿器单独看没意义,关键看级联。

fc = 0:1e3:fs_out/2; Hcic = abs((sin(pi*fc*R*M/fs_in) ./ (R*M*sin(pi*fc/fs_in))).^N); Hc2 = abs(freqz(b, 1, fc, fs_out)); Htot = Hcic .* Hc2; figure; plot(fc/1e6, 20*log10(Hcic), '--', ... fc/1e6, 20*log10(Htot), '-'); grid on; legend('CIC 单独','级联后'); xlabel('频率 (MHz)'); ylabel('幅度 (dB)'); xlim([0 fstop/1e6]);

级联曲线在 0 到 3 MHz 之间应该基本是一条平线,波动幅度在 dp 量级以内。如果边缘还翘着或者塌着,说明补偿不足或过量,回头调 C 或者调 wo。

群延迟这边要注意,两级滤波器的延迟是相加的,而且单位不一样:

环节延迟表达式本例数值
CICN·(R·M-1)/2 个输入样点17.5
补偿 FIRn/2 个输出样点 = n·R/2 个输入样点256
合计—273.5 个输入样点

换算成时间,100 MHz 下就是 2.735 μs。这个延迟在做多通道时间对齐时必须算进去,否则通道之间的相位关系全错。补偿滤波器的延迟比 CIC 大一个数量级,因为它在低速侧工作,n/2 个输出样点折算回来要乘 R。

你要是对延迟极其敏感,可以考虑把补偿滤波器挪到抽取之前。代价是阶数要乘 R,资源翻好几倍,得不偿失。我的经验是延迟只要在系统预算内,就别折腾。

4.4 定点化:系数量化、位宽估算与饱和策略

这一节是真正让人掉头发的地方。浮点仿真过了,定点一跑就崩,问题基本都出在这里。

先算峰值增益。下垂 4.18 dB 对应线性增益 10^(4.18/20) = 1.618。也就是说补偿滤波器在通带边缘的输出,是输入的 1.6 倍以上。

系数量化时,先定小数位宽 Q。如果 Q = 16,系数绝对值之和的最大值(在通带边缘处最坏)大约是 1.618 × 65536 ≈ 106,000。加上符号位需要 18 位。

数据位宽这么估:假设输入数据 12 位有符号,系数 18 位,乘积 30 位。累加器要留 log2(系数个数) 的余量,65 个系数对应 6 位,再留 2 位保护,累加器至少 38 位。实际实现里我一般取 40 位,宽一点心里踏实。

饱和策略上有个细节:补偿滤波器的输出动态范围比输入大,如果后级是固定增益的截位,很容易在通带边缘削顶。我的做法是在补偿器输出加一级饱和保护,同时把后级的增益预算按峰值增益重新算一遍,别按直流增益算。

还有系数量化误差。firceqrip 出来的是双精度系数,量化到 18 位之后,阻带衰减通常会掉 3 到 6 dB。所以设计时 ds 要留余量,想要 60 dB 就按 65 dB 设计。

4.5 硬件实现结构:对称折叠与多相

线性相位 FIR 的系数是对称的,这是白送的资源优化。65 个系数折叠成 33 组,乘法器数量直接砍半。

接着算复用。输出采样率 12.5 MHz,系统时钟 200 MHz,一个输出周期有 16 个时钟可用。33 组系数在 16 个时钟内做完,需要 ceil(33/16) = 3 个乘法器。这个规模对绝大多数器件都是小意思。

如果时钟只有 100 MHz,复用度降到 8,乘法器要 5 个,也不难。真正吃资源的是系数存储和移位寄存器,65 阶的移位寄存器在低速侧跑,用分布式 RAM 就够,别用触发器堆。

有个结构上的选择值得提:补偿滤波器可以和后面的半带滤波器合并成一级多相结构。如果 CIC 之后还要做 2 倍抽取,把补偿和半带放在同一个多相分解里,公共子表达式能省掉一部分乘法。我做过一次合并,乘法器从 8 个降到 6 个,代价是调试复杂度上升不少。资源不紧张的话,不建议为了省两个乘法器去合并。

4.6 实测验证:多音扫频与时域对齐

仿真对上了不代表板子上对。我的验证流程分三步。

第一步是窄带单音。在通带内取 0.5、1.5、2.5、3 MHz 四个点,逐个灌单音,测输出幅度。四个点的幅度差应该在 0.2 dB 以内。这一步能快速暴露增益标定的问题。

第二步是多音。一次性灌 8 到 16 个等间隔单音,看频谱上的平坦度。多音的好处是能同时看到整个通带的形状,不用来回改频率。注意多音的峰值因子,别让总功率把后级推到饱和,回退 10 dB 再测。

第三步是扫频。用 DDS 产生一个从 0 扫到 fstop 的线性调频信号,看输出的包络。理想情况下包络是一条平线,实际会看到轻微起伏,起伏幅度就是残余平坦度。这一步对定位"边缘翘起"这类问题特别有效,因为它能连续看到整条曲线。

时域对齐这块,如果通道里有多个并行的 CIC 加补偿链路,一定要用同一个参考信号测一遍各通道的延迟差。我踩过的坑是两条链路的补偿滤波器阶数取了不同的值(一条 60 一条 64),延迟差了 2 个输出样点,做完波束形成之后合成效率掉了一大截,查了两天才定位到。

5. 踩过的坑:常见问题与排查实录

这一节全是实际调试中撞出来的,按出现频率排。

5.1 补偿过量与欠补偿

现象很好认:级联曲线在通带边缘往上翘,就是过量;往下塌,就是欠补偿。

过量的常见原因是 C 填大了。有人觉得 C 越大补偿越猛,直接填了 N·M·2,结果补偿器在边缘给出 8 dB 增益,而 CIC 只塌了 4 dB,级联之后翘起来 4 dB。

欠补偿的常见原因是 wo 算小了。wo 定得比实际通带边缘靠内,补偿器在边缘还没爬到目标增益就进过渡带了。

还有一种隐蔽的情况:CIC 的实际下垂比你算的大。原因可能是 CIC 前面还串了一级模拟滤波或者别的数字滤波,整体下垂叠加了。这种时候不要硬调 C,先用实测的 CIC 频响反推一个等效 C,再填进去。我一般会在链路仿真里把 CIC 的实测频响导出来,用曲线拟合估一下等效幂次。

5.2 阶数爆炸的三种成因

阶数从 40 涨到 200,资源直接翻五倍,这种事我遇到过两次。

第一种成因是通带定得太靠外。前面算过,3 MHz 到 4 MHz 这一小段,下垂从 4.2 dB 跳到 7.6 dB,补偿阶数跟着涨一大截。解决办法是回头跟系统方商量,把有效通带往里收一点。这一收,往往能省掉一半资源。

第二种成因是阻带要求过严。有人直接抄了"阻带 80 dB"这样的指标,实际上 CIC 后面还有半带滤波器在兜底,补偿滤波器的阻带只要做到 50 dB 就够了。指标放宽 30 dB,阶数能降三成。

第三种成因是过渡带留得太窄。fpass 到 fstop 之间只留了 0.5 MHz,等波纹设计在这种窄过渡带下阶数会飙升。把 fstop 往外推一点,代价是混叠抑制变差,但如果后面有多级半带,这个代价是可以接受的。

5.3 定点溢出与量化噪声

溢出好判断,波形削顶,频谱上出现一堆谐波。难判断的是量化噪声,因为它表现为底噪抬升,很容易被误认为是前级的问题。

定位方法:把补偿滤波器旁路掉,看底噪有没有变化。如果旁路之后底噪明显下降,问题就在补偿器这一级。

成因通常是两个。一是系数量化位宽不够,18 位量化到 12 位,阻带衰减从 60 dB 掉到 40 dB。二是累加器位宽不够,中间结果溢出被饱和,产生非线性。

我的经验值:系数至少 16 位,累加器至少留 log2(系数长度) + 峰值增益位数 + 4 位余量。别在这上面省,一个累加器位宽也就几个触发器的事。

5.4 群延迟错位的隐蔽问题

这个问题最阴,因为它不影响单通道的任何指标。单通道测什么都对,多通道一合成就出问题。

典型表现是:波束形成的合成增益达不到理论值,或者通道间的相位差随频率变化。查的时候容易怀疑到本振、怀疑到 ADC 采样对齐,唯独想不到是补偿滤波器的延迟。

排查方法很直接:给所有通道灌同一个脉冲,看各通道输出的峰值位置。差值除以采样周期就是延迟差,应该精确等于各自滤波器群延迟的差。如果对不上,就是有链路用了不同的阶数或者不同的抽取因子。

预防的办法是在设计阶段就把延迟预算做成一张表,每个环节的延迟列清楚,改动任何一级都要更新这张表。我现在养成了习惯,滤波器参数一变,第一件事是重新算延迟,不是看频响。

5.5 常见问题速查表

现象最可能原因排查动作处理办法
通带边缘翘起补偿过量,C 填大单独看补偿器幅频,边缘增益是否超下垂量减小 C 或降低 wo
通带边缘仍塌欠补偿,wo 偏小检查通带边缘归一化频率重算 wo,用输出速率
阶数异常高通带太靠外或过渡带太窄扫描 fstop 与 fpass 差值收窄有效通带或放宽阻带
底噪抬升系数量化位宽不足旁路补偿器对比底噪系数加位宽至 16 位以上
输出削顶峰值增益未计入增益预算测通带边缘输出幅度加饱和保护,重算后级增益
多通道合成效率低群延迟不一致灌脉冲测各通道峰值位置统一阶数,更新延迟预算表
阻带衰减不达标量化损失未留余量对比浮点与定点阻带设计时 ds 多留 5 dB

6. 边界情况与扩展思路

6.1 多级抽取链里的位置选择

补偿滤波器不是非得紧贴 CIC。如果后面还有两级半带抽取,可以把补偿放在半带之后,速率更低,阶数需求更小,但这时候补偿器要同时补偿 CIC 和半带的通带下垂,曲线形状不再是纯 sinc 幂次,firceqrip 的模板就不完全匹配了。

我的取舍原则是:只有 CIC 一级抽取的时候,补偿紧跟 CIC;有两级以上抽取且后级半带的通带很宽(比如 0.8 倍 Nyquist)时,把补偿放在最后一级,用 firpm 手工构造复合补偿曲线。这样资源最省,代价是设计周期长一些。

还有一种做法是把补偿和第一级半带合并设计,用一次优化同时满足两边的指标。这个思路在文献里很常见,实际做起来需要一定的迭代经验,新手不建议一上来就这么干。

6.2 低资源场景的降级方案

如果综合下来乘法器实在不够,可以按这个顺序降级:

第一,先砍阶数。把 dp 放宽到 0.02,看看残余平坦度还能不能接受。很多时候指标是拍脑袋定的,实际系统对 ±0.3 dB 也完全可以容忍。

第二,改用对称折叠加时分复用,把乘法器降到 2 个。这个基本没有性能损失,只是控制逻辑复杂一点。

第三,退回多项式补偿。三到五个抽头的短滤波器,把 2 dB 以内的下垂压到 0.5 dB,够用就行。这时候就别追求精确的曲线拉平了,先让系统跑起来。

第四,如果连这个都做不到,说明前级 CIC 的参数一开始就选激进了,回头把 R 或者 N 降下来,从源头解决问题。

我在一个资源卡死的项目里走过第三条路,用 5 个抽头的对称 FIR 做近似逆 sinc,带内平坦度做到 0.4 dB,虽然不漂亮,但通过了系统验收。后来复盘的时候发现,如果把 CIC 的级数从 5 降到 4,下垂小了将近一半,后面用 3 个抽头就够了。所以真正的最优解往往在上一级,而不是在补偿器本身。

最后分享一个我个人一直在用的检查习惯:每次改完补偿滤波器的参数,不要只看频响图,一定要把级联后的通带平坦度和群延迟同时打出来,再对照延迟预算表核一遍。频响对了延迟错了,单通道测不出问题,多通道一联调就是灾难。这个习惯帮我省掉的返工时间,比任何一次参数优化的收益都大。

返回列表