资讯动态

复数滤波器与复数积分器:从原理到FPGA定点实现

发布时间:2026/9/10 3:52:50 来源:尧图企业网站定制
复数积分器和复数滤波器这俩词搞通信或者信号处理的人应该都不陌生但很多刚接触的人都被“复数”这两个字吓住了。其实它没那么玄乎你在工程里见到的正交混频器、数字下变频DDC、镜像抑制接收机、QAM解调器里面到处都藏着复数信号处理的身影。复数积分器和滤波器正是这套系统的骨架。这篇文章我不讲教科书式的推导直接围绕“它到底解决了什么问题、系数怎么定、在FPGA/DSP上怎么落地”来写也会把我在实际项目中踩过的坑一并说清楚。不管是刚开始做软件无线电的还是被镜像抑制指标折磨得头疼的工程师这篇文章应该能帮你省不少时间。1. 从实数到复信号为什么非要用复数处理1.1 I/Q双通道的本质是频域“裁剪”先说最底层的问题实际物理信号都是实数为什么处理的时候非要整出复数来这得从频谱说起。一个实数信号经过傅里叶变换后频谱一定是左右对称的正频率和负频率的幅度相同、相位相反。这个对称性意味着有一半的信息其实是冗余的。但在通信接收机里我们经常只关心正频率或者只关心某个目标频带。比如零中频接收机把射频信号搬移到基带后有用的信号可能只在5MHz附近而镜像干扰落在-5MHz附近。这时候你拿出一套只保留正频率、抑制负频率的处理工具问题就简单多了。复信号天然具备“单边频谱”的能力一个复数信号IjQ它的频谱不需要对称正频率和负频率可以完全独立。复数滤波器本质上就是干这个的——它能在z平面的特定位置放极点或零点把某一侧的频带留住另一侧压掉。I/Q两路可以理解为复信号的实部和虚部。硬件上你看到的是一对正交本振混频产生的两路正交基带信号数字域里把它们拼成一个复数序列就行。我在项目里最常用的一句话是I路和Q路不是两个独立通道它们是同一个复数的实部和虚部处理时永远要把它当成一个整体。1.2 复系数滤波器带来的“非对称频率响应”实数滤波器的频率响应一定满足H(e^jω)的共轭对称性也就是说幅频响应关于零频对称。这种滤波器只能做“以0Hz为中心”的带通或低通处理。但复系数滤波器没有这个限制它的冲激响应是复数序列频率响应可以在正频率和负频率各自独立设计。一个最直观的例子复系数单极点低通滤波器极点放在p r·e^(jω0)其中r是极点半径ω0是期望通带中心对应的数字角频率。这个滤波器的频响峰值出现在ωω0附近而对ω-ω0附近基本没有响应。这就是实现单边带选频的关键。你在数字域里见到的大多数“非对称带通滤波器”本质上都是复系数结构。1.3 复数积分器与实数积分器的本质差异积分器分实数积分器和复数积分器差别体现在零点和极点位置。实数积分器在z域的传递函数是H(z) 1/(1-z⁻¹)它的极点在z1也就是直流点。这样的积分器对直流附近的信号有无穷大的增益适合处理基带信号或者构建一阶环路。复数积分器更像是把一个“旋转坐标系”引入积分过程。经典的复积分器传递函数可以写成H(z) 1/(1 - a·z⁻¹)其中a是单位圆上的复数例如a e^(jωc)。它的极点不在直流而是落在某个非零频点ωc上。这种积分器对频率接近ωc的信号有很高的增益对远离ωc的频率增益较低。用在锁相环的环路滤波器里它能实现对特定频偏信号的“无静差”跟踪这是实数积分器做不到的。另一个常见场景是正交鉴频器里的环路积分你需要对I/Q复数信号计算相位差后做积分实际上就是在一个旋转参考系里做累加。2. 复系数滤波器设计从系数到参数计算2.1 从一阶实数低通推导到复系数低通我之前在Matlab里搭过一个镜像抑制接收机的基带模型第一版偷懒直接用了实数低通滤波器滤I路和Q路结果镜像抑制只有20多dB后来换成复系数滤波器镜像抑制直接做到60dB以上。这个过程中最关键的一步就是把标准实数一阶低通滤波器的系数“复数化”。实数一阶低通滤波器的差分方程是y[n] (1-α)·x[n] α·y[n-1]其中α对应极点位置0α1时极点在实轴上滤波器是稳定的低通。换算成传递函数就是H(z) (1-α)/(1-α·z⁻¹)现在把α换成一个复数a r·e^(jω0)差分方程变成y[n] g·x[n] a·y[n-1]其中g 1 - ra r·(cosω0 j·sinω0)。这里x[n]和y[n]都是复数序列。实际工程里你用定点实现时把这个复数乘法拆成四个实数乘法就行。这个滤波器对正频率ω0附近信号表现接近“低通”特性同时抑制负频率本质上是一个复带通滤波器。2.2 参数算例5MHz中心频率、1MHz带宽我以一个实际的数字中频信号处理项目为例采样率fs 100MHzNCO频率设定在5MHz所以复信号的中心频率是5MHz需要保留的带宽为1MHz。设计复系数一阶低通滤波器数字中心角频率ω0 2π·5MHz/100MHz 0.1π期望的-3dB单边带宽BW 1MHz对应的极点半径由公式r ≈ 1 - BW/(fs/2π)计算简化工程公式r ≈ 1 - π·BW/fs 1 - π/100 ≈ 0.9686取r 0.968则a 0.968·(cos0.1π j·sin0.1π) 0.968·(0.9511 j·0.3090) ≈ 0.9207 j·0.2991系数g 1 - r 0.032。实现时每一拍处理y[n] 0.032·x[n] (0.9207 j·0.2991)·y[n-1]拆成实部虚部就是yr[n] 0.032·xr[n] 0.9207·yr[n-1] - 0.2991·yi[n-1] yi[n] 0.032·xi[n] 0.2991·yr[n-1] 0.9207·yi[n-1]注意这里交叉项0.2991·yi和0.2991·yr它就是实现“旋转”和“非对称频响”的关键。如果你把这两个交叉项去掉整个结构就退化成两个独立的实数滤波器镜像抑制能力立刻垮掉。2.3 多相滤波结构工程上更稳的实现方式单极点的复系数IIR结构简单但滚降特性比较粗糙带外抑制也只有十多dB。如果系统指标要求带外抑制超过40dB我一般会多级级联或者改用多相polyphaseFIR滤波结构。多相复数滤波器的核心思路是用四个实数FIR滤波器或两组实数滤波器组合出复数频响。假设复数低通冲激响应h[n] hr[n] j·hi[n]那么输出yr[n] hr[n]∗xr[n] - hi[n]∗xi[n] yi[n] hr[n]∗xi[n] hi[n]∗xr[n]这就是复数卷积展开工程上用两个交叉FIR滤波器实现。设计时可以先在Matlab中用firpm设计一个复数带通滤波器得到复数系数然后拆成实部和虚部两套实数系数分别加载到两个FIR滤波器里。它的好处是系数是有限长、相位线性可控坏处是资源翻倍、FIR阶数高。对于FPGA实现如果DSP Slice资源充裕我优先选这个方案因为可预测性比IIR强得多。下面这个表是我在实际方案选型时常用的对比结构类型复杂度镜像抑制能力稳定性适用场景复数一阶IIR低中等20~40dB需监视极点半径快速原型、带宽需求不高的锁相环复数多级IIR中较高40~60dB需做级联稳定性分析有一定滚降要求的中频选频Polyphase FIR高高60dB天然稳定对线性相位、镜像抑制要求高的接收链路复系数CIC低低需要补偿稳定抽取率高的宽带信号预滤波3. 复数积分器在正交系统中的落地要点3.1 正交数字下变频里的复数积分器角色数字下变频系统里有几个关键环节NCO产生正交本振、复数混频把中频搬移到基带、然后滤波抽取。你会发现混频器输出的是I/Q两路基带信号后续的载波同步环路里就需要一个复数积分器。最典型的应用是Costas环里的环路滤波器。很多教材把环路滤波器画成一个实数比例器加一个实数积分器这没错但基带信号是复数形式。如果你只对I路做积分会丢相位信息。工程上正确的做法是鉴相器输出误差信号e[n]后环路滤波器中的积分项是对整个复数误差矢量做积分再反馈给NCO控制字。这个复积分器的极点应当设置在某个偏频上以匹配残余频偏。我在一个QAM解调项目中接收信号有约200ppm的晶振频偏换算成基带就是若干kHz。第一版用实数环路积分器锁定后星座图始终有一圈旋转后来把环路积分器的极点从z1改到ze^(j·2π·Δf/fs)旋转问题直接消失。这个改动很小但物理意义完全不同它意味着积分器在“以载波旋转的坐标系”里积分滤掉了剩余的固定频偏。3.2 CIC积分梳状滤波器数字下变频的标配积分器提到复数积分器软件无线电工程师的第一反应多半是CICCascaded Integrator-Comb滤波器。CIC的本质就是一组积分器加一组梳状滤波器用来做高倍抽取。CIC里的积分器都是复数形式因为输入的I/Q数据是复数流。CIC传递函数H(z) [(1 - z^(-DM)) / (1 - z⁻¹)]^N其中D是微分延迟M是抽取因子N是级数。积分器部分就是1/(1-z⁻¹)对应每个通道的累加器。位宽增长是设计CIC时最需要算清楚的一件事。增益上限是 (D·M)^N假设D1, M32, N4则增益最大为 32^4 1048576约2^20。输入数据16bit则积分器内部寄存器至少要36bit否则必然溢出。这个计算务必先做我见过不止一个项目因为位宽不够CIC输出直接乱跳查了半天才发现是积分器累加溢出。实际工程中CIC一般不用来单独完成精细滤波它的作用是提供大的抽取比和简单的结构CIC后级再跟一个复数补偿FIR来修正通带纹波。整个链路上CIC的复数积分器负责把窄带信号做“累加平均”补偿FIR负责整形频响曲线。3.3 锁相环环路滤波器复极点位置要仔细调再单独说复数积分器在锁相环环路滤波器里的应用。环路滤波器的传输函数在s域一般写为F(s) (1sτ2)/(sτ1)对应的积分器极点位于原点。如果把它换成复数积分器把1/s换成1/(s - jωc)那么环路就在ωc处有无限增益可以无差地跟踪该频率。这在航天测控和雷达多普勒跟踪里很常见需要在强多普勒频移下还能锁定信号。工程上需要注意复极点的引入会改变环路的相位裕度。不能简单替换必须重新做开环增益波特图分析。我曾经按经验把环路积分器的极点挪到多普勒频率上结果锁定时间变长了好几倍相位裕度从50°掉到20°左右差点振荡。后来把积分极点的虚部调小同时增加一个超前校正零点才让环路的动态性能和稳态误差同时满足要求。这里给一个参考在数字锁相环里积分极点频率ωc一般不超过环路带宽的1/5否则相位裕度损失太大稳定性和捕获时间都会很头疼。4. FPGA/DSP上的定点化实现与调试记录4.1 从浮点原型到定点的第一步先跑通浮点模型不要一上来就写Verilog。我习惯先用Python或Matlab把复数滤波器和积分器的浮点模型跑通验证系数和系统指标。以前面那个5MHz中心频率、1MHz带宽的例子为例我会先做以下几步生成一个包含信号和镜像干扰的测试序列信号在5MHz镜像干扰在-5MHz信干比0dB。用浮点复系数滤波器滤除镜像测量输出信干比和误差向量幅度EVM。将滤波器系数量化到16bit观察量化带来的镜像抑制恶化。模型通过后再移植到FPGA。为什么不直接跳FPGA因为复系数滤波器一旦系数错了频谱上看到的可能是整个通带偏移很难分清是系数问题还是时序问题。浮点模型可以精确观察每个中间节点的信号帮助建立预期值。后面硬件调试时抓回来的数据可以直接和浮点模型对照这是最快的定位方式。下面的Python伪代码示意了浮点模型的框架import numpy as np from scipy import signal fs 100e6 N 8192 t np.arange(N)/fs fc 5e6 bw 1e6 # 复指数信号 镜像干扰 x np.exp(1j*2*np.pi*fc*t) x x np.exp(-1j*2*np.pi*fc*t) # 镜像 # 归一化角频率 omega0 2*np.pi*fc/fs r 1 - np.pi*bw/fs a r*np.exp(1j*omega0) g 1-r # 复系数一阶低通 y np.zeros(N, dtypecomplex) for n in range(1, N): y[n] g*x[n] a*y[n-1] # 分析频响验证镜像被抑制 freq_resp np.fft.fft(y)实际项目中这个循环会被CORDIC或乘加器替代但验证思路不变。4.2 FPGA定点实现位宽、舍入与稳定性检查FPGA定点化时我一般是这么分配位宽的输入I/Q数据16bit有符号数复系数实部虚部16bit有符号数按Q1.15格式归一化乘法结果32bit累加器36bit预留4bit增长余量以处理瞬态输出根据需要截位到16bit截位时用“先加舍入偏置再截断”不要直接截断系数a的量化尤其要小心。复数IIR滤波器极点半径r直接决定稳定性r必须严格小于1。如果系数是Q1.15格式能表示的最大值约0.99997这通常够用但如果设计得r0.9999量化后可能被舍到1.0滤波器就变成振荡器了。我的经验是极点半径至少留0.001的裕量比如目标r0.968那实际代码里用0.967。你也可以在初始化时监控系数值如果abs(a)0.9999强制饱和。定点实现复数乘法时我强烈建议用DSP Slice的级联结构而不是LUT搭乘法器。Xilinx的DSP48E1一个就能完成18x18乘法复数乘法拆开后需要4个乘法器后续加法可以共用。两路交叉项可以放到同一个DSP Slice的预加器里实现“一次复数乘法用一个DSP48”的优化。很多书里写复数乘法需要4个DSP Slice但利用预加器结构可以压到2~3个省下来的资源留给后级FIR。一个Verilog风格的复系数一阶滤波器核心代码片段如下module complex_iir ( input wire clk, input wire rst_n, input wire signed [15:0] xr, input wire signed [15:0] xi, output reg signed [15:0] yr, output reg signed [15:0] yi ); localparam signed [15:0] a_r 16sd30180; // 0.9207 in Q1.15 localparam signed [15:0] a_i 16sd9800; // 0.2991 in Q1.15 localparam signed [15:0] g 16sd1049; // 0.032 in Q1.15 wire signed [31:0] mult_yr_r, mult_yr_i, mult_yi_r, mult_yi_i; wire signed [31:0] mult_xr_g, mult_xi_g; assign mult_xr_g xr * g; assign mult_xi_g xi * g; assign mult_yr_r yr * a_r; assign mult_yr_i yr * a_i; assign mult_yi_r yi * a_r; assign mult_yi_i yi * a_i; wire signed [31:0] acc_r mult_xr_g mult_yr_r - mult_yi_i; wire signed [31:0] acc_i mult_xi_g mult_yr_i mult_yi_r; always (posedge clk or negedge rst_n) begin if (!rst_n) begin yr 16sd0; yi 16sd0; end else begin yr acc_r[30:15]; // 舍入截位 yi acc_i[30:15]; end end endmodule这里演示的是最直接的写法。实际项目里我一般会用AXI-Stream接口把I/Q打包成64bit总线并在内部用流水线寄存器切分乘法与加法保证时序收敛。4.3 调试案例镜像抑制参数从30dB到60dB说一个印象很深的调试过程。项目是做宽带接收机的镜像抑制指标要求镜像抑制大于55dB。第一版固件用了一个5阶实系数低通分开滤I/Q现场测试只能到30dB左右无论怎么调系数都上不去。当时我判断是镜像信号和有用信号的幅度相位不匹配产生“镜像泄漏”。后来换成复系数IIR滤波器系数按上文公式计算仿真阶段已经显示镜像抑制约58dB。上板后实测却只有45dB左右多了十几个dB的恶化。排查过程分三步第一步抓取滤波器输入的I/Q数据在Matlab里复算一遍浮点输出确认算法逻辑没问题。 第二步检查FPGA内部定点输出和浮点模型之间的误差发现定点量化误差导致的镜像泄漏贡献约2dB不至于恶化到45dB。 第三步怀疑是本振泄漏和直流偏移。测量混频器输出发现I/Q两路存在约5%的幅度不平衡和3°的相位不平衡。这个量级足以解释镜像抑制从58dB掉到45dB。最终在FPGA里增加一个复数系数校准模块用自适应算法估计增益误差和相位误差并补偿实测镜像抑制回到58dB以上。这个项目给我的教训是复数滤波器本身的设计再完美前端I/Q不平衡不消除镜像抑制永远上不去。所以如果你做完复数滤波器后指标不达标别急着改滤波器系数先测前端I/Q的幅度和相位一致性。4.4 常见问题与排查技巧实录关于复数积分器和滤波器的调试我把常见问题和排查顺序整理成了一张表基本按从“系统级”到“代码级”的顺序排列现象可能原因排查方法输出信号中心频率偏移系数a的ω0算错用浮点模型对比检查ω0是否等于2πf/fs镜像抑制明显变差I/Q幅度/相位不平衡用单音校准信号测增益误差和相位误差滤波器输出发散/自激极点半径r1检查系数定点格式确认abs(a)1且有裕量频谱有周期性尖峰累加器溢出或截位方式不对检查位宽增长把直接截断改为带偏置的舍入CIC输出噪声底部抬高CIC级数过高或微分延迟不合理降低N加入补偿滤波器检查D/M取值环路锁定慢或失锁复积分器极点频率过高/过低检查ωc与环路带宽的比值建议小于1/5输出直流偏移严重混频器本振泄漏或ADC直流偏置加直流校准环路或先在时域估算均值并扣除另外一个很实用的小技巧给复数滤波器输入一个幅度为1、频率等于中心频点的复数正弦波观察输出幅度。如果输出幅度稳定在某个值且没有明显波动说明滤波器在该频率点增益正常极点位置正确如果输出出现缓慢的幅度起伏多半是I/Q路处理不同步或者数据位宽截位导致的有效位丢失。这个检查在板级调试时比看频谱图更快更直观。FPGA里调试复数信号还有一个天然优势你可以同时抓取I和Q数据直接在ChipScope或ILA里以李萨如Lissajous图形方式观察圆轨迹。复数信号是圆形的轨迹如果看到椭圆说明幅度不平衡如果圆整体偏移原点说明直流偏置如果圆发散成螺旋形说明滤波器不稳定。这个判断在几秒钟内就能完成比拉频谱图效率高一截。最后分享一点个人体会复数积分器和滤波器这套东西单独看每个公式都不复杂难的是把“复数”这个概念真正落到硬件里。我刚开始做的时候也走过弯路总觉得把I/Q当两路实数信号分开处理就行了结果性能就是上不去。后来想明白一个道理复数不是一个数学玩具它代表的是信号的“相位维度”I路和Q路必须是同一个运算的不同投影拆开处理等于破坏了这个维度。后面再设计正交接收机链路我都先在Matlab里把复数结构完整跑一遍再写定点代码效果好了很多。项目里如果再有类似的选频、跟踪、镜像抑制需求优先考虑用复系数结构会比在实数滤波器里打补丁舒服得多。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价