极化码在高斯信道下的CA-SCL译码:MATLAB实现与性能仿真 📅 发布时间:2026/9/11 18:25:46 👁 浏览次数: 简介这套Matlab代码包实现了极化码在高斯信道下的CA-SCL译码算法面向通信工程、电子信息与数学等专业学生可用于课程设计、期末大作业或毕业设计中的性能验证与算法对比。代码采用参数化编程列表深度、信噪比等关键参数可灵活调整注释明细、结构清晰并配有可直接运行的案例数据即使新手也能快速替换数据展开实验编码、信道、译码各模块独立封装便于二次开发和不同方案间的对照分析。压缩包共17个文件其中以11个m脚本为主干另有2个fig与2个png辅助查看波形和流程图cpp与mexw64文件用于加速似然比计算整体仅57KB轻量且完整覆盖极化码编码、信道模拟、CRC辅助校验、SCL译码与误码率绘制。已有132人学习/下载适合希望从原理走向仿真、深入理解SCL/CA-SCL路径度量与剪枝策略的读者。1. 极化码在高斯信道下用 CA-SCL 译码差的那零点几个 dB 藏在这里在 5G NR 控制信道里极化码已经成为标准编码方案之一但真正把极化码推到可工程用的是 CA-SCL 译码而不是最基础的 SC 译码。SC 按顺序硬判决一旦某一位错后续级联错误很难挽留SCL 维护多条候选路径再用 CRC 从中挑一条高斯信道下性能可以逼近最大似然译码。很多人拿到 MATLAB 实现后第一个卡点不是主循环而是把高斯信道的 LLR 算错或者把 CRC 校验位放错位置。这篇文章从高斯信道输入到 CA-SCL 的路径度量、MATLAB 模块拆分和 BER 仿真排错一步步讲清楚适合要自己复现极化码译码链路、又不想只当调包侠的工程师。2. 高斯信道下 CA-SCL 的输入到底该是什么LLR 与路径度量2.1 先把 BPSK 映射和噪声方差算准极化码在高斯信道下的发射机通常用 BPSK 映射信息比特经过极化编码后得到码字c映射成x 1 - 2c也就是 0 映射为 1、1 映射为 -1。接收信号为y x n其中n是均值为 0、方差为sigma^2的高斯白噪声。信道对数似然比 LLR 定义为L log( P(y|x0) / P(y|x1) )代入高斯概率密度函数后化简得到L 2y / sigma^2。这个公式很基础但仿真里最常错的不是公式本身而是sigma^2的换算。如果给定的是每比特信噪比EbN0_dB且码率是R K/N那么符号能量归一化为 1 时有sigma^2 1 / (2 * R * EbN0)。function sigma2 awgn_sigma2(EbN0_dB, R) EbN0 10^(EbN0_dB / 10); sigma2 1 / (2 * R * EbN0); end这里的R必须是含 CRC 校验位的完整码率也就是(信息比特数 CRC 长度) / 码长。很多人只拿原始信息长度去算结果噪声方差偏大仿真曲线在高信噪比下提前出现平台。如果仿真使用复基带信道还要把实部和虚部的噪声功率各分一半本文默认实 BPSK 加高斯白噪声直接用上式。2.2 路径度量为什么能一路叠加SCL 译码把 SC 的逐位硬判决改成候选路径扩展。每译一个比特一条父路径分裂成u0和u1两条子路径路径度量 PM 表示该路径与接收信号的对数似然累积代价。PM 越小候选路径越可靠。PM 的递推式可以写成PM_i PM_{i-1} log(1 exp(-(1 - 2u_i) * L_i))其中L_i是当前译码位置的 LLR。实际 MATLAB 实现为了避免exp溢出一般用 min-sum 近似增量 max(0, -(1 - 2u_i) * L_i)这个近似等价于如果u_i与 LLR 的硬判决一致路径增量是 0如果不一致增加|L_i|作为惩罚。近似值在低信噪比下和高斯信道里损失很小但代码简单且不会出现NaN。function pm_delta path_metric_delta(llr, u_bit) hard_bit double(llr 0); % 负 LLR 判 1 if u_bit hard_bit pm_delta 0; else pm_delta abs(llr); end endpm_delta是每个候选路径在当前位置的增量父路径的 PM 加上它就是子路径的新 PM。正因为 PM 是可加的所以 SCL 可以维护一个长度不超过L的有序数组每层扩展后只保留最小的L个这也决定了 SCL 的复杂度是O(L*N*logN)量级而不是指数级。2.3 CRC 不做纠错只做选路SCL 译完一整帧后列表里有L条完整候选路径。如果没有外部约束直接取 PM 最小的一条SCL 退化成一种“并行 SC”。CA-SCL 的做法是在信息比特末尾附加 CRC 校验位译码完成后先对每条候选路径做 CRC 校验然后选择通过校验且 PM 最小的路径。注意一个关键点CRC 不参与路径扩展它只作用于最后一步的路径选择。实际仿真里如果列表大小L较小CRC 帮助有限如果L足够大性能会明显逼近最大似然译码。不同场景下三种译码方式的差别如下。译码方式候选路径数终点选择策略高斯信道下相对增益实现复杂度SC1无选择基线低SCLL取 PM 最小比 SC 好 0.3~0.8 dB中CA-SCLLCRC 校验后选 PM 最小比 SCL 再提升 0.2~0.5 dB中高这里的“相对增益”是一个经验范围具体值受码长、码率、冻结位置构造方式影响但趋势是稳定的。实现 CA-SCL 时CRC 多项式长度直接决定码率损失因此要在增益和码率之间做取舍。3. 用 MATLAB 把 CA-SCL 译码器拆成可复现的模块3.1 全局参数怎么设写 CA-SCL 代码最好从一开始就把参数集中放在脚本顶部避免在循环里反复改动。常见做法是先设定码长、信息位长度、列表大小和 CRC 长度。N 256; % 极化码码长 K 128; % 信息位长度含 CRC L 8; % SCL 列表大小 crc_len 8; % CRC 校验位长度 crc_poly 0x2F; % 8-bit CRC 多项式 EbN0_dB 2.0; % 仿真信噪比 R K / N; % 含 CRC 的码率 sigma2 awgn_sigma2(EbN0_dB, R);这里的N必须是 2 的整数次幂比如 256、512、1024。极化码编码本质上是对长度为N的输入向量做log2(N)级蝶形异或变换所以非 2 次幂长度无法直接用标准结构。L一般取 2 的幂MATLAB 里方便用zeros预分配路径数组。3.2 信息位选择与编码输入极化码需要把信息放在极化后可靠性高的子信道里。高斯信道下常见的做法是用高斯近似构造冻结位置而不是用 BEC 的巴氏参数。两者在高信噪比下差别不大但在中低信噪比下会有零点几个 dB 的差距。frozen_bits ga_frozen_positions(N, K);这个函数可以用密度进化或者高斯近似生成。为了不引入通信工具箱依赖可以用经典的高斯近似递推式实现初始对数似然均值设为2/sigma2然后按极化核递归更新。构造好frozen_bits后把信息位和 CRC 位填进非冻结位置。info_bits randi([0 1], K - crc_len, 1); crc_bits crc_encode(info_bits, crc_poly); u zeros(N, 1); u(~frozen_bits) [info_bits; crc_bits]; % 此处顺序要与译码器一致 cw polar_encode(u); x 1 - 2 * cw; % BPSK 映射 y x sqrt(sigma2) * randn(N, 1); % 高斯信道加噪 llr_channel 2 * y / sigma2; % 信道 LLR逻辑说明polar_encode是对输入u做 Arikan 极化变换frozen_bits为 1 的位置传 0为 0 的位置传真实比特。接收端拿到llr_channel后把它当作译码器首层输入不断做 f 节点和 g 节点的 LLR 更新。3.3 SCL 主循环与路径裁剪SCL 译码器的核心是一个逐比特递推循环。每一层对当前列表里的每条路径分裂成两个候选计算新的 PM然后按 PM 排序截断到L。function [cand_u, cand_pm] scl_decode_loop(llr_channel, L) N length(llr_channel); paths_u zeros(N, 1); paths_pm 0; path_count 1; for i 1:N new_u []; new_pm []; for p 1:path_count for bit 0:1 % 这里用完整因子图更新得到当前比特对应的部分和 LLR L_i polar_llr_update(llr_channel, i, paths_u(:, p)); pm paths_pm(p) path_metric_delta(L_i, bit); temp_u paths_u(:, p); temp_u(i) bit; new_u [new_u, temp_u]; new_pm [new_pm, pm]; end end [sorted_pm, idx] sort(new_pm, ascend); kept idx(1:min(L, length(idx))); paths_u new_u(:, kept); paths_pm sorted_pm(1:length(kept)); path_count length(kept); end cand_u paths_u; cand_pm paths_pm; end这段代码展示了 SCL 的骨架但polar_llr_update需要实现因子图递推。实际生成 LLR 时对角线上的 f 节点用sign(a)*sign(b)*min(abs(a),abs(b))g 节点用b (1-2*u_s)*a。其中u_s是已经确定的部分和。不要试图在每一层重新计算整棵 SC 树而应该用类似 O(N logN) 的递归更新结构否则仿真会慢到没法用。3.4 终点处的 CRC 辅助选择SCL 主循环返回的是L条完整候选比特序列每条候选里已经包含信息位和 CRC 位。最终判决逻辑是先找出所有通过 CRC 校验的候选再从其中挑 PM 最小的一条。function u_hat crc_select(cand_u, cand_pm, crc_len, crc_poly) L size(cand_u, 2); chosen L; % 默认取最小 PM for p 1:L if crc_check(cand_u(:, p), crc_len, crc_poly) if cand_pm(p) cand_pm(chosen) chosen p; end end end u_hat cand_u(:, chosen); end注意这里的crc_check只检查信息位和 CRC 位不能把冻结位纳入 CRC 计算。如果chosen始终没有更新说明没有任何候选通过 CRC此时默认选择 PM 最小路径。这就是 CA-SCL 相对纯 SCL 的全部额外开销代价很小但带来的性能收益在高斯信道下很明显。4. 在高斯信道下跑 BER/FER 仿真参数与排错4.1 蒙特卡洛仿真脚本结构验证译码器正确性不能只跑一帧。高斯信道下极化码的误码率本身起伏较大至少需要统计几百甚至上千帧错误。常见做法是把从上到下整条链路用一个循环包起来最后统计误块率。fer_count 0; block_count 0; for trial 1:2000 % 生成信息、CRC、编码、调制、加噪、译码 u_hat ca_scl_full_decode(params); if ~isequal(u_hat(~frozen_bits), u(~frozen_bits)) fer_count fer_count 1; end block_count block_count 1; end FER fer_count / block_count;这里的ca_scl_full_decode是把第 3 章的编码、信道、SCL 和 CRC 选择串起来的封装函数。统计 FER 时要拿译码输出与发送端完整输入做比较不能只比较信息位否则 CRC 位出错也会被误判为正确。BER 则是在错误帧内统计比特错误数除以总比特数。4.2 列表大小 L 和 CRC 长度的实际影响在高斯信道下CA-SCL 的“好”不是线性的。L2比L1提升有限L8或L16通常会有明显改善继续增大到L64时增益开始饱和。下表是一个典型的中短码情况具体数值以本地仿真为准但趋势可以参考。配置LCRC 长度相对 FER 表现N256, K1281无FER 曲线约 3 dB 时有可见平台N256, K12888比 SC 好约 0.4 dBN256, K128328比 L8 再好约 0.2 dBN256, K1283216接近 ML 曲线但码率损耗变大CRC 长度不是越长越好。CRC-8 在L8时足够用CRC-16 在高信噪比下能进一步清除残留错误但代价是信息位减少 8 bit这对短码帧可能得不偿失。实际工程里要根据K和帧长需求选择 CRC 位宽比如 5G NR 的极化码使用 11 bit 或 24 bit CRC。4.3 三个最容易踩的坑第一个坑是 LLR 符号约定。很多实现里x 1 - 2*cw那么接收端llr 2*y/sigma2此时 LLR 为正表示 0、为负表示 1。如果译码器内部用的是x 2*cw - 1的映射符号会正好相反导致高信噪比下误码率不降反升。最直接的检查方式是构造一个无噪声帧看译码器能不能全对。第二个坑是 CRC 位在冻结位序列中的位置。信息位和 CRC 位必须全部放在非冻结位里而且发送端填充顺序要和译码端 CRC 校验顺序一致。更隐蔽的问题是 CRC 位本身也被极化编码译码器输出候选路径后 CRC 校验对象不能是编码后的码字而必须是极化码编码前的输入比特序列。第三个坑是路径更新时的变量覆盖。MATLAB 中如果在循环体内直接修改paths_u的列会破坏还需要使用的父路径数据。正确做法是先复制到临时数组等所有候选计算完成后再统一截断。使用sort排序后要保留原始索引否则候选路径和 PM 的对应关系错位整个 CRC 选择都会出错。5. CA-SCL 在 MATLAB 里的运行效率和边界技巧5.1 用log1p和近似剪枝把仿真速度拉上去高信噪比下路径度量差值经常很小直接用log(1 exp(...))会产生大量指数运算。可以把 PM 更新改成 min-sum 近似前面已经给出path_metric_delta这是首选。如果仍想保留精确 LLR推荐用log1p(exp(-abs(x)))而不是log exp能避免中间量过大溢出。另一个常见加速手段是提前判断不再分裂。当某条路径在当前比特的 LLR 绝对值很大时两种比特方向产生的 PM 一个接近 0、一个接近|LLR|后者几乎不可能留在最终列表。这时可以缩减分裂数量只保留硬判决方向。5.2 浮点归一化防止 PM 下溢随着译码长度增加PM 会不断累加长码帧下可能整体偏移到很大的数值。由于译码只关心 PM 相对大小可以在每层排序后减去最小 PM让最小值归一化为 0paths_pm paths_pm - paths_pm(1);这个操作不影响候选路径的排序结果但能避免长时间仿真中出现-Inf或NaN。尤其是低信噪比下多条路径 PM 接近归一化后数值稳定性更好。5.3 把 CA-SCL 映射到 5G NR 的极化码配置5G NR 的极化码并非直接使用 CRC 位做全部校验而是将 CRC 分成“外 CRC”和“内 CRC”两层但核心译码思想与 CA-SCL 一致。工程人员用 MATLAB 做算法验证时可以保留本文的参数接口把crc_len和crc_poly替换成 NR 标准的 11 bit CRC冻结位置替换成 NR 定义的可靠性排序表就能快速评估链路性能。最后的曲线验证建议固定随机种子并在每条 SNR 点上统计不低于 100 个错误帧否则 FER 曲线会因样本不足出现抖动。本文还有配套的精品资源点击获取