简介这是基于MATLAB的Polar编解码联合检测仿真源码面向5G通信、无线信号处理领域的研究者与进阶学习者。整套方案聚焦PSS/SSS联合检测成功率以及BER、BLER性能指标输出可用于同步算法验证、信道估计和编码性能评估。源码共68个文件以56个.m脚本为核心涵盖信号生成、Polar编码解码、联合检测策略、信道模型及性能计算模块另含.mat数据文件、.bin信道样本、说明txt与mexw64辅助运行文件打包后约2.63MB。目前已有146人学习。通过阅读和运行源码可直观掌握Polar码在系统同步中的实际应用理解PSS/SSS联合检测的流程与参数配置并借助现成的BER/BLER计算模块完成自定义场景仿真对未来5G协议研究和算法设计具有较高参考价值。1. 联合检测不是串行流程Polar译码器如何反哺PSS-SSS同步估计在LTE/NR物理层仿真里PSS-SSS同步检测和Polar信道译码通常被当作两个独立的模块先做时频同步再做下行控制信道如PBCH的Polar译码。但拿到这套MATLAB工程后会发现它的核心设计思路是把两者揉进同一条链路——PSS/SSS联合检测得到的信道估计结果不只是在同步阶段用一次而是作为Polar译码器计算LLR对数似然比时的先验信息同时译码输出的CRC校验结果又反向决定是否需要重新调整同步参数。这种闭环结构对仿真平台的复用性要求很高工程里通过Runme.m统一调度发端、信道、收端三个目录下的函数用全局变量结构体比如system_param在模块间传递软信息而不是各自为政地重复估计信道。这个工程适合两类人一是做NR物理层算法验证的工程师需要对照PSS-SSS检测成功率、BER、BLER三类指标来评估同步误差对Polar译码性能的影响二是准备5G相关课程设计的学生源码里cellsearch.mat、TU_channel_An11_I.bin这类文件直接对应3GPP TR 38.900定义的TDL信道模型可以省去自己搭链路的大半工作量。需要提醒的是项目默认的采样率和子载波间隔是按30 kHz子载波间隔、1536点FFT配置的如果直接跑Runme.m拿到的是固定参数下的仿真结果想换带宽或 numerology 要同时改系统参数.m里的FFTSize和PSS生成函数里的ZC序列根索引。2. Polar编解码的软信息表示从信道极化到LLR更新2.1 信道极化与编码矩阵的生成逻辑Polar编码的理论基础是信道极化——把N个独立信道通过递归的蝶形结构合并又分裂使一部分信道容量趋近于1信息位另一部分趋近于0冻结位。在MATLAB工程里对应的是Polar编码目录下的PolarEncoder.m它并不直接调用comm.PolarEncoder系统对象而是按Arikan论文的G_N矩阵递推公式手动实现核心代码段是这样的function [encoded, info_bits] polar_encode(data, K, N, frozen_set) % N: 码长必须是2的幂K: 信息位长度frozen_set: 冻结位索引 G 1; for stage 1:log2(N) G [G 0; G G]; % Kronecker 幂构造生成矩阵 end u zeros(1, N); u(info_bits) data; % 信息比特放入信息位 u(frozen_set) 0; % 冻结位置零 encoded mod(u * G, 2); end这段代码里的G矩阵每迭代一次就做一次Kronecker幂扩张本质上是在复现Polar编码的蝶形变换。注意info_bits和frozen_set这两个向量不能有交集它们的并集必须是1:N的全集否则生成的码字直接错乱。实际5G NR标准里信息位选择用Q函数计算巴氏参数但这套工程用的是离线算好的frozen_set存在cellsearch.mat的frozenTable字段里好处是省去每次仿真都重算极化的时间。2.2 SC译码的LLR递归更新译码端实现的是SCSuccessive Cancellation译码器Polar编码目录下SCDecoder.m的核心是LLR的递归计算。与BCJR这类最大后验算法不同SC译码按比特序号依次判决第i个比特的LLR由两部分组成一是接收符号直接给出的信道LLR二是前面i-1个已判决比特通过蝶形结构传递过来的冻结约束。关键代码是递推式用f函数和g函数两个分支function LLR_out sc_node_update(LLR_left, LLR_right, u_left_hat) % f 节点用于偶数位对应异或约束 LLR_f 2 * atanh(tanh(LLR_left/2) .* tanh(LLR_right/2)); % g 节点用于奇数位需要用到已判决的左侧比特 LLR_g LLR_right (-1)^u_left_hat .* LLR_left; end在实际仿真中f函数里的tanh计算在长码长下会有数值下溢风险工程里用了近似公式sign(a)*sign(b)*min(abs(a),abs(b))替换代价是大约0.1 dB的增益损失但仿真速度提升一倍以上。建议你在修改这段代码时把近似开关做成一个参数SC_approx_enable对比两种模式下的BLER差异。2.3 速率匹配与CRC附加的工程处理3GPP NR的Polar码不是裸的Arikan码还要做速率匹配——从母码长度N中按QAM映射顺序打孔或缩短出实际传输的E比特。这套源码里rate_match.m实现的是最简单的BPSK映射下均匀打孔对编码后的encoded按puncture_pattern向量做索引选取puncture_pattern在系统参数.m里通过nrPolarRateMatch接口生成如果MATLAB版本低于R2022a需要把该函数替换为自实现的比特选择。CRC部分要注意PolarEncoder.m的输出encoded长度是N crc_length还是N取决于调用方式工程里默认在Runme.m中先调用crc_attach.m对信息比特附加24位CRC生成多项式0x1864CFB然后才送进polar_encode。这意味着如果自己写测试脚本复用SCDecoder.m解码出来的info_bits前K-24个才是真实业务比特后面24位是CRC校验位——BLER统计时就是靠这24位判断码块是否正确。3. PSS-SSS联合检测相关性峰值融合与判决门限3.1 PSS/SSS序列生成与频域资源映射PSS用的ZCZadoff-Chu序列根索引在NR里有三个候选值29、34、37SSS用的m序列则由PSS索引和小区ID共同决定。工程里发端目录下的pss_generator.m按3GPP TS 38.211第7.4.2节实现核心参数是频域偏移v NID20到2取值SSS的加扰序列生成依赖NID10到335所以cellsearch.mat里存的NID1和NID2是同步检测的目标值。联合检测的输送到收端后接收机先做频偏估计用PSS的共轭相关峰再做时偏估计用SSS的差分相关峰。但工程里的联合检测.m没走这条串行老路而是把PSS和SSS的相关结果在时域上直接相加得到联合判决度量joint_metric abs(xcorr(rx_pss, pss_ref)) .^ 2 abs(xcorr(rx_sss, sss_ref)) .^ 2; [max_val, max_idx] max(joint_metric); if max_val detection_threshold sync_success 1; else sync_success 0; enddetection_threshold的取值直接影响PSS-SSS联合检测成功率曲线设低了虚警多设高了漏检多。这是个牵一发动全身的参数——联合检测成功率统计的是正确检测到NID1和NID2的仿真帧数占总帧数的比例而不是相关峰位置是否精确。你会发现工程里默认阈值取0.75归一化后的相关峰功率在TU信道低信噪比SNR -2 dB下漏检率上升很快这时候二段判决法更稳先用PSS相关峰粗定界再在粗定时附近搜索SSS相关峰。3.2 联合检测成功率的统计口径联合检测成功率这个指标在MATLAB里不是直接用detect (NID_est NID_true)判断的因为PSS检测错了小区组内IDNID2但SSS检测正确的情况也存在。工程里把两者拆开pss_success单独统计NID2的检测正确率sss_success单独统计NID1的检测正确率joint_success要求两个都正确才算同步成功。统计代码在Runme.m里循环体的末尾% 每次快照(snapshot)统计 if nid2_est nid2_true nid1_est nid1_true joint_detect_cnt joint_detect_cnt 1; end pss_success_rate pss_detect_cnt / total_snapshots; sss_success_rate sss_detect_cnt / total_snapshots; joint_success_rate joint_detect_cnt / total_snapshots;如果发现仿真输出的joint_success_rate比pss_success_rate低很多优先怀疑SSS的加扰序列初始化问题——SSS的生成需要NID2作为输入如果发端和收端的NID2索引对不上SSS相关峰直接淹没在噪声里即使在AWGN信道下也解不出来。3.3 DMRS辅助的信道估计如何影响后续Polar译码R_hh_dh_viena_DMRS_frontloaded2LRB.mat里存的是维耶纳Wiener滤波器系数用于DMRS解调参考信号信道的插值。这套信道估计用在前导符号front-loaded DMRS上估计出的信道频响H直接影响Polar译码前的LLR计算。联合检测输出的时偏估计值timing_offset_est要反馈给信道估计模块做时域补偿否则OFDM符号的循环前缀错位会在DFT后引入相位旋转——这个相位误差如果不补偿SC译码器的LLR置信度会系统性偏差BLER曲线出现平台。4. TU信道模型与BER/BLER仿真统计的坑4.1 TU信道系数文件的使用方式TU_channel_An11_I.bin和TU_channel_An11_Q.bin是Typical Urban信道模型的实部和虚部时域冲激响应采样率与仿真带宽有关工程里是30.72 Msps对应20 MHz带宽。读取方式不是MATLAB的load直接导入而是用fread按float32格式读入因为.bin是纯二进制文件不带头fid fopen(TU_channel_An11_I.bin, rb); h_real fread(fid, float32); fclose(fid); fid fopen(TU_channel_An11_Q.bin, rb); h_imag fread(fid, float32); fclose(fid); h_tu complex(h_real, h_imag);.mat文件R_hh_dh_viena_DMRS_frontloaded2LRB.mat可以直接load加载里面包含R_hh维耶纳滤波的相关矩阵、dh时延向量、viena维耶纳滤波器系数三个结构体。注意这个MAT文件里的相关矩阵是基于特定SNR点通常是10 dB预计算的如果仿真时信噪比偏差过大建议按当前SNR重新生成R_hh否则信道估计误差在高SNR段会反而成为主导噪声。4.2 BER与BLER的计算差异BER和BLER在代码里是两套独立的统计逻辑。BER在调制解调符号级统计把接收的软比特做符号判决后和发端原始比特对比ber sum(rx_bits ~ tx_bits) / length(tx_bits);BLER统计的粒度是码块code block判断依据是CRC校验% 译码后做CRC校验 [crc_ok, dec_bits] crc_check(decoded_info_bits); if ~crc_ok bler_count bler_count 1; % 一个码块错误即计数 end bler bler_count / total_blocks;这里有个容易踩的坑如果跑的是高吞吐仿真比如连续发10000个码块MATLAB脚本在parfor并行循环里统计BLER时会遇到随机数流问题——每个worker的rng默认独立但如果不显式设置不同worker产生的信道衰落可能重复。工程的Runme.m里统一在循环开始前调用了rng(seed snapshot_idx)确保每个快照的随机种子可复现这个习惯值得留用。4.3 仿真参数对Polar编解码性能的影响Polar码的参数K, N, CRC长度在不同SNR点的表现差异很大。工程里默认N512, K128, CRC24在TU信道下BLER0.01对应的SNR大约比AWGN信道高2-3 dB。调整参数时要注意frozen_set与码长N是绑定的如果从512改成1024需要重新生成极化权重表——cellsearch.mat里的frozenTable是按N512存储的盲目改N会直接报维度错误。常用的做法是在系统参数.m里增加一个N_target 1024的配置用PolarConstruction.m里的calculate_frozen_set(N_target, K)方法临时生成但生成时间在N1024时大约需要20秒高吞吐仿真前先单独跑一次验证生成逻辑。5. 验证Polar译码器与同步模块联调的三个自查手段5.1 用极简AWGN链路隔离同步模块的影响如果发现联合检测成功率曲线异常先不要急着调Polar译码参数。把Runme.m里的channel_type改成AWGN并把TU_channel_An11_I.bin的读取段注释掉这样链路里没有多径时延PSS-SSS相关峰应该是干净的冲击响应。此时统计的joint_success_rate如果仍然不到100%说明问题出在发端PSS序列生成或收端相关检测的索引映射上跟信道估计和Polar译码无关。我一般会在SNR0 dB下跑100帧要求joint_success_rate不低于95%否则就检查PSS的频域资源映射位置是否与FFT移位有关。5.2 软比特LLR的可视化检查Polar译码前把LLR序列画出来用plot(LLR_in)是排查译码器冻结位集合错误的最快方法正常情况下信息位对应的LLR绝对值明显高于冻结位因为冻结位不携带信息LLR应接近0。如果看到所有LLR分布杂乱无章说明信道估计或解映射环节出了问题——先查R_hh_dh_viena_DMRS_frontloaded2LRB.mat中的维耶纳系数是否与当前SNR匹配再查LLR计算时除以噪声方差N0是否用了1/SNR_linear而不是1/(2*SNR_linear)BPSK和QPSK的LLR公式里噪声方差系数不同。5.3 BLER曲线的置信区间确认仿真输出的BLER曲线在低BLER区低于1e-3波动剧烈因为要统计到足够多的错误块才能让曲线平滑。工程里bler_count的统计位宽是uint32如果跑到total_blocks为百万级需要把计数器改成uint64防溢出。经验法则是total_blocks至少是10 / target_BLER比如要统计BLER1e-3至少发10000个码块。最后检查Runme.m里有没有把skip_first_frames参数设为大于0——前几帧因为信道估计器收敛未稳BER会偏高通常跳过前10帧再开始统计最稳妥。本文还有配套的精品资源点击获取