资讯动态

HARQ链路仿真:软合并增益计算与MATLAB实现详解

发布时间:2026/9/14 15:08:41 来源:尧图企业网站定制
简介一份以HARQ混合自动重传请求为核心的MATLAB仿真资源压缩包共1个m脚本文件、大小仅6KB专门面向通信系统设计者、信号处理学习者以及无线通信方向的学生用于快速掌握HARQ原理与系统级性能评估也可作为课程设计、课题研究或工程预研的起点。脚本以信号处理为基础围绕HARQ系统的吞吐量分析和重要参数提取展开覆盖Chase合并、停等ARQ、增量冗余等典型HARQ类型并集成FEC编码如Turbo码、LDPC码、卷积码、AWGN与Rayleigh信道模型以及基于反馈的重传决策逻辑同时定义了误码率、帧错误率、信噪比、重传次数、编码速率等关键参数的统计口径和输出方式。已有162人浏览/学习。运行主脚本后读者能直观获得各指标随信道条件和系统配置的变化曲线理解重传次数、编码速率与有效吞吐量之间的权衡关系还可通过修改参数观察不同HARQ策略对可靠性和效率的影响为课程实验、毕业设计或论文仿真提供可直接修改的基础模板。整体结构紧凑便于在此基础上扩展新的信道模型、调制方式或协议算法。1. HARQ 在链路仿真里为什么不能省做物理层链路仿真的人迟早会遇到这个场景AWGN 信道下 BER 曲线已经贴着理论值走了一换到衰落信道相同 SNR 下的误块率突然抬高一到两个数量级。这时候单纯加大发射功率往往不是最优解因为时变信道下的深衰落是功率换不回来的真正有效的手段是把时间分集用起来——HARQ 做的就是这件事。HARQ 是混合自动重传请求本质是把前向纠错FEC和自动重传ARQ揉在同一个闭环里让接收端把错误帧的软信息缓存下来和重传帧合并后再译码。它和普通 ARQ 的差别在于重传不是把旧数据丢掉了重来而是带着上一次译码失败的“记忆”参与联合译码。对于手里有一份yingteng.zip解出来的 HARQ MATLAB 代码、想在仿真环境里复现或改造它的人来说这篇文章会把 HARQ 的类型、软合并增益计算、Turbo 码和 LDPC 码两条实现路径、5G Toolbox 的标准进程都拆开讲清楚并且给出可以直接跑的脚本骨架。内容面向做链路级仿真和算法验证的工程师也面向正在啃 HARQ 相关代码的研究生。2. HARQ 的三种合并方式与 MATLAB 仿真选型2.1 类型 I、Chase 合并与增量冗余的本质区别HARQ 从实现机制上分三代MATLAB 代码里最常见的三种写法对应三种不同的重传策略。类型 I HARQ 最朴素接收端译码失败后直接丢弃当前帧请求发送端重传同样的编码数据重传帧独立译码。这种方式的缓存开销最小但没有任何合并增益本质上和普通 ARQ 加 FEC 没有区别唯一的价值是实现了“重传”这个闭环动作。类型 II HARQ 也叫增量冗余Incremental RedundancyIR每次重传发送的是上一帧没有发过的校验比特接收端把多次传输的软比特拼在一起拼出一个更低码率的码字再译码。Chase 合并类型 II 的特例也叫软合并则是对每个比特的多个副本做加权平均重传内容与首传完全相同合并后等效获得分集增益。三种方式里 IR 的频谱效率最高因为每次重传都在贡献新的校验信息Chase 合并实现最简单只需要一个加法器类型 I 在三者中性能最差已经被前两者取代。MATLAB 中判断一份代码用的是哪种方案只需要看一件事——接收端有没有对上一次的 LLR 做缓存。2.2 软合并的增益到底怎么算Chase 合并的增益可以精确算出来。假设第 i 次传输时某个比特的 LLR 值为 L_i那么合并后的 LLR 是L_combined sum(L(1:N)) % N 次传输的 LLR 直接相加这个式子成立的前提是各次传输经历的是独立衰落且噪声方差不变。在 AWGN 信道下L_combined 的信噪比是单次的 N 倍也就是 10*log10(N) dB 的增益。但 Rayleigh 信道下这个增益不固定因为各次传输的信道系数不同合并后等效信道系数变为各次信道系数的模平方和。实际仿真中观察到的 Chase 合并增益通常在 1.5 到 3 dB 之间具体取决于重传次数和信道的相关时间。IR 的增益来源不同。每次重传增加新的校验比特等效码率从 R 降到 R/(N)距离 Shannon 限更近所以 IR 在低码率区域的表现优于 Chase 合并。MATLAB 仿真里验证这一点的方法是对同一份数据分别跑 Chase 和 IR 的 BLER 曲线观察固定 BLER0.1 处的 SNR 差值。2.3 用哪个工具箱Communications Toolbox 还是 5G Toolbox写 HARQ 仿真代码前先确认手里的工具箱版本。Communications Toolbox 提供的是底层的 FEC 函数比如comm.TurboEncoder、comm.TurboDecoder、comm.LDPCEncoder这些函数只管编解码不管 HARQ 进程管理所有重传时序、软合并缓存、RV 选择都要手工写。5G Toolbox 则是把 HARQ 进程整个封装好了nrDLSCH、nrULSCH这些 System object 内部已经包含 CRC、码块分段、速率匹配、RV 轮转、软合并逻辑适合做标准符合性测试。选型的判断标准很简单如果目标是验证 HARQ 算法本身的性能比如对比合并方式、设计新的重传策略用 Communications Toolbox 手写控制逻辑如果目标是和 5G 协议对齐用 5G Toolbox。前者灵活但代码量大后者省事但对算法级别的修改不友好。提示检查工具箱版本用ver(5G Toolbox)如果返回空说明当前 MATLAB 环境没有安装该工具箱。3. 用 MATLAB 手写 Type-II HARQTurbo 码 速率匹配 软合并3.1 发射端CRC 追加、Turbo 编码与打孔Type-II HARQ 的发射端核心是“编码一次多次打孔”。先看完整的发射端代码% 发射端参数 K 1024; % 信息比特长度 R 1/3; % Turbo 母码码率 crvList [0 2 3 1]; % RV 轮转序列5G 标准定义 nMax 4; % 最大重传次数 % 信息比特流 data randi([0 1], K, 1); % 1. CRC 追加 crcGen comm.CRCGenerator(Polynomial, [1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1]); dataCrc crcGen(data); % 2. Turbo 编码母码码率 1/3 turboEnc comm.TurboEncoder(TrellisStructure, poly2trellis(4, [13 15], 13), ... InterleaverIndicesSource, Random); coded turboEnc(dataCrc); % 3. 速率匹配根据 RV 选择打孔位置 [rvIdx, rmBits] rateMatchTurbo(coded, K, crvList(1), R); % 4. QPSK 调制 modulator comm.QPSKModulator(BitInput, true); txSignal modulator(rmBits);这里的rateMatchTurbo需要自己实现它的核心逻辑是把母码比特循环缓冲到一个虚拟环形缓冲区中RV 决定从哪个位置开始截取。5G NR 标准里 RV0 从缓冲区起点取RV2 从 1/2 位置取RV3 从 1/4 位置取RV1 从 3/4 位置取。这样做的好处是不同 RV 取出的比特段重叠度不同RV 之间距离越远重传提供的新校验比特越多。3.2 接收端LLR 解调和重传软合并接收端的核心是软合并缓存和去速率匹配。每次重传到达后先把新传输的 LLR 填入环形缓冲区对应位置再和缓存里已有的 LLR 相加% 接收端软合并缓存初始化 llrBuffer zeros(3*length(dataCrc), 1); % 存放合并后的 LLR alpha zeros(3*length(dataCrc), 1); % 记录每个位置的有效合并次数 % 对每次传输 for tx 1:nMax % 1. QPSK 软解调得到 LLR demodulator comm.QPSKDemodulator(BitOutput, true, DecisionMethod, LLR); rxLLR demodulator(rxSignal); % 2. 去速率匹配把接收 LLR 放回母码位置 [deRateLLR, validBits] deRateMatchTurbo(rxLLR, K, crvList(mod(tx-1, 4)1), R); % 3. 软合并相同位置的 LLR 叠加 idx find(validBits); llrBuffer(idx) llrBuffer(idx) deRateLLR(idx); alpha(idx) alpha(idx) 1; % 4. 归一化可选避免 LLR 幅度不一致 llrNorm llrBuffer ./ max(alpha, 1); % 5. Turbo 译码 turboDec comm.TurboDecoder(TrellisStructure, poly2trellis(4, [13 15], 13), ... InterleaverIndicesSource, Random, NumIterations, 6); decoded turboDec(llrNorm(1:2*length(dataCrc))); % 6. CRC 校验 crcDet comm.CRCDetector(Polynomial, [1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1]); [~, err] crcDet(decoded); if ~err % 译码成功清空缓存 llrBuffer zeros(size(llrBuffer)); break; end end软合并时有一个关键细节llrBuffer必须存原始 LLR不要提前归一化。因为 Turbo 译码器对 LLR 输入的幅度尺度有一定容忍范围但多次重传后 LLR 幅度会自然增长如果每次合并后都做归一化会丢失合并次数的信息。正确做法是译码前一次性归一化或者干脆不归一化直接给译码器。3.3 主循环脚本重传次数与误块率统计完整仿真链路需要一个外层循环来统计不同信噪比下的 BLER以及一个内层循环来跑足够多的帧snrVec 0:1:6; % 仿真 SNR 范围 numFrames 1000; % 每个 SNR 点帧数 bler zeros(size(snrVec)); for snrIdx 1:length(snrVec) errors 0; for frameIdx 1:numFrames % 生成数据、编码、调制、过信道 % ...此处省略信道模型和收发代码见上文 % HARQ 重传循环 for txIdx 1:4 % 发射端根据 RV 打孔并发送 % 接收端软合并 译码 CRC % 如果 CRC 通过errors 不变break % 如果 4 次都失败errors errors 1 end end bler(snrIdx) errors / numFrames; end figure; semilogy(snrVec, bler, o-, LineWidth, 1.5); grid on; xlabel(SNR (dB)); ylabel(BLER);统计 BLER 时有个常见误区把每次重传当作独立试验来计数。比如一帧数据第一次传输就失败、第二次成功这不叫 0.5 个错误而是 0 个错误最终正确接收。BLER 的分子是“经过全部重传后仍然失败的帧数”分母是总帧数不要和 PERPacket Error Rate混为一谈。4. 基于 5G Toolbox 的标准 HARQ 进程实现4.1 nrDLSCH 和 nrRateMatch 的参数对照如果手里代码是用 5G Toolbox 写的核心对象是nrDLSCH它的参数比手写方案多了很多协议概念。先看一个典型配置% 创建 DLSCH 对象 dlsch nrDLSCH; dlsch.TargetCodeRate 0.5; dlsch.Modulation QPSK; % 配置 HARQ 进程 harq HARQProcess; harq.NRed 2; % 冗余版本数 harq.RVSequence [0 2 3 1]; % 传输块处理 [trBlk, trBlkInfo] dlsch.encode(tb, harq);TargetCodeRate决定速率匹配的基准码率Modulation决定调制阶数二者共同决定传输块能承载的比特数。HARQ 进程中RVSequence是关键参数5G 标准里定义 RV 的轮转顺序是 0→2→3→1每次重传按这个顺序取下一个 RV。对比手写代码和 5G Toolbox 的参数可以发现以下对应关系参数手写方案5G Toolbox说明母码码率R 1/3内部固定Turbo 母码固定 1/3LDPC 内部处理目标码率打孔比例决定TargetCodeRate数值越大有效传输比特越少冗余版本crvList [0 2 3 1]RVSequence决定每次重传的打孔起点交织器自定义协议内建5G 的交织模式由协议规定CRC 多项式自行选择协议内建5G 使用标准 CRC24A/B/C4.2 HARQ 进程时序RV 轮转和 NDl 标志5G 标准中的 HARQ 是同步的发送端和接收端对重传的时序有严格约定。MATLAB 里模拟这个过程时harqProcess对象需要跟踪每个进程的状态classdef HARQProcess handle properties RVSequence [0 2 3 1] CurrentRV 0 NDI 0 % New Data Indicator Buffer end methods function retransmit step(obj, crcPass) if crcPass % 译码成功重置为新的传输 obj.CurrentRV obj.RVSequence(1); obj.NDI mod(obj.NDI 1, 2); % NDI 翻转 retransmit false; else % 译码失败取下一个 RV idx find(obj.RVSequence obj.CurrentRV); obj.CurrentRV obj.RVSequence(mod(idx, length(obj.RVSequence)) 1); retransmit true; end end end endNDINew Data Indicator是 HARQ 进程里的一个重要标志位NDI 不变表示当前传输是上一次数据的重传NDI 翻转表示这是一个新的传输块。接收端靠 NDI 来判断软合并缓存是否需要清空而不是靠 RV 是否为 0——因为 RV0 也可能是重传。4.3 用 nrDLSCH 跑一次完整的重传链路结合nrDLSCH和自定义 HARQ 进程管理可以搭一条完整的链路% 系统参数 nFrames 100; snr 2.0; % dB % 初始化收发对象 dlsch nrDLSCH; dlsch.TargetCodeRate 0.5; dlsch.Modulation QPSK; harq HARQProcess; rxBuffer []; % 主循环 for n 1:nFrames % 生成传输块 tbSize 512; tb randi([0 1], tbSize, 1); % 编码并调制 [coded, info] dlsch.encode(tb, harq); txSig nrSymbolModulate(coded, QPSK); % 过信道AWGN Rayleigh chGain 0.5 0.5*randn; % 信道系数 rxSig txSig.*chGain 10^(-snr/20)*randn(size(txSig)); % 解调和译码 rxLLR nrSymbolDemodulate(rxSig, QPSK, 10^(-snr/10)); % 如果存在待合并的缓存先合并 if ~isempty(rxBuffer) rxLLR rxLLR rxBuffer; end % 译码 [tbHat, crcPass] dlsch.decode(rxLLR, harq, TargetCodeRate, 0.5); % 更新 HARQ 进程状态 retransmit harq.step(crcPass); % 如果需要重传保存当前 LLR if retransmit rxBuffer rxLLR; else rxBuffer []; end end这段代码的帧结构做了极大的简化真实 5G NR 链路还需要考虑 OFDM 调制的资源映射、PDSCH 的时频资源分配等内容。这里把物理层简化成符号级是为了把 HARQ 进程的逻辑单独拎出来。实际项目中dlsch.encode返回的info结构体里有G传输块编码后的总比特数等重要参数用于后续的速率匹配和资源映射不要忽略。5. HARQ 仿真的 4 个常见坑从误码平台到符号对齐5.1 打孔表读错导致的高误码平台这是手写速率匹配时最隐蔽的坑。Turbo 码的循环缓冲区长度是3*K 12包含尾部比特如果打孔索引计算错误重传数据会和首传数据撞在同一个位置导致合并时某些位置的 LLR 被重复相加而另一些位置始终没有数据。表象是误码率在高 SNR 区域出现平台且 BLER 曲线斜率变小。排查方法是在发射端打印每次传输实际取出的比特索引检查 RV0 和 RV2 取出的比特重叠率是否和理论一致——重叠率过高说明打孔起点算错了。5.2 软合并时没有做符号对齐从 zip 包移植代码时常见的错误是直接把解调后的 LLR 相加但两次传输经过的信道和调制过程不同LLR 的幅度尺度就不一致。比如第一次传输经过衰落信道第二次是 AWGN两次 LLR 的方差不同直接相加会让合并结果偏向方差大的一方。解决方法是先估计每帧的噪声方差对 LLR 做归一化再合并% 对每帧的 LLR 做噪声归一化后再合并 llrNorm rxLLR ./ noiseVar; llrBuffer llrBuffer llrNorm;对应地发射端所有重传的调制方式必须相同否则 LLR 的映射规则不一致合并数学上不再成立。5G 标准允许 RV 不同但调制方式不变就是这个原因。5.3 RV 顺序和冗余版本的映射错误RV 的轮转顺序不是 0→1→2→3而是 0→2→3→1。这个顺序是经过优化的RV0 和 RV1 的比特重叠最少约 25%保证重传提供最多新校验信息RV2 和 RV3 之间的间距也类似。如果代码里把 RV 顺序写成自然序前两次重传的增益会下降 0.5 到 1 dB。检查方法很简单打印每次重传取出的比特在环形缓冲区中的起始位置应该分别是 0、1/2、3/4、1/4 总长度处。5.4 从 zip 包移植代码时的浮点与定点问题最后是代码移植中一个容易忽略但很实际的场景很多导师或同事给的 MATLAB 代码里同时包含浮点链路和定点链路两套实现。yingteng.zip这类包里浮点版本通常用来验证算法性能定点版本需要转成 C 或 Verilog。做定点化时软合并缓冲区的位宽选择会直接影响性能位宽太窄多次重传累加后溢出高 SNR 下 BLER 反升位宽太宽硬件面积浪费。经验法则是缓冲区位宽比单次 LLR 位宽多 log2(最大重传次数) 比特比如 LLR 是 6 bit、最大 4 次重传缓冲区用 8 bit 就不会溢出。用 MATLAB 验证定点性能最直接的方式是把每帧的 LLR 用quantizer对象做量化后再合并对比浮点和定点下的 BLER 差异是否在 0.1 dB 以内。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价