ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

5G NR UCI 配置与验证实战:从参数规划到日志排查

2026/10/2 10:11:55 拓冰建站 浏览量
5G NR UCI 配置与验证实战:从参数规划到日志排查 简介这份文档面向5G网络优化工程师及无线通信学习者系统梳理NR网络中上行控制信息UCI的承载机制与PUCCH设计要点帮助读者理解调度请求、HARQ ACK/NACK及CSI等控制信令如何在物理上行控制信道上传输。资源为1个docx文件压缩包约18KB内容以表格与参数对照为主便于快速查阅。文档重点讲解PUCCH五种格式Format 0与1适用于短UCI并支持同一PRB内UE复用Format 2采用频率分集且不支持复用Format 3与4面向大UCI负载并具备不同程度的复用与跳频能力同时依据3GPP TS 38.300-5.3.3列出各格式的UCI比特长度、符号数、起始PRB、循环移位、时域OCC、跳频及最大码率等参数差异。已有369人学习下载适合需要掌握PUCCH格式选型、优化上行资源利用率与调度策略的读者参考。1. 5G(NR) 里的 UCI从一条控制信息看终端与基站的对话方式做 5G 终端或基站侧调试的人迟早会碰到一个绕不开的东西UCI。你在抓 PUCCH 日志、看 PUSCH 上的 CSI 上报、排查调度异常时背后几乎都有它在起作用。UCI 全称 Uplink Control Information上行控制信息是 NR 终端向 gNB 反馈“我这边情况如何”的核心载体。它承载 HARQ 反馈、CSI 报告、调度请求这几类关键内容直接决定基站下一拍怎么给你分配资源。很多人把 5G 峰值速率计算公式背得滚瓜烂熟却在实际链路里发现速率上不去问题往往就出在 UCI 的配置或时序上。这篇笔记面向做 5G 协议栈、终端射频、基站测试的工程师把 UCI 是什么、在哪些信道上发、参数怎么配、坑在哪一层层拆开讲清楚让你看完能自己动手复现一套 UCI 的配置与验证流程。2. UCI 到底装了什么三类内容与两条上行信道2.1 HARQ-ACK、CSI、SRUCI 的三类核心载荷UCI 不是单一消息而是一组上行控制信息的统称。按 3GPP 的框架它主要装三类东西。第一类是 HARQ-ACK也就是混合自动重传请求的确认反馈。基站通过 PDSCH 给你发下行数据你收到后要告诉它“收到没收到、解对没解对”。这个反馈就是 HARQ-ACK一个比特对应一个 TB 或一个 CBG。它是闭环重传的命脉反馈晚了或错了基站要么盲目重传浪费资源要么误判链路质量。第二类是 CSI信道状态信息。终端测量下行参考信号后把 CQI、PMI、RI、LI 等指标上报给基站。基站靠这些信息决定给你用什么调制编码策略、几层 MIMO、预编码矩阵怎么选。CSI 报得准不准、报得及不及时直接决定下行吞吐。很多现场“信号满格但速率低”的玄学问题根子就在 CSI 上报周期和精度上。第三类是 SR调度请求。当终端有上行数据要发但还没拿到上行授权时通过 SR 向基站“举手”要资源。SR 本身只占一个比特但它的配置周期和时机直接影响上行时延。这三类内容可以单独发也可以复用在一起发。理解它们的优先级和复用规则是读懂 UCI 的第一步。2.2 PUCCH 与 PUSCHUCI 的两条承载路径UCI 不能凭空发出去它必须寄生在上行物理信道上。NR 里承载 UCI 的信道有两个PUCCH 和 PUSCH。PUCCH 是专门给 UCI 用的上行控制信道不传用户数据。它分多种格式Format 0 到 Format 4不同格式对应不同的载荷大小和符号长度。Format 0 和 1 适合小载荷1 到 2 比特Format 2、3、4 适合大载荷CSI 报告可能几十上百比特。选哪个格式取决于你要发多少比特、覆盖条件如何、是否要做跳频。PUSCH 本来是传用户数据的但当 UCI 和上行数据在同一时隙撞车时UCI 会被复用到 PUSCH 上一起发。这叫 UCI on PUSCH。复用有严格的规则HARQ-ACK 会打孔或速率匹配到数据里CSI 按 beta 偏移量插入SR 则通常不单独在 PUSCH 上发。复用做得好省资源做得不好数据解调直接翻车。提示判断一条 UCI 走 PUCCH 还是 PUSCH先看同一时隙有没有上行授权。有授权且满足复用条件就复用到 PUSCH没有授权才走 PUCCH。2.3 用一张表看清 UCI 类型与信道的对应关系UCI 类型典型载荷首选信道复用信道关键参数HARQ-ACK1~2 bit单 TBPUCCH Format 0/1PUSCHK1、PUCCH 资源索引CSI Part 1固定比特PUCCH Format 2PUSCH上报周期、beta 偏移CSI Part 2可变比特PUCCH Format 2/3/4PUSCH码本配置、子带大小SR1 bitPUCCH Format 0/1一般不复用SR 周期、SR 资源 ID这张表是我在配 UCI 时最常翻的对照。它帮你快速定位手上这条 UCI 该走哪条路涉及哪些参数。实际配置里K1PDSCH 到 HARQ-ACK 的时隙偏移和 PUCCH 资源索引是最容易配错的两个后面会专门讲。3. 动手配一套 UCI从参数规划到日志验证3.1 先规划 PUCCH 资源集与 SR 周期配置 UCI 的第一步不是写代码而是规划资源。你需要确定几件事PUCCH 资源集里放几个资源、每个资源用什么格式、SR 周期设多少、CSI 上报周期设多少。常见做法是给 HARQ-ACK 配 2 到 4 个 PUCCH 资源覆盖不同载荷大小给 SR 单独配一个资源周期根据业务时延要求定比如 10ms 或 20msCSI 上报周期根据下行调度需求定周期越短越准但开销越大。下面是一段用 Python 描述 PUCCH 资源规划的示例模拟配置生成逻辑# PUCCH 资源集规划示例 # 定义每个 PUCCH 资源的格式、起始符号、符号数和 PRB 偏移 pucch_resource_set [ {res_id: 0, format: 0, start_symbol: 12, n_sym: 2, prb_offset: 0}, {res_id: 1, format: 1, start_symbol: 10, n_sym: 4, prb_offset: 0}, {res_id: 2, format: 2, start_symbol: 4, n_sym: 8, prb_offset: 3}, {res_id: 3, format: 3, start_symbol: 0, n_sym: 14, prb_offset: 5}, ] # SR 配置周期 20ms偏移 5 个时隙 sr_config {sr_period_ms: 20, sr_offset_slot: 5, sr_res_id: 0} # CSI 上报配置周期 40ms使用 PUCCH Format 2 csi_config {csi_period_ms: 40, csi_format: 2, csi_res_id: 2} def validate_resource_set(res_set): 检查资源集是否有格式覆盖小载荷和大载荷 formats [r[format] for r in res_set] has_small any(f in (0, 1) for f in formats) has_large any(f in (2, 3, 4) for f in formats) if not (has_small and has_large): print(警告资源集未同时覆盖小载荷和大载荷格式) else: print(资源集格式覆盖检查通过) validate_resource_set(pucch_resource_set) print(SR 配置:, sr_config) print(CSI 配置:, csi_config)这段代码的逻辑很直白先定义资源集再定义 SR 和 CSI 的周期参数最后做一个覆盖性检查。参数说明上start_symbol和n_sym决定 PUCCH 在时隙里占哪几个符号prb_offset决定频域位置。实际配置时这些值要和基站的调度器对齐否则会出现终端发了但基站没在对应位置收的情况。3.2 用命令行工具抓 PUCCH 与 PUSCH 日志规划完参数下一步是验证。如果你在 OAI 或类似开源 5G 协议栈上做实验可以用命令行抓日志。常见做法是启动 gNB 和 nrUE 后用日志级别控制输出过滤出 UCI 相关的内容。# 启动 gNB开启 PHY 和 MAC 层日志 sudo ./nr-softmodem -O gnb.conf --log_config.phy_log_level debug \ --log_config.mac_log_level debug 21 | tee gnb_uci.log # 另开终端启动 nrUE sudo ./nr-uesoftmodem -O ue.conf --log_config.phy_log_level debug 21 | tee ue_uci.log # 过滤 UCI 相关日志行 grep -iE UCI|PUCCH|HARQ-ACK|SR|CSI ue_uci.log | head -50这段命令的关键在日志级别和过滤词。phy_log_level debug会把物理层的细节打出来包括 PUCCH 的格式、资源索引、HARQ-ACK 的比特值。grep过滤时UCI、PUCCH、HARQ-ACK、SR、CSI 这几个词能覆盖大部分相关行。如果你看到 HARQ-ACK 的比特一直是 NACK先别急着怀疑射频去查 K1 配置和 PDSCH 的解调结果。参数说明-O指定配置文件--log_config控制日志级别。不同版本的 OAI 参数名可能略有差异以你本地--help输出为准。3.3 验证 HARQ-ACK 时序K1 到底怎么算K1 是 PDSCH 到对应 HARQ-ACK 的时隙偏移。它决定终端在收到下行数据后隔几个时隙才反馈。K1 配小了终端还没解调完就要发反馈只能报 NACKK1 配大了重传时延增加吞吐下降。计算 K1 时要考虑终端处理时延N1、时序提前量TA和调度时隙。常见做法是先按协议最小处理时延定一个基准值再根据实测的 PDSCH 解调时间微调。下面是一个简单的 K1 校验脚本def check_k1(k1_slots, n1_symbols, slot_symbols14, ta_slots0): 校验 K1 是否满足最小处理时延要求 k1_slots: 配置的 K1 值时隙 n1_symbols: 终端最小处理时延符号 slot_symbols: 每时隙符号数常规 CP 为 14 ta_slots: 时序提前量折算的时隙数 n1_slots n1_symbols / slot_symbols min_k1 n1_slots ta_slots if k1_slots min_k1: print(fK1{k1_slots} 小于最小要求 {min_k1:.2f}可能导致 NACK) else: print(fK1{k1_slots} 满足要求余量 {k1_slots - min_k1:.2f} 时隙) # 示例N18 符号TA 折算 0.5 时隙配置 K12 check_k1(k1_slots2, n1_symbols8, ta_slots0.5)逻辑说明把 N1 从符号折算成时隙加上 TA 折算值得到最小 K1。配置值小于它就会出问题。参数上N1 取决于终端能力capability不同 UE 不一样查你设备的 capability 信令就能拿到。TA 折算要看小区半径和子载波间隔。注意K1 不是越大越好。K1 增大虽然给终端更多处理时间但会拉长 HARQ 往返时延影响上行调度效率。找到满足 N1 的最小值附近通常是最优的。4. UCI 配置里最容易翻车的五个地方4.1 PUCCH 资源冲突导致 HARQ-ACK 丢失现象终端日志显示发了 HARQ-ACK但基站侧收不到重传率居高不下。原因多个 UE 的 PUCCH 资源在频域或码域上撞了基站解调时互相干扰。或者同一个 UE 的 SR 资源和 HARQ-ACK 资源配到了同一个 PRB。解决检查 PUCCH 资源集的 PRB 偏移和循环移位配置确保不同 UE 之间正交。同一 UE 的 SR 和 HARQ-ACK 资源要分开。用基站侧的 PUCCH 接收功率日志确认是否有干扰。4.2 CSI 上报周期与下行调度不匹配现象下行速率波动大CQI 上报值长期偏低或偏高。原因CSI 上报周期设得太长基站拿到的信道信息已经过期或者 CSI 的 beta 偏移量设得太小CSI 在 PUSCH 上被数据挤掉。解决把 CSI 周期调到和下行调度周期匹配一般 20ms 到 40ms 是常见起点。检查 PUSCH 上 CSI 的 beta 偏移确保 CSI 有足够的编码增益。对比基站侧记录的 CQI 和终端上报的 CQI偏差大就调周期。4.3 SR 周期过长导致上行时延飙升现象上行数据要等很久才发出去时延测试不达标。原因SR 周期设得太大比如 40ms 甚至 80ms终端有数据时要等下一个 SR 机会才能请求资源。解决根据业务时延要求缩短 SR 周期。eMBB 场景 10ms 到 20ms 通常够用URLLC 场景要更短。但 SR 周期太短会增加 PUCCH 开销要在时延和容量之间权衡。4.4 UCI on PUSCH 复用时的打孔规则搞错现象PUSCH 上的数据解调错误率高尤其是 HARQ-ACK 比特多的时隙。原因HARQ-ACK 复用到 PUSCH 时打孔位置算错把数据的关键比特打掉了。或者 CSI 的插入位置和 HARQ-ACK 重叠。解决严格按协议规定的复用顺序排列先放 HARQ-ACK再放 CSI Part 1最后放 CSI Part 2。检查打孔后的有效编码速率确保不超过阈值。用链路级仿真验证复用后的 BLER。4.5 K1 配置忽略了终端能力差异现象同一小区里部分 UE 的 HARQ-ACK 正常部分 UE 一直 NACK。原因不同 UE 的 N1 处理能力不同用同一个 K1 值能力弱的 UE 来不及处理。解决查每个 UE 的 capability 信令按最弱 UE 的 N1 来定 K1或者给不同 UE 配不同的 K1 集合。在调度器里做区分别一刀切。5. 把 UCI 验证做成可复现的自动化流程前面讲的都是单点配置和排查。实际项目里UCI 的问题往往在版本迭代或参数调整后重新出现。我后来养成的习惯是把 UCI 的关键检查做成一个自动化脚本每次改配置后跑一遍省得反复踩同样的坑。具体做法是用 Python 读取配置文件提取 PUCCH 资源集、SR 周期、CSI 周期、K1 值然后逐项做规则校验。校验规则包括资源集是否覆盖小载荷和大载荷格式、SR 周期是否在合理范围、K1 是否满足最小处理时延、CSI beta 偏移是否在有效区间。任何一项不通过就报错并打印出具体参数和建议值。import json def load_config(path): with open(path, r) as f: return json.load(f) def validate_uci_config(cfg): errors [] # 检查 PUCCH 资源集格式覆盖 formats [r[format] for r in cfg[pucch_resource_set]] if not any(f in (0, 1) for f in formats): errors.append(缺少小载荷 PUCCH 格式0/1) if not any(f in (2, 3, 4) for f in formats): errors.append(缺少大载荷 PUCCH 格式2/3/4) # 检查 SR 周期 if cfg[sr_period_ms] 40: errors.append(fSR 周期 {cfg[sr_period_ms]}ms 偏大建议不超过 40ms) # 检查 K1 n1_slots cfg[n1_symbols] / 14 if cfg[k1_slots] n1_slots: errors.append(fK1{cfg[k1_slots]} 小于 N1 折算 {n1_slots:.2f} 时隙) # 检查 CSI beta 偏移 if not (1.0 cfg[csi_beta_offset] 20.0): errors.append(fCSI beta 偏移 {cfg[csi_beta_offset]} 超出常见范围) return errors # 示例配置 cfg { pucch_resource_set: [ {res_id: 0, format: 0}, {res_id: 1, format: 2}, ], sr_period_ms: 20, k1_slots: 2, n1_symbols: 8, csi_beta_offset: 5.0, } errs validate_uci_config(cfg) if errs: for e in errs: print(配置问题:, e) else: print(UCI 配置校验通过)这个脚本的价值在于把散落在协议文档和血泪经验里的规则固化成可执行的检查项。每次改配置先跑它能挡掉大部分低级错误。参数上n1_symbols从 UE capability 取csi_beta_offset的合理范围参考协议表格不同 CSI 比特数对应不同 beta 值。再进一步可以把日志解析也加进来。抓完 PUCCH 和 PUSCH 日志后用正则提取 HARQ-ACK 的 ACK/NACK 比例、CSI 上报的 CQI 分布、SR 的触发次数和配置校验结果一起输出成一份报告。这样每次版本迭代UCI 的健康状况一目了然。我自己的习惯是新配一套 UCI 参数先跑配置校验再跑一轮短时间的业务测试抓日志最后看报告里的 ACK 比例和 CQI 分布是否正常。三步都过了才认为这套配置可以上测试床。这个流程帮我省了很多后悔药也让我在排查 UCI 问题时不再靠猜。希望帮到你。本文还有配套的精品资源点击获取