4、OFDM与SC-FDMA:IFFT/FFT的流水线设计、循环前缀插入、峰均比抑制
各位同学,今天我们来聊聊物理层里两个绕不开的模块——OFDM和SC-FDMA。说实话,这两个东西在4G/5G里几乎是天天见。我当年刚入行时,觉得IFFT不就是个数学变换嘛,有啥难的?结果第一次做芯片实现时,被流水线时序和面积折腾得够呛。嗯,今天就把这些坑和经验一并讲清楚。
4.1 OFDM与SC-FDMA的核心差异
先理清一个基本概念。OFDM是正交频分复用,SC-FDMA是单载波频分多址。说白了,OFDM是多个子载波并行发数据,SC-FDMA是先做一次DFT再映射到子载波上。
为什么要搞SC-FDMA?因为OFDM的峰均比(PAPR)太高了。我记得在LTE项目里,终端发射功率本来就受限,OFDM信号一上去,功放效率直接掉到20%以下。SC-FDMA相当于把时域信号先“摊平”了,PAPR能低3-4dB。你想想看,这对电池续航意味着什么。
| 特性 | OFDM | SC-FDMA |
|---|---|---|
| PAPR | 高(约10-12dB) | 低(约6-8dB) |
| 实现复杂度 | 低(单次IFFT) | 高(DFT + IFFT) |
| 适用场景 | 下行(基站发射) | 上行(终端发射) |
| 频域均衡 | 简单 | 简单 |
4.2 IFFT/FFT的流水线设计
做芯片实现时,IFFT/FFT是核心计算单元。我见过很多新手直接拿教科书上的蝶形运算图去写RTL,结果综合出来面积大得吓人。为什么?因为没有考虑流水线结构。
我个人习惯用基-2 流水线FFT架构。以128点FFT为例,需要7级蝶形运算。每一级包含一个蝶形处理单元(BFU)和一个旋转因子乘法器。关键是怎么安排流水线。
核心设计原则:
- 每级流水线深度控制在2-3个时钟周期
- 旋转因子用ROM存储,地址由级数和当前索引生成
- 数据采用乒乓RAM缓冲,避免读写冲突
我曾经在一个项目里,为了省面积把流水线深度压到1个周期,结果时序收敛不了。后来老老实实加了2级寄存器,面积只多了5%,时序却轻松过了。所以啊,流水线深度不是越浅越好。
下面是一个简化的流水线控制代码示例,我用Verilog描述一下核心思路:
// 流水线FFT控制逻辑(简化版)
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
stage_cnt <= 0;
data_valid <= 0;
end else begin
// 每级流水线延迟2个时钟
if (stage_cnt == N_FFT_POINTS-1) begin
stage_cnt <= 0;
data_valid <= 1;
end else begin
stage_cnt <= stage_cnt + 1;
data_valid <= 0;
end
end
end
// 蝶形运算单元
always @(posedge clk) begin
if (data_valid) begin
// 从RAM读取a和b
// 计算 a + b * W, a - b * W
// 写回RAM
end
end
小技巧:旋转因子的精度很关键。我建议用16位量化,其中1位符号位、1位整数位、14位小数位。这样在128点FFT下,信噪比损失可以控制在0.1dB以内。
4.3 循环前缀插入
循环前缀(CP)的作用是消除符号间干扰(ISI)。原理很简单:把OFDM符号末尾的一段数据复制到开头。但实现时有个细节——CP长度是动态可配的。
在LTE里,常规CP是4.69μs,扩展CP是16.67μs。5G NR更灵活,CP长度跟子载波间隔有关。所以芯片设计时,CP插入模块必须支持参数化配置。
我建议用双指针RAM控制法:
- 写指针:IFFT输出数据按顺序写入RAM
- 读指针:先读末尾CP长度的数据,再从头读到尾
这样做的好处是,不需要额外的存储空间。我曾经看到有人专门开一块RAM存CP数据,白白浪费了面积。
注意:CP插入后,符号长度会变化。后续的加窗、上变频模块都要同步调整时序。我吃过这个亏,CP长度配错了,导致整个发射链路时序错位,查了两天才找到原因。
4.4 峰均比抑制技术
PAPR抑制是OFDM系统里绕不开的话题。高PAPR意味着功放需要很大的回退,效率低得可怜。常用的方法有几种:
- 限幅(Clipping):最简单粗暴,但会引入带外辐射
- 压扩变换(Companding):对信号做非线性变换,PAPR能降2-3dB
- 选择性映射(SLM):生成多个候选信号,选PAPR最低的
- 部分传输序列(PTS):把子载波分块,优化相位
我个人在项目中用得最多的是限幅+滤波的组合方案。限幅把峰值砍掉,再用滤波器把带外噪声滤除。实现起来不复杂,效果也还行。
下面是一个限幅的数学表达:
// 限幅处理
if (|x[n]| > A_th) then
y[n] = A_th * exp(j * angle(x[n]))
else
y[n] = x[n]
end
其中A_th是限幅门限,通常设为信号均方根的3-4倍。门限设低了,PAPR降得多但EVM恶化;设高了,PAPR改善不明显。这个平衡点需要根据系统要求来调。
经验值参考:
- 限幅门限 = 3.5倍RMS:PAPR降低约2.5dB,EVM恶化约1%
- 限幅门限 = 4.0倍RMS:PAPR降低约1.8dB,EVM恶化约0.5%
对于SC-FDMA,PAPR本来就低,一般不需要额外抑制。但如果你做的是NB-IoT或者Cat-M这类窄带系统,终端发射功率极小,PAPR哪怕高1dB都会影响覆盖。这时候建议加一个简单的压扩变换,实现成本很低。
4.5 整体架构图
下面我用一张SVG图来展示OFDM/SC-FDMA发射链路的整体流程。这张图里包含了我们今天讲的所有模块:
从这张图可以看到,OFDM和SC-FDMA的主要区别就在DFT那块。OFDM直接走子载波映射,SC-FDMA先做DFT再映射。后面的IFFT、CP插入、PAPR抑制都是共用的。
4.6 实现中的常见陷阱
最后,我总结几个实际项目中容易踩的坑:
- IFFT/FFT的位宽选择:输入位宽和输出位宽要匹配。我见过有人输入用16位,输出截成12位,结果EVM直接炸了。建议每级流水线保留1-2位增长,最后再截断。
- CP插入的时序:CP插入后,数据率会变化。比如128点IFFT加32点CP,输出数据率是输入数据率的(128+32)/128=1.25倍。后续模块的时钟或使能信号要相应调整。
- PAPR抑制的EVM代价:限幅虽然简单,但会引入EVM恶化。3GPP对EVM有严格要求(比如64QAM要求EVM<8%),所以限幅门限不能设太低。
我的建议:在做芯片验证时,一定要用真实的信道模型去测PAPR和EVM。我曾经在仿真环境里PAPR降了3dB,结果拿到信道模拟器上一测,EVM超标了。后来发现是限幅后的滤波没做好,带外噪声串回来了。
好了,关于OFDM和SC-FDMA的物理层实现,今天就讲到这里。这些内容都是我在项目里一点点试出来的,希望能帮大家少走弯路。
公众号:蓝海资料掘金营,微信deep3321