news 2026/9/29 20:57:38

中频采样与数字下变频:FPGA实现带通采样及抽取滤波链路设计

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
中频采样与数字下变频:FPGA实现带通采样及抽取滤波链路设计

1. 从射频到基带:中频采样到底在解决什么问题

搞过软件无线电或者雷达接收链路的人,大概率都绕不开一个经典架构选择:射频信号下来之后,到底是在射频直接采样,还是先搬到中频再采样?这个问题我在不同项目里反复遇到过,每次选型都得重新算一遍账。中频采样与数字下变频这套组合拳,本质上解决的是一个很朴素的矛盾——ADC的采样率上限和信号带宽需求之间的冲突。

先说背景。按照奈奎斯特采样定理,要无失真地恢复一个信号,采样率至少得是信号最高频率的两倍。假设你有一个中心频率2.4GHz、带宽20MHz的射频信号,如果直接对这个射频信号采样,理论上采样率得超过4.8GHz。这个量级的ADC不仅贵得离谱,功耗和散热也是灾难。但如果你先把射频信号通过模拟混频搬到一个较低的中频,比如70MHz或者140MHz,这时候信号的中心频率降下来了,带宽还是20MHz,你只需要一个采样率略高于140MHz的ADC就能搞定。这就是中频采样存在的第一个理由:用模拟混频换取ADC采样率的降低。

但中频采样还有第二个更精妙的地方,叫做带通采样。这个概念很多人第一次接触会觉得反直觉。假设中频信号中心频率70MHz,带宽20MHz,信号实际占据的频谱范围是60MHz到80MHz。按照低通采样的思路,采样率得大于160MHz。但带通采样定理告诉我们,只要采样率满足特定条件,用远低于信号最高频率的采样率也能无混叠地采到这个带通信号。具体来说,如果信号带宽为B,中心频率为f0,采样率fs满足2B ≤ fs ≤ 2f0/(m)这样的关系(m取满足条件的整数),就能实现频谱搬移式的采样。比如上面这个例子,选fs=50MHz,信号会被搬到12.5MHz附近,依然完整保留20MHz带宽的信息。

这里有个关键点容易被忽略:带通采样不是没有代价的。采样之后信号的频谱会以fs为周期进行延拓,如果参数选得不好,延拓出来的频谱副本会和原始频谱重叠,产生混叠。所以选采样率的时候必须画频谱图验证,不能拍脑袋。我一般会先在纸上把信号频谱、采样频率、各次谐波的位置都标出来,确认没有重叠再往下走。

那数字下变频又是在干什么?ADC采样之后,你拿到的是一个实信号序列,频谱关于零频对称,正负频率各有一半。但通信或者雷达处理真正关心的是基带复信号,也就是I/Q两路。数字下变频的核心任务就是把中频上的带通信号搬到零频附近,同时产生正交的I/Q两路,并且通过抽取滤波把采样率降下来,减轻后续处理压力。整个过程用数字方式实现,避免了模拟混频器的本振泄漏、I/Q不平衡等一堆麻烦事。

所以这套架构的完整链路是:射频信号 → 模拟混频搬到中频 → ADC带通采样 → 数字下变频(混频+抽取+滤波)→ 基带I/Q信号 → 后续解调或脉压处理。每一步都有它的道理,缺一不可。适合阅读这篇内容的人,应该是对FPGA信号处理有一定了解、正在做接收机链路设计、或者想搞清楚软件无线电底层原理的工程师。如果你之前只是调用过现成的IP核,没自己算过参数、没踩过混叠的坑,那接下来的内容应该能帮你把这条链路真正吃透。

2. 带通采样的参数计算:别让混叠毁掉你的链路

2.1 采样率选择的约束条件推导

带通采样的采样率选择不是随便挑一个大于两倍带宽的数就行。我见过太多人在这里翻车,包括我自己早期做的一个项目,当时选了个自认为很安全的采样率,结果频谱搬移之后发现边带刚好压在一起,信噪比直接掉了十几个dB。后来老老实实把公式推了一遍才搞明白问题出在哪。

带通采样定理的完整表述是这样的:对于一个带宽为B、最高频率为fH的带通信号,如果采样率fs满足:

  • fs ≥ 2B(保证带宽信息不丢失)
  • 存在整数m,使得 2fH/m ≤ fs ≤ 2fL/(m-1)

