基带与中频FPGA算法实现:从DDC到QPSK解调的完整工程指南
2026/9/9 11:23:32 网站建设 项目流程

通信FPGA这个方向,我接触了快十年,从刚毕业那会儿对着Xilinx文档一头雾水,到现在能独立调通一发完整的收发链路,中间踩过的坑比写过的代码还多。今天借“基带与中频的FPGA算法实现与应用”这个题目,把那些真正值得沉淀的东西梳理一遍。这篇文章不是教科书式的原理复述,而是围绕一个核心问题展开:当你拿到一个信号处理任务,该用什么思路在FPGA上把它落地,并且做到资源可控、时序收敛、结果可靠。

1. 先搞清楚基带和中频在FPGA里到底承担什么分工

很多初学者最大的误区是:一上来就翻IP核手册,急着写RTL代码,结果做了几个星期发现连需求都没理解透。实际上基带和中频在FPGA内部是两个性格完全不同的世界,搞清楚它们的分工,后面做算法才谈得上有的放矢。

1.1 中频部分:靠的是确定性的数学运算

中频信号的本质是什么?是带着载波频率的信号,通常在几十MHz到几百MHz这个区间。FPGA在中频段干的事情可以归纳成五类:数字下变频(DDC)、数字上变频(DUC)、滤波抽取、增益控制、以及各种检波处理。

DDC的典型结构是混频器加CIC滤波器加FIR补偿滤波器再加抽取。混频器做的是把中频信号搬到零频附近。CIC滤波器负责大倍数抽取,FIR负责补偿CIC的通带衰减和做精细滤波。这一套下来,中频信号就变成了低速率的基带I/Q数据。

DUC则是反着来:内插、滤波、混频到中频。这里最容易出问题的地方是内插后的镜像抑制。做DUC的时候,如果半带滤波器阶数不够、阻带衰减不足,镜像分量会直接落在带外,后端模拟电路怎么滤都滤不干净。

中频部分的特点是:运算类型非常固定,基本都是乘加、延迟、累加这三板斧。它的难度不在于算法本身,而在于时序和资源。一个128阶的FIR滤波器,工作在250MHz采样率下,如果用纯乘加器实现,资源消耗相当可观;如果用DSP48的时分复用结构,就能把资源降下来。

1.2 基带部分:拼的是算法架构和状态控制

基带信号通常是低速率的I/Q数据,速率可能只有几MHz甚至几百kHz。到了基带,处理的不再是波形层面的数学运算,而是符号层面的解调映射、同步、均衡、编解码。

基带部分的核心难点在于算法逻辑的复杂度上来了:载波同步环里要分频偏估计和相偏跟踪两个阶段的切换;符号同步里的定时误差检测(TED)有多种算法可选——早迟门、Gardner、Mueller&Muller——每种适应的调制方式和滚降系数都不一样;均衡器要决定是上LMS还是RLS,抽头怎么定。

这部分在FPGA里的工作方式和中频完全不同:更多是状态机、查找表、反馈环路、缓存管理这一类的逻辑密集型设计。时序收敛反而相对好做一些,因为速率通常不高,真正考验人的是算法架构设计。

这里给出一个核心建议:中频部分优先考虑用IP核和成熟的DSP微架构,基带部分优先自己设计控制通路和算法流水线。原因后面逐步展开。

2. 中频检波到底有哪几种方法,工程上该怎么选

热搜词里有一个“中频检波有几种方法”,这个关键词值得展开。检波就是从已调中频信号中提取出调制信息的过程。在FPGA工程里,最常用的方法有三大类:峰值/包络检波、同步检波、以及基于数字信号处理的I/Q正交检波。

2.1 包络检波:简单粗暴,但要接受它的局限

包络检波的原理是取中频信号的幅度包络。在FPGA里实现包络检波,常见做法是先求绝对值再用低通滤波器平滑。比如用一个滑动平均窗或者一阶IIR低通,把中频载波频率滤掉,剩下的就是包络线。

代码看起来很简单:

// 一阶IIR低通实现包络提取 always @(posedge clk) begin if (rst) begin envelope <= 0; end else begin envelope <= envelope + (abs_sample - envelope) * alpha; end end

