简介面向5G网络优化工程师及移动通信学习人员围绕新空口上行控制信息的承载内容与结构展开讲解有助于理解物理上行控制信道与物理上行共享信道上传输的各类控制信令为网络性能优化和参数配置提供参考。资源为一份Word文档共一个docx文件压缩包仅15KB内容精炼便于快速查阅。文档从物理下行控制信道承载下行控制信息的类比切入说明上行控制信息在不同场景下可由物理上行控制信道或物理上行共享信道承载随后梳理混合自动重传请求的确认与否定反馈、调度请求、信道状态信息三类内容及其五种组合方式并依据3GPP规范详解比特结构包括码块组配置前后的反馈比特数差异、时分双工场景的特殊处理、调度请求仅需一比特、信道状态信息不同反馈类型的结构区别等。对涉及5G空口信令分析、优化排障的工程师有直接参考价值。目前已有335人学习下载适合网优、测试及研发人员快速补齐相关知识。1. 5G NR里的UCI一张上行控制上报的“快递单”做过LTE的人刚转NR时最容易低估的其实不是波束管理也不是 numerology而是 UCI——上行控制信息Uplink Control Information。它看起来只是 HARQ-ACK、CSI、SR 三类信息的打包但 5G NR 里它的格式数量、时频位置和承载方式都远比 LTE 复杂。很多项目初期把 UCI 当“小字段”处理结果外场一跑就发现PUCCH 解调门限不对、CSI 上报 bit 数算错、HARQ-ACK codebook 对不上调度器看到的终端状态全是黑匣子。这篇笔记从 UCI 承载内容讲起一直落到格式选择、参数配置和排错手法最后给一套我自己常用的验证习惯。适合刚接触 NR 协议栈的开发者也适合做基站侧调度或 UE 协议实现、正被上行反馈问题折磨的工程师。2. UCI 承载的三个内容HARQ-ACK、CSI 与 SR 各自的脾气2.1 HARQ-ACK从 DAI 到 Codebookbit 是怎么数出来的HARQ-ACK 在 UCI 里是优先级最高的内容因为 ACK/NACK 直接决定发送端是否重传。NR 里 HARQ-ACK 反馈与下行调度绑定终端需要根据 PDCCH 上 DCI 的调度信息判断“该反馈哪几个 PDSCH 的接收结果”。这段逻辑在协议栈里对应两个概念半静态 codebook 和动态 codebook。半静态 codebook 是一个固定 bit 位图终端和基站通过 RRC 配置的候选 PDSCH 时机集合对齐每个候选位置对应一个 bit。它的优点是简单缺点是哪怕基站只调度了一个 PDSCH终端也会按整个集合大小反馈。动态 codebook 则用 DCI 里的 DAIDownlink Assignment Index字段指示调度的累计数终端按最近一次 DAI 决定反馈 bit 数。两者叠加上行链路里可能出现的 HARQ-ACK 合并、多载波和 multi-TRP 场景位宽就不容易一眼看穿了。实际开发中我一般先确定终端用的是哪种 codebook再决定后续链路怎么验。RRC 里由pdsch-HARQ-ACK-Codebook字段控制可选semi-static或dynamic。默认值是 semi-static很多试验系统没改这个字段就会用固定位宽回传。如果你在外场里看到 UE 反馈的 bit 数跟预期不一致优先查这一项。2.2 CSI 反馈RI/PMI/CQI 与 Part 1、Part 2 的拆分逻辑CSIChannel State Information在 UCI 里的结构比 HARQ-ACK 更复杂。NR 把 CSI 分成 Channel Quality Indicator (CQI)、Precoding Matrix Indicator (PMI)、Rank Indicator (RI)以及可选的 CSI-RS Resource Indicator (CRI)。这些字段在物理层编码时不是简单拼在一起而是按 38.212 分成 CSI Part 1 和 CSI Part 2。Part 1 的 bit 数固定承载 RI、CQI 以及 Part 2 的 bit 数指示Part 2 承载 PMI 的低优先级部分。这种设计是为了让接收端先以固定开销解出 Part 1再依据里面的“长度指示”去解 Part 2。如果 Part 1 的 bit 数算错后面整包都白解。很多调试新手把 CSI 当“就一个整数”直接用 RRC 里的reportQuantity字段值去算 payload忽略了 wideband 和 subband 的差异最后解出来全是错值。我在计算 CSI 大小时习惯先确认三件事上报模式是 periodic / semi-persistent / aperiodic频域粒度是 wideband 还是 subband以及码本类型是 Type I 还是 Type II。Type II 码本的 PMI 体积大不少经常超过 PUCCH format 2 的容量这时候网络会把 CSI 挪到 PUSCH 上传输。这个判断不是看“能不能塞下”而是看优先级和功率预算下面会细说。2.3 SR只有“有没有”没有“是多少”SRScheduling Request在 UCI 里的信息量最小不带具体数据只表达“我有上行数据要传”。正因为它语义简单很多实现容易踩坑SR 不单独编码位图而是通过 PUCCH format 0 或 format 1 的不同时频资源来表达“有”和“没有”。也就是说SR 是有专用 PUCCH 资源的而不是随便拿一个上行资源塞一个 bit。终端被配置了 SR 资源后在特定周期内若没有数据就不发送 PUCCH有数据才在对应资源上发规定格式。接收端做的是能量检测不是比特解调。理解了这一点你在分析“UE 为什么没发 SR”时就不会去查解调星座图而是先看能量检测门限。SR 的周期和时隙偏移由 RRC 参数schedulingRequestConfig配置里面periodicityAndOffset可配 1、2、4、8、10、20、40、80 个时隙等。工程上最常犯的错是把 SR 周期配得太长导致上行数据排队延迟飙升用户面时延从 20ms 级变成 100ms 级还查不出原因。3. UCI 在物理信道上的承载PUCCH format 0 到 format 4 怎么选UCI 不管内容多少最终都要落到 PUCCH 或 PUSCH 上。PUCCH 在 NR 里有五种格式很多初学者把它们当“协议规定的五种情况”背下来就完事实际上选型逻辑是围绕两个维度展开的能承载多少 bit以及能覆盖多大范围。表NR PUCCH format 概览Format符号数最大 UCI bit 数复用能力典型用途01-21-2 bit通过序列选择表达SR、少量 HARQ-ACK14-141-2 bit通过 OOK 表达长时延场景的 SR/ACK21-2约几十到上百 bitBPSK/QPSK 调制小包 CSI、ACKCSI34-14数百 bitDFT-S-OFDM多 UE 频分大包 CSI、多载波 ACK44-14数百 bit支持多 UE 频分最多 4 个正交端口容量受限场景3.1 format 0 和 format 1低时延小载荷的正交资源玩法format 0 用 1 到 2 个 OFDM 符号承载最多 2 bit 的 UCI但它不靠 QPSK 调制传递 bit而是通过不同的循环移位cyclic shift和时频位置来表达“哪组 bit”。这是 NR 与 LTE 差异较大的地方因为 LTE 的 PUCCH 主要靠 QPSK 调制。format 0 的接收端实际上做的是相关检测在预知的一组候选序列里找能量最大的那条。format 1 是长格式最多 14 个符号依然只承载 1-2 bit。它用 OOK 方式表达“有无”通过正交覆盖码OCC区分多个 UE。选择 format 1 的关键原因往往是覆盖符号拉长后能量累积多解调门限可以降低几 dB。代价是时延和资源占用变大。如果你的基站覆盖边缘 UE 频繁出现 ACK 丢失不一定是链路预算问题先看看是不是把 format 1 配成了 format 0。具体配置在PUCCH-Config里以pucch-Format0、pucch-Format1为节点填入startingSymbolIndex和nrofSymbols。我常用的配置是 format 0 用 2 符号、format 1 用 14 符号。前者放在时隙靠后位置后者放在靠前位置以便在时域上错开。3.2 format 2/3/4大 payload 的容量与复用权衡当 UCI bit 数超过 2 bit比如 CSI 里带了 RIPMICQI就得换 format 2、3、4。format 2 是短格式占用 1-2 个符号用 QPSK 调制可以承载几十到上百 bit。它适合放在时隙尾部用于快速反馈。format 3 和 format 4 是针对更大 payload 的长格式。format 3 的调制方式基于 DFT-S-OFDM承载几百 bit 没问题。format 4 的典型特征是支持最多 4 个正交端口也就是说一个 PRB 可以频分给多个 UE但同一个 PRB 上不同 UE 用不同端口来区分。选 format 3 还是 format 4本质是在问瓶颈是容量还是复用规模如果小区里反馈 CSI 的 UE 数量多format 4 的复用优势明显如果单个 UE 的 CSI 上报特别大format 3 更直接。这里有一个参数值得特别注意PUCCH-Format3里的nrofPRBs。很多实现默认给 1 个 PRBCSI 大时编码率过高BER 一路恶化。我一般先按 8 bit 一个 PRB 的粗略经验估算再根据 MCS 和 SNR 修正。实际项目里 format 3 最多可以配到 16 个 PRB但 PRB 越多与 PUSCH 抢资源越严重。做容量规划时PUCCH 占用的 PRB 总数要控制在小区总带宽的 5% 到 10%否则数据信道会被严重挤压。3.3 UCI on PUSCH速率匹配与抢占的边界UCI 不只在 PUCCH 上走当 PUCCH 资源不够或 UE 正在发 PUSCH 时UCI 会被栽到 PUSCH 上。整个过程涉及两个关键动作HARQ-ACK 符号先占据离 DMRS 最近的资源CSI 再往两侧放如果空间不够CSI 按优先级丢弃部分内容。工程上这叫“UCI on PUSCH 的速率匹配”。实现时最容易出错的是UCI 占用的 RE 数改变了 PUSCH 数据区的实际可用 RE 数而速率匹配是按这个“新 RE 数”做的。不少终端实现为了省事先按无 UCI 的 RE 数做速率匹配再把 UCI 硬塞进去结果就是 PUSCH 的编码率被悄悄抬高BLER 掉不下来。另外PUSCH 上放置 HARQ-ACK 的密度要看betaOffsetACK-Index这个参数它决定 UCI 相对数据的功率偏置。这个值不是越大越好偏置大了数据信道功率被打压偏置小了 ACK 解调失败触发重传反而浪费更多资源。我做外场调测时会把 ACK 的 beta 偏置从 1.0 起步每档 0.25 步进扫观察小区上行 BLER 和重传率找到平衡点。4. 让 UCI 真正落地的参数从配置到调度器的 5 个必调点4.1PUCCH-Config里的资源配置顺序PUCCH 资源不是给每个 UE 单独订制的而是由基站配置一个资源集再用 DCI 里的 PUCCH resource indicator 字段在集合里动态选一个。这个过程在 RRC 里叫pucch-Resource一组资源按pucch-ResourceId编号。新手常犯的错是只配置了 format 0/1没配 format 2/3结果调度器给 UE 发了 CSI 上报请求UE 却没有对应格式的资源可用反馈直接失踪。我一般建议按这个顺序检查 RRC先看pucch-ResourceCommon有没有给初始接入用再看pucch-ResourceDedicated里是不是覆盖了全部需要的 format最后确认pucch-ResourceSet里的资源数量是否与 DCI 指示位宽度匹配。DCI 里的 PUCCH resource indicator 通常是 3 bit对应最多 8 个候选资源若集合里只有 4 个另外 4 个索引就不会被调度到资源利用率腰斩。4.2 时频位置、优先级与冲突处理PUCCH 的时频位置直接影响解调性能。时域上PUCCH 的起始符号不能与 PDSCH 的 DMRS 位置重叠频域上尽量把 PUCCH 分散在带宽两侧避免集中在一侧导致频率选择性衰落同时影响所有 PUCCH。很多局点为了方便把 PUCCH 全放在带宽边缘的同一个 PRB 上外场测试时一遇到窄带干扰全部反馈一起挂掉这属于典型的资源规划翻车。冲突处理是另一个必须提前想清楚的点。当 HARQ-ACK 和 CSI 要同时上报且 PUCCH 资源冲突时NR 协议规定只发 HARQ-ACKCSI 丢弃当两个不同优先级的 PUCCH 冲突优先发高优先级。这个逻辑看似清晰但实现里涉及信道选择multiplexing和丢弃dropping两条路径一旦代码分支没写干净线上就会出现“偶尔丢 ACK”。排查时不要只看丢包率先看代码路径是否把冲突场景走到了 dropping 分支。4.3 用一个小脚本估算 CSI payload 尺寸我在写 CSI 相关代码前习惯先用脚本把 payload 尺寸粗算一遍避免到联调时才被解码器打回来。下面这个脚本按 38.212 的表格逻辑做了一个简化版估算用来核对 RI、CQI、PMI 的 bit 数是否合理。import math def csi_payload_size(ri, cqi_wideband, cqi_subband, pmi_bits_wideband, pmi_bits_subband, subband_count): # 简化模型仅用于链路联调前的数量级核对 part1_ri_bits math.ceil(math.log2(ri 1e-9)) if ri 1 else 1 part1_cqi_bits 4 2 * subband_count # 4 bit wideband CQI 每 subband 2 bit part1_pmi_bits pmi_bits_wideband part2_bits pmi_bits_subband * subband_count part1_total part1_ri_bits part1_cqi_bits part1_pmi_bits 2 # 2 保留位 return part1_total, part2_bits # 例4 个 subbandwideband PMI 用 2 bitsubband PMI 用 1 bit p1, p2 csi_payload_size(ri2, cqi_wideband5, cqi_subband2, pmi_bits_wideband2, pmi_bits_subband1, subband_count4) print(fCSI Part1 ≈ {p1} bit, Part2 ≈ {p2} bit) print(f总 CSI ≈ {p1 p2} bit)这段脚本的part1_cqi_bits是按“4 bit 宽带 CQI 每 subband 2 bit”估算的实际标准里 subband CQI 的 bit 数与cqi-FormatIndicator有关需要查表。这么写的目的是让你在配 PUCCH format 2 时先算清楚“装不装得下”。如果算出来的总尺寸超过 100 bit我会直接放弃 format 2改用 format 3 或 PUSCH 上报。这里要提示一个代码实现常踩的坑math.log2(ri)在 ri 为 1 时结果是 0需要加保护。我见过有同事在 RI1 时算出 0 bit 的 RI 字段导致编码器与解码器 bit 流错位联调排查了一整天最后发现是 log 函数边界没处理。4.4 与调度器的配合避免 PUCCH 与 PUSCH“互踩”调度器在分配上行资源时默认只知道 PUCCH 占用的 PRB 和时隙位置但 UCI on PUSCH 的场景里PUSCH 时频资源里会被 UCI 占掉一块。如果调度器在计算 TBS 时没有预留这部分 RE就会高估可传数据量实际传输时数据挤不进预定的 RE 数终端只能降码率硬塞或把尾部数据打孔。工程上有一个经验值PUSCH 里若携带 HARQ-ACK预留 RE 一般占 PUSCH 总 RE 的 2% 到 5%若携带大 CSI预留可能到 10%。调度器做 MCS 选择时最好参考 UE 实际上报的betaOffset来估算 UCI 占用。这个值在终端侧会随功率偏置变化不能拿一个固定百分比算到底。4.5 测量与验证用日志核对 UCI 时频位置验证配置是否正确最直接的办法是抓 UE 侧的物理层日志看 PUCCH 实际发送的时隙、符号、PRB 起始位置是否符合 RRC 配置。很多协议栈实现里PUCCH-Config的startingSymbolIndex和nrofSymbols只被静态读取了一次后续 RRC 重配后没刷新导致 UE 一直按老配置发。这类问题的现象是终端重配置后 ACK 丢失率突然升高而且只在重配后出现。我习惯在每次 RRC 重配后对比一次“配置下发的 PUCCH 资源集合”和“UE 侧记录的 PUCCH 发送记录”做一个自动比对脚本。只要有一个符号位置不一致就立刻抛错。别相信“配置已经下发成功”这个信息真正的保障是你的日志比对而不是信令层的成功回执。5. UCI 调测避坑4 个上行反馈的典型翻车现场5.1 PUCCH format 0 的 ACK 偶尔解不出来现象小区边缘 UE 上传速率正常但下行 TCP 吞吐忽高忽低重传率高企。抓日志发现 HARQ-ACK 在 PUCCH format 0 上偶尔解不出不是每次失败。原因format 0 只有 1-2 个符号能量累积少边缘 UE 的 SNR 刚好在解调门限附近。加上 format 0 用的是序列检测不同循环移位之间的相关性在低 SNR 时会互相泄漏导致误检。配置侧为了省资源把 format 0 设成 1 个符号加剧了这个问题。解决把 format 0 改为 2 个符号同时确认循环移位间隔不是最小粒度。若覆盖仍不足直接把该 UE 的 PUCCH 切到 format 1用 14 符号的长时间累积换解调增益。这个操作会牺牲少量资源但对边缘 UE 的吞吐收益很明显。5.2 CSI Part 1 的 bit 数算错整包被网络丢弃现象PUSCH 上带 CSI 时基站侧连续解调失败但纯数据 PUSCH 正常。去掉 CSI 后故障消失。原因终端编码用的是“简化脚本算出来的 bit 数”而基站解码按标准表得到的 bit 数两边不一致。典型场景是 wideband CQI 之后又配了 subband CQI终端只算 wideband 的 4 bit漏了 subband 字段导致后续 bit 流整体错位。解决CSI 的 bit 数计算必须以 38.212 的表为准尤其是 subband 数量、CDM 类型和码本配置。我在团队里要求所有 CSI 相关代码必须先用下面这个思路自测从 RRC 配置的csi-ReportConfig里提取上报量再按宽频/子带逐一累加最后用标准里的计算公式核对。任何“约等于”都不可接受。5.3 DAI 对不上动态 codebook 长度错位现象下行多载波调度时UE 反馈的 HARQ-ACK bit 数比基站预期少。单载波正常双载波必现。原因动态 codebook 里DAI 在跨载波调度场景下按载波遍历顺序计数终端按收到的最后一个 DAI 决定反馈长度。如果终端实现把 DAI 按“每个载波独立计数”处理多载波一开就对不上。解决重读 38.213 里 DAI 计数规则确认实现是按“先时隙、后载波”的全局顺序累计。修复后需要做多载波联合调度回归测试至少覆盖 2 载波、3 个时隙、不同 DCI 分布的组合不能只测单载波 happy path。5.4 UCI 挤占 PUSCH 数据BLER 不掉反涨现象开启 UCI on PUSCH 后上行 BLER 从 5% 涨到 15%但 MCS 没有变。关掉 CSI 上报后恢复正常。原因UCI 占用 PUSCH 的 RE但 TBS 还是按无 UCI 的 RE 数计算的导致实际编码率高于目标。终端侧为了硬塞数据把 PUSCH 数据打孔或降低编码冗余BLER 自然恶化。解决调度器必须根据 UCI 的 beta offset 和 payload 预估调整 TBS。如果 UCI 里既有 HARQ-ACK 又有 CSI优先保证 ACK 的 beta offset 不被打折CSI 的 beta 可以适当调低。若 PUSCH 资源本身紧张宁可在调度器里推迟 CSI 上报也不要硬塞导致一整包数据加反馈全部失败。6. 验证 UCI 的进阶习惯从信令到比特级的一整条证据链排查 UCI 问题时我最后总会回到一个习惯一条反馈信息要有“从 RRC 配置到物理层比特”的完整证据链只信一半日志往往会把问题定位错方向。我的检查顺序是这样的先从 RRC 拿到PUCCH-Config和csi-ReportConfig确认 format、周期、资源 ID 都在预期内再去 MAC 层看 PUCCH 的实际调度记录确认资源未被抢占或跳过最后到物理层解调日志里核对 UCI bit 流和校验结果。这三段对不上就不急着改参数先找是哪一层丢了信息。举一个实际例子有次外场反映某型号终端做完 CSI 上报后 PUSCH 始终误码。我按上述证据链查了一遍RRC 配置正常MAC 调度正常物理层解调却发现上报的 CSI 里 PMI 的 bit 全为 0。这台终端的 RI 被配为 2但 PMI 反馈的秩却对应不上说明终端上报的 RI 和 PMI 根本不是同一时刻的信道估计。后来查代码发现它的 RI 用上一次测量结果PMI 用当前时隙的测量结果两者差了 2 个时隙。移动性稍强的小区里这种“时间错位”会导致波束成形增益大幅下降。修复方式是让 RI 和 PMI 使用同一份信道估计结果不能各取各的触发时刻。最后说一个经验UCI 相关的参数尤其是 PUCCH format 2/3 的 PRB 数和 CSI payload 容量我在每次版本更新后都会重新用脚本核对一遍而不是沿用“上次能跑”的配置。NR 协议演进快RRC 字段的默认值可能随版本变化旧配置在 OTA 升级后行为会变。养成每次发版前跑一遍配置自检脚本的习惯能省去大量外场返工。希望帮到你。本文还有配套的精品资源点击获取
