在协议栈仿真这条路上,物理层(PHY)往往是很多人最不想碰的一块。原因很简单:MAC层再复杂,至少都是状态机加队列,逻辑上能把人绕晕,但调试手段清晰;物理层一旦沉下去,面对的是一堆I/Q样本、FFT、卷积码和载波频偏,纯软件里看不见摸不着,出了问题都不知道该往哪个方向查。但这个坎绕不过去——MAC层所有的退避、重传、速率选择,都要建立在物理层能给出正确的信道状态和收包结果之上,否则整个仿真就是空中楼阁。这篇文章是IEEE 802.11协议仿真系列的第二篇,专门聊物理层仿真的整体设计与细节实现,重点放在802.11a/g/n中最经典的OFDM物理层,也会带上802.11b中DSSS/CCK的部分对比。内容核心不是堆理论公式,而是把物理层从发端到收端拆成一个个可以编码实现的模块,讲清楚每一步在干什么、为什么这样干、仿真中哪些地方容易出幺蛾子。
1. 物理层仿真到底在仿什么
很多初学者第一次接触802.11物理层仿真时,第一反应是去搜“802.11a matlab simulation”,然后下载一份代码,跑通后看到误码率曲线就以为完事了。这其实是本末倒置。物理层仿真不是用来“证明OFDM能工作”的——OFDM能不能工作,几十年前就已经被理论和实测反复验证过了,没必要再靠仿真证明一次。仿真的真正目的,是让你在可控环境中观察信号从发射机到接收机每一级处理所发生的变化,理解噪声、干扰、失真、频偏、定时误差这些非理想因素如何一步步侵蚀系统性能,也为上层协议验证提供一个可复现的物理层接口。
以802.11a/g/n的OFDM物理层为例,整个物理层可以拆成一条清晰的处理链路:发送端从MAC层拿到PSDU(PLCP Service Data Unit),依次经过扰码、FEC编码、交织、星座映射、导频插入、IFFT、加循环前缀(CP)、加前导码(Preamble),最后上变频发射;接收端则反过来,先检测信道上有无信号(分组检测),然后做定时同步、载波频偏估计与补偿、FFT解调、信道估计与均衡、相位跟踪、解交织、Viterbi译码、解扰,最终把PSDU交还给MAC层。这条链路本身不复杂,复杂的是链路两端之间的那条“信道”——它决定了你的仿真可信度有多少。
在仿真场景中,信道既可以是纯加性高斯白噪声(AWGN),也可以包含多径衰落、多普勒频移、载波频偏(CFO)、采样时钟偏移(SCO)、相位噪声等非理想因素。物理层仿真的第一要务,是把这些非理想因素用一个可配置的模型注入系统,然后观察接收机算法在不同条件下的性能退化曲线。说得直白一点:物理层仿真就是造一个数字的双胞胎信道,把发射机算法和接收机算法放在里面对抗,看谁先扛不住。
从工程实践角度,我更推荐把物理层仿真分成三个层次来做。第一层是链路级仿真,只关注单条链路的收发性能,适合验证PHY算法本身;第二层是系统级仿真,把多个节点、多条链路放到一起,考虑同频干扰和资源竞争,适合和MAC层联调;第三层是硬件在环(HIL)仿真,通过USRP这类软件无线电设备把真实射频信号灌进算法里,验证代码在真实环境下的表现。对协议栈仿真来说,第一层和第二层是主力,第三层通常留给产品化阶段。这篇文章聚焦链路级,也就是那些在纯软件环境里可以把误码率算到小数点后好几位的场景。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. OFDM物理层整体架构与关键模块选型
2.1 为什么802.11a/n选择了OFDM而不是单载波
在动手写代码之前,有必要先讲清楚OFDM为什么能成为802.11a/g/n物理层的基石。OFDM本质上是把高速串行数据流拆成N路低速并行子载波去传输,每路子载波带宽变窄,符号周期变长,对多径时延的容忍度大大提高。更妙的是,通过插入循环前缀,可以把多径信道造成的符号间干扰(ISI)转化成子载波间的乘性干扰,接收端只需要一个单抽头均衡器就能把信道掰直,远比时域均衡器简单。代价是OFDM对频偏极其敏感,子载波间隔一旦被频偏破坏,子载波间干扰(ICI)会直接抬底噪。所以802.11a的物理层把大量功夫花在同步上,从这个角度去理解接收机的每一个模块,就顺理成章了。
对于做仿真的人来说,OFDM的另一个好处是模块边界极其清晰:发端IFFT前是一套处理,收端FFT后是一套处理,中间的信道模型可以独立建模。这意味着你完全可以分段实现和验证,不必等整个链路写完才跑通。我在实际项目里通常先写好AWGN信道下的端到端通路,再逐步往里面加频偏、多径、相位噪声,每加一种非理想因素就重新做一次性能回归,这样出问题时定位范围可以收得很小。
2.2 802.11a/g物理层仿真参数速查
开始写代码前必须把参数表钉在墙上。802.11a的OFDM物理层核心参数如下,这些参数是所有实现的基础,背不下来也要能随时查阅:
| 参数项 | 数值 | 说明 |
|---|---|---|
| 信道带宽 | 20 MHz | 标准信道宽度 |
| FFT点数 | 64 | 48个数据子载波 + 4个导频 + 12个空子载波 |
| 数据子载波数 | 48 | 索引 -26~-22, -20~-8, -6~-1, 1~6, 8~20, 22~26 |
| 导频子载波数 | 4 | 索引 -21, -7, 7, 21 |
| 子载波间隔 | 312.5 kHz | 20 MHz / 64 |
| IFFT/FFT周期 | 3.2 us | 64个采样点 @ 20 MSps |
| 循环前缀长度 | 0.8 us | 16个采样点,即800 ns |
| OFDM符号总长 | 4.0 us | 3.2 us + 0.8 us |
| 短训练序列(STS) | 10个重复 | 共8 us,用于分组检测、AGC、粗频偏估计 |
| 长训练序列(LTS) | 2个重复+CP | 共8 us,用于信道估计与精频偏估计 |
| Signal字段 | 1个OFDM符号 | BPSK调制,速率为1/2,承载速率与长度信息 |
这些参数彼此咬合得很紧:64点FFT配16点CP,是因为在20 MHz带宽下,CP需要覆盖室内信道典型的均方根时延扩展(通常几百纳秒)。4个导频子载波分布在频带两侧,是为了在接收端能持续跟踪残余频偏和相位噪声。STF(短训练字段)和LTF(长训练字段)各有分工:短训练序列的自相关性好,每0.8 us重复一次,便于快速粗同步;长训练序列可以提供两个完整的OFDM符号周期的训练数据,让接收机得到每个数据子载波上的信道频率响应估计。
仿真中一个常见问题是参数配置和标准不一致,最后导致性能曲线整体偏移但找不到原因。我自己的习惯是先把这些参数写成常量表放在