其中alpha是滤波系数,决定包络跟踪的带宽。alpha太大会滤不干净载波分量,alpha太小会导致包络失真。

但包络检波有硬伤:对信噪比要求高,而且对于调相信号(PSK)无效——因为PSK信号的幅度没有变化,包络里根本没有调制信息。所以在实际工程中,包络检波主要用在AM解调、幅度检测和信号存在性判断这类场景,比如AGC的功率测量、通道自检等。

2.2 同步检波:底噪好,但对相位同步有要求

同步检波就是让本地的参考载波与输入信号载波同频同相,然后相乘取基带分量。从频域看,同步检波相当于做了一次频谱搬移。它的优势是信噪比性能好,AM信号同步检波比包络检波有大约3dB的改善,对DSB/SSB信号更是必须用同步检波才能解调。

FPGA里实现同步检波的基本结构是:

// 同步检波核心:混频 + 低通 assign mixer_out = if_in * nco_out; // NCO产生本地载波 // 低通提取基带 filtered_out = fir_filter(mixer_out);

难点在于“同频同相”这四个字。如果收发两端不是锁相的,本地NCO的频率和相位必须靠载波恢复环路来跟踪。常见的载波恢复环路有Costas环和判决反馈环,其中Costas环对BPSK/QPSK特别友好。

2.3 I/Q正交检波:FPGA里的主流方案

真正在FPGA里大量使用的是I/Q正交检波。结构上,输入中频信号分两路,分别和NCO输出的cos/sin相乘,得到I路和Q路,然后各自低通滤波。

为什么说正交检波是FPGA主流?因为它的好处是信息完整。I/Q两路合起来,幅度、相位信息一个不少,无论后面是解调、测向、还是做频谱分析,都能直接处理。而且I/Q方法和各种数字信号处理算法兼容性极好——FFT、数字下变频、均衡器,全都基于I/Q工作。

三种检波方式的对比如下:

检波方式硬件消耗可提取信息适用信号工程难度
包络检波极低幅度AM、ASK最易
同步检波幅度、相位AM、DSB、SSB、PSK
I/Q正交检波较高幅度、相位、频率全类型较难

工程选型时我的建议很直接:除非是极简的幅度检测场景,优先选I/Q正交检波。因为你现在省下的那几个乘加器,将来做算法升级时一定会在时序收敛上加倍还回来。

3. 频域那把尺子:FPGA里的FFT工程化处理

聊到基带和中频算法,绕不开FFT。无论是做频谱监测、信道估计、还是基于频域的滤波,FFT都是底层的基石。Xilinx和Intel都有现成的FFT IP核,但直接用IP核不等于万事大吉,实际工程里的坑一个不少。

3.1 FFT点数、数据格式与时序的联调思路

选FFT点数不是越大越好。点数N越大,频率分辨率越高(fs/N),但处理延迟和资源消耗也线性增长。工程上要优先搞清楚:你要分辨的最小频率间隔是多少,你要处理的最短突发是多少,这两个参数直接决定N。

数据格式是另一个大坑。FFT IP核的输入输出都有多种定点格式可选。定点FFT的问题是字长增长——每一级蝶形运算都会引入舍入误差。如果中间截位策略不对,噪声基底会明显抬升。

我常用的做法是,仿真时先跑一版浮点参考模型,再把具体定点参数代入,对比两者的频谱差异。FFT IP核里通常有配置缩放计划(scaling schedule)的选项,这个必须根据输入信号最大幅度仔细算,否则溢出溢出到怀疑人生。

3.2 并行还是串行,资源与时延的取舍

FFT IP核一般提供四种架构选择:流水线流式、基4突发、基2突发、以及轻量级流式。它们的对比如下:

架构资源消耗处理时延适用场景
流水线流式连续数据流、实时性高
基4突发突发数据、中等实时性
基2突发非实时、资源受限
轻量级流式最低极低速率、极小面积

在很多窄带接收机里,数据是突发到达的,两帧之间有明显空闲,这时候用基4突发就够用,省出来的资源可以让给后端的解调逻辑。在宽带实时处理场景里,数据一直不断流,那就老老实实上流水线流式。工程选型的核心逻辑不是选择最强架构,而是选择刚好合适的架构。