其中fL是信号最低频率,fH是最高频率,m取满足条件的正整数。这个公式看起来有点绕,但实际操作的时候可以换个思路:先确定你希望信号被搬到哪个频率位置,然后反推采样率。

举个实际例子。假设中频信号中心频率140MHz,带宽20MHz,所以fL=130MHz,fH=150MHz。我想让采样后的信号落在20MHz到40MHz这个区间(中心30MHz),那么采样率应该选多少?信号搬移后的中心频率f_if和原始中心频率f0、采样率fs的关系是:f_if = |f0 - k·fs|,其中k是某个整数。代入f0=140MHz,f_if=30MHz,如果k=1,则fs=110MHz;如果k=2,则fs=55MHz。验证一下55MHz是否满足带通采样条件:2B=40MHz ≤ 55MHz,且2fH/m ≤ fs ≤ 2fL/(m-1),取m=5,2×150/5=60,2×130/4=65,60 ≤ 55不成立。取m=6,2×150/6=50,2×130/5=52,50 ≤ 55 ≤ 52不成立。所以55MHz不行。再试110MHz:m=2时,2×150/2=150,2×130/1=130,130 ≤ 110不成立。m=3时,2×150/3=100,2×130/2=130,100 ≤ 110 ≤ 130成立。所以110MHz是可行的。

这个计算过程看起来繁琐,但实际做几次就有感觉了。我通常会在Excel里拉一个表,把可能的m值和对应的采样率范围都列出来,然后从中挑一个和ADC器件支持的采样率最接近的值。

2.2 采样后频谱搬移的直观理解

很多人对带通采样的频谱搬移感到困惑,觉得信号怎么就从140MHz跑到30MHz去了。其实用一句话就能解释清楚:采样就是在频域上把原始频谱以fs为周期进行复制粘贴。原始信号在140MHz附近,采样之后,它的频谱副本会出现在140±n·fs的位置上。你只需要找到其中一个落在低频区域的副本,那就是你想要的。

还是用上面的例子,fs=110MHz,原始信号在130到150MHz。采样后频谱副本出现在:

  • 130-110=20MHz 到 150-110=40MHz(这就是我们要的)
  • 130+110=240MHz 到 150+110=260MHz
  • 130-220=-90MHz 到 150-220=-70MHz(负频率,对应正频率的镜像)

可以看到,20到40MHz这个副本完整保留了20MHz的带宽信息,而且和别的副本没有重叠。这就是带通采样的精髓:用低采样率把高频信号"折叠"到低频,同时保证折叠后的频谱不重叠。

但这里有个坑:如果信号本身不是理想的带通信号,比如带外有噪声或者杂散,这些成分也会被折叠进来。所以中频滤波器的作用非常关键,必须在ADC之前把带外成分滤干净。我一般会在中频放大器后面加一个声表滤波器或者LC带通滤波器,把带外抑制做到40dB以上,这样折叠进来的噪声才不会影响灵敏度。

2.3 采样时钟抖动对信噪比的影响

选好了采样率,接下来要关注的是采样时钟的质量。ADC的信噪比不仅取决于量化位数,还和采样时钟的抖动密切相关。时钟抖动会导致采样时刻偏离理想位置,对于高频信号来说,这个偏差会被放大。

具体的关系可以用这个公式估算:SNR_jitter = -20·log10(2π·f·σ_t),其中f是信号频率,σ_t是时钟抖动的RMS值。假设你的中频信号在140MHz,时钟抖动是1ps RMS,那么SNR_jitter = -20·log10(2π×140e6×1e-12) ≈ -20·log10(8.8e-4) ≈ 61dB。如果你用的是12位ADC,理论SNR大约是74dB,但时钟抖动把实际SNR限制到了61dB。如果时钟抖动恶化到10ps,SNR直接掉到41dB,12位ADC就浪费了。

所以选中频采样方案的时候,时钟源的选择和PCB布局的走线质量必须重视。我一般会选相位噪声指标好的晶振或者时钟芯片,比如-150dBc/Hz@10kHz偏移这种级别的。PCB上时钟走线要远离数字信号线,尽量走差分,包地处理。这些细节看起来不起眼,但实测的时候差别很大。

