LDPC信道编解码MATLAB仿真:从校验矩阵到BER曲线一次跑通
发布时间:2026/10/1 18:23:03来源:尧图网络
简介低密度奇偶校验LDPC码是一种逼近香农限的高效纠错编码技术在5G无线通信、卫星与深空通信、数据存储等领域应用广泛。面向通信工程、电子信息类专业学生及技术开发者压缩包以MATLAB程序还原LDPC信道编解码的关键环节可用于理解稀疏校验矩阵构造、BP信念传播迭代解码等核心机制。包内共有1个文件为.m格式的MATLAB脚本体积约4KB代码结构紧凑便于直接阅读与调试。目前已有155人浏览学习说明该主题具有一定的关注度。通过研读该脚本读者能够梳理编码端生成矩阵与校验矩阵的关系掌握硬判决初始化、消息传递及迭代停止等解码流程结合AWGN信道下的噪声模拟与误码率评估还可以直观观察不同解码参数对系统可靠性的影响为后期学习Polar码、Turbo码等先进编码技术打下坚实基础。1. LDPC 信道编解码这套 MATLAB 脚本帮你把校验矩阵到 BER 曲线一次跑通做过物理层仿真的人都知道LDPC 信道编解码是 5G NR、Wi-Fi、卫星通信里绕不开的一环。5G 物理层数据信道选的就是 LDPC 码原因很直白逼近香农限、支持并行解码、错误地板可控。可真正想跑通一套完整的 LDPC 编解码并不轻松光校验矩阵构造、生成矩阵求取、BP 解码迭代这几个坎就能卡掉不少人。这套 LDPC.rar 里只有一个 LDPC.m但它把编码、加噪、解码、误码率统计的主流程串起来了——解压后改改码长、信噪比范围就能直接跑。适合做物理层算法验证、毕业设计选信道编码方向或者想从 Turbo 码切到 LDPC 的工程人员当起点脚本。2. 先把 LDPC 码的底子打牢稀疏校验矩阵、Tanner 图与 LDPC.m 的文件主线拆这套资源之前先聊一个很多人不重视的点LDPC 的「低密度」到底低在哪又为什么值得你花时间理解。LDPC 码由 Robert Gallager 在 1962 年提出核心是一个稀疏校验矩阵 H。H 的每一行对应一个校验方程每一列对应码字里的一个比特。“低密度”指 H 中非零元素占比非常低——通常每行每列只有几个 1其余全是 0。正是这种稀疏性让 BP 解码的消息传递变得可行也让码的性能可以逼近香农限。2.1 为什么「低密度」是关键H 矩阵的结构与 Tanner 图H 矩阵有两个最基本的参数行重和列重。列重是每列中 1 的个数行重是每行中 1 的个数。如果所有行重、列重都一致叫规则 LDPC 码如果不一致叫非规则 LDPC 码。工程里常见的列重取 2 到 4行重按码率自然推出来。列重太小H 容易出短环列重太大解码性能又会被拉低。这个平衡是构造 H 时的第一道选择题。构造方式大致分两类。一类是随机构造比如 Gallager 的原始方法、Mackay 的随机生成法核心是随机摆放 1 的位置再通过约束剔除坏结构。另一类是结构化构造典型代表是准循环 LDPCQC-LDPC——基矩阵里的每个元素被替换成循环移位矩阵或零矩阵5G NR 选的就是这种。结构化构造的好处是存储量小、便于硬件并行这也是为什么 5G LDPC 基站侧和终端侧都愿意用它。理解 Tanner 图对调参非常重要。Tanner 图把 H 矩阵画成两类节点变量节点对应列校验节点对应行非零元素就是连接边。当图中存在长度为 4 的环girth4两个校验节点之间会有两条不同路径连通BP 解码时消息会在环里循环累积外信息就失真了。所以构造 H 时至少要让 girth 达到 6。这套资源里的 LDPC.m 如果用的是随机生成 H跑出来的性能曲线在高信噪比段出现水平地板第一嫌疑就是短环。2.2 LDPC.m 里的文件主线与仿真流程这类信道编解码脚本的结构通常很清晰从参数设置到 BER 统计是一条直线。展开 LDPC.m 后代码主线大概是先定义码长 n、校验位数量 m、最大迭代次数 max_iter 和信噪比扫描范围然后生成 H 矩阵再由 H 求生成矩阵 G编码后过 AWGN 信道接收端做 BP 解码最后统计不同 Eb/N0 下的误码率。这个流程没有多余的模块适合做单次仿真也适合套一层外部循环做性能扫描。参数典型取值对仿真结果的影响码长 n192 / 648 / 1296 / 1944码越长越逼近香农限但每次仿真耗时近似线性增长码率 R1/2、2/3、3/4由 H 行数决定R (n-m)/n行数越多冗余越大列重 dv2~4列重 2 容易出短环列重 3 是性能和复杂度折中最大迭代次数5~50太小误码率下不去太大只增加耗时不显著提升性能调制方式BPSK / QPSKBPSK 的 LLR 公式最简单QPSK 可视为两个 BPSK拿到脚本后我建议先不改性能参数原样跑一遍确认 BER 曲线能随 Eb/N0 增加平滑下降。跑通之后再逐个改码长和迭代次数看曲线变化趋势。这一步能帮你快速判断 H 矩阵是否有短环问题、解码收敛是否正常。提示如果 H 矩阵不满秩后面求 G 矩阵会直接报错表现是 rank 不足、矩阵求逆失败。这在随机生成 H 时很常见后面会专门讲怎么处理。3. 拆开 LDPC.m从生成矩阵 G 到 BP 解码的消息传递完整走一遍这一章把 LDPC.m 里最核心的三段逻辑拆开讲编码端怎么由 H 得到 G信道软信息怎么初始化为 LLR解码端 BP 迭代到底在算什么。三段逻辑环环相扣任何一段出错最后的 BER 都不会正常。3.1 编码端从校验矩阵 H 求生成矩阵 GLDPC 编码的基础关系是 G 与 H 正交即 G 的每一行都和 H 的每一行满足 G*H0。有了生成矩阵 G信息序列直接乘 G 就得到码字。大多数 MATLAB 脚本里求 G 的常见做法是对 H 做高斯消元化成系统码形式。% 生成随机稀疏校验矩阵 H列重 dv3 n 192; m 96; dv 3; H zeros(m, n); for col 1:n rows randperm(m, dv); % 随机选 dv 行 H(rows, col) 1; end % 高斯消元成行最简形注意是模 2 运算 Hr mod(rref(double(H)), 2); if rank(Hr) ~ m error(H 未满秩需要重新生成或做列置换); end % 拆分校验部分 P 与单位阵构造 G [P | I] P Hr(:, 1:m); G [mod(P, 2), eye(n-m)];逻辑说明rref 是 MATLAB 内置的高斯消元函数把 H 变成行最简形因为 LDPC 里所有运算都在 GF(2) 上所以消元结果必须再做一次 mod 2否则单位阵位置会出现 2 之类的非法值。rank 检查是必要的随机生成的 H 可能正好线性相关这时候 G 矩阵解不出来。参数说明n 是码长m 是校验位数量dv 是列重。码率 R(n-m)/n这个例子是 1/2 码率。列重取 3 是 LDPC 仿真的常用起点性能比较好短环概率也低于列重 2。这段代码是教学级写法适合验证原理工程里更推荐用 H 直接做编码避免 G 矩阵稠密化带来的复杂度爆炸。如果你只是想验证解码性能用这段求 G 的方式足够了。3.2 软判决输入AWGN 信道下的 LLR 初始化编码完成后码字经过 BPSK 调制、AWGN 加噪接收端拿到的是软信息——不再是 0/1 硬判决而是每个比特的对数似然比 LLR。LLR 的正负代表该比特更可能是 0 还是 1绝对值代表置信度。BP 解码的输入就是这组 LLR初始化错一个符号整条 BER 曲线都会废掉。% 信息位随机生成编码得到码字 info randi([0 1], 1, n-m); coded mod(info * G, 2); % BPSK 映射0 - 11 - -1 x 1 - 2 * coded; % 由 EbN0 换算噪声功率 N0 EbN0dB 2.0; EbN0 10^(EbN0dB / 10); R (n - m) / n; N0 1 / (EbN0 * R); % 注意除以码率 y x sqrt(N0/2) * randn(size(x)); % LLR 初始化BPSK AWGN 下 LLR 2*y/N0 LLR_ch 2 * y / N0;逻辑说明这里最容易被忽略的是 N0 的换算。EbN0 是每比特能量与噪声功率谱密度之比仿真里通常给的是 EbN0dB需要先换算成线性值再用 N0 1/(EbN0*R) 得到噪声方差。很多新人直接写 N0 1/EbN0忽略码率 R 的修正结果曲线整体偏右。BPSK 调制下 x 取值正负 1噪声功率为 N0/2所以加噪公式里是 sqrt(N0/2)。参数说明LLR_ch 数组长度等于码长 n送入解码器时代表每个位的信道先验信息。如果你后面改 QPSK 或更高阶调制LLR 计算方式要换成符号软解映射不能再用 2*y/N0 这个公式。3.3 解码端BP 消息传递的核心循环与停止准则BP 解码是 LDPC 的灵魂。它在 Tanner 图上反复传递两类消息变量节点告诉校验节点“我认为这个位是什么”校验节点反馈“按校验方程约束你应该是什么”。理论上要用和积算法但 MATLAB 验证性能更常用 Min-Sum 近似——把校验节点更新里的连乘换成取最小绝对值省掉大量 tanh 计算性能损失很小。function [dec, iter] decodeLDPC_minSum(LLR_ch, H, max_iter) % Min-Sum 近似 BP 解码 % LLR_ch: 1 x n 信道软信息H: m x n 校验矩阵 [m, n] size(H); v2c repmat(LLR_ch(:), 1, m); % 变量节点到校验节点初始为信道信息 for iter 1:max_iter c2v zeros(m, n); % 校验节点到变量节点 % 校验节点更新取外信息最小绝对值和连乘符号 for j 1:m idx find(H(j, :)); for k 1:length(idx) others idx([1:k-1, k1:end]); c2v(j, idx(k)) prod(sign(v2c(others, j))) * ... min(abs(v2c(others, j))); end end % 变量节点更新信道 LLR 与除自身外的校验消息求和 for i 1:n idx find(H(:, i)); if ~isempty(idx) v2c(i, idx) LLR_ch(i) sum(c2v(idx, i)) - c2v(idx, i); end end % 后验 LLR 求和并硬判决 L_total LLR_ch(:) sum(c2v, 1); dec double(L_total 0); % 停止准则校验子全零则提前退出 if mod(H * dec, 2) 0 return; end end end逻辑说明v2c 矩阵的维度是 n×mv2c(i,j) 表示变量节点 i 发给校验节点 j 的消息。初始时每个变量节点没有校验信息可用所以直接把信道 LLR 复制到每一列。校验节点更新时对某个目标变量节点要排除它自己的消息用其余节点的符号连乘和最小绝对值构成外信息。变量节点更新同理排除来自目标校验节点自己的反馈避免消息自我循环放大。最后的判决条件是后验 LLR 小于 0 判为 1对应 BPSK 映射里 1 映射为 -1。参数说明max_iter 是最大迭代次数工程经验值是 10 到 30。超过 30 次还没有收敛基本可以判定这帧解码失败继续迭代只会浪费算力。停止准则用校验子H*dec是否全零判断全零说明当前判决结果满足所有校验方程这是一个非常可靠的收敛判据。Min-Sum 和标准 BP 的差距在高信噪比时大约 0.1~0.2 dB做算法验证完全够用。4. LDPC 调参与避坑BER 曲线下不去、误码地板与五个翻车现场这段内容是做 LDPC 仿真最容易反复折腾的部分。参数搭配不合理或者 H 构造有问题表现往往是 BER 曲线卡在某个值下不去或者解码结果比理论曲线差一大截。先说参数怎么搭再列几个我实际遇到的典型问题。4.1 参数选型码长、列重、迭代次数怎么搭才不踩坑参数选型没有万能答案但有稳定的套路。码长决定了性能上限码长越接近 1000 以上瀑布区越陡。如果你只是验证解码算法建议从 192 到 648 这个区间起步仿真速度快现象明显。等算法逻辑确认无误再上 1296 或 1944 看长码性能。列重选 3 是最稳妥的起点列重 2 的码在随机构造时几乎必然出现短环列重 4 会让 BP 解码收敛变慢。迭代次数我一般设 20。低于 10 次中低信噪比下解码往往还没收敛就结束了BER 曲线会整体抬高高于 50 次仿真耗时显著增加但性能提升基本看不出来。真正有效的做法是像上面代码那样加校验子停止准则大多数帧在 5 到 8 次迭代内就满足校验方程提前退出只有坏帧才会跑满迭代次数平均耗时远低于固定迭代。注意如果你把随机生成的 H 换成 5G NR 那种 QC-LDPC 标准基矩阵列重和 girth 都是设计好的但需要额外处理基矩阵扩展和打孔不要直接套用随机构造的代码结构。有一个常见误区是看到 BER 地板就疯狂加迭代次数。实际上高信噪比下的误码地板大概率是 H 矩阵里存在小环BP 消息在环内互相加强或抵消迭代多少次都翻不过去。这时候该做的是重新生成 H、调整列重或者改用结构化构造保证 girth而不是堆迭代。4.2 常见问题排查五个典型翻车现场1H 矩阵不满秩求 G 时报错现象运行到 rref 或 inv 操作时报“Matrix is singular”或 rank 不足。 原因随机生成 H 时行与行之间出现线性相关行最简化之后零行不为 0m 行无法张成完整校验空间。 解决先对 H 做列置换把线性无关的列移到前面再消元如果仍不满秩重新随机生成 H或者用 Mackay 的构造方法显式剔除线性相关行。我通常加一个 while 循环直到 rank(Hr)m 才继续。2LLR 符号反了BER 稳定在 0.5 附近现象无论 Eb/N0 加到多高误码率都在 0.5 左右曲线是水平直线。 原因BPSK 映射和 LLR 公式里的正负号约定不一致。比如映射写成 0 - -1、1 - 1但 LLR 仍用 2y/N0符号就反了。 解决把映射和 LLR 公式写在一起对照检查。标准约定是 0 - 1、1 - -1LLR 2y/N0LLR 为正判 0为负判 1。改完符号后 BER 会出现明显的瀑布区。3N0 换算漏掉码率曲线整体右移现象BER 曲线形状正常但比理论曲线落后约 1 dB。 原因N0 1/EbN0 写成 N0 1/(EbN0*R)。LDPC 是编码系统每比特能量 Eb 是符号能量除以码率噪声功率谱密度换算必须乘上码率修正。 解决检查代码里N0 1 / (EbN0 * R);是否完整。漏掉 R 会让仿真里等效信噪比偏高所有点整体左移。4高信噪比段出现误码地板迭代次数无效现象BER 在 10^-3 附近变成水平线把 max_iter 从 20 加到 100 仍然不动。 原因H 矩阵的 girth 为 4存在两个校验节点被两条不同路径连通BP 消息在环上循环外信息置信度失真。 解决重新生成 H 时增加 girth 检查最短环长至少保证 girth 6或把列重从 2 提升到 3降低短环出现概率。还有一种做法是换用 QC-LDPC 结构从基矩阵层面规避短环。5固定迭代次数仿真极慢数据量大时跑不动现象扫描多个 Eb/N0 点、每个点跑几百帧时仿真时间成倍增长。 原因每帧都跑满 max_iter没有提前停止且 H 用满矩阵存储find 操作遍历开销大。 解决在解码循环里加上校验子全零判断满足即 return把 H、v2c、c2v 都改成 sparse 稀疏存储。这两个改动通常能让仿真提速 3 倍以上性能结果不变。5. 验证技巧先跑校验子再谈 BER 曲线少走一半弯路最后讲一个我每次拆信道编码脚本都会用的验证习惯。很多人拿到 LDPC.m 就直接跑 BER 扫描跑完发现曲线不对再回头查代码。我一般会先把噪声关掉做一次无错误传输验证编码 → 过理想信道不加噪声→ 解码 → 检查校验子是否全零。这一步通过了说明编码端 G 矩阵和解码端 H 矩阵匹配环路闭合正确再去加噪声才有意义。% 无噪声自检校验子必须全零 info randi([0 1], 1, n-m); coded mod(info * G, 2); y 1 - 2 * coded; % 完美信道不加减噪 LLR_ch 1e6 * y; % 高置信度软信息 [dec, ~] decodeLDPC_minSum(LLR_ch, H, 20); syndrome mod(H * dec(:), 2); if all(syndrome 0) fprintf(自检通过编码解码链路一致\n); else fprintf(自检失败帧索引%d\n, find(syndrome)); end这段代码里用 1e6 放大软信息等价于把信道置信度拉到极高解码器必然一次收敛。如果这一步校验子不为全零说明 G 和 H 的正交关系没满足通常是求 G 时列置换没有正确映射回原 H ——这是随机构造 H 最常见的问题比解码算法本身更容易翻车。等自检通过再跑 AWGN 下的 BER 扫描曲线不对就优先怀疑短环和参数设置而不是怀疑代码框架。从那以后我每次拿到信道编码脚本第一件事永远是先把噪声关掉跑一遍无错传输校验子全零了再谈 BER 曲线。这个习惯帮我少翻了好几次车尤其是面对从别人手里传过来的 LDPC.m 时它能用一分钟验证整套代码的链路正确性比盯着屏幕猜问题在哪儿高效得多。希望帮到你。这套 LDPC.rar 解压后直接打开 LDPC.m按注释把码长和信噪比范围改成你需要值基础流程基本能一次跑通。本文还有配套的精品资源点击获取
网站建设高端定制企业官网