3.3 FFT之后那些容易被忽略的收尾工作

FFT输出的是复数频谱数据,很多人拿到幅度谱就完事了。但真实工程里,后面还有谱峰搜索、去镜像、加窗补偿、以及fft leakage处理这些事。

  • 窗口补偿:如果加了汉明窗或者海宁窗,那幅度谱的峰值会偏低,需要乘以窗口系数的倒数。
  • 谱峰搜索:如果要做频率估计,不能只取最大值那个频点,更好用抛物线插值或者chirp-z变换在峰值附近做细化。
  • 去镜像:实数信号的FFT结果正负频对称,有些应用只需要一半的谱线,处理的时候可以省掉一半的运算。

有一次做宽带频谱监测,我用1024点FFT加Blackman窗,刚出来峰值偏了差不多1dB。排查半天才意识到是窗口增益补偿没做。这是非常基础但极容易忘的细节。

4. 把算法放到可综合的层面去思考

FPGA算法和PC上跑算法最大的区别是什么?PC上是顺序执行的,指令一条条过;FPGA里是并发的,所有模块一起动。这个根本差异决定了设计思路必须不一样。从算法公式到可综合RTL,中间有一层很重要的思维转换,简单说是三个关键词:流水线、定点化、复用。

4.1 乘法器资源是硬约束,要学会“省着花”

FPGA里最值钱的运算资源是DSP48,也就是内嵌的硬乘加单元。一片中端型号的FPGA通常有几百到上千个DSP48,听上去不少,但用起来极快。一个复数乘法器要4个DSP48,一个32阶复数FIR要32个DSP48,做两路就翻倍,三下两下资源就紧张了。

控制DSP48消耗的几个招数:

  • 乘法器复用:通过时分复用,用4个DSP48在一个时钟周期内分时完成两个乘法,代价是吞吐减半。如果速率有余量,这是非常划算的交换。
  • 转置结构FIR:相比直接型FIR,转置结构在滤波器抽头多时能够更好地利用DSP48的级联特性,减少逻辑延迟。
  • CORDIC替代乘法器:做三角函数、极坐标转换这些运算时,CORDIC算法只用移位和加减法,不消耗DSP48,特别适合DSP吃紧的设计。
  • 查找表换资源:如果是固定的常数乘法,比如某个固定的混频系数,完全可以提前算好放成查找表,用BRAM实现。

4.2 从浮点到定点:误差和位宽的拔河

算法验证阶段大家用MATLAB或C浮点模型,精度美得很。但到了FPGA里,浮点运算要么消耗巨量资源(做浮点IP核),要么根本跑不到目标频率。所以绝大多数基带处理都走定点路线。

定点的核心问题是位宽规划。位宽太小导致量化噪声大、甚至溢出;位宽太大导致面积暴涨、时序恶化。一般的做法是,先跑数据,统计出各级信号的动态范围,再逐级确定位宽。这个过程叫字长优化,说法比较学术,实际做起来就是从输入到输出逐级仿真,观察各级信号的峰值和噪声底。

一个实用的原则是,对于通信接收链路,从天线到解调输出,整体增益和每级位宽要统一规划,中频之前的数字增益保证信号到达解调器时幅度不过低也不溢出。

定点化信号幂次不重要,重要的是信噪比。在做定点仿真时盯着EVM(误差矢量幅度)或者SNR变化,比盯着瞬时波形更有意义。

4.3 时序收敛的常规检查和优化顺序

写完RTL,跑综合布线,时序报红,这是FPGA工程师最熟悉的日常。“时钟频率上不去”这个问题的排查顺序值得理理清楚,因为很多人一上来就乱调。

第一步查代码风格:有没有在同一个always块里做太长的组合逻辑链?有没有把异步信号直接打进同步逻辑?有没有在时钟域边界忘记做同步处理?

第二步查关键路径:打开时序报告,找到最差路径,看它从哪个寄存器到哪个寄存器,路径延迟主要消耗在组合逻辑还是走线。如果是组合逻辑过长,就拆流水线,在中间多插几级寄存器。

第三步查布局布线:频繁报红的模块可能是布局太分散,尝试在综合时加入模块级约束或者pblock,让相关逻辑靠得更近。