3. 数字下变频的FPGA实现:从混频到抽取的完整链路

3.1 数字混频:把中频信号搬到零频

ADC采样之后,你拿到的是实信号序列,假设采样率110MHz,信号中心在30MHz。数字下变频的第一步是混频,也就是把这个30MHz的信号搬到零频。做法很简单:把ADC数据分别乘以cos(2π·30e6·n/110e6)和-sin(2π·30e6·n/110e6),得到I路和Q路。

在FPGA里实现这个乘法,通常用查找表或者CORDIC算法生成正余弦值。查找表的做法是把一个周期的正余弦波形量化成N个点存到ROM里,然后用一个相位累加器控制读取地址。相位累加器的位宽决定了频率分辨率,比如32位累加器,时钟110MHz,频率分辨率就是110e6/2^32 ≈ 0.0256Hz,完全够用。

这里有个实际的问题:NCO(数控振荡器)的输出频率必须和ADC采样率相干,否则混频之后会有残余的频率偏差。所谓相干,就是NCO频率和采样率之比是有理数,而且最好能整除。比如采样率110MHz,NCO频率30MHz,110/30=11/3,不是整数比,但相位累加器每3个采样点走11个周期,还是能保证相位连续。如果NCO频率是27.5MHz,110/27.5=4,正好整除,相位累加器每4个点走一个完整周期,实现起来更简单。

混频之后的信号是复数形式,I路和Q路各一路。这时候信号的频谱已经从30MHz搬到了零频附近,正频率部分在0到10MHz,负频率部分在-10到0MHz。但注意,由于输入是实信号,I路和Q路是相关的,不是独立的。真正要得到独立的I/Q,还需要后面的低通滤波和抽取。

3.2 抽取滤波:降采样率同时保留有用信号

混频之后,信号带宽还是20MHz,但采样率还是110MHz,数据率太高,后续处理吃不消。这时候需要抽取,也就是每隔M个点取一个,把采样率降到110/M MHz。但直接抽取会出问题:如果抽取后的采样率不满足奈奎斯特条件,信号会混叠。所以在抽取之前必须先低通滤波,把信号带宽限制到新的奈奎斯特频率以内。

假设我要把采样率降到27.5MHz,抽取因子M=4。新的奈奎斯特频率是13.75MHz,而信号带宽是20MHz(从-10到10MHz),超过了13.75MHz。所以不能直接抽4倍,得先滤波把带宽限制到13.75MHz以内。但这样会损失信号带宽,不行。那怎么办?答案是用多级抽取,先滤掉一部分,抽一次,再滤再抽。

实际工程中常用的结构是CIC滤波器加半带滤波器再加FIR滤波器。CIC滤波器适合大倍数抽取,不需要乘法器,但通带不平坦,需要后级补偿。半带滤波器系数对称,有一半是零,乘法器用量少,适合2倍抽取。FIR滤波器可以做成任意响应,但资源消耗大,一般放在最后一级做精细整形。

我做过的一个项目中,采样率110MHz,信号带宽20MHz,目标是把采样率降到27.5MHz。方案是:第一级CIC抽取2倍,采样率降到55MHz;第二级半带滤波器抽取2倍,降到27.5MHz。CIC的通带衰减在10MHz处大约是0.5dB,半带滤波器在10MHz处也有约0.5dB衰减,加起来1dB左右,可以接受。如果对通带平坦度要求更高,可以在最后加一个小的补偿FIR。

3.3 多相滤波结构:资源优化的关键技巧

抽取滤波器的直接实现有个问题:如果先滤波再抽取,滤波器在每个采样点都要算一遍,但抽取之后只保留M个点中的一个,意味着M-1个点的计算被浪费了。多相滤波结构就是来解决这个问题的。

多相滤波的思路是把滤波器的系数按照抽取因子M分成M组,每组系数对应一个相位。输入数据也按照M的节奏分配给不同的相位分支,每个分支只计算自己那一路的卷积,最后把M个分支的输出按顺序拼接起来。这样计算量降到了原来的1/M,资源消耗大幅降低。

具体实现的时候,假设滤波器有N个抽头,抽取因子M,那么每个多相分支有N/M个抽头。输入数据以M为周期轮流进入各个分支,每个分支的输出就是该分支系数和对应输入数据的卷积。最后用一个M选一的并串转换把各路输出合成一路。

