解码
现在我们已经校正了残余 CFO,也校正了通道增益,下一步是将 FFT 输出映射到实际数据位。这是对数据包进行编码的逆过程。
- 解调:复数到位
- 解交织:对每个 OFDM 符号内的比特进行混洗
- 卷积解码:去除冗余并纠正潜在的位错误
- 解扰。
步骤1和3取决于调制和编码方案,可以从SIGNAL字段获得。信号字段在长前导码之后的第一个 OFDM 符号中进行编码,并且无论实际调制如何,始终采用 BPSK 调制。回想一下,在 802.11a/g 中,一个 OFDM 符号包含 48 个数据子载波,相当于 BPSK 方案中的 48 个数据位。信号字段也以 1/2 速率进行卷积编码,因此信号字段中有 24 个实际数据位。
接下来,我们首先完成解码过程,然后解释传统 (802.11a/g) 和 HT (802.11n) 信号格式的格式。
解调
- 模块:
demodulate.v
- 输入:
rate (7), cons_i (16), cons_q (16)
- 输出:
bits (6)
此步骤将 FFT 平面中的复数映射为比特。图19 示出了BPSK、QPSK、16-QAM和64-QAM的星座编码方案。OpenOFDM 也支持。
图 19 BPSK、QPSK、16-QAM 和 64-QAM 星座比特编码
在每个 OFDM 符号内,每个子载波根据调制方式被映射为 1、2、4 或 6 位。,n即位数。
解交织
- 模块:
deinterleave.v
- 输入:
rate (7), in_bits (6)
- 输出:
out_bits (2), erase (2)
在每个 OFDM 符号内,编码位是交织的。要了解块交织器的工作原理,首先我们需要定义一些参数。这里我们只考虑802.11a/g和802.11n单空间流模式。
调制 | 编码率 | 比特率 | |||
BPSK | 1/2 | 6 | 1 | 48 | 24 |
BPSK | 3/4 | 9 | 1 | 48 | 36 |
四相相移键控 | 1/2 | 12 | 2 | 96 | 48 |
四相相移键控 | 3/4 | 18 | 2 | 96 | 72 |
16-QAM | 1/2 | 24 | 4 | 192 | 96 |
16-QAM | 3/4 | 36 | 4 | 192 | 144 |
64-QAM | 2/3 | 48 | 6 | 288 | 192 |
64-QAM | 3/4 | 54 | 6 | 288 | 216 |
在这里:
- :每个子载波的位数
- :每个 OFDM 符号的编码位数
- :每个 OFDM 符号的数据位数
让s=max(/2,1)是星座平面中沿实(或虚)轴的位数。交织器基于按行写入数据位并按列读出数据位。为奇数时,s=1;为偶数时,s=/2。
802.11a/g | 802.11n 20MHz | |
16 | 13 | |
× | 4 × |
交织过程涉及两种排列。让k是第一次排列之前的位索引的索引,i是第一个排列之后但第二个排列之前的索引,并且j是第二次排列后的索引。
这里先介绍了交织再介绍了反交织,前俩公式是交织的过程,后面俩才是解交织。交织分为两步,一个是把原本的数据流按行排列,再按列取出,这时候原本的数据已经乱了。第二步是在映射到星座图的时候,把相邻的码位映射到星座图中的对角线位置。解交织是前面的逆过程,先把码位从星座图上排列下来,再按列排,按行取,以恢复原本的顺序。
第一个排列 (k →i)的交织确保相邻码位映射到非相邻子载波,定义为:
以及第二个排列(i→j) 确保相邻码位交替映射到星座点中的较低或较高有效位,并定义为:
解交织过程还涉及两种排列,以及反转交织过程中的两种排列。
首先,反转第二个排列 ( (2) ):
并反转第一个排列:
在 OpenOFDM 中,解交织是使用查找表来执行的。首先,一个 OFDM 符号中的比特存储在双端口 RAM 中。然后根据查找表读取这些位。
图 20解交错查找表
如图20所示,一个OFDM符号的原始比特首先被存储在置换缓冲器中。缓冲区条目为 6 位宽,可容纳 64-QAM。对于其他调制,只有较低的位有效。缓冲区有 48 (802.11a/g) 或 52 (802.11n) 行,具体取决于是否使用 HT。这个表就是用来缓存数据的,方便按解交织的思路去恢复原来的码位顺序。
将一个 OFDM 符号内的所有位写入置换缓冲区后,我们首先获得当前调制方案的子查找表的基地址。对于 802.11a/g,关键是信号字段内的速率位。对于 802.11n,关键是mcs + 16。下一步是读取查找表以确定接下来要输出哪些位。
查找表条目的宽度为 22 位,其中包含:
null_a/null_b
:当前位是否有效(用于接下来维特比解码中的标点符号)addra/bita
:输出的第一位addrb/bitb
:要输出的第二位out_stb
:输出选通done
:电流调制子 LUT 结束
请注意,解交错模块在每个时钟周期输出 2 位。查找表由 生成scripts/gen_deinter_lut.py
。
对于非 1/2 调制率,我们需要补偿解交织步骤中的标点符号,以使后续的维特比解码更容易。这是通过相应地插入虚拟位(通过null_a/null_b
位)来实现的。确切的标点符号模式可以在 18-9 中的图中找到。802.11-2012 std
维特比解码
传输的比特经过卷积编码,增加了比特的冗余并帮助接收器修复比特错误。可以使用维特比算法来执行解码 ,我们使用 Xilinx 提供的 Viterbi IP 核。它不是免费的,但您可以获得评估许可证。评估许可证的限制是FPGA上电后一定时间(几个小时)后内核将停止工作。
Viterbi 核心处理大部分繁重的工作,我们只需要向它提供解交织模块输出的解穿孔比特。
对于 SIGNAL 或 HT-SIG 字段,解码在此停止。对于数据符号,最后一步是解扰。
这部分没有介绍详细过程,直接是Viterbi IP 核实现。
解扰
发送端的加扰步骤是为了避免长连续的 0 或 1 序列。加扰和解扰过程可以使用相同的逻辑来实现。这部分没咋看懂,反正就是先介绍了加扰的过程,再介绍了解扰的过程。
图 21加扰器/解扰器逻辑
假设当前输入位是, 扰乱位加扰器的内部状态更新如下:
在这里是第 n 个输入位之前的扰码器状态,n = 0 , 1 , 2 , …。
在发送端,对于每个数据包,扰码器都用伪随机值进行初始化。数据位的前 7 位在加扰之前被预设为零,以便接收器可以使用加扰位来估计值。
现在让我们看看接收器如何恢复发送器扰码器的初始状态。有两种方法可以解释这一点。
首先,我们可以计算初始状态。由于前 7 个未加扰位(B0 to B6) 均为零,则扰码位可由下式获得:
从中我们可以反算出X如下:
这种解释不会导致有效的 Verilog 实现,因为我们需要首先缓冲前 7 位,计算初始状态,然后再次从前 7 位进行解扰。
第二种解释是:前7个加扰比特是这7个比特加扰后的状态。换句话说,我们有:
例如,看一下,
我们还知道:
所以=。这样我们就直接得到状态来解扰下一位,得到一个非常简单的 Verilog 实现。
原文:Decoding — OpenOFDM 1.0 documentation