1. 差错控制编码到底在解决什么问题
1.1 数字通信系统里的误码是从哪来的
先讲个特别常见的场景。你调试一套无线数传系统,发射功率明明已经开到最大了,接收端还是时不时冒出几个错bit,解调出来的数据要么出现乱码,要么干脆丢包。这时候你拿示波器去看接收波形,发现信号幅度还行,但频谱上明显有毛刺——那是干扰和噪声混进去了。
数字通信里所谓的“误码”,说白了就是接收端把0判成了1、把1判成了0。这个误判的根源,是信号在信道里传播时叠加了噪声、受到了衰落、碰到了多径干扰。理想情况下,接收端只要判断信号电平是高还是低就行,但现实里信号电平会被噪声“拉扯”,高电平可能被拉低,低电平可能被抬高,判决器一哆嗦就判错了。信噪比越低、信道环境越差,判决时出错的可能性就越大。
这个误码率(BER,Bit Error Rate)不是一个绝对的门槛,而是连续变化的。信噪比低的时候,每秒钟可能错出来几百个bit;信噪比高的时候,可能跑一天都错不了几个。但很多业务场景对误码的要求非常苛刻:比如文本传输,一个bit错了,整个字符就错了;再比如压缩后的图片或视频流,一位出错可能会导致一整块解码失败。问题是,实际工程里你并不能把所有场景的信噪比都拉满,很多环境是你没法选择的。
1.2 靠提高发射功率解决问题为什么不现实
有人说,既然信噪比低才出错,那把发射功率加大不就行了吗?这句话在实验室里成立,在实际系统里往往走不通。
第一个问题是功率限制。手持设备、IoT终端、太空探测器,电池和发射功率都有限,不可能无限加功率。第二个问题是干扰。所有无线设备都在同一个频段里争抢资源,你提高发射功率,等于给别的系统制造了更大的干扰源,这在很多频段是违规的,甚至会触发系统自干扰。第三个问题是信道本身,比如卫星通信、高速移动场景,信道衰落是随机波动的,峰值功率再高,深衰落一出现,照样误码。
真正成熟的工程做法,是在发射端主动给数据“加点结构”,让接收端有能力发现错误、甚至纠正错误。这就是差错控制编码(也叫信道编码)干的事情。我在早期做无线模块的时候,对这个问题理解还不深,总觉得只要硬件指标过关就行。后来遇到一个尴尬情况:射频链路明明调得很好了,接收灵敏度也够,但误码率就是卡在某个数值上不去。后来把信道编码加上去,同样的射频指标,误码率直接降了好几个数量级。从那时起我才真正意识到,信道编码不是通信系统里的“选修课”,而是和调制解调并列的“必修课”。
1.3 差错控制的三种基本形态:ARQ、FEC、HEC
差错控制编码按照工作方式,基本分三大类,工程上经常配合使用。
第一种是自动重传请求(ARQ)。接收端检测到错误之后,直接请求发送端重新发送。这种方式实现简单,但代价是引入了重传延迟,而且信道质量差的时候,重传次数暴增,吞吐率会急剧下降。适合对时延要求不高、但可靠性要求高的场景。
第二种是前向纠错(FEC)。发送端在数据中主动加入足够的冗余信息,接收端收到后直接通过纠错算法把错误“修”回来,不需要反馈通路。这种方式没有重传延迟,吞吐稳定,是实时通信(语音、视频、卫星通信)里的主力。
第三种是混合纠错(HEC),也叫HARQ(Hybrid ARQ)。它是ARQ和FEC的结合:先做前向纠错,如果FEC能纠回来就万事大吉;万一纠不回来,再触发重传。现代移动通信系统(4G/5G)里大规模使用的就是HARQ方案。
这三种方式并不矛盾,很多系统里是共存的。你看一个典型的通信协议栈,物理层由FEC兜底,链路层用CRC检错,一旦CRC校验失败,高层再通过ARQ机制重传。我这篇笔记重点讲信道编码的部分,也就是FEC里的那些核心内容,但先把这套框架搞清楚,后面看什么协议都容易理解。
2. 读懂信道编码的几个关键参数
2.1 汉明距离:衡量编码能力的那把尺子
学习信道编码,绕不开一个概念:汉明距离(Hamming Distance)。两个等长码字之间,对应位置上不同bit的个数,就叫汉明距离。比如10110和10010,只有第3位不一样,那它们的汉明距离就是1。
一个编码方案里,所有码字两两之间的汉明距离,取最小值,就是该编码的最小汉明距离,记作d(min)。这个值就是判断编码能力的关键参数。
为什么d(min)这么重要?因为接收端做译码时,默认遵循“最大似然”原则:谁离接收序列最近(汉明距离最小),就判谁是发送码字。如果发送码字A在传输中错了一个bit,它可能还是离A最近,接收端能正确译码;如果错了太多bit,导致它离另一个合法码字B更近了,那接收端就会错误地译成B。所以,最小汉明距离直接决定了这个编码能“救回来”多少错位。
严格来说,一个编码的最小汉明距离为d(min),它最多能检测出 d(min)-1 位错误,最多能纠正 ⌊(d(min)-1)/2⌋ 位错误。这个结论要记牢,后面所有编码的性能分析都建立在这条规则上。
2.2 编码增益:编码带来的“虚拟功率提升”
做通信系统的人,常提到编码增益(Coding Gain)。这个指标特别直观:在相同的误码率要求下,用了信道编码之后,需要的信噪比(Eb/N0)可以降低多少dB。这省下来的dB数,就相当于编码白送给你的“虚拟功率”。
举个例子,假设未编码的系统要达到1e-5的误码率,需要8dB的Eb/N0;加上某种纠错编码后,同样误码率只需要4dB,那这个编码就提供了4dB的编码增益。在发射功率不变的前提下,这意味着你可以传更远的距离,或者在有更多干扰的环境下依然稳定工作。发射机功率翻一倍,也就增加3dB的增益,一个好编码能省下好几个3dB,这就是信道编码的威力所在。
这个指标在做系统预算的时候特别实用。我之前设计一段无线链路,链路余量差1个dB死活凑不齐,后来换了更强的信道编码,编码增益直接补回来2-3个dB,问题一下就解决了。很多硬件上悬而未决的问题,其实换个编码方案就能绕过去。
2.3 码率与冗余的取舍
信道编码的本质,是在原始信息中加入冗余。加入的冗余越多,纠错能力越强,但同时真正有效的信息传输速率也会降低。衡量这个关系的指标叫码率(Code Rate),记为R。
一个分组码通常写成(n,k),意思是每k个信息bit,编码后变成n个bit,其中(n-k)个是冗余校验bit。码率就是R = k/n。R越高,说明冗余占比越少,传输效率越高;R越低,说明冗余越多,纠错能力更强,但有效吞吐率也更低。
很多初学的人会问:码率低一点,最好干脆用1/2码率,是不是误码性能一定最好?其实不一定。码率太低会导致频谱效率下降,相同带宽下能传的信息速率变小,系统总吞吐反而可能变差。所以在实际系统设计里,码率的选择往往是一个平衡:先满足误码率和时延要求,再尽量把码率提高一点,让系统的有效吞吐更大。后面的LDPC、Turbo码为什么能灵活调整码率,正是为了在多种信道条件下寻找这个平衡点。
3. 几种常用信道编码的实战拆解
3.1 CRC循环冗余校验:工程现场最离不开的检错码
如果要选一个每个通信工程师都用过的编码,那一定是CRC(Cyclic Redundancy Check,循环冗余校验)。它属于循环码的一种,主要用来检错,不纠错,但实现简单、检错能力强大,在以太网、Wi-Fi、蓝牙、USB、存储系统里到处都是它的影子。
CRC的原理,可以理解成把数据当作一个多项式,用生成多项式G(x)去做模2除法,余数就是校验码。发送端把数据后面附上余数,一起发出去。接收端收到后,用同样的G(x)去除整个码字,如果余数为0,就认为数据没有出错;如果不为0,就直接判定数据出错。
实际工程里选CRC多项式是有讲究的。比如常见的CRC-16-CCITT(多项式0x1021),适合一般的串口通信;CRC-32(多项式0x04C11DB7),以太网在用,检错能力更强。注意,CRC的检错能力取决于多项式阶数,阶数越高,越不容易漏检。但不是说用了高端的CRC就万事大吉,CRC只是“检错”,发现错误之后还得靠重传或丢弃来处理。
我特别提醒一下,CRC实现里的初值、异或输出、输入反射这几个细节,很容易出错。不同厂家协议里定义的CRC参数可能完全不一样,如果双方配置不一致,哪怕数据本身没错,算出来的CRC也对不上,这个问题在联调的时候很容易坑人。
3.2 汉明码:最经典的线性分组码
汉明码是1950年由Richard Hamming提出的,属于线性分组码。它的特点是能用最少的冗余bit完成“单比特纠错”,适合信道差错率不高、主要以随机单比特错误为主的场景。经典的(7,4)汉明码,每4个信息bit配上3个校验bit,能纠正1个错误bit。
它的原理本质上是把一个码字划分到若干个校验方程组里去。每个校验方程对应一个“监督关系”,接收端根据校验结果算出一个“校验子”(Syndrome),这个校验子的二进制数值直接告诉你是哪个bit错了。举个例子,(7,4)汉明码有3个校验方程,可以产生3位校验子,3位二进制可以表示8种状态,其中7种分别指示7个码元位置的错误,剩下一种表示“没错”。
很多教材会把汉明码讲得很复杂,矩阵、生成矩阵、监督矩阵一大推。但理解汉明码的钥匙其实是“校验子定位错误位置”这件事。简单说,发送端构造码字时,让每个校验bit和部分信息bit构成偶校验关系;接收端收到后,重新按这种关系做校验,每个校验位的计算结果组合起来,就能“算”出错在哪里,直接取反就能纠正。
汉明码在现代系统里已经很少单独当主力用,但它的价值在于揭示了“冗余如何换来纠错能力”的本质,是理解更复杂线性分组码的基础。当年我做第一版遥测系统时,就是用(7,4)汉明码做纠错,把指令链路的误码率从千分之一级别拉到了十万分之一级别,效果立竿见影。
3.3 卷积码:用状态记忆换取更强的纠错能力
分组码处理的是一个一个独立的分组,而卷积码的思路完全不同:它不是把数据切成独立的块,而是让编码器像一个移动的“滑窗”,每个输出bit不仅和当前输入bit有关,还和之前若干个输入bit有关。
卷积码的输入输出关系可以用三个参数描述:(n,k,m)。k表示一次输入几个bit,n表示一次输出几个bit,m表示编码器里移位寄存器的个数(也叫约束长度相关参数)。常见的如(2,1,7)卷积码,每输入1bit,输出2bit,码率为1/2,约束长度较长,纠错能力不错。
卷积码的译码,最经典的是Viterbi译码算法。它把编码器的状态转移看成一张“篱笆图”(Trellis图),接收序列进来后,在每个时刻都保留“幸存路径”,最后选一条整体度量最优的路径当作译码结果。这个算法的本质是动态规划,把指数级的搜索复杂度降到了可接受范围。Viterbi译码里用到的度量通常是汉明距离(硬判决)或者欧氏距离(软判决)。软判决比硬判决一般能多拿大约2dB的增益,工程里会做软判决尽量做软判决。
我早期用FPGA实现过一个Viterbi译码器,踩过最大的坑是“路径度量溢出”。因为幸存路径度量会随着时间累积越来越大,如果不做归一化缩减,定点数早晚溢出。解决办法是在度量值到一定阈值时,统一把所有路径度量减去一个基准值,这样不影响路径比较结果,又不会溢出。
卷积码在2G/3G时代是绝对主力,直到现在很多卫星通信、深空通信、语音业务里依然在用。它的优点是实现成熟、延迟可控;缺点是码率固定,灵活性差一些,而且性能天花板不如Turbo码和LDPC码。
3.4 交织与级联:对付突发差错的两个实用思路
信道编码的经典理论大多假设错误是随机独立出现的,但实际信道里,错误经常不是“零散分布”的,而是一来就一大片。雷暴天气下的微波链路、高速移动环境下的多径衰落,都会导致连续的bit被破坏,这种错误叫突发差错。
如果错误突发长度超过了编码的纠错能力,再好的FEC也会崩溃。这时候就需要交织(Interleaving)。交织的思路特别直白:把数据按行写入、按列读出,或者更复杂一点按某种伪随机顺序排列,让原本相邻的bit在传输时被拉得很远。接收端做“去交织”把顺序还原,原本连续的一长串错误,就被打散成了若干单独的随机错误,正好落进FEC的纠错范围。
很多系统里还会把两种编码级联在一起,比如外码加上内码:内码负责纠掉大部分信道错误,外码负责“扫尾”,清理内码没处理干净的残余错误。最典型的案例就是CDMA/卫星通信里的“卷积码+RS码”级联,卷积码先做粗纠,RS码再针对残余突发错误做纠错,两级配合下来,误码率能降到极低。这个思路在今天的高性能系统里依然沿用,只是内码换成了更强大的Turbo或LDPC。
3.5 现代高性能编码:Turbo码、LDPC码和Polar码
Turbo码是3G/4G时代绕不开的名字。它的核心思想是“并行级联卷积码 + 迭代译码”:两个分量编码器对同一份数据做不同顺序的编码,译码时两个译码器不停交换“软信息”,像两个人反复讨论修正对方的判断。这种迭代译码的机制,让Turbo码逼近了香农极限,在相当长一段时间里都是信道编码的热门选手。
LDPC码(低密度奇偶校验码)是5G和很多现代通信系统的主力编码。它不是靠复杂的编码结构取胜,而是靠“稀疏校验矩阵”配合迭代译码算法。LDPC译码里最常见的是置信传播(BP)算法,核心是让每个校验节点和信息节点在因子图上传递概率信息。LDPC的一个突出优点是校验矩阵可以设计得很稀疏,译码复杂度可控,而且可以通过打孔(Puncturing)技术方便地调整码率,特别适合自适应调制编码的场景。
Polar码是信道编码家族里比较年轻的一个,也是5G控制信道采用的编码方案。它的基本原理叫做“信道极化”:通过对多个信道进行合并与拆分,一部分信道变得特别好,一部分信道变得特别差,直接把信息放在那些好的信道上传输。Polar码的理论基础非常漂亮,是第一个被严格证明可以达到信道容量的编码方案。
从实践来看,具体选哪种编码,主要看场景:低时延且实现简单的场合,卷积码+交织往往性价比很高;接近香农极限但可以接受一定译码复杂度的场合,LDPC是当前主流;如果要在很宽的码率范围内灵活调整,LDPC优势更明显;Polar码在短码、控制信道这类场景里表现也很亮眼。
4. 工程实战:选型经验与问题排查
4.1 不同场景下怎么选编码方案
选编码方案不能只看性能曲线,还得看功耗、时延、复杂度、专利、硬件资源、协议兼容性。我根据这些年做项目的经验,列一个直观的选型对照表:
| 使用场景 | 推荐方案 | 理由 |
|---|---|---|
| 低速传感器/遥控遥测 | CRC检错 + 重传 | 简单可靠,成本极低 |
| 实时语音/短报文 | (7,4)汉明码 / 卷积码 | 低时延,硬件开销小 |
| 卫星/深空通信 | 卷积码 + RS码 / LDPC | 高增益,抗极端信道 |
| 移动通信数据信道 | Turbo / LDPC | 逼近香农限,码率灵活 |
| 光纤/存储系统 | LDPC / BCH | 吞吐高,误码率要求极高 |
| 5G控制信道 | Polar码 | 短码性能好,标准化成熟 |
这张表不是绝对标准,但能反映一个核心趋势:没有“最强编码”,只有“最合适的编码”。你在一个具体项目里,先列需求指标——误码率、时延上限、吞吐率、FPGA/DSP资源、许可协议限制,再把这些约束代进去选。我见过不少团队一上来就追求最先进的LDPC,结果FPGA资源吃紧、时延超标,最后不得不回退到卷积码。先把需求边界画清楚,再谈选型,顺序不能反。
4.2 误码率上不去的几个常见原因
在实际调试里,编码也加了,参数的曲线看起来也对,可误码率就是达不到预期,这种情况很常见。我整理了几个高频原因,你可以逐条排查。
第一个原因是收发端编码参数不一致。两边使用的生成多项式、码率、交织深度、打孔模式只要有一处不一样,整个编解码就失效。这类问题往往表现为“单环测试没毛病,对接就错乱”。联调之前先把双方的编码参数列表逐项核对一遍。
第二个原因是比特序问题。很多编码算法对bit顺序敏感,编码前和数据进调制之前,比特是否经过反转、字节是否做了大小端转换,都会影响结果。特别是从外部IP核拿来的编解码器,经常和你的系统比特序不同,需要加额外的bit重排逻辑。
第三个原因是硬判决丢失了软信息。同一个编码,硬判决译码和软判决译码能差出2dB左右。如果你的系统ADC分辨率不够,软信息量化位数太少,编码增益会被白白浪费掉。很多团队在仿真里用浮点软判决,到FPGA定点化时压缩到3bit、4bit,性能就掉了一截。我的经验是软信息至少给5bit量化,低于这个值编码实际增益会明显打折。
第四个原因是交织深度不够。如果信道模型是突发错误很多的快衰落信道,交织深度必须超过突发长度。可有时候突发长度是变化的,你得按最恶劣情况设计交织深度,否则突发一长,FEC就被冲垮了。
第五个原因则是同步问题。编码系统对同步的要求比裸数据更高——帧同步不准确,解出来的序列整个移位,译码器看到的是完全错误的码字。排查这类问题时,先用固定测试图案发一遍,看译码输出是否完全对齐,再逐步加入噪声测试。
4.3 从仿真到工程落地的一些经验心得
做信道编码的仿真和把编码器放到真实系统里跑,完全是两件事。仿真里你可能用浮点模型验完性能就结束了,但工程落地要处理一连串实际问题。
第一件是定点化的精度问题。前面提过软信息量化,这是最关键的一处。Viterbi译码里的路径度量、LDPC的置信传播消息,在浮点模型里没什么压力,但转成定点数后,每级迭代都会累积量化误差。我在FPGA上调LDPC的时候,发现定点化之后误码平台比仿真高了一截,后来把消息更新的scale因子做微调,才把性能拉回来。这种微调没有捷径,只能先对照仿真曲线逐点排查。
第二件是时序和吞吐的折中。译码器往往比编码器复杂得多,特别是迭代译码器,每次迭代都要一段时间。如果你的系统对时延有硬要求,比如实时控制链路,那么多迭代几次虽然性能更好,但时延可能就超了。一个取巧的做法是固定最大迭代数,比如LDPC译码迭代8次,当检测到校验子全部为0时提前退出,大部分帧根本跑不满8次,平均时延大幅下降。
第三件是加扰/白化的问题。有些编码方案里会有连续的长串0或长串1,这可能让接收端的时钟恢复和均衡器工作点漂移。正规系统里通常在编码之前先做加扰,让数据流足够随机。我见过有团队在实验室里用全0测试序列调通了系统,上了真实业务数据后又出问题,最终查出来是缺少加扰环节导致的直流偏置。
第四件是协议兼容性。现代通信系统通常都规定了必须使用哪种编码方案,比如Wi-Fi里从卷积码到LDPC的演进是分不同标准的,你不能在旧设备上强行用新编码。所以在设计一个系统前,先看清楚目标协议支持哪些编码方式,再做编码选型决策,省得后期推倒重来。
还有一个经验,就是多留测试接口。编码器/译码器模块最好都能通过寄存器配置切换不同的码率、不同迭代次数、不同软判决位宽,同时在板子上留出“误码统计器”的观测接口。有了这些,你在外场测试时就能快速对比不同配置的实际表现,而不必回实验室重跑一遍测试。这个习惯帮我省了特别多时间。
5. 最后分享一点个人的体会
做通信系统这些年,我最深的一个感受是:信道编码不是万能药,但它是最具性价比的可靠性手段之一。很多人一开始会神化编码,觉得加了编码就一定能解决问题;也有一些人过于轻视编码,觉得只要把射频链路调好就够了。这两种极端,我在项目里都见过,最后都付出了代价。
实际做链路预算时,我常用的一个思路是这样的:先把调制方式、带宽、发射功率这些约束条件列出来,算出基础信噪比,然后看离目标误码率还差多少dB。差的这几十dB,先用信道编码去补,实在不够再调整发射功率或天线增益。这样既不会过度设计,也不会留下性能短板。
另外,学习信道编码不要只停留在公式推导上,一定要亲手做一次从编码到调制、过信道、解调再译码的闭环仿真,再去FPGA或DSP上实现一次定点化的编解码器。过程中踩过的坑——比特序、定点精度、同步、交织深度——比你看十本书都管用。
关于后续扩展,信道编码和数据压缩算是一对互补的“编译码工程师”必修课——一个负责去掉冗余提高效率,一个负责增加冗余保障可靠。把这两块串起来看,你对整个通信链路的理解会通透很多。这篇笔记里的内容,我后续也会顺着这个方向继续整理下去。