这个结构在FPGA里实现起来很自然,因为FPGA本来就擅长并行处理。我一般会用移位寄存器组来缓存输入数据,然后用M个并行的乘加单元同时计算各分支的输出。如果资源紧张,也可以只用一个乘加单元分时复用,但那样时钟频率得跑得更高。

4. 实测中容易踩的坑与排查思路

4.1 频谱出现镜像:I/Q不平衡的排查

数字下变频之后,理想情况下正频率和负频率应该完全分开,频谱上只看到一边。但实际调试的时候,经常会在另一边看到一个镜像分量,幅度可能只比主信号低20到30dB。这个镜像就是I/Q不平衡造成的。

I/Q不平衡的来源有几个:一是NCO产生的正余弦幅度不一致,二是I路和Q路的滤波器系数有差异,三是混频之后的增益不一致。排查的时候可以逐级看:先在混频输出接一个频谱仪(或者用FPGA的ILA抓数据做FFT),看I路和Q路的幅度是否一致;然后看滤波器的频率响应是否对称;最后看NCO的查找表精度是否够。

解决I/Q不平衡的办法,最直接的是提高NCO查找表的精度和滤波器的对称性。如果硬件已经定了,也可以在数字域做校正,比如用一个复数滤波器来补偿幅度和相位误差。我一般会在设计阶段就把NCO的查找表做到16位以上,滤波器系数用对称结构,这样镜像抑制能做到50dB以上。

4.2 输出频谱出现杂散:时钟泄漏与量化噪声

另一个常见问题是输出频谱上有莫名其妙的杂散。有一次我调一个链路,发现输出在某个特定频率上总有一个小尖峰,换了采样率就消失,换回来又出现。后来查了半天,发现是采样时钟的谐波和NCO频率混频产生的。

这种杂散的根源是时钟泄漏。ADC的采样时钟会通过电源或者地平面耦合到模拟输入端,和信号一起被采样。如果时钟频率的某个谐波刚好落在信号带内,就会产生固定的杂散。解决办法一是改善时钟的屏蔽和滤波,二是在数字域用陷波器把已知的杂散频率滤掉。

量化噪声也是杂散的来源之一。ADC的量化误差不是白噪声,而是和输入信号相关的确定性误差,会产生谐波失真。如果输入信号幅度太接近满量程,谐波失真会恶化。我一般会把输入信号幅度控制在满量程的-6dB到-12dB之间,留足够的余量。

4.3 抽取滤波器通带边缘衰减过大

抽取滤波器的通带边缘衰减是个容易被忽视的问题。CIC滤波器的频率响应是sinc函数,在通带边缘衰减很明显。如果信号带宽刚好到通带边缘,衰减可能达到3dB甚至更多,导致信号幅度不一致。

解决这个问题有两个思路:一是让滤波器的通带比信号带宽宽一些,比如信号带宽20MHz,滤波器通带做到25MHz,这样20MHz处的衰减就很小了;二是加补偿滤波器,把CIC的sinc衰减补回来。补偿滤波器的系数可以用MATLAB的firls函数设计,让它的频率响应和CIC的衰减相反。

我一般会先用MATLAB把整个抽取链路的频率响应仿真一遍,看看通带波动和阻带衰减是否满足要求。如果通带波动超过0.5dB,就加补偿;如果阻带衰减不够,就增加滤波器阶数或者换更高级的滤波器结构。

5. 从仿真到上板:我的调试流程与经验

5.1 MATLAB仿真:先把算法跑通再写RTL

我见过不少人直接上手写Verilog,结果调了半天发现算法本身就有问题。我的习惯是先在MATLAB里把整个链路仿真一遍,包括信号生成、带通采样、数字混频、抽取滤波,最后看频谱和星座图是否正常。MATLAB仿真的好处是可以快速试错,改个参数几秒钟就能看到结果,比在FPGA里改代码再综合快得多。

仿真的时候要注意几点:一是采样率要设成和实际一致,二是要加入噪声和时钟抖动模型,三是要用定点数仿真而不是浮点数,因为FPGA里是定点运算。定点数的位宽选择很关键,位宽不够会导致量化噪声大,位宽太大浪费资源。我一般会先用浮点仿真确认算法正确,然后逐步降低位宽,看性能恶化到什么程度,找到一个平衡点。

