ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

BCH-极化码级联设计:循环码与极化码如何配合消除误码平台

BCH-极化码级联设计:循环码与极化码如何配合消除误码平台 简介面向通信专业学生、竞赛选手与算法研究人员这套MATLAB源码包聚焦信道编码核心主题覆盖BCH码、极化码、汉明码、卷积码及循环码的编码与译码实现可用于课程设计、通信仿真与算法改进。包内含48个m文件均为MATLAB源码压缩后仅34KB体量虽小却五脏俱全既有BCH.m、hamming.m、cycle.m等基础编码程序也有极化码SSC实现、code_turbo交织分析、维特比译码及香农极限计算等进阶内容。各脚本结构清晰注释与参数设置便于直接运行修改帮助读者理解伽罗华域运算、信道极化现象、冗余纠错机制等抽象概念。目前已有373人学习下载适合需要结合理论做仿真验证的入门与进阶用户。1. 信道编码_BCH-polar到底在做什么把循环码和极化码绑在一起的理由做信道编码选型时我见过太多团队盯着极化码的理论增益却没有把BCH这类循环码一起考虑。单独用极化码中短码长下误码平台很难压下去单独用BCH码信噪比低了以后纠错能力又不够。BCH-polar级联的思路就是让极化码逼近香农限让BCH码作为外码把残余错误再清一遍。这个标题里的“循环”并不只是说BCH码是循环码还牵扯到极化码常用的CRC循环冗余校验。本文讲透两者怎么配合、参数怎么设、仿真怎么做以及哪些坑会让人反复翻车。2. 两类码的两条主线BCH码的循环结构与极化码的信道极化2.1 BCH码的循环结构生成多项式决定能纠几个错BCH码是一大类纠错码它的名字来自Bose、Chaudhuri和Hocquenghem。工程上最常遇到的BCH码都是二进制循环码也就是说码字的循环移位仍然是合法码字。正是这个循环性质让BCH码的编码可以用一个生成多项式 (g(x)) 通过GF(2)多项式取模完成译码也可以用校验子加Chien搜索或Berlekamp-Massey来实现。循环码的编码最常见的做法是系统编码。假设外码码长是 (n)信息位长度是 (k)校验位长度就是 (n-k)。把信息多项式 (d(x)) 左移 (n-k) 位变成 (d(x)x^{n-k})然后对这个多项式除以生成多项式 (g(x))余数就是校验位。整个过程和CRC循环冗余校验在数学上是同一套除法区别只在于BCH码对生成多项式的选择有严格的设计距离约束而CRC只要求检错能力。生成多项式是BCH码的“命根子”。设计距离 (d) 决定了能纠正多少个错误。对二进制BCH码如果要在码长为 (n2^m-1) 的本原BCH码上纠 (t) 个错生成多项式要取若干最小多项式的LCM使得码的最小距离 (d_{\text{min}} \ge 2t1)。例如 (t1) 的汉明码就是BCH码的一个特例(t2) 的BCH(15,7,5)也是工程里很常见的短码。参数上最直观的关系是生成多项式的次数越高校验位越多码率越低但纠错能力越强。比如BCH(7,4)生成多项式次数是3能纠正1位错误BCH(15,7,5)生成多项式次数是8能纠正2位错误。实际选型不要凭感觉定 (t)。我一般先看剩余误码平台的量级再决定外码要不要 (t2) 或 (t3)因为BCH每多一位纠错能力码率都会明显下降。2.2 极化码的信道极化SC译码和CRC辅助的SCL靠“循环冗余”选路径极化码不是循环码而是基于信道极化现象的线性分组码。它的核心思路是把一堆独立信道的组合通过递归的极化变换拆成容量不同的虚拟信道。一部分信道容量接近1传信息位另一部分容量接近0固定发约定值也就是冻结位。只要传输的信息放在那些“好”的信道上整体就能逼近信道容量。编码端Arkan给出的变换矩阵可以递归定义。通常取[ F \begin{bmatrix} 1 0 \ 1 1 \end{bmatrix} ]然后对长度 (N2^n) 做 (n) 次Kronecker幂得到生成矩阵 (G_N)。信源比特 (u_1,\dots,u_N) 中信息位放在可靠性高的位置冻结位固定为0编码输出就是[ x_1^N u_1^N G_N ]信道符号调制后经过AWGN或衰落信道接收端用串行抵消译码也就是SC译码逐位估计信源比特。SC译码的问题是一旦某一位判错后续位会被带偏。工程上大规模应用的是CA-SCL也就是带CRC校验的串行抵消列表译码。SCL译码器不再只保留一条路径而是同时保留 (L) 条候选路径最后用CRC循环冗余校验从候选路径里选出一条校验通过的。这里的CRC码本身是循环码虽然只负责检错不负责纠错但它和“循环”的关系非常大。很多人误以为极化码依赖CRC就等于用了BCH实际不是CRC只是SCL的路径筛选器BCH才是真正能纠错的循环外码。3. 外码BCH、内码极化的级联设计参数怎么选才不浪费3.1 为什么是“BCH在外、极化在内”而不是反过来级联码的内外层次看的不是哪边“更好”而是哪边“更适合补哪类错”。极化码在低信噪比下逼近香农限的能力很强但在码长有限时错误分布不是均匀的SCL译码失败时错误的比特往往集中在一小段内或者以误码平台的形式出现在高信噪比区域。BCH码对独立随机错误有着明确的设计距离虽然纠突发错误能力不强但把极化码输出中的剩余错误当作随机错误来处理是有效的。反过来如果把极化码放外面、BCH放里面外部极化码接收的是BCH硬判决后的硬比特软信息就丢了而且极化码需要长码才能发挥极化效果放在外码位置会让整体时延变大。所以“BCH在外、极化在内”是更常见的做法极化码先把信道噪声和衰落啃掉一大块BCH再做一次硬判决纠错把极化码没啃干净的小部分残余错误收尾。还有个实际工程原因BCH外码可以采用硬判决输入译码复杂度低适合放在极化SCL译码后面做最后一道接口而极化内码可以直接输出软判决、LLR和路径度量。两级之间的信息不需要来回迭代链路的时钟和存储压力都小很多。3.2 码率分配和生成多项式一组可复用的起步参数级联码的码率不是两个码直接相乘那么简单要先确保外码码字长度能被内码信息位长度装下。设有用信息位 (K)BCH外码码长 (N_{\text{bch}})极化内码码长 (N_{\text{polar}})那么总码率是[ R \frac{K}{N_{\text{polar}}} ]内码的信息位长度必须等于 (N_{\text{bch}})否则要加缩短BCH或者打孔。下表是我在链路仿真里常用的起步参数适合先跑通再调场景内码信息位极化码长BCH外码总码率适用说明短包控制信道1532BCH(15,7,5)缩短匹配7/32先验证链路和误码统计中包数据51128BCH(63,51,5)51/128中等负载外码冗余小长包数据106256缩短BCH(127,106,7)106/256需要更低误码平台要注意这里BCH(15,7,5)的生成多项式不能随手写必须查表或按设计距离求最小多项式LCM。常见的选择是取 (g(x)) 次数为8但不同原多项式得到的生成多项式不一样。我实际用的时候会先用MATLAB或者其他现成函数库查一遍标准多项式再在Python里固化下来避免因为原多项式选择不同导致仿真结果对不上。极化内码的冻结位位置也不是随便放。工程上最稳妥的做法是先做一个信道容量排序或者用高斯近似给每个比特位算可靠性再确定信息位集合。5G NR的极化码有协议里的排列顺序但那套顺序是针对LDPC外码设计的不能直接照搬到BCH级联上必须根据当前码长和码率重算。3.3 两层的循环关系BCH校验子与CRC路径选择不能互相顶替BCH外码有校验子计算极化SCL有CRC路径校验两者都用了循环码的除法结构但作用完全不同。BCH的校验子用于定位错误位置并纠错CRC的校验结果只用于从SCL候选列表里剔除错误路径。一个负责“纠”一个负责“选”不能互换。实际设计时我见过有人为了省那几比特CRC把BCH外码的校验位砍掉想让SCL自己选对路径。短码下多数时候能工作但到高信噪比时会突然出现误码平台因为SCL在没有CRC筛选时list内的正确路径一旦被剪掉就完全没有后悔药。反过来说如果只靠CRC不靠BCH遇到极化译码输出中出现多个持续错误时CRC只能检测到失败无法告诉极化码该怎么修正。所以两级都有存在的必要但冗余也要克制第一版配置里我会保留BCH设计距离纠1~2位CRC用8位或16位再根据平台位置调整。4. 用Python跑通最小BCH-polar链路GF(2)模运算、极化矩阵与误码统计4.1 GF(2)多项式取模BCH编码的地基BCH编码的核心是GF(2)多项式除法。下面这段代码用int的二进制位表示多项式系数直接把数据左移后做模运算校验位就是除法余数。def gf2_poly_mod(data, gen): GF(2)多项式取模data、gen都是intbit位代表多项式系数。 g_len gen.bit_length() while data.bit_length() g_len: data ^ gen (data.bit_length() - g_len) return data逻辑说明每次循环先把生成多项式的最高次对齐到被除数最高位然后做异或减法。GF(2)里减法和加法都是异或所以不需要处理借位。循环一直做到被除数的位数小于生成多项式为止返回值就是余数。参数说明data是被除数gen是生成多项式。生成多项式的bit长度必须严格大于0如果把gen传成0b1011对应多项式就是 (x^3x1)也就是BCH(7,4)的标准生成多项式。这段代码也是CRC循环冗余检查的基础换一个gen就是另一种循环冗余码。4.2 BCH(7,4)编码与1bit纠错最小闭环样例用上面这个模运算编一个BCH(7,4)码字非常短def bch74_encode(msg): msg是4bit整数输出7bit BCH码字。 gen 0b1011 # x^3x1 data msg 3 # 信息位左移3位预留校验位 parity gf2_poly_mod(data, gen) return data | parity def bch74_decode(r): 接收7bit码字只纠正1bit错误返回信息和纠正位置。 gen 0b1011 for i in range(7): if gf2_poly_mod(r ^ (1 i), gen) 0: corrected r ^ (1 i) return corrected 3, i return r 3, None逻辑说明编码时msg 3让信息位占据高位低3位放校验位gf2_poly_mod算出的余数就是校验位。解码时遍历7个可能的比特错误位置把每个位置上翻转后的码字再做一次模运算如果余数为0说明翻转后变成了合法码字这个位置就是错误位置。BCH(7,4)的最小距离是3所以只能保证纠正1位错误。参数说明msg必须小于16函数里硬编码了gen0b1011如果换生成多项式要根据新的码长调整循环次数。这个纠错方法在小模型上很好用但对于大码长遍历所有位会浪费算力工程上要改成校验子查表或Berlekamp-Massey。4.3 极化码生成矩阵与编码Kronecker幂实现极化码的生成矩阵可以递归用Kronecker积构造。下面的代码只做编码部分适合先把链路打通import numpy as np def polar_generator(n): 生成n2^m的极化码生成矩阵。 F np.array([[1, 0], [1, 1]], dtypeint) G F while G.shape[0] n: G np.kron(G, F) return G def polar_encode(inner_msg, info_pos, G): inner_msg是内码信息位整数info_pos是冻结位表。 n G.shape[0] u np.zeros(n, dtypeint) bits np.array([(inner_msg i) 1 for i in range(len(info_pos))], dtypeint) u[info_pos] bits return (u G) % 2逻辑说明polar_generator不断把基础核矩阵 (F) 和自身做Kronecker积长到指定码长。polar_encode把一个整数信息位按位拆开放到info_pos指定的信息位位置上冻结位默认置0然后乘生成矩阵。向量是行向量矩阵乘法后取模2得到编码后的比特。参数说明n必须是2的幂info_pos的长度必须等于内码信息位数量。第一版做链路自检时可以先用一个近似的可靠性顺序例如把位置数组取成[5,6,7,9,10,11,12]但正式仿真前必须用高斯近似替换否则性能偏差会让人误以为级联方案失效。4.4 仿真主循环BCH外码、极化内码、AWGN和误码统计下面的主循环没有展开SC译码器而是用极化生成矩阵的自逆性做线性反变换得到一个能跑通链路的基线。它不用于真实性能评估只用于确认编码、调制和统计模块没写错。def simulate_trial(msg, esno_db, info_pos, G): cw bch74_encode(msg) # 外码4bit - 7bit tx_bits polar_encode(cw, info_pos, G) # 内码7bit - 16bit tx 1 - 2 * tx_bits # 0映射成11映射成-1 snr_linear 10 ** (esno_db / 10.0) sigma np.sqrt(1 / (2 * snr_linear)) rx tx np.random.normal(0, sigma, sizetx.shape) rx_bits (rx 0).astype(int) # 硬判决0表示LLR0 u_hat (rx_bits G) % 2 # G自逆线性反变换 cw_hat 0 for i, pos in enumerate(info_pos): cw_hat | int(u_hat[pos]) i msg_hat, _ bch74_decode(cw_hat) return msg_hat msg逻辑说明每个循环里先做BCH编码再把7位BCH码字塞进极化码的7个信息位输出16位码字。调制后加高斯白噪声接收端先硬判决再用生成矩阵反变换回信源端。最后用BCH译码器纠正1位硬判决错误比较最终信息是否一致。参数说明esno_db是符号信噪比不是比特信噪比。因为系统有纠错编码比特信噪比需要加上码率的换算。sigma的计算来自BPSK在AWGN下噪声方差和符号能量1的关系如果换QPSK或高阶调制这里的公式要一起改。这里要特别强调线性反变换不是极化码真正的工作方式。它只是保证编码链路自洽的自检基线真实方案必须用SC或者SCL译码器替换这一层否则高信噪比下的误码平台会完全失真。5. BCH-polar级联避坑笔记生成多项式、SCL列表和循环冗余检查的四个坑5.1 现象BCH生成多项式随手给一个短码能用中长码全部崩溃原因BCH码的生成多项式必须与设计距离、码长配套。中长码下如果生成多项式次数不够实际最小距离达不到预期纠错能力直接从 (t2) 掉到 (t1) 甚至更差。表面上是信道问题实际上是代数结构没算对。解决不要背常数也不要拍脑袋。固定查表得到标准本原多项式后再按 (g(x) \operatorname{lcm}(m_1(x),m_3(x),\dots,m_{2t-1}(x))) 计算生成多项式。完成之后用随机错误注入验证一遍每个重量小于等于 (t) 的错误模式都能被纠正再进入蒙特卡洛仿真。5.2 现象SCL译码器把CRC校验位当成信息位一起编码列表选路径全乱原因CRC辅助极化码的常规做法是把CRC-16或者CRC-8附加在信息位之后再一起做极化信息位的可靠性排序。如果CRC位和真实信息位混在一起做可靠性分配SCL列表里的候选路径就无法区分“校验失败”和“真实数据损坏”路径选择完全失去意义。解决先把外部BCH码和信息位合并再用CRC做一次路径约束最后才做极化信息位分配。顺序不能反。具体到链路是先加CRC还是先加BCH要看级联结构如果BCH在外那么CRC应该放在极化内码的信息位里BCH编码在CRC之前。每加一层冗余都要明确它究竟服务于哪个译码器。5.3 现象SCL译码器list值一调大BCH外码不仅没帮忙误码率反而上升原因这是典型的冗余越界。SCL译码器list增大后内部译码已经逼近最优最大似然性能此时BCH外码如果仍采用硬判决译码无法利用极化码内部的软信息反而会把部分正确候选路径当作错误路径纠正。两级码之间不匹配时冗余越高损失越明显。解决先固定list值观察误码平台落在哪个信噪比再决定BCH外码是否需要存在。如果list已经够大且平台已经低于系统要求可以把外码去掉只保留CRC。如果仍然需要BCH就让SCL输出候选路径的软信息而不是只输出硬判决比特让BCH在可能有二义性的位置做最小距离纠错。5.4 现象仿真平台报类似“ERR 23数据错误循环冗余检查失败”的错链路却查不出问题原因这个报错往往不是信道噪声造成的而是收发两端的数据打包顺序不一致。极化码编码前BCH码字的比特位被塞进信息位时谁在高位谁在低位没有统一接收端反序列化时按另一种顺序组合于是CRC循环冗余检查总是失败BCH校验子也永远对不上。解决给每一个码字定义一个明确的比特排序函数在BCH编码、极化解码和CRC校验三个位置做同一个位序变换。我的习惯是在仿真代码里定义一个pack_bits和unpack_bits先做单元测试保证无噪条件下1000个随机包全部通过再开始跑AWGN。循环冗余检查报错永远先怀疑打包顺序而不是先怀疑信道。6. 验证与进阶误码率曲线、SCL list和外码纠错能力的配合拿到一套BCH-polar级联方案第一步不是跑大仿真而是先做无噪冒烟测试。用4.4节那个最小链路把噪声方差设成0随机生成几千组信息要求误比特数严格为0再人为翻转BCH外码的1位、2位验证译码器行为是否符合设计距离。这两步过了再上AWGN。进阶验证时要同时看三条曲线第一是内码极化码单独跑的误字率和误码平台第二是加外码BCH后整体误字率第三是SCL译码器中list分别为4、8、16时的对比。判断方案值不值得投入关键不是看低信噪比区而是看高信噪比区有没有平台。如果平台打不下去多半是SCL路径选择和外码纠错能力没有配合好先调list再调BCH的 (t)不要一上来就改码长。我现在做信道编码_BCH-polar这块习惯是先写短码版本跑通端到端再逐步扩码长。长码极化码的冻结位排序是玄学最多的部分没有现成协议表时就花半天做一遍高斯近似可靠性计算比靠感觉猜强得多。希望帮到你。本文还有配套的精品资源点击获取
返回列表