ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

FPGA基带与中频处理:算法实现、工程取舍与避坑指南

2026/9/6 8:45:17 拓冰建站 浏览量
FPGA基带与中频处理:算法实现、工程取舍与避坑指南 做通信基带或者中频信号处理这一块的工程师大多都有过类似的经历算法仿真跑得漂漂亮亮波形图完美得能当壁纸一旦落到FPGA上各种问题就全冒出来了。不是资源爆了就是时序收敛不了要么就是上板之后频谱里冒出一堆不该有的杂散。这篇文章我想把基带与中频处理里最常见的FPGA算法实现思路、工程设计中的取舍、以及我踩过的一些坑完整地梳理一遍希望能给正在做类似项目或者准备入门这块的朋友一些参考。基带处理和中频处理核心其实是同一件事对数字信号做实时、确定性的数学运算。之所以用FPGA而不是DSP或者CPU原因也很简单——高并行度、低延迟、确定性强。像DDC、DUC、CIC滤波、FIR整形、同步环路、卡尔曼滤波这类算法FPGA都能以流水线的方式高效实现。这篇文章会覆盖从数字中频架构选型、DDC算法拆解、中频检波的几种方法到基带同步与均衡、资源估算与时序收敛再到上板调试的常见坑尽量做到既有原理讲解也有可以直接拿去用的工程参数。适合已经会写Verilog/VHDL、想深入理解信号处理链路实现的同学也适合刚接触FPGA无线通信项目、需要快速搭建方案的工程师。1. 做基带中频处理为什么绕不开FPGA1.1 实时性与并行性的底层逻辑先聊一个最基础的问题基带和中频算法在FPGA里实现的优势到底是什么。说穿了就是两个词实时性和并行性。实时性意味着从数据进入芯片到处理结果输出延迟是确定的、可预测的这在通信协议和控制系统里非常关键。并行性则意味着你可以同时处理几十路通道、上百个乘加操作这对DSP和CPU来说是很吃力的。举个例子一套相控阵接收系统32个通道的中频信号需要同时做数字下变频每个通道还有128阶的抽取滤波。在DSP上你只能按顺序处理一帧数据算下来延迟可能已经到了毫秒级别但在FPGA里你完全可以让每个通道拥有独立的混频器和滤波器资源所有通道并行处理延迟就只有纯逻辑级联的几十纳秒。这就是为什么在雷达、5G基站、卫星通信这类对实时性要求极高的场景里FPGA几乎是不可替代的。1.2 从模拟中频到数字中频的架构演进以前的中频处理是纯模拟的模拟混频器、模拟滤波器、模拟AGC那一堆分立元件调试起来相当痛苦温漂、元件一致性全是问题。现在的新设计基本都走向了数字中频方案也就是让中频信号经ADC采样后直接变成数字量后续的混频、滤波、检波、抽取全部在FPGA内部完成。这里有个关键概念叫带通采样也叫欠采样。它利用的是信号频谱的周期延拓特性让一个几十甚至上百MHz的中频信号用一种比它频率低得多的采样率来完成数字化。工程上常用的中频频率有70MHz、140MHz、70MHz的零中频方案也很多常规做法是选择采样率满足带通采样定理同时让镜像频谱不要落在信号带内。比如一个70MHz中频、10MHz信号带宽的系统采样率定在80MSPS兆采样每秒就是一种常见选择一次采样既完成了数字化又等效完成了一次频谱搬移后面接DDC就更方便了。从系统层面看数字中频方案体积小、一致性好、可编程性强更改载波频率或者带宽往往只需要改寄存器不需要动硬件这是模拟方案完全没法比的。2. 数字下变频DDC的算法拆解与实现2.1 混频与NCO设计镜像频率怎么处理数字下变频是几乎所有中频接收链路的第一级处理结构上就三个模块NCO数控振荡器、混频器、抽取滤波器。NCO产生本振信号混频器把ADC采样的中频信号搬到零频附近后面再接滤波器把带外噪声和镜像频率滤掉。NCO的FPGA实现最常用的就是DDS直接数字频率合成结构。相位累加器每周期累加一个频率控制字查正弦表输出本振波形。这里面有个参数选择的关键点相位累加器的位宽。相位累加器位宽决定了频率分辨率计算公式是Δf fclk / 2^NN是位宽。比如100MHz工作时钟、32位相位累加器频率分辨率大约是0.023Hz这在绝大多数通信场景里都够用了。但是存储正弦表不可能用32位地址一般只截取高14到16位去查表。这就引入了相位截断它会产生杂散。相位截断杂散的抑制能力大约等于6.02×截断位数dB。如果你用16位查表地址理论上SFDR能到96dB但实际因为正弦表量化、时钟抖动等因素会打折扣。工程上还有个常用技巧是加抖动dither在相位截断前叠加一个小随机数可以把离散杂散能量打散为宽带噪声底让SFDR指标更干净。这一点在要求高的项目里非常有用。混频器本身很简单就是乘法器。但要注意数据位宽匹配问题比如ADC是16位输出NCO本振是16位混频后的乘积就是32位后面做抽取滤波时必须考虑怎么截位否则后面的资源会成倍上涨。2.2 抽取滤波器组设计CIC和补偿FIR的搭配逻辑抽取滤波器是DDC里资源消耗的大头。很多工程师一上来就想用FIR滤波器直接实现几十倍的抽取结果发现滤波器阶数高得离谱乘法器资源根本扛不住。正确思路是采用多级滤波器结构最常见的就是CIC滤波器加补偿FIR的组合。CIC滤波器是一种不需要乘法器的滤波器全部由积分器和梳状器组成非常适合做高倍数抽取。它的传递函数增益很大而且带内容差比较大所以后面一定要接一个补偿滤波器来修正频响。CIC滤波器的设计关键参数有三个抽取因子R、差分延迟M、级数N。输出位宽的计算公式是B_out B_in N × ceil(log2(R×M))这里的ceil是向上取整。实际工程中我见过很多人在这个位宽计算上栽过跟头输出位宽算少了直接截位导致信号饱和或者信噪比恶化。补偿FIR的设计思路是让幅频响应在信号带宽内抵消CIC的通带衰减。简单场景下用ISOP滤波器就能凑合但正规项目还是建议用MATLAB的Filter Designer工具或者firls函数设计一个逆CIC响应的FIR。补偿FIR的阶数一般不需要太高几十阶就够了因为它只需要校正通带纹波不需要承担主要的抽取任务。2.3 多级抽取的速率规划实例举个实际例子。假设中频信号经ADC以80MSPS采样信号带宽10MHz期望最终输出数据率是10MSPS那么总抽取因子就是880除以10。如果直接用8倍抽取CIC的旁瓣抑制可能不够补偿FIR阶数也偏高。更合理的做法是分两级第一级CIC抽取4倍把80MSPS降到20MSPS第二级FIR再抽取2倍降到10MSPS同时完成匹配滤波和抗混叠滤波。这样每一级的工作时钟压力都小很多FIR也能用更少的阶数达到指标。数据率规划上有一个原则叫级联抽取的速率匹配每一级的输出速率必须高于该级滤波器通带带宽的两倍以上否则会引入混叠。很多人只盯着最终输出速率忽视了中间级最后频谱里出现莫名其妙的混叠分量溯源排查特别费时间。做这一层设计时建议在仿真阶段就把每级输出的频谱都调出来看一遍确认每一级都没有混叠再往下走。3. 中频检波的几种常见方法与选型3.1 同步检波相干检波的FPGA实现中频检波是从中频信号中提取幅度、相位或者频率信息的过程。同步检波也叫相干检波是性能最好的一种方式但前提是本地必须有一个与输入信号载波同频同相的参考信号。同步检波的数学原理其实就是一个乘法加低通输入信号乘以本地正交本振得到I、Q两路再各自低通滤波。这样幅度信息就是|IjQ|相位信息就是atan(Q/I)非常干净。FPGA里实现同步检波的典型例子里中频信号经过带通采样后进入FPGANCO产生两路正交本振信号经过混频器和低通滤波器就能得到正交解调后的I/Q基带信号。这套结构最大的好处是它同时保留了幅度和相位信息后面不管是做解调、测距还是识别调制方式都有充足的信息可用。同步检波比较挑本振同步。NCO设的载波频率和实际信号中心频率如果有偏差基带I/Q会叠加一个残余频差频谱会展宽甚至翻转。频率偏差小的时候可以用后面的载波同步环路纠正偏差大的话就得靠粗同步先拉回来。3.2 包络检波与正交检波的适用场景包络检波是最传统的方式结构上就是一个二极管加电容数字域里对应的是取绝对值加低通滤波。它不要求本地有相干本振实现非常简单但只能检幅度无法区分正负频率抗噪声能力也差。在FPGA里包络检波适合用在信号检测、自动增益控制AGC、功率估算这类不关注相位信息的场景我经常用这种方法做接收机的快速能量检测。正交检波比同步检波更广义一些它包含通过希尔伯特变换得到解析信号并提取包络谱的方法。希尔伯特变换在FPGA里的实现一般是用希尔伯特FIR滤波器这个滤波器的特点是实部为0、虚部为冲击响应奇对称阶数通常取奇数。正交检波在单边带信号处理和瞬时频率估计里有优势但它需要额外的希尔伯特滤波器资源信号带宽窄时效率较高宽带宽时阶数会很高要权衡着用。同步检波和正交检波的选择最终取决于你是否需要相位信息以及本振参考是否可靠。不需要相位就包络检波需要相位就同步检波需要解析信号再做正交处理这算是选型时的一个基本顺序。3.3 小信号下检波后处理卡尔曼滤波的思路检波出来的幅度或者相位序列往往含有比较大的噪声特别是小信号场景。此时单纯的低通滤波会带来滞后而卡尔曼滤波能在一定模型假设下给出统计最优估计。卡尔曼滤波在FPGA里的实现我见过不少项目把它用在接收信号强度估计和目标跟踪上。卡尔曼滤波的FPGA实现不复杂但有几个工程上的难点。一是矩阵运算的状态维数维数越高资源开销和定点化难度就越大所以实际项目中尽量把状态向量压缩到两维甚至一维。二是一些乘法项包含除法FPGA里除法是很耗资源的通常的做法是用位宽扩展配合移位近似来实现。三是对过程噪声和量测噪声协方差阵的初始化这两个参数直接决定滤波收敛速度和稳态误差需要现场调整。对于幅度检波这种一维问题卡尔曼滤波的运算量其实很小5个状态方程表达式用定点化实现在几百个逻辑单元内就能搞定性能却比一阶低通滤波好不少。4. 基带算法的常用模块与工程化设计的思路4.1 成形滤波与匹配滤波的统一实现基带发送端要加成形滤波接收端要加匹配滤波两者的实现方式在FPGA里高度一致区别只是系数不同。最常见的基带成形是升余弦滤波器和根升余弦滤波器滚降因子α一般在0.22到0.35之间滚降因子越小频谱效率越高但时域拖尾越严重对定时同步的要求也越高。FPGA实现成形滤波器时大部分场景都采用多相结构。比如发射端数据率是10MSPS成形滤波器过采样倍数是4那么滤波器的工作速率就是40MHz。如果直接用一个40MHz的FIR滤波器每个输出周期要算40个乘加资源开销不小。改成多相结构以后等效为输入每周期只对一个子滤波器做10次乘加乘法器用量直接降到原来的四分之一。具体实现时我习惯把多相分解后的子滤波器系数存到ROM里按符号周期轮询读取系数参与运算。这种实现的结构非常规整时序也容易收敛。有一个容易出错的点是系数对称性的使用在设计时如果系数是偶数阶线性相位可以只存一半系数利用对称性减少乘法器。注意量化后的系数可能不再是严格对称的所以工程上要么对称量化要么就别省这一点资源。4.2 位同步与载波同步的环路参数设置基带接收机的同步环是一个非常经典的反馈系统常见的位同步算法是Gardner算法载波同步常用Costas环和判决引导环。FPGA实现同步环时环路的参数设置直接决定收敛速度和稳态抖动这部分往往是一个项目里最花时间调试的环节。数字环路滤波器通常用比例积分结构比例系数和积分系数决定环路带宽和阻尼系数。工程经验是阻尼系数取0.707左右环路带宽要根据实际信噪比和动态要求来折中带宽太窄捕获时间太长跟不上频率变化带宽太宽稳态抖动增大解调误码率会恶化。初调时可以先用仿真工具把环路带宽算出来再换算成FPGA里的定点参数。一个很重要的细节是环路内的位宽管理。环路滤波器和一个普通滤波器不同它含有反馈位宽长期不截位就会一直涨。很多人在仿真里跑得好好的上板后环路失锁或者震荡原因就是环路积分器总线溢出了。我的习惯是给环路滤波器单独做饱和保护在关键节点加限幅宁可让捕获速度稍微慢一点也不能让环路发散。4.3 面向接口场景的FPGA配合从FMC到BISS-C基带与中频处理不仅仅发生在芯片内部还涉及大量与外部器件、接口协议之间的数据交换。这些接口看起来只是数据搬运但时序做不好整个链路就转不动。STM32H743这类MCU与FPGA之间用FMC接口通信是工程里非常常见的组合。FMC总线协议相对简单关键是地址建立时间、数据建立时间和访问周期这几个时序参数的匹配。FPGA侧做FMC从机时建议把异步总线的信号先同步到FPGA的系统时钟域再用双口RAM做跨时钟域缓冲避免亚稳态问题。我踩过的一个坑是FMC的时序参数没按MCU侧最短读写周期去约束结果批量生产时一部分板子偶发读写错误。后面在XDC里把input delay和output delay约束加上问题就消失了。BISS-C是工业编码器常用的双向同步串行协议FPGA做主站时负责向编码器提供时钟并接收编码器返回的位置数据和CRC校验。它的时序基础是MA时钟信号和SLO应答信号之间的相位关系具体参数因编码器而异。做BISS-C的FPGA实现时我用一个小状态机完成请求、接收、CRC校验、寄存器缓存这几个阶段的调度整个设备工作得很稳定。主要注意点是MA时钟的占空比和停止时间要满足编码器手册要求否则偶发通信错误会很难定位。调试这类接口还有一个通用法宝在FPGA内部预留一个在线逻辑分析仪核比如Xilinx的ILA或者Intel的SignalTap把关键控制信号抓出来看时序。相比拿着示波器去点引脚这种数字域调试的效率高一个数量级。4.4 模块化设计与IP复用的经验FPGA里的基带算法链路很长如果写成一个大模块后面维护起来绝对是灾难。我现在的习惯是每一个算法模块独立成工程子模块用AXI-Stream接口或者自定义的valid-ready握手来互联模块之间只通过接口协议通信。模块化设计有三个直接的好处。第一是单独仿真每个模块很方便缺陷定位快第二是同一套DDC模块可以在不同项目间复用稍微改一下参数就能适配不同的中频频率和数据率第三是时序收敛容易做模块内部频率统一模块之间做好跨时钟域处理系统整体时序会干净得多。接口协议里我比较推荐加入valid-ready握手机制。valid表示数据有效ready表示下游可以接收这样一来上下游模块之间速率不匹配的问题就被解耦了。DDC输出数据率、AGC模块、解调环路各自的工作节奏可以独立变化只要握手信号正确就不会丢数据。加一个AXI-Stream总线协议规范里推荐的最低延迟寄存器打拍规则也能有效避免跨模块时序路径过长的问题。5. 资源估算与性能优化FPGA工程里的“账”5.1 乘法器、块RAM和DSP48的使用测算一个经典问题FPGA的乘法器到底够不够。很多项目在方案设计阶段没做资源估算结果综合到一半发现乘法器超了只能推倒重来。FPGA里的DSP48单元就是为乘法累加设计的一块不用白不用但也要精打细算。来看一个简单的资源估算示例。假设一个8通道的接收链路每通道做128阶FIR匹配滤波工作时钟是100MHz数据率是10MSPS。每个通道的FIR采用了全串行结构也就是一个乘法器分时复用128次100MHz下每个符号周期能算10个乘加所以这个FIR需要13个DSP48128除以10向上取整。8个通道就是104个DSP48这还不包括DDC混频器和NCO的资源。如果选用的FPGA只有80个DSP48那这个方案就必须改成多相结构把乘法器复用率进一步拉高或者减少通道数。块RAM的资源估算类似。一个NCO的16位正弦表大概需要128KB一个32K深度的FIFO需要128KB。把每个模块的容量需求列个表和FPGA的BRAM总数做个比较很快就能判断选型是否合理。这块我强烈建议在做原理图、画板子之前就完成否则等板子回来了再发现资源不够改方案的代价极其惨痛。5.2 定点量化与位宽管理的避坑参考FPGA理论上算无限精度但工程上你不可能真的用无限精度成本不允许。定点化的核心就是位宽折中位宽越宽功耗和资源越高信噪比损失越小位宽越窄资源越省但量化噪声会抬高噪声底。ADC采样后的数据位宽一般是14或者16位FIR滤波器内部的乘法结果通常要扩展到32位每经过一级累加都按需截位。信噪比损失是可以计算的。每降低一位位宽理想情况下信噪比损失约6dB。多位处理器里的截位处理应该采用带符号舍入而不是直接截断直接截断会引入直流偏置这在基带处理里往往是无法接受的。我在滤波器输出截位时习惯加上一个随机抖动这叫噪声整形或者加法抖动它能把量化噪声的能量从固定的杂散变成平坦的噪声底对频谱纯度帮助很大。5.3 时序收敛与性能优化手段FPGA做算法处理最怕即使逻辑正确也跑不快。综合频率上不去整个系统的数据率就上不去。时序收敛的核心手段就是流水线和多相结构。流水线的思想是在关键路径上插入寄存器把长组合逻辑拆成多段。比如一个64阶FIR如果所有乘法器的结果一次性累加组合逻辑的延迟会非常长时序一定差改成树形累加每级加法之间都打一拍关键路径变成单级加法器的延迟时序就会好很多。多相结构前面已经说过了它从算法层面降低了对DSP48的需求量兼具降低工作时钟的作用。有的工程师会把多相结构和流水线混为一谈其实是两回事多相是算法分解流水线是物理实现手段。两者经常配合使用效果最好。资源共享也是一个常用的优化方向但要注意代价。多个滤波器分时复用一组乘法器资源能省很多但会让输入数据的处理延迟变长控制逻辑也变复杂。数据率不高、对延迟不敏感的场景可以这么干像雷达信号处理这种对延迟要求极高的场景宁可多用资源也要保住时延。6. 实测排查与常见故障对照表6.1 频谱异常镜像抑制差和杂散偏高的排查DDC出来的频谱如果不干净第一件事就是看NCO的杂散指标。前面提到的相位截断杂散是最大嫌疑。打开在线逻辑分析仪抓NCO的波形直接做FFT看频谱底能快速判断问题是不是出在本振上。如果NCO本身很干净接下来怀疑混频后的截位策略乘法器输出截位不对会引入低频噪声。镜像抑制差是另一个常见问题尤其是零中频接收机里IQ幅度不平衡和相位不平衡会产生镜像信号。FPGA里做镜像校准的思路是输入一个已知的单音信号通过FFT测量镜像分量的幅度和相位计算出IQ失配参数再在链路里加一个补偿矩阵。校准参数可以在上电初始化时自动估算也可以在测试模式下采用外部注入标定业界管这套方法叫IQ校准或者镜像抑制校准。实测下来好的IQ校准算法能把镜像抑制从30dB提升到60dB以上。6.2 失锁和不同步反馈环路的关键检查点同步环路失锁先别急着调参数先把数据抓出来看环路滤波器里的中间变量。正常的失锁通常有两种表现一是误差信号一直不为零说明频率粗同步就有问题NCO初值偏差太大二是误差信号在零附近来回抖动但幅度异常大这往往是环路滤波器的积分通路位宽溢出了。我遇到过一个典型项目GPS接收机的载波环路总是失锁。排查到最后发现NCO的频率控制字在更新的时候采用了异步清空操作导致phase累加器出现了毛刺。改成同步复位并把更新时刻对齐到固定时钟沿之后失锁问题就解决了。这种问题没有太多规律可循主要靠对关键信号的实时观测来判断所以在同步环路里提前预留好观测端口和在线逻辑分析仪核能省掉大量猜测试探的时间。6.3 资源暴涨但频率上不去怎么定位综合之后发现资源用量比预期高好几倍这是新手很容易遇到的情况。一个常见原因是某个常量大数组被综合成了查找表ROM而不是块RAM另一个原因是代码里不小心写出了大面积组合逻辑环综合器为了保护逻辑正确性自动复制了很多资源。频率上不去也一样先用时序报告看关键路径在哪个模块。如果是乘法器到加法器的路径太长就插流水线。如果关键路径出现在跨时钟域的位置应该检查CDC跨时钟域设计是否规范该用异步FIFO的地方绝对不能用双口RAM打拍瞎凑合。时序约束文件也是个高频坑区。XDC约束里如果漏了某个跨时钟域的set_max_delay综合器往往不会报错但最终实际时序可能完全不及格。做工程建议从一开始就给系统时钟、接口时钟都加上明确的约束并开启时序分析的完整检查不要等到上板出问题了再返工。7. 设计与验证平台的选择从仿真到上板7.1 仿真验证中容易被忽略的环节FPGA算法的仿真验证很多团队都有完整流程但有几个环节经常被轻视。第一是定点化模型与浮点模型的对比。浮点模型是黄金参考定点模型跑出来的结果要在每个关键节点和浮点模型做误差统计误差大小不能只凭感觉应该设定一个阈值比如误差不超过信号满幅度的1%超了就说明位宽分配不合理。第二是跨时钟域的验证。纯功能仿真里寄存器亚稳态和异步FIFO空满信号的问题很难模拟很多bug在上板时才暴露。建议在仿真环境中引入异步时钟模型甚至把时钟抖动的随机因素都加上这样能提前暴露多数CDC设计缺陷。第三是极端参数和边界条件的测试。输入信号设为最低信噪比、最大频偏、最大增益波动看同步环能不能锁定AGC会不会过冲。普通场景能过不代表系统能稳边界测试做不足上板调试就会变成体力和心力的双重消耗。7.2 常用FPGA平台与调试回传技巧板级调试的效率和工具链的选择密切相关。Xilinx、Intel、高云等主流FPGA厂商都提供了类似在线逻辑分析仪的工具用起来很方便但我也发现不少项目从设计初期就没把观测端口定下来最后调试时到处加探针重新布局布线后逻辑和时序又变了非常耽误进度。所以设计初期就应该规划好内部测试总线把DDC输出的频谱信息、同步环路的误差信号、AFC控制字这类关键信号全部接到可观测的寄存器上并通过UART、以太网或者PCIe回传到上位机做显示和记录。PCIe接口调试方面如果用Xilinx的XDMA IP做数据回传的路径搭建会快很多BMDBus Master DMA方式在连续传输场景里效率很高。FPGA和上位机之间配合调试效率提升不止一个档次。还有一类接口值得提一下LVDS接收在高速ADC和FPGA之间非常普遍。LVDS的时序约束里最有挑战的是source-synchronous接口需要根据ADC的时钟和数据相对关系设置合适的input delay参数。很多项目在LVDS数据翻转率高的场景下出现偶发错位查到最后都是约束没设对或者没有使用Bitslip对齐机制。7.3 关于FPGA入门到进阶的一条路径内容讲到现在还是要给刚开始接触FPGA基带处理的朋友一点路线参考。入门阶段先用一个小型DDC项目跑通全流程理解NCO、混频、FIR、抽取这四件套的组合方式这里面最核心的不是调用IP核而是理解每一级为什么这么连接、每一级输出的频谱长什么样。第二个阶段可以做一套完整的收发链路加上AGC、同步环路和均衡器体验一下反馈环路和定点化的复杂度。第三个阶段再往高性能方向走比如多通道相控阵处理、多速率信号处理、自适应滤波这些内容看起来高大上但底层还是那些最基础的模块在反复排列组合。实验平台方面入门可以选Xilinx或者高云的性价比开发板信号源方面一个带10MHz左右中频输出能力的信号发生器就够了。如果想省预算直接用FPGA内部产生的DDS信号做自测也是一个常用做法这样链路调试和板卡资源都不依赖外部仪器尤其适合原型验证阶段。这套内容往后还能扩展的方向很多比如把DDC链路升级为同时支持多频段多速率配置的通用射频前端或者在基带处理里加入自适应均衡和干扰抑制再往上还可以和深度学习加速器结合在FPGA上做实时的信道辨识和预测。我个人的体会是基带与中频算法这一块越往深做越能感受到FPGA的能力边界在哪里很多当年觉得“软件跑跑就行”的算法在实时系统里的工程化实现才是真正拉开差距的地方。