第1章:调制与星座映射

各位同学,咱们今天聊聊调制和星座映射。说实话,这是物理层里最“看得见摸得着”的部分之一。你想想看,一串二进制比特怎么变成空口上的波形?中间最关键的一步就是星座映射。

1.1 从比特到符号:星座映射的本质

调制说白了就是给比特“化妆”。QPSK一次画2个比特,16QAM画4个,64QAM画6个,256QAM画8个。每个组合对应星座图上一个点。我刚开始做这个的时候,总觉得星座图就是个数学概念,直到第一次用示波器看实际信号——嗯,那感觉完全不一样。

核心公式:每个符号携带的比特数 = log2(M),M是调制阶数。

QPSK: 2比特/符号 | 16QAM: 4比特/符号 | 64QAM: 6比特/符号 | 256QAM: 8比特/符号

1.2 硬件实现:查表法 vs 计算法

在芯片里做星座映射,主流就两种路子:查表和计算。我个人习惯用查表法,尤其是高阶调制的时候。为什么?因为省逻辑,时序好收敛。

// 查表法示例:QPSK映射
// 输入:2比特 [b1, b0]
// 输出:I/Q 值

const int qpsk_table[4][2] = {
    { 1,  1},  // 00
    { 1, -1},  // 01
    {-1,  1},  // 10
    {-1, -1}   // 11
};

int idx = (b1 << 1) | b0;
int I = qpsk_table[idx][0];
int Q = qpsk_table[idx][1];

计算法呢?适合面积敏感的场景。比如16QAM,I路和Q路各取2比特,直接算幅度。我在一个低功耗项目里用过,面积省了大概15%,但时序稍微紧张了点。

我的经验:256QAM一定要用查表法。计算法在256QAM下,组合逻辑路径太长,很难跑到高频。我曾经试过,最后不得不插了两级流水线才搞定。

1.3 软比特生成:LLR计算的硬件实现

接收端解调时,我们需要软比特——也就是LLR(对数似然比)。硬判决只告诉你“0还是1”,软判决告诉你“有多大概率是0或1”。Turbo码和LDPC解码器都吃软比特,所以这步很关键。

LLR的数学定义是:

LLR(b) = ln( P(b=1|r) / P(b=0|r) )

但在硬件里,我们不会真的算对数。实际实现用的是max-log近似:

LLR(b) ≈ (1/σ²) * (min_distance_0 - min_distance_1)

说白了,就是找离接收点最近的“0”星座点和最近的“1”星座点,算它们到接收点的距离差。

1.4 QPSK的LLR计算:最简单的情况

QPSK的LLR计算特别简单。因为I路和Q路独立,每路只对应1个比特。公式可以简化成:

// QPSK LLR计算
// 输入:接收符号 (rI, rQ)
// 输出:LLR0, LLR1

// 假设星座点归一化幅度为1/√2
float LLR0 = 2 * rI / (sigma * sigma);  // 对应b0
float LLR1 = 2 * rQ / (sigma * sigma);  // 对应b1

我在一个NB-IoT项目里用过这个,因为信噪比低,LLR的精度直接影响解码性能。当时我们做了定点化仿真,发现6比特量化就够用了。

1.5 16QAM的LLR计算:分段线性近似

16QAM稍微复杂点。每路2个比特,不能直接线性映射。但可以用分段线性函数近似。以I路为例:

// 16QAM I路LLR计算
// 假设星座点:-3d, -d, d, 3d, d为归一化因子

float abs_I = abs(rI);
float LLR_b0 = (rI > 0) ? (2*d*(rI - d)) / (sigma*sigma) 
                         : (2*d*(rI + d)) / (sigma*sigma);
float LLR_b1 = (2*d*(d - abs_I)) / (sigma*sigma);

你想想看,b0是符号比特,b1是幅度比特。符号比特的LLR跟接收值正相关,幅度比特的LLR跟接收值的绝对值负相关——离原点越近,越不确定是“1”还是“0”。

避坑指南:我曾经在16QAM的LLR计算里忘了处理abs_I > 2d的情况。结果高信噪比时,幅度比特的LLR反而变小了。后来加了个饱和处理才解决。

1.6 64QAM和256QAM:更复杂的映射

64QAM每路3个比特,256QAM每路4个比特。规律是这样的:

  • 最高位(MSB):符号比特,线性映射
  • 次高位:幅度比特,分段线性
  • 低位:更细粒度的幅度信息,需要更多分段

以64QAM的I路为例(星座点:-7d, -5d, -3d, -d, d, 3d, 5d, 7d):

// 64QAM I路LLR计算(简化版)
float abs_I = abs(rI);
float LLR_b0 = (rI > 0) ? (4*d*(rI - 4*d)) / (sigma*sigma) 
                         : (4*d*(rI + 4*d)) / (sigma*sigma);
float LLR_b1 = (2*d*(4*d - abs_I)) / (sigma*sigma);
// b2需要更复杂的条件判断

256QAM就更麻烦了。我在一个5G NR项目里实现过,光是LLR计算模块就占了整个解调器面积的30%。不过没办法,256QAM的频谱效率高,基站侧必须支持。

1.7 硬件架构:流水线设计

实际芯片里,调制和解调是成对出现的。我画个架构图给大家看看:

调制与解调硬件架构 比特输入 星座映射 I/Q输出 I/Q输入 LLR计算 软比特输出 流水线设计要点 • 星座映射:1级流水线(查表)+ 1级流水线(输出寄存器) • LLR计算:2-3级流水线(绝对值计算、距离计算、归一化) • 256QAM建议额外加1级流水线处理分段逻辑

流水线级数怎么定?我一般遵循这个原则:每级组合逻辑的延迟不超过时钟周期的60%。留40%给时钟偏斜和寄存器建立时间。256QAM的LLR计算,我通常分3级流水线:

  1. 第一级:取绝对值,判断符号
  2. 第二级:计算距离差,分段选择
  3. 第三级:乘以归一化因子,输出

1.8 定点化实现:精度与面积的权衡

浮点仿真跑通了,不代表硬件能直接做。定点化是绕不开的坎。我给大家一个参考:

调制方式 I/Q量化比特 LLR量化比特 性能损失(BLER @1%)
QPSK 6 5 <0.1dB
16QAM 8 6 <0.2dB
64QAM 10 7 <0.3dB
256QAM 12 8 <0.3dB

这个表是我从实际项目中总结的。注意,LLR的量化比特可以比I/Q少2-3比特,因为LLR的动态范围相对小。但别省太多,我曾经试过把256QAM的LLR量化到6比特,结果高码率下BLER直接掉了0.5dB。

我的建议:定点化仿真一定要跑足够多的点。至少跑1000个以上的子帧,统计BLER曲线。只看几个符号的SNR是不够的——我吃过这个亏。

1.9 本章小结

调制和星座映射,说白了就是比特和符号之间的桥梁。发送端查表映射,接收端分段算LLR。硬件实现时,查表法省逻辑,计算法省面积,看你的需求选。LLR计算用max-log近似,分段线性实现,注意饱和处理。定点化时,I/Q和LLR的量化比特要留够余量。

嗯,这一章就到这儿。下一章咱们聊信道估计——那又是另一番天地了。


公众号:蓝海资料掘金营,微信deep3321