5.2 FPGA上板调试:ILA抓数据做FFT

算法仿真通过之后,接下来是写RTL、综合、上板。上板之后第一件事是用ILA抓ADC的原始数据,做一次FFT看看频谱对不对。如果频谱和MATLAB仿真不一致,那说明ADC配置或者时钟有问题。确认ADC数据正确之后,再逐级抓混频输出、滤波输出,看每一级的频谱是否符合预期。

ILA抓数据的深度有限,一般只能抓几千个点,做FFT的频率分辨率不够高。如果需要更精细的频谱分析,可以把数据通过UART或者以太网传到上位机,用MATLAB或者Python做离线分析。我一般会在FPGA里加一个数据缓存模块,把需要分析的数据存到RAM里,然后慢慢往外传。

5.3 资源与时序的平衡

数字下变频链路在FPGA里占的资源不少,尤其是FIR滤波器,乘法器用量很大。如果FPGA资源紧张,可以考虑几个优化方向:一是用时分复用的方式共享乘法器,二是用CSD编码或者分布式算法减少乘法器数量,三是降低滤波器阶数或者用更高效的滤波器结构。

时序方面,高速采样率下(比如110MHz以上),乘加运算的流水线设计很关键。我一般会把乘法和加法分成多级流水,确保每级之间的逻辑延迟不超过时钟周期。如果时序不满足,可以插入额外的寄存器,但会增加延迟。延迟增加会影响整个链路的实时性,需要权衡。

6. 几个值得关注的扩展方向

6.1 多通道幅相一致性校准

如果你做的是相控阵或者多通道接收机,数字下变频之后还需要关注各通道之间的幅相一致性。不同通道的ADC、混频器、滤波器不可能完全一致,会导致波束形成的时候旁瓣升高。校准的方法是在每个通道注入一个已知的参考信号,测量各通道的幅度和相位差异,然后在数字域补偿。

6.2 自适应滤波在数字下变频中的应用

如果干扰信号很强而且频率会变化,固定系数的滤波器就不够用了。这时候可以用自适应滤波,比如LMS算法,让滤波器系数根据输入信号自动调整,把干扰抑制掉。自适应滤波的计算量比固定滤波大不少,但在FPGA里用并行结构实现也是可行的。

6.3 高采样率下的JESD204B接口

当采样率超过200MHz的时候,传统的并行LVDS接口走线太多,PCB布局困难。JESD204B接口用高速串行链路传输ADC数据,线数少,同步机制完善,适合高采样率多通道的应用。但JESD204B的调试比LVDS复杂,需要配置链路参数、做同步测试,上手门槛高一些。

我在实际项目里用JESD204B的时候,最头疼的是链路同步问题。有时候链路能建立但数据不对,查半天发现是SYSREF信号的时序不满足要求。后来学乖了,每次上电都先读JESD204B的状态寄存器,确认链路同步、帧同步、多帧同步都正常了再往下走。这个习惯帮我省了不少调试时间。

最后分享一个小技巧:数字下变频链路里的NCO频率、抽取因子、滤波器系数这些参数,最好做成寄存器可配置的,而不是写死在RTL里。这样调试的时候可以通过上位机动态修改,不用每次都重新综合。我一般会用一个SPI或者UART接口来配置这些参数,配合上位机软件,调试效率能提高好几倍。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/29 20:56:06

博客1_九个坑实录

手写 FASTA 解析器踩了 9 个坑:从 0 条记录到 3 条的完整调试实录本文是《手写 FASTA 解析器》系列第 1 篇我是生信方向研一新手,Python 零基础起步,研究方向是小鼠 VNTR(可变数目串联重复)变异分析。 为了搞懂序列文件是怎么被读进程序的,我从零手写了一个 FASTA 解析器 —— …

作者头像 李华
网站建设 2026/9/29 20:55:09

射频PA模块选型:五大关键参数权衡与实战指南

做射频的人都知道,PA模块选型看起来是个“按参数挑器件”的活儿,实际上更像是在做一次系统级的权衡博弈。我见过不少项目,前期讨论方案时大家把注意力全放在输出功率上,觉得“功率够了就行”,结果样机一测,…

作者头像 李华