ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

FBMC调制实现全解析:从OQAM预处理到多相网络与仿真验证

FBMC调制实现全解析:从OQAM预处理到多相网络与仿真验证 做物理层算法这些年我前后不下五次被人问到同一个问题都说FBMCFilter Bank Multi-Carrier滤波器组多载波是OFDM的接班人但它的基本调制究竟是怎么一步步实现的说实话市面上讲原理的文章不少真正能直接照着把发射链路跑通、还能跟传统OFDM做公平对比的内容很稀缺。这篇文章想把这块补上。我会从“为什么要折腾FBMC”讲起再把从比特流到发射信号的完整链路拆开包括OQAM预处理、原型滤波器设计、多相网络实现、仿真验证和工程折中每步都给出参数、代码片段和我自己踩过的坑。适合刚接触新波形的研究生、准备做波形验证的通信工程师以及想评估FBMC在下一代系统里有没有可用性的方案选型人员。1. 为什么最终选择了FBMCOFDM解决不了的那几个麻烦1.1 先说结论FBMC到底改变了什么FBMC和我们熟悉的OFDM最本质的区别是一个字滤。OFDM对每个子载波做矩形窗频谱上天然带着高旁瓣而FBMC在子载波层面引入精心设计的原型滤波器让每个子载波的频谱能量快速收拢。这个改动带来三个直接影响第一带外泄漏大幅降低频谱感知和动态频谱共享场景里不需要再留一大段保护带第二不需要循环前缀CP频谱效率高出一截第三对时间异步和频率偏移更宽容大大缓解了上行多用户同步压力。注意这三点不是白送的。代价是发射和接收端都从“一次IFFT搞定”变成“滤波器组重叠相加”的流水线符号之间出现K个符号周期K是重叠因子的拖尾复杂度、时延、MIMO适配都跟着受影响。所谓FBMC调制实现本质上就是把这套滤波器组链路老老实实搭建起来同时把里面的增益、相位、时序关系算清楚。1.2 OFDM的带外泄漏问题有多严重先看一个我实测过的数据。用64个子载波、子载波间隔15kHz、16QAM调制CP长度为1/4符号算出来的OFDM基带信号PSD第一旁瓣相对主瓣只低大约13dB。这是什么概念在动态频谱共享场景里如果你旁边有个窄带系统在用频你必须给人家留足够宽的保护带否则OFDM那长长的旁瓣尾巴会直接“糊”到别人的频段上。实测里为了满足邻带泄漏指标保护带宽经常占到可用总带宽的10%~20%。这在频谱资源紧张的今天非常奢侈。FBMC用的原型滤波器只要重叠因子K取到4主瓣外的频谱衰减能做到-50dB甚至更低。这意味着两个系统可以靠得相当近保护带从十几个子载波缩到一两个子载波频谱效率一下就上来了。我在仿真里对比过同样的发射功率和邻带干扰约束OFDM需要约12个空子载波当保护带FBMC只需要2到3个。这个数字在真实频谱共存项目里就是真金白银的带宽收益。1.3 多用户异步接入同步要求太高另一个让我下决心用FBMC的场景是异步接入。OFDM的正交性依赖一个隐含假设接收端能精确同步到每个符号的起始时刻而且子载波频偏足够小。上行多用户场景里不同用户来自不同地理位置时延各不相同一旦时间偏差超出CP容忍范围子载波间干扰ICI就会显著抬升系统整体吞吐量掉得很明显。FBMC因为每个子载波都在频域被滤波器收窄能量不再像sinc那样拖到很远所以它对时间偏移的容忍度明显更好。即便用户不同步也只是本子载波附近的轻微干扰不会像OFDM那样一串子载波集体“阵亡”。在电力线通信、工业物联网这类基础设施不提供严格同步的场合这种特性特别关键。我记得有次拿实测的信道模型跑异步上行仿真OFDM在时延差超过半个符号时性能开始明显下降FBMC还能保持接近理想的误码率水平那个对比结果给当时的项目决策提供了很直接的依据。2. FBMC基本调制链路从比特流到发射信号的完整流程2.1 发射端整体链路一套完整的FBMC发射链路可以分成这么几块比特流经过信道编码、交织后按调制阶数映射成复数QAM符号比如16QAM的每个符号带4比特对复数QAM符号做OQAM预处理拆成实部和虚部实部原位发射虚部延时半个符号周期在子载波维度叠加相位因子保证相邻子载波之间满足“实偶虚奇”的正交条件经过扩展IFFT得到时域展开结果再送入原型滤波器的多相分支网络PPN进行滤波相邻符号块做重叠相加生成连续的基带信号最后经并串转换、上采样、DAC和射频前端发射出去。接收端是发射端的逆过程先做分析滤波器组AFB同样使用PPNFIF结构然后做OQAM后处理把实虚交错的符号重新拼回复数QAM再解映射、去交织、译码。下面的小节逐个展开这些模块的实现细节。2.2 OQAM预处理为什么必须分实偶虚奇在OFDM里我们能在相邻子载波上直接放复数QAM符号是因为矩形窗让子载波严格正交。但FBMC换成了频谱收窄的滤波器时域上符号被拉长相邻子载波之间必然产生部分重叠直接用复数QAM会破坏正交性接收端提取信号时会有永远消不掉的串扰。OQAM解决这个问题的思路很巧妙与其抵抗重叠不如把重叠变成可分离的。具体做法是把一个复数QAM符号拆成两半实部在nT时刻发射虚部在nTT/2时刻发射。同时引入一个相位因子j^(kn)其中k是子载波索引n是符号索引。这样一来无论你看哪个子载波、哪个时刻任意一个采样点位置上来自相邻子载波干扰的相位关系都是确定的一部分是纯实干扰一部分是纯虚干扰。接收端只要做取实部或取虚部的操作就能把目标信号留下来同时把对方那一路干扰当作正交分量丢弃。举个例子。子载波k上的T/2相位偏移符号是实部相邻子载波k1上同一位置的重叠符号恰好是虚部。接收端提取子载波k时先解调到基带再取实部那么来自k1的纯虚部干扰天然不进入判决变量。这就是“实偶虚奇”四个字的全部含义。我见过不少人在这里踩坑直接拿复数QAM符号扔进滤波器组结果BER在0.5附近徘徊还找不到原因。按下面这段Python风格伪代码生成OQAM符号相位因子就稳妥了# M: 子载波数量 # symbols: 形状为 (M, N) 的复数QAM符号N为符号数 oqam_real np.zeros((M, N)) oqam_imag np.zeros((M, N)) for k in range(M): for n in range(N): phase 1j ** ((k n) % 4) # 等效于 j^(kn) s symbols[k, n] * phase if (k n) % 2 0: # 当前时刻承载实部 oqam_real[k, n] s.real else: # 当前时刻承载虚部 oqam_imag[k, n] s.real # 注意这里再乘相位因子后取实部 # 后续虚部序列整体延后 T/2 再发射这个相位因子的起点索引必须和仿真里子载波编号、符号编号的起点保持一致否则正交集体会整体翻转BER同样会崩掉。2.3 综合滤波器组与扩展IFFT多相网络PPN把OQAM符号变成时域信号最直接的做法是每个子载波乘上自己的滤波器冲激响应再相加但计算量太大。工程上几乎都走扩展IFFT加多相网络这条路。具体来说原型滤波器的长度取Lp K*M 1K是重叠因子。把这段滤波器的系数按M个相位拆开每个子载波的滤波操作就退化为对IFFT输出的一路信号乘上对应的多相抽头。这个变换的关键是先用一个M点IFFT把频域符号展开然后对每个输出分支做K路延迟和乘加最后把所有分支叠加起来。为什么可以这样简化因为综合滤波器组的本质是先把原型滤波器移位到每个子载波频率上再和对应的数据符号相乘求和。这正好和“IFFT多相滤波”结构在数学上是等价的。滤波器越长K越大多相分支越多但每个分支的计算量基本是常数级整体复杂度主要被M点IFFT主导。我自己写实现时多相网络的索引是最容易出错的地方。滤波器系数总长是K*M1这意味着拆成M个分支后大部分分支长度是K但有一个分支长度是K1。高位补零要对齐否则叠加时会出现一个分支整体滞后信号上会看到周期性的毛刺。补零方法很简单每个分支统一对齐到长度K多出来的一个系数放进第一个或最后一个分支单独处理。不同论文里的补零位置不一样但只要发射端和接收端对称算法性能不受影响。2.4 实际发送时域的拼接重叠相加滤波器长度决定了每个FBMC符号的时域拖尾会跨越K个符号周期。发射时不能让符号边界干干净净地切开必须让相邻符号在时域上重叠相加。这也是很多人第一次写FBMC发射机感到迷惑的地方。假设基带采样率下一个FBMC符号的时域长度为Lf K*M 1个样点那么每个符号周期新增的样点数大约是M个。发送第n个符号时它的时域波形头尾会分别和n-1、n-2、n-K1个符号的波形交叠。标准的做法是准备一个长度为Lf的累加器窗口每来一个新符号块先做时移M个样点再重复叠加进去然后把最新可判决的M个样点搬出到输出缓冲区。这里有一个隐藏的增益问题直接做重叠相加发射信号的均方根幅度会随符号数目慢慢变化尤其在符号数较少时能看到明显的起落。原因是不同位置叠加的符号数量不同。解决方式是干脆不做严格归一化而在接收端统一除以一个常数或者在幅度测量时只统计稳态部分。我在验PAPR时被这个坑折腾过一回后来学乖了仿真信号都留足前K-1个符号的预热段后面分析只取有效区间。2.5 接收端的对应处理匹配滤波与OQAM后处理接收端不能用发射端的综合滤波器直接逆运算而是用一组匹配的分析滤波器每个子载波对应的分析滤波器冲激响应是发射滤波器冲激响应的时间反演版本如果是实系数滤波器那就是原系数本身。实际工程里直接复用同一组原型滤波器系数配合相同的PPN结构只是在时域上做共轭翻转对齐。在AWGN信道下接收端对每个子载波做匹配滤波后得到的是实虚交错的符号序列。此时只需要按照发射端的相位因子约定在对应时刻取实部或虚部再串起来成复数QAM符号就能恢复原始数据。如果信道是频率选择性衰落的就不能直接取实部了需要在每个子载波上做一次频域均衡然后才进入OQAM后处理。这一点我放到第4节的仿真实例里详细展开。3. 原型滤波器设计直接决定频谱质量和系统性能3.1 重叠因子K与滤波器长度怎么定原型滤波器是FBMC系统里最关键的“零部件”没有之一。它直接决定频谱旁瓣能压到多低也决定符号拖尾长度、系统时延和整体复杂度。工程上最常见的选择是重叠因子K滤波器长度Lp时域扩展典型旁瓣水平适用场景22M12个符号约-30dB左右对时延敏感、频谱要求不极端33M13个符号约-40dB量级兼顾实现复杂度和频谱性能44M14个符号约-50dB或更低动态频谱共享、异步接入等主流场景K越大滤波器频域边缘越陡峭但时域拖尾更长收发时延和复杂度同步增长。我做频谱共存仿真时基本只用K4因为-50dB这个量级的带外抑制才够在保护带只有两三个子载波时保证邻带系统不受明显干扰。如果是纯学术验证或硬件资源紧张的场景K2到3也够用。3.2 PHYDYAS与Hermite滤波器系数滤波器系数的生成方法有两大类主流PHYDYAS滤波器和Hermite窗设计。PHYDYAS来自欧盟FP7 PHYDYAS项目是FBMC研究里流传最广的一套系数选K4时归一化系数序列大致如下h[0] 0.97195983 h[1] sqrt(2)/2 0.70710678 h[2] 0.23514695 部分论文里的值为0.204302或微调版本不同精度略有差异 h[3] 0.07055810 h[4] 0.01004043实际滤波器长度是4M1中间最核心的系数用这些值两边以近似线性插值方式扩展。更严谨的做法是对指定频域采样点进行频率采样设计。Hermite滤波器则是在频域用Hermite多项式基展开在时频聚集性上更优但其离散化实现稍显复杂除非是做纯理论研究否则我建议先用PHYDYAS系数跑通链路再回头评估换滤波器的影响。3.3 频域响应实测PSD怎么对比评价滤波器设计最直观的手段是看发射信号PSD。我通常会用Welch方法估计功率谱窗函数选汉宁窗窗长度至少覆盖几十个符号周期重叠率50%。这里有个容易犯的错如果FFT窗长度太短频域分辨率不足FBMC那点窄主瓣优势在图上根本看不出来。我一般是设置FFT点数不小于8192才能把子载波级主瓣和旁瓣清晰拉开。对比实验里我把CP-OFDM和FBMC设置成相同的总带宽和发射功率生成的信号长度相同然后用同一套PSD估计参数。结果差异非常明显OFDM在子载波间隔整数倍处能看到经典的sinc旁瓣阶梯FBMC则是一根根尖锐的主瓣旁边平坦得像噪声地板。把-40dB作为邻带泄漏阈值画一条参考线能直观看出OFDM需要的保护带宽比FBMC大三到五倍。这个图几乎是我跟团队讲FBMC价值时的首选素材。3.4 设计权衡与注意点滤波器设计不是旁瓣压得越低越好有几个权衡要把握住。旁瓣越低对滤波器系数截断误差越敏感。定点实现时系数位宽不够旁瓣会反弹甚至比OFDM还差。我建议硬件阶段给滤波器系数至少留16位定点位宽仿真阶段用双精度不要提前量化。滤波器长度和符号拖尾的权衡。K4是性价比很高的选择但如果在纯时延敏感业务比如低时延URLLC场景硬上FBMCK带来的额外时延可能无法承受。接收端和发射端必须保持“同一个滤波器”。收发不匹配的情况下正交性被破坏BER会有一个看不见的地板怎么加高SNR都降不下去。这点在硬件回环测试里尤其要小心。4. 一次完整建模仿真参数选择、过程与关键验证点4.1 仿真参数表为了说明方便下面给出一套我在仿真里常用的参数组合。你可以直接抄过去改。参数取值说明子载波数M64小规模便于查错子载波间隔Δf15kHz沿用LTE习惯便于与OFDM对比重叠因子K4PHYDYAS滤波器调制方式16QAM每符号4bit符号数N200个复数QAM符号仿真时长适中采样率fsM * Δf 0.96MHz基带过采样率取1时OQAM调制实虚交替、虚部延时T/2T1/Δf子载波间隔15kHz时OQAM符号周期为T66.7us。注意OQAM把每个QAM符号拆成两个实符号等效符号速率和CP-less OFDM相比并没有吃亏因为实符号周期是T/2两个实符号合起来正好还是一个T周期内的复数QAM容量。4.2 发射链路代码核心段下面是发射端核心流程的Python风格实现省略了上采样和RF部分基带脉冲成型足够说明问题import numpy as np M 64 # 子载波数 K 4 # 重叠因子 N 200 # QAM符号数 Lp K * M 1 # 滤波器长度 # 原型滤波器示意PHYDYAS近似实际需按频率采样法生成 h np.zeros(Lp) # ... 用3.2节的系数表按频率采样法填充 h ... # 1. 随机生成16QAM符号 rng np.random.default_rng(42) qam_symbols (rng.integers(0, 4, size(M, N)) * 2 - 3) 1j * (rng.integers(0, 4, size(M, N)) * 2 - 3) # 2. OQAM预处理 d np.zeros((M, N), dtypecomplex) for k in range(M): for n in range(N): ph 1j ** ((k n) % 4) d[k, n] qam_symbols[k, n] * ph if (k n) % 2 1: # 虚部位置延时到下一个T/2 d[k, n] d[k, n] * 1j # 把实部变成虚部承载 # 3. 多相滤波器网络 重叠相加 tx_blocks [] # 每个长度为4M的符号块 for n in range(N): # 对第n列符号做M点IFFT freq_in np.zeros(M, dtypecomplex) for k in range(M): freq_in[k] d[k, n] * np.exp(1j * np.pi * k) # 频域移位IFFT的等效 ifft_out np.fft.ifft(freq_in, M) # 原型滤波器多相展开每个分支长度K不足补零 poly np.zeros((M, K), dtypefloat) for k in range(M): vals h[k:Lp:M] # 每隔M取一点 poly[k, :len(vals)] vals[:K] # 每个子载波分支分别卷积再叠加 block np.zeros(Lp, dtypecomplex) for k in range(M): for p in range(K): block[p*M k] ifft_out[k] * poly[k, p] tx_blocks.append(block) # 4. 重叠相加成连续基带信号 tx_signal np.zeros((N-1)*M Lp, dtypecomplex) for n, blk in enumerate(tx_blocks): start n * M tx_signal[start:startLp] blk上面的代码刻意写得偏“教学式”每个循环都拆开便于对照理解。工程版本会尽量向量化但核心步骤完全一致。其中有几个点要特别说明d[k, n]在虚部位置乘了1j这等价于把经过相位因子旋转后的实部搬到了虚部位置block[p*M k]的索引实际上就是把IFFT输出按相位展开到滤波器长度的对应位置上这正是多相网络的时域含义。4.3 三大指标怎么测PSD、PAPR、BER信号发出来后至少要测三个指标功率谱密度PSD、峰均比PAPR和误码率BER。PSD测量我按3.3节说的做注意FFT点数要够大。PAPR则用互补累积分布函数CCDF来画横轴是PAPR门限值纵轴是超过门限的概率一般对比CP-OFDM和FBMC各自的曲线。实测下来FBMC的PAPR通常比CP-OFDM略高0.5到1dB原因是符号间重叠导致时域幅值波动更剧烈。如果系统对PAPR极其敏感就得考虑加限幅或者预留峰抵消算法。BER测试的SNR折算经常被人搞混。先把SNR门限换算成每比特能量与噪声功率谱密度之比Eb/N0公式是Eb/N0(dB) SNR(dB) 10*log10(B/Rb)其中B是噪声等效带宽这里取基带采样率fsRb是总比特率。因为FBMC没有CP而CP-OFDM有CP开销对比时必须把“是否包含CP开销”这个条件写清楚。更公平的做法是让两个系统占据相同的物理带宽CP开销直接从信息速率里扣掉再看谁的BER曲线更靠前。4.4 常见问题排查为什么我的FBMC BER比OFDM差我自己调试FBMC时的经验和教训集中在这里。出现BER异常先按顺序检查这几件事相位因子符号j^(kn)里k和n的起点是不是0整段代码是不是统一。这个错经常发生在从MATLAB迁移到Python时索引差1导致整个正交性翻转。重叠相加窗不对滤波后符号块长度是Lp时间移动是M不是Lp。把移动步长写成Lp会让相邻符号完全错开时间上全是空洞。多相分支对齐滤波器系数隔M抽一根抽出来的分支长度不齐补零位置必须固定。收发不一致时BER会有本底。接收端取实虚的符号错位OQAM符号在时间上错开T/2接收端如果按照整数倍T去抽样取到的全是串扰成分。需要先做定时同步确立OQAM符号网格的偏移。均衡器假设过强拿OFDM式的每个子载波复单抽头均衡去均衡FBMC效果不会好。因为FBMC子载波在频域不是严格独立的建议先做一次原型滤波器匹配滤波再在频域做增强型均衡或迭代干扰消除后面小节展开。4.5 信道场景验证AWGN与频选衰落AWGN信道是最快的验证通道。跑通理想链路、BER曲线贴近理论值时基本可以确认收发基带实现没毛病。频选信道下我第一次简单套用OFDM的导频插值思路结果惨不忍睹。原因在于FBMC导频符号本身是实虚交错每个导频只能承载实部或虚部复数导频没法直接放上去。比较成熟的做法是周边空置子载波法在导频周围留出一定范围的虚子载波导频处只发实部虚部置零接收端只用实部做估计需要复数信道估计时再用相邻符号干扰可预测的性质把已知干扰从接收信号里减掉。这个处理增加了导频开销和复杂度是FBMC工程化绕不过去的坎。5. FBMC的代价与工程上绕不开的折中5.1 复杂度估量与实现方式选择FBMC的复杂度不能简单说“比OFDM高几倍”要分实现方式看。直接子载波滤波每个子载波都要独立做卷积复杂度约O(M^2 * K)M一大就看不了只适合M很小的教学演示。多相网络PPN IFFT核心是M点IFFT加每路K阶乘加复杂度约O(M log2 M MK)。以M128、K4为例纯IFFT之外的额外乘加大约MK512次每个符号周期对现代DSP完全不是负担。频域扩展FS-FBMC把滤波放到频域用更长的IFFT点数做逐点频域处理硬件流水线更规整代价是FFT点数变大。FPGA实现里我个人反而更喜欢FS-FBMC因为多相网络在高并行度实现时叠加逻辑的内存控制比FFT还烦人。在我做过的FPGA原型里K4、M256的配置逻辑资源和DSP乘法器占用比同等CP-OFDM大约多一倍其中大头在滤波器分支的乘累加和重叠相加缓冲管理。这个代价换来的频谱增益是否值得完全取决于场景。5.2 MIMO适配问题为什么OFDM更顺理论上FBMC在MIMO里的表现一直是被重点攻击的软肋。OFDM天然支持复数域的正交变换所以Alamouti空时编码可以直接套用而FBMC的OQAM把符号拆成了实虚交替每个符号间隔内只有一个实维度在承载数据直接应用复数Alamouti矩阵会破坏数据配对关系性能大打折扣。常见解法有这么几类一是实数域Alamouti干脆在实OQAM符号层面构造正交空时码损失一些码率和性能但完全兼容FBMC二是采用时频反转结构把两个符号的实部和虚部重新配对换取MIMO检测的便利三是改用CS-FBMC给每个符号补CP并强制符号隔离几乎退化成一个带滤波的OFDM代价是放弃FBMC最引以为傲的频谱效率和异步优势。所以如果你是一个准备把FBMC用于大规模MIMO系统的团队我建议先冷静评估是不是真有必要为了频谱包络牺牲MIMO复杂度。单流、窄带、频谱受限的场景FBMC优势很突出高流数MIMO场景OFDM还是最顺手的那个。5.3 导频与信道估计的工程处理FBMC信道估计这块在工程上最磨人。OQAM的实虚交错结构让传统复数导频没有直接立足之地。一个工程化程度较高的做法是“辅助导频(auxiliary pilot)”方案在导频的相邻时频位置额外放一个或多个已知辅助符号用来在接收端对消掉导频受到的固有干扰。辅助导频的设计涉及干扰系数计算需要针对不同原型滤波器的相关性查表。另一个方向是迭代接收机先用初始估计恢复数据把数据符号再调制回去算出干扰项并从接收信号中扣除然后重新做信道估计如此循环两三轮。性能好但复杂度呈倍数增长。我在项目中折中的方案是在导频周围预留一圈空子载波减少干扰来源再对导频符号本身做一次匹配滤波得到粗糙信道值后插值。对普通仿真验证够用但对性能要求极端的系统还不够必须上辅助导频或迭代方案。5.4 什么场景适合FBMC什么场景还是OFDM实在调制方案的优缺点不能脱离场景谈。把FBMC的优势和代价摆在一起看项目FBMCCP-OFDM带外泄漏极低可支持频谱碎片化高需要保护带CP开销无有约7%~20%异步容忍度高低实现复杂度高低MIMO支持费劲成熟流畅时延滤波拖尾更长符号独立、时延可控所以我的选型经验很简单频谱碎片化、异系统共存、非同步上行接入、需要对邻带泄漏指标严苛受限的窄带场景优先考虑FBMC。常规宽带移动通信、大流数MIMO、对时延和复杂度敏感的终瑞侧系统老老实实用OFDM。虽然行业内常说FBMC是5G/6G的候选波形但真正落地时要对新波形做“按需取用”而不是全盘替换。我参与的一个项目里正是把FBMC用在频谱感知和随机接入那一小段链路上效果比整体替换OFDM实用得多。最后说一点我在实际调试里的体会。学FBMC调制最容易掉进“原理都懂、链路跑不通”的怪圈。我建议第一次写仿真时只做M4、K2、QPSK这种最小配置把每个中间信号的维度用手算验算一遍确认多相网络、OQAM偏移和重叠相加三个模块的衔接完全正确再扩大参数。另外对比OFDM时一定明确带宽、导频开销、CP开销这些前提条件否则两类波形的性能指标直接比结论会失真。这套路我带着好几个新人走过基本都能在一个下午内把发射接收链路调到BER贴在理论曲线上。
返回列表