第四步查综合选项:retiming、register duplication这些综合选项有时能带来立竿见影的效果,但也会导致网表难读,一般等代码优化失效时才用。

5. 从算法到系统:一次中频接收机的完整链路

前面把各个模块单独展开讲了,这一节串起来看一个完整的中频接收机是什么样的。这个案例是通用窄带接收机的中频+基带处理链路,涵盖一个很典型的需求:10MHz中频输入、200kHz信号带宽、QPSK解调。

5.1 链路级设计和高层指标拆解

链路结构从输入到输出依次是:ADC接口 → 数字混频(NCO+混频器) → CIC抽取滤波 → FIR补偿滤波 → AGC → 载波同步(Costas环) → 符号同步(Gardner环) → QPSK解映射 → 输出比特流。

在设计之前先把核心指标定下来:

指标参数
ADC采样率80MSPS
中频频率10MHz
信号带宽200kHz
抽取倍数40
输出符号速率100ksps
调制方式QPSK

这个实例里,在混频后,先是CIC抽取倍数20,再是FIR抽取倍数2,级联总共40。CIC负责大倍数抽取,FIR做补偿和精细滤波。符号速率和采样率差800倍,正好由抽取链路来消化。

指标拆好后,逐级参数的规划又回到前面几节讲的那些:位宽、资源、时钟域、控制时序。这个整体思路有了,具体干活的时候路就顺得多。

5.2 完整链路中的几个控制要点

实际跑链路时,有一个点要特别提醒:AQ借位问题和环路稳定时间

CIC抽取滤波器有一个著名的特性是寄存器位宽必须按公式严格计算,否则会溢出。CIC的输出位宽公式为:

[ B_{out} = B_{in} + \lceil N \cdot \log_2(M\cdot R) \rceil ]

其中N是级数,M是微分延迟,R是抽取倍数。比如输入16bit、4级CIC、抽取20倍、微分延迟1,那么输出位宽至少要是 (16 + \lceil 4 \times \log_2(20) \rceil = 16 + 18 = 34) bit。很多人在这一步喜欢赌一把,结果就是信号突变时溢出造成误码。

AGC在启动阶段也值得留心。首发AGC和跟踪AGC是不同的工作模式。启动时,AGC需要快速收敛,把增益拉到一个合理范围;跟踪时,增益微调要慢,避免把信号的调制信息给吞掉。这个慢快节奏如果没控制好,接收机的误码性能会很难看。

Costas环的环路带宽和环路滤波器参数也需要按照阻尼系数设计,一般选阻尼系数0.707,环路噪声带宽选取信号带宽的10%以内。环路带宽太宽,相位噪声大;带宽太窄,捕获时间太长。具体值用仿真迭代比用理论硬算来得更快。

5.3 实测中的效果与调优经验

这版链路在Xilinx 7系列上跑,资源占用大概是:DSP48用了不到40%,BRAM用了30%左右,LUT用了50%左右。QPSK解调的EVM在信噪比20dB环境下大概做到3%以内,误码率表现符合理论预期。

调优过程中印象最深刻的两个地方:

第一个是CIC补偿滤波器的设计。直接用MATLAB的fdatool设计了一个通带补偿滤波器,但因为CIC的幅度响应是 (\text{sinc}) 形状的,补偿滤波器要用 (\text{sinc}) 函数的倒数来逼近。一开始设计阶数不够,通带边缘补偿不足,星图边缘发糊,后来增加阶数才好。

第二个是Gardner定时恢复环路的插值器,用的是线性插值,性能只能说勉强能用。后来换成立方插值器(Farrow结构),星图的聚类明显好了一个档次,代价是多用了几个乘法器——非常划算。

6. 工具链和调试验证,从仿真到上板之后

算法写得再漂亮,仿真跑得再完美,最后还是要落到板子上接受真实信号的检验。这个阶段遇到的问题,往往是仿真环境里根本不会出现的。

6.1 仿真验证:从MATLAB模型到RTL的背靠背比对

工程上最稳妥的验证流程是:

第一步,用MATLAB或Python搭建浮点模型,确认算法本身的正确性; 第二步,搭建定点模型,确认量化误差在接收指标范围内; 第三步,写RTL,用同样的测试向量把RTL仿真结果和定点模型结果一一对比。

