
简介基于polar编解码的PSS-SSS联合检测仿真资源面向通信方向本硕博教研与学习人群用于掌握polar编解码算法及PSS-SSS联合检测流程。资源基于MATLAB实现输出联合检测成功率、误码率BER与误块率BLER等关键指标可作为算法验证与课程设计参考。压缩包共70个文件包含56个m脚本、5个mat数据、4个bin信道文件、2个txt说明、1个mexw64可执行文件及1个avi操作录像整体大小2.91MB目录按发端、收端、信道等模块划分结构清晰。已吸引288人学习下载。配套操作视频演示了从运行Runme.m到查看仿真结果的完整过程同时提供Polar编解码、PSS/SSS检测、信道估计等子函数方便读者分模块研读与二次开发。1. 开机找小区这件事PSS-SSS 联合检测为什么要拉着 polar 编解码一起算5G UE 上电后第一件事是小区搜索先在时频域里把 PSS 和 SSS 找出来确定符号定时、频偏和物理小区 ID才能去解 PBCH而 PBCH 的 MIB 是 polar 码保护的BER 和 BLER 是衡量这条链路最直接的体检指标。很多做物理层仿真的同事习惯把同步检测和信道译码分成两套代码维护可真实链路上同步估计的残差会直接转化为 LLR 劣化最后 BLER 曲线对不上谁都不认账。这篇笔记围绕“基于 polar 编解码的联合检测”拆讲从 SSB 生成、PSS-SSS 联合检测到 PBCH 解调和 CA-SCL 译码把检测成功率、BER、BLER 三个指标的统计口径和常见翻车点一次说清。适合正在做 5G NR 小区搜索算法验证、物理层链路仿真或者想把同步与译码串成完整链路的从业者。2. 先立住协议框架PSS-SSS 给 polar 译码喂了什么输入2.1 同步信号不是“找峰值”那么简单5G NR 的 SSBSS/PBCH block时域占 4 个 OFDM 符号频域占 240 个子载波。PSS 放在第 1 个符号的中间 127 个子载波上是长度 127 的 m 序列只有 3 个候选循环移位对应小区内 IDN_ID^2 ∈ {0,1,2}SSS 放在第 3 个符号的同样位置由两个 m 序列相乘得到携带小区组 IDN_ID^1 ∈ {0,1,…,335}。物理小区 ID 按PCI 3 × N_ID^1 N_ID^2计算所以同步检测不只是找相关峰、对齐符号定时它本质上是一个 3×336 的联合假设检验既要猜对定时也要猜对 PCI。接收端的常规做法是本地生成所有候选序列把接收序列和每个候选做互相关最大峰值对应的候选同时给出 N_ID 和定时。这里要区分两类相关时域滑动相关适合在还没有 OFDM 符号边界时做定时捕获频域相关则适合在定时已知后做精估计。PSS 检测通常先做时域相关因为接收机此时连 FFT 窗口在哪都不知道。实现时用一次xcorr算完整相关函数比逐点滑动循环快一个量级。信号长度序列类型携带信息频域位置PSS127m 序列3 个循环移位N_ID^20~2SSB 符号 0 中间 127 子载波SSS127两个 m 序列乘积N_ID^10~335SSB 符号 2 中间 127 子载波联合检测的第一步就在 PSS 和 SSS 之间发生用 PSS 估计出的定时位置去约束 SSS 的频域抽取窗口只有 PSS 定时可信的候选才进入 SSS 假设检验。单独看 PSS检测成功率做到 99% 以上不难难的是加上 SSS 联合校验后还能维持住。我习惯把成功率口径定成“PCI 完全正确且定时误差落在半个 CP 以内”而不是“相关峰超过门限”——口径一松仿真报告里的数字好看但进了真实信道全是问题。2.2 NR polar 编码链56 比特怎么变成 864 个编码比特PBCH 是 polar 码在 5G NR 里的标准样本。信息比特 A32 比特包括 MIB 主体以及 SFN 高位、半帧指示、SSB index 等先按 TS 38.212 的 CRC24C 附加校验得到 B56 比特送入 polar 编码器母码长度 N512。polar 编码的核心是信道极化对一个 2 的幂长度的信道向量做 Kronecker 变换一部分子信道容量趋于 1另一部分趋于 0。编码器把信息比特放在可靠度最高的 K 个位置其余位置放冻结比特。NR 的可靠信道排序是按规范里的 Q 函数近似量化表计算的和经典论文里巴氏参数的排序有细微差别自研编码器时这里最容易埋雷。编码之后不是直接调制还要做速率匹配子块交织加比特选择把 512 比特变成 E864 比特再 QPSK 调制到 432 个 RE 上。E 比 N 长所以这里的速率匹配以循环重复为主但重复不是简单复制而是交织后按顺序选取。为什么 PBCH 要重复这么多因为一个 SSB 里 PBCH 需要占满 432 个 QPSK 符号而信息比特只有 32 个polar 母码 512 也不够填。这个“交织重复”的组合让同步估计误差非常致命同一个信息比特的多个副本被拉开到不同的频域位置信道频率选择性会同时影响所有副本LLR 一错全错。译码端对应 SC 或 CA-SCL。PBCH 自带 CRC24C天然适合 CRC 辅助的列表译码。list 大小 L8 是常见折中L16 能再捞回零点几 dB但译码复杂度和运行时间接近翻倍。我一般先把 L8 跑通最后再确认一次 L16 的增益值不值得。译码器工作前必须先做与发射端镜像的去速率匹配把 864 个 LLR 按交织映射关系放回 512 个母码位置重复位做 LLR 相加冻结比特位置置 0然后才进 polar 译码器。整个尺寸链我建议打印出来核对A32 → B56 → N512 → E864 → 432 symbols哪个环节对不上后面全白跑。2.3 联合检测到底“联合”了什么联合检测的信息流是PSS 给出粗定时和粗频偏 → SSS 在约束窗口内确认 PCI 并做精频偏 → DMRS 做信道估计 → PBCH 软解调 → polar 译码。同步估计的残余误差不会停留在同步模块内部它会一路传进 LLR。比如残余频偏 Δf 会让相邻 OFDM 符号间产生相位旋转DMRS 估计出的信道相位如果跟不上这种旋转数据 RE 的 LLR 幅度会被整体压缩CA-SCL 译码器把这些不可靠比特当可靠比特处理BLER 从 10^-2 恶化到 10^-1 很常见。所以联合检测的“联合”不是指某个模块同时吐出同步和译码结果而是指同步质量参数必须能一路传递到底并且在仿真里可以单独注入偏差来观察影响。我在工程里把残余频偏、定时偏移做成可配置输入解调模块统一从结构体里取参数。这样既能跑“理想同步”的基线也能跑“真实同步”的劣化曲线。仿真时三个指标分开度量检测成功率找同步级的问题BLER 找端到端的问题BER 夹在中间用来分辨是解调坏了还是译码坏了。三条曲线一起看才能定位到具体是哪一级掉了链子。3. 仿真链路搭建从 SSB 生成到 PSS-SSS 联合检测3.1 生成 SSB 资源网格频域 240 点、时域 4 符号先固定仿真参数子载波间隔 30 kHz常规 CPFFT 大小 4096对应 100 MHz 带宽SSB 的频域起点给一个固定偏移不做栅格盲检。资源网格里符号 0 放 PSS符号 1 和 3 放 PBCH 数据加 DMRS符号 2 中间放 SSS、两侧放 PBCH。PBCH 数据加 DMRS 一共 576 个 RE其中 DMRS 按每 4 个 RE 一个的密度插入数据 RE 正好 432 个对应 864 个编码比特。% 生成 PSS 和 SSS 序列 ncellid 42; % 随便挑一个 PCI nid1 floor(ncellid / 3); % 小区组 ID0~335 nid2 mod(ncellid, 3); % 小区内 ID0~2 pss nrPSS(nid2); % 127 长 PSS m 序列 sss nrSSS(nid1); % 127 长 SSS 序列 % 摆进 SSB 资源网格240 子载波 x 4 符号 ssb_grid zeros(240, 4); pss_idx (240 - 127)/2 1 : (240 127)/2; % 中间 127 个子载波 ssb_grid(pss_idx, 1) pss; ssb_grid(pss_idx, 3) sss; % PBCH 和 DMRS 在符号 1/2/3 的剩余位置分别填充nrPSS和nrSSS是 5G Toolbox 的序列生成函数也可以按 TS 38.211 的 7.4.2 节自己写生成式核心就是 m 序列的移位映射。PSS 的循环移位是43 × N_ID^2对 127 取模SSS 的 m0/m1 由 N_ID^1 查表得到不要自己编规律。PSS 和 SSS 的映射位置必须是 127 个点且放在 240 个子载波正中间这样才能保证接收端抽取时不需要知道 SSB 的频域绝对位置以外的额外信息。3.2 PSS 检测用 xcorr 做滑动相关先拿到定时和粗频偏PSS 检测的输入是基带接收波形输出是符号定时估计和粗频偏。最简单可靠的做法是时域滑动相关本地准备 3 个 PSS 候选与接收波形做互相关找全局峰值。% 接收信号 rx已下变频到基带 pss_cands {pss_0, pss_1, pss_2}; % 3 个 PSS 假设由 3.1 序列循环移位得到 peak_val 0; for cand 1:3 [acor, lags] xcorr(rx, pss_cands{cand}); % 一次算完整互相关 [v, idx] max(abs(acor)); if v peak_val peak_val v; nid2_est cand - 1; % PSS 假设号即 N_ID^2 估计 timing_est lags(idx); % 符号定时单位是采样点 phase_est angle(acor(idx)); % 峰值相位含频偏信息 end end % 粗频偏换算delta_f -phase_est / (2 * pi * Ts)逻辑说明xcorr返回所有时延点的相关值省掉逐点循环。timing_est是峰值对应的时延折算成采样点后就是 OFDM 符号起始位置phase_est里混着频偏和定时偏差需要按符号时长换算成频偏。nid2_est是三个 PSS 假设里胜出的那个。实际工程里这一步之后要先做一次频偏补偿再去做 SSS否则 SSS 的频域相关峰会明显变矮。参数上要留意PSS 相关归一化应该用接收信号能量而不是本地序列能量否则噪声大的时段会出现假峰。频偏较大时比如超过子载波间隔的一半时域相关峰会展宽定时估计会偏向一侧这是正常现象交给后面的 CP 相关或 SSS 精估计去修正。3.3 SSS 假设检验与联合成功率统计口径PSS 定时确定后把接收波形按定时做 FFT 抽取符号 2 的频域数据取中间 127 个子载波和 336 个 SSS 假设做互相关选最大峰。SSS 的互相关特性比 PSS 差一些因为它是两个 m 序列相乘的复合序列所以低 SNR 下更容易选错假设。% 在 PSS 定时基础上抽取符号 2 的频域向量 sym2 fft(rx_waveform(timing_est sym_start(2) : ... timing_est sym_start(2) N_fft - 1)); sym2 sym2(ssb_freq_range); % 取中间 127 个子载波 sss_metrics zeros(1, 336); for nid1 0:335 sss_local nrSSS(nid1); sss_metrics(nid1 1) abs(sym2. * conj(sss_local)) / ... (norm(sym2) * norm(sss_local) eps); end [~, sss_idx] max(sss_metrics); nid1_est sss_idx - 1; pci_est 3 * nid1_est nid2_est;联合检测成功率的统计口径要这样定义pci_est pci_true且abs(timing_est - timing_true)小于容限比如 CP 长度的一半。只有 PCI 猜对而定时差很多SSB 后面的 PBCH 照样解不出来。统计脚本里把每个块的真实 PCI、真实定时和估计值全部存下来最后统一汇总success (pci_est pci_true) (abs(timing_est - timing_true) tol); detect_rate mean(success) * 100; % 联合检测成功率单位 %容限tol必须按采样率折算。仿真里加了频偏后PSS 定时估计会有系统性偏移如果发现检测成功率在低 SNR 下掉得异常快先检查频偏补偿是否在 SSS 检测之前生效。另外一个工程技巧是单个 SSB 检测成功率不够时可以做跨帧的多次检测再投票但那是后话先把单次链路跑通。4. PBCH 解调与 polar 译码BER 和 BLER 怎么算才不虚4.1 DMRS 信道估计与 QPSK 软解调 LLRPBCH 的 432 个 QPSK 数据符号散布在符号 1、符号 2 两侧、符号 3 中DMRS 按每 4 个 RE 一个的密度插入。信道估计的常见做法是先取 DMRS 位置的接收值与本地参考序列做 LS 估计再插值到数据位置。% DMRS 位置提取与 LS 信道估计 dmrs_rx rx_grid(pbch_dmrs_indices); % DMRS 位置由 N_ID 决定 dmrs_ref nrPBCHDMRS(ncellid); % 本地 DMRS 参考 hest dmrs_rx .* conj(dmrs_ref) ./ (abs(dmrs_ref).^2 eps); % LS 估计 hest_data interp1(..., hest, pbch_data_indices); % 插值到数据 RE逻辑说明nrPBCHDMRS生成与 PCI 相关的参考序列dmrs_rx是资源网格上对应位置的接收值。LS 估计得到每个 DMRS RE 上的信道响应再插值铺到数据 RE 上。频率选择性信道下线性插值基本够用多径时延扩展大时可以换样条插值代价是复杂度上升。噪声方差noise_var必须和 SNR 统计口径保持一致否则 LLR 幅度失真polar 译码性能会整体偏差。QPSK 软解调把 432 个符号拆成 864 个比特的 LLR近似做法是把 QPSK 看成两路正交的 BPSK% 均衡后的符号按实部虚部分别计算 LLR eq rx_data .* conj(hest_data) ./ (abs(hest_data).^2 noise_var); llr [real(eq); imag(eq)] * (2 / (sqrt(2) * noise_var)); % 结果是一个 864 长的 LLR 向量对应 864 个编码比特这里2 / (sqrt(2) * noise_var)是 QPSK 星座点距离和噪声方差的折算系数。有人图省事把噪声项直接填 1曲线看起来也能跑但换 SNR 口径后完全不可复现属于典型的血泪经验。4.2 CA-SCL 译码器配置list 大小与去速率匹配LLR 向量拿到后先做去速率匹配再进 CA-SCL 译码器。自研译码器时我通常把 list 大小和 CRC 校验开关做成可配置参数。% CA-SCL 译码L8CRC24C 辅助路径选择 [info_bits, crc_ok] ca_scl_polar_decode(... llr_dematted, ... % 去速率匹配后的 512 长 LLR n_polar512, ... % 母码长度 k_info32, ... % 信息比特数 crc_len24, ... % CRC24C list_size8); % 候选路径数逻辑说明译码器内部按 polar 因子图做 SC 展开维护list_size条活跃路径每扩展一层按路径度量排序剪枝最终输出时用 CRC24C 从剩余路径中挑选合法的一条。crc_ok直接作为这个码块是否译码成功的判据BLER 的分子就靠它。注意llr_dematted不是原始 LLR而是经过解交织、重复位合并、冻结位置零之后的 512 长向量。译码方式list 大小复杂度适用场景SC1最低快速验证编码链路SCL8~16中不依赖 CRC 的性能基准CA-SCL8~16高PBCH/PDCCH 实际译码list 大小从 8 加到 16BLER 通常能下移 0.2~0.5 dB但译码时间接近翻倍。仿真预算有限时先在 L8 上跑通最后再决定是否提升到 16。4.3 BER vs BLER统计口径和蒙特卡洛点数仿真输出三条曲线PSS-SSS 联合检测成功率、BER、BLER。检测成功率按“PCI 和定时同时正确”的比例统计BER 按译码输出的 32 位信息比特与原始 32 位逐位对比BLER 按crc_ok 0的比例统计。BER 和 BLER 不能互相换算一个块错 1 个比特和错 10 个比特对 BLER 的贡献完全一样。指标统计单位判定条件建议最小统计量检测成功率一次 SSB 检测PCI 和定时容限同时正确1000 次以上BER单个信息比特译码比特对比原始比特至少 100 个错误比特BLER单个 PBCH 码块CRC24C 校验失败至少 100 个错误块蒙特卡洛点数决定曲线可信度。想看 BLER10^-2至少需要跑出 100 个错误块也就是约 1 万个块每个块做一次 4096 点 FFT 加 CA-SCL 译码仿真时间会相当可观。常见做法是低 SNR 段少跑高 SNR 段设置最大块数上限按累计错误块数自适应停止。BER 的最小统计量建议比 BLER 更大因为一个错误块只贡献一个 BLER 错误计数但可能贡献几十个比特错误。BER 曲线通常比 BLER 曲线更快收敛别被假象骗了。5. 参数调优与避坑三条曲线对不上时先查这五处5.1 PSS 相关峰出现等间隔旁瓣定时估计周期性跳变现象检测成功率在中等 SNR 下无故下降打印定时误差发现估计值与真实值之差总在正负一个 OFDM 符号附近跳。原因PSS 序列的循环移位自相关旁瓣不低加上 CP 结构在没做频偏预校正时相关峰会周期性出现在符号边界上最大峰值选到了旁瓣。解决在 PSS 相关之前先用 CP 自相关做一次粗定时把搜索窗口缩到 CP 范围内再做 PSS 精相关或者在频域做 PSS 相关时对序列做加窗处理压制旁瓣。5.2 残余频偏让星座整体旋转polar 译码雪崩现象PSS-SSS 联合检测成功率很高98% 以上但 PBCH 的 BLER 在低 SNR 下明显高于同参数的理论曲线甚至出现误码平台。原因PSS 粗频偏估计精度不够残余频偏使 QPSK 星座缓慢旋转DMRS 估计出的信道跟不上符号间相位变化LLR 幅度被压缩。解决在 SSS 确认之后用 SSS 或 DMRS 做一次精细频偏估计对 PBCH 符号做逐符号相位补偿仿真里把“理想频偏补偿”和“实际频偏补偿”做成两条 BLER 曲线两条线的差就是频偏估计模块的优化空间。这个问题最隐蔽因为它不影响检测成功率只影响端到端 BLER。5.3 SNR 口径不统一曲线整体平移 2~3 dB现象同一套链路今天跑出的 BLER 曲线和上周差 2 dB或者和标准参考曲线差 3 dB。原因SNR 定义口径混乱——有人按信号总功率/噪声总功率有人按每个 RE 的 Es/N0还有人按 E_b/N0。QPSK 下 Es/N0 和 E_b/N0 差 3 dB如果再把 864 个编码比特折算成 32 个信息比特差距更大。解决仿真脚本里固定用 Es/N0每数据 RE 符号能量对噪声功率谱密度在配置文件里显式打印 SNR 换算关系确保每条曲线都能被别人复现。5.4 蒙特卡洛点数不够BLER 低段乱跳现象BLER 在 10^-3 附近出现强烈的锯齿同样参数跑两遍结果差一倍。原因高 SNR 下错误块是稀有事件固定块数仿真可能只碰到一两个错误块统计方差极大。解决按累计错误块数自适应停止至少累计 100 个错误块对 10^-3 量级目标预先估算需要的最大块数并设max_blocks上限避免无限跑下去。检测成功率统计同理想看 99% 的检测成功率至少跑 1000 次独立 SSB 检测。5.5 信息位集合不按标准来高 SNR 出现错误平台现象BLER 曲线在高 SNR 下不再往下走稳定在 10^-4~10^-5 的平台怎么加大 list 都没用。原因自研 polar 编码器用的信息位集合是经典巴氏参数排序或旧版本计算与 NR 标准指定的 Q 函数量化表不完全一致个别本应冻结的比特被当成信息位这些位置恰好是极化质量最差的产生不可约的错误。解决用 5G Toolbox 的编码器做交叉验证把信息位集合导出成文本文件固化下来每次跑仿真前校验一次避免静默错误。这个坑一旦踩进去排查周期通常以周为单位。6. 代码怎么组织才能稳定复现三条曲线工程结构与验证顺序6.1 模块划分与主循环仿真工程按发射、同步、解调译码、统计四个方向拆。主循环是 SNR 外层、块内层块循环适合并行加速parfor blk 1:max_blocks [det_ok, ber, bler] sim_one_block(snr_esn0, cfg); results(blk, :) [det_ok, ber, bler]; end每个块独立生成 SSB、加信道、走完整接收链路块之间不共享状态这是并行仿真的前提。配置项集中在cfg结构体里包括频偏、定时偏移、信道类型、list 大小、统计容限。打印每个阶段的尺寸链A→B→N→E→symbols排障时能省一半时间。6.2 先验证译码器再逐级打开同步链路建议按“理想同步 → 半联合 → 全联合”的顺序解锁。第一步关闭频偏和定时偏移直接把发射端的 PBCH 符号对齐到接收端单独验证 polar 译码器和统计脚本BER/BLER 应当和理想曲线一致。第二步只加频偏不加定时偏移验证频偏估计与补偿模块。第三步全链路跑通对比三条曲线。每一步留一个 golden 输出文件防止后续改动把已验证的结果弄坏。6.3 操作视频对应的演示路径代码操作视频按这个演示路径录制先跑单次仿真脚本打印每个阶段的尺寸链和中间估计值再跑蒙特卡洛脚本展示三条曲线随 SNR 从 -5 dB 到 3 dB 的变化最后演示如何把残余频偏注入解调模块观察 BLER 劣化曲线。视频里出现的参数和这里的cfg结构体一一对应照着改就能复现。我做这个仿真最深刻的一次教训是检测成功率做到 99.5% 之后得意了很久结果发现 PBCH 一直没解扰BER 卡在 50% 左右。那周我天天在查 polar 译码器最后发现是扰码的问题。从那以后我给自己定了个规矩所有模块先在理想条件下单测再逐级打开非理想因素每一步留 golden 输出。这个习惯帮我少走了很多弯路希望帮到你。本文还有配套的精品资源点击获取