这个流程里的关键点在于:测试向量必须是真实场景的,不是随便给一段正弦波就完事。要拿一段真实采集的中频信号来做仿真,并且要做信噪比扫描,保证不同信噪比下行为都符合预期。

6.2 在线调试三板斧:ILA、VIO、还有逻辑分析仪

板级调试时,ILA(集成逻辑分析仪)是我用得最多的工具。抓数据有个技巧:不要把ILA插到所有信号上,那样不仅布线困难,而且数据量太大没法看。正确做法是,先在关键位置抓一小段数据,确认基本走向没问题,再逐级往后查。

VIO(虚拟输入输出)则是调整参数的利器。环路带宽、AGC增益、导频相位这些,都可以通过VIO实时改,不用频繁重新编译。比起每调一次参数就重跑一遍综合布线,这能省下大把时间。

值得一提的是,当算法逻辑出问题时,不要急着怀疑FPGA逻辑本身,先用示波器和频谱仪确认ADC输入的信号没有问题。我遇到过几次,忙了半天,最后发现是同轴线没接稳。

6.3 高速接口容易忽略的坑:LVDS和同步

现在ADC和DAC大多走LVDS或者JESD204B接口。JESD204B这种高速串行接口的调通本身就是一个大工程,要关注时钟同步和确定性延迟。相比之下,LVDS接口简单一些,但也要注意源同步时钟的约束和训练序列的对齐逻辑。

很多中频算法的功能正确性最终取决于接口数据的对齐正确性。我在内联ADC接口时,最常犯的错误就是bit顺序没对齐,导致后面的频谱全乱了。所以拿到新板子的第一件事,一定是先跑一个已知信号的接口测试,确认数据落位正确,再做算法调试。

7. 给入门和进阶者的一些实在话

文章写到这儿,该聊的硬核内容基本都聊了。最后说几句这几年工作下来沉淀的体会,也许对正在这条路上的读者更有参考价值。

7.1 入门路线:从工程角度切入比从理论角度高效

很多朋友一上来抱着《数字信号处理》和《通信原理》啃,试图先把数学吃透再动手。这个路径不能说错,但效率确实不高。更好的切入方式是:先搭一个能跑通的简单链路,比如用开发板做一个DDS信号源加一个数字下变频,在这个过程中理解每个模块的输入输出是什么,再去回头看书上的公式,那些公式一下就活了。

基础工具方面,建议优先把Vivado/Quartus、MATLAB/Simulink、以及Python的numpy/scipy用熟。这三样几乎覆盖了从算法到实现的全流程。学习顺序上,建议先掌握Verilog/VHDL和基础时序约束,再逐步深入DSP算法实现。很多调试技巧,是在实际调试中自动积累的。

7.2 进阶路线:哪类项目积累的经验最有含金量

在我的经验里,扎实做完完整收发链路带来的成长远大于断断续续做各种零散模块。因为完整链路会让你面对很多模块级联才有的问题——增益规划、时钟同步、控制时序、定点误差传播,这些都是面试和实际项目中区分深度的重要话题。

如果条件允许,选一个带真实ADC/DAC的项目从头到尾调一遍,收获比做十个仿真项目都大。通信方向的读者可以从通用SDR平台入手,图像方向的读者可以从MIPI接口的图像采集处理入手,逻辑框架是相通的。

7.3 遇到问题时的排查思路比代码本身更重要

写代码是最容易的部分,调试才是最见功力的。工程里遇到诡异问题,先问三个问题:时钟对不对?复位释放时机对不对?数据位宽和数据顺序对不对?这三个问题排查干净,能解决掉九成以上的表面问题。

剩下那不到一成的深层问题,往往才是真正让人成长的。碰到这类问题时,把仿真波形、在线抓的信号、以及MATLAB重跑的结果三者放在一起对比,通常能找到线索。这条“三源对比”的排查思路,在多次实战里帮我节约了大量时间。

FPGA上的基带与中频算法实现,前期是数学、中期是工程、后期是经验。这篇内容没有覆盖所有细节,但把最核心的思路和最常见的坑都点到了。希望大家都能在调试通过的那一刻,觉得之前的折腾值得。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询