5G NR PDCCH与DCI盲检机制及CORESET参数配置
2026/9/18 2:49:27 网站建设 项目流程

调过小区的人都有体会,一个 5G NR 小区能不能起来,第一道坎往往不是 PDSCH 解调、也不是功率有没有顶满,而是 UE 能不能在 PDCCH 上准确找到属于自己的那条 DCI。PDCCH 是整个空口里唯一"不请自来"的信道——UE 事先不知道它占哪几个符号、用哪个聚合等级、塞在哪个 CCE 上,只能靠一套约定好的 CORESET 加搜索空间规则去"盲找"。找对了,后面的 PDSCH、PUSCH、HARQ 才有资格谈;找错了,链路就卡在原地。

这篇东西我按实际调试顺序来写:先把 DCI 和 PDCCH 的关系、NR 相比 LTE 到底改了哪里讲透,再把 DCI 格式和字段一层层拆开,然后重点聊盲检机制——这是很多新入行的朋友最容易含糊过去的环节,接着用一段可复现的流程把 PDCCH 从时频资源还原成 DCI 字段,最后落到容量估算、参数取舍和排查清单。工具链会提到 MATLAB 5G Toolbox、srsRAN、OAI 这几套,适合做物理层开发、网优参数配置、协议栈调试以及准备相关认证的读者参考,零基础也能跟着看下来。

1. 为什么PDCCH是整个5G NR里最"憋屈"的信道

1.1 先把PDCCH和DCI的关系理清楚

很多人一开始会把 PDCCH 和 DCI 混着说,其实它俩是一个"载体 + 内容"的关系。DCI(Downlink Control Information)是一串几十比特的调度指令——告诉你这次下行数据占哪几个 RB、用什么调制编码、HARQ 进程号是几、什么时候回 ACK;PDCCH(Physical Downlink Control Channel)是承载这串指令的物理信道,负责把它映射到具体的时频资源上发出去。

打个比方:DCI 就是快递面单,上面写着收件人、件数、取件码;PDCCH 是把面单送到你家楼下公告栏的那辆车。麻烦的地方在于——你家楼下公告栏很大,而且你并不知道面单贴在哪一格,只能按规则把可能的位置挨个看一遍,看哪一张的收件人写的是你。这个"挨个看"的过程就是盲检(Blind Decoding)。

这个机制决定了 PDCCH 的两个天然属性:第一,它的资源开销必须是可控的,否则 UE 的盲检次数会爆炸,基带功耗和时延都受不了;第二,它的可靠性直接决定了整条链路的可用性,PDCCH 一丢,PDSCH 和 PUSCH 一起丢,用户的感知就是"网卡住了"。

1.2 NR相对LTE动了哪三刀

LTE 时代的 PDCCH 很好懂:整个小区带宽铺满,固定在每个子帧的前 1 到 3 个符号(最多 4 个),PCFICH 用 2 个比特明示占几个符号,UE 一看就知道去哪儿找。到了 NR,这套规矩被彻底推翻了,主要有三个变化:

第一刀是频域可配。NR 的 PDCCH 不再铺满带宽,而是装在一个叫 CORESET 的"盒子"里。这个盒子频域上可以是 6 的整数倍个 RB(最多 45 组共 270 RB),时域上可以是 1 到 3 个符号。盒子的位置还能在 BWP 内任意摆。为什么要这么改?因为 5G 的载波动辄 100 MHz,让一个只需要 20 MHz 能力的 UE 去监听整个 100 MHz 的控制信道纯属浪费电,把控制信道收窄,UE 的射频和基带都能歇一会儿。

第二刀是时域自由。LTE 的 PDCCH 永远在子帧开头,NR 的 PDCCH 可以在一个时隙内的任意符号开始——只要 searchSpace 里的monitoringSymbolsWithinSlot位图允许。这一改动是为了配合模拟波束赋形和多波束扫描:控制信道得跟着波束走,不能死守在时隙头。

第三刀是每 BWP 独立配置。每个 BWP 有自己的子载波间隔、自己的 CORESET、自己的搜索空间集合。UE 切换 BWP 的时候,控制信道的"地图"整套换掉。这一点在实测里最容易翻车,后面第 6 节会专门讲。

1.3 为什么偏偏是PDCCH最容易出问题

我做过的几个项目里,物理层问题排下来,PDCCH 相关的占了一半以上。原因其实很朴素:

  • 覆盖最薄弱。PDCCH 的有效载荷小,能用的聚合等级有限,DMRS 密度又低(每个 REG 只有 3 个 RE 的 DMRS,占 12 个 RE 的四分之一),信道估计精度天生比 PDSCH 差。边缘用户能不能接入,常常就卡在 PDCCH 解不出来。
  • 容量最容易撞天花板。控制信道占的 CCE 总数是固定的,每调度一个用户至少要吃掉 1 个 CCE(边缘用户要 8 个甚至 16 个)。用户一多,CCE 就不够分了。
  • 配置错了没有兜底。PDSCH 配错了还能靠 HARQ 重传救回来,PDCCH 配错了连"重传"这个指令都发不出去——SIB1 都解不出来,小区直接起不来。

所以从影响范围上讲,PDCCH 是个"单点放大型"的环节:单个参数填错,影响的是整小区所有用户;聚合等级配置偏保守,影响的是边缘吞吐;CORESET 符号数给多了,影响的是所有用户的峰值速率(数据资源被控制信道吃掉了)。做参数规划的时候,这几个账都要算清楚。

2. DCI格式全解析:从0_0到2_6,每种格式到底管什么

2.1 DCI格式族谱对照

NR 的 DCI 格式比 LTE 多得多,原因是要支持的东西变多了:BWP、多载波、波束、URLLC、省电、侧行链路。我把常用的格式整理成一张表,实际调试的时候对着看会快很多。

格式方向典型用途搭配的RNTI特点
0_0上行回退调度、随机接入Msg3C-RNTI、TC-RNTI、CS-RNTI尺寸固定,不允许BWP切换
0_1上行常规上行调度C-RNTI、CS-RNTI支持SUL、载波指示、SRS请求、CSI请求
0_2上行URLLC低时延上行C-RNTI、CS-RNTIRel-16引入,字段可裁剪
1_0下行回退调度、SIB1、寻呼、RAR、Msg4SI/P/RA/TC/C-RNTI尺寸固定,DCI 1_0在CSS中与0_0对齐
1_1下行常规下行调度C-RNTI、CS-RNTI支持CBG、TCI、速率匹配图样
1_2下行URLLC低时延下行C-RNTI、CS-RNTI同0_2
2_0下行时隙格式指示SFISFI-RNTI按小区广播,控制TDD方向
2_1下行预占指示INT-RNTI告诉UE哪些资源被URLLC抢了
2_2下行PUSCH功控TPC-PUSCH-RNTI组播式功控命令
2_3下行PUCCH/SRS功控TPC-PUCCH/TPC-SRS-RNTI同上
2_4下行上行取消指示CI-RNTIRel-16,紧急叫停上行发送
2_5下行软资源可用性指示AI-RNTIRel-16,IAB场景
2_6下行省电唤醒PS-RNTIRel-16,DRX唤醒信号

有个规律很好记:格式号的首位是"0 表示上行、1 表示下行",2 打头是"与具体用户无关的组公共控制"。做日志分析的时候,看到 2_x 就知道这不是普通业务调度,而是小区级的公共指令。

2.2 逐字段拆解DCI 1_1:一条调度指令里藏着什么

DCI 1_1 是下行调度的主力格式,字段最全,把它吃透其他都是减法。下面按实际排布顺序说(字段具体顺序和大小以 38.212 的表为准,不同配置下会有出入):

  • 载波指示(0 或 3 bit):跨载波调度时才存在。
  • DCI 格式标识(1 bit):在 0_1 和 1_1 尺寸相同时用来区分上下行。
  • BWP 指示(0 到 2 bit):指示 PDSCH 落在哪个 BWP,最多支持切换 3 个。
  • 频域资源分配(FDRA):位数取决于 BWP 大小和分配类型,通常 10 到 18 bit。
  • 时域资源分配(TDRA,0 到 4 bit):查 RRC 配的pdsch-TimeDomainAllocationList,索引出 K0、映射类型、起始符号和长度。
  • VRB 到 PRB 映射 / PRB 捆绑大小(各 0 或 1 bit)
  • 速率匹配指示、ZP CSI-RS 触发(各 0 到 2 bit)
  • MCS(5 bit):0 到 31,查 MCS 表。
  • NDI(1 bit):新数据指示,用来判断是不是重传。
  • RV(2 bit):冗余版本,0/1/2/3。
  • HARQ 进程号(4 bit):0 到 15,共 16 个进程。
  • DAI(0/1/2/4 bit):下行分配索引,动态 HARQ 码本时用来防漏检。
  • PUCCH 功控命令(2 bit)PUCCH 资源指示(3 bit)PDSCH 到 HARQ 反馈定时指示(3 bit)
  • 天线端口(4 到 6 bit)TCI(0 或 3 bit)SRS 请求(2 或 3 bit)DMRS 序列初始化(1 bit)

这里有两个字段值得单独拎出来说,因为它们和实测现象关联度最高。

PUCCH 资源指示只有 3 bit,最多选 8 个资源,但 PUCCH 资源集合里可能配了 16 个甚至更多。多出来的怎么选?靠 PDCCH 自己的第一个 CCE 索引算出来的隐式偏移:

若 PUCCH 资源集合内资源数 > 8: r_PUCCH = floor(2 × n_CCE / N_CCE) 最终索引 = r_PUCCH + Δ_PRI

也就是说,PDCCH 占的 CCE 位置会反向影响 PUCCH 用哪个资源。这条规则在排查"上行反馈总是撞车"的问题时特别有用——同一个时隙里如果多条 DCI 的 CCE 起始位置很接近,算出来的 r_PUCCH 就会重复,PUCCH 资源冲突概率直线上升。

DAI是 HARQ 码本的关键。配置成半静态码本时,DAI 位宽为 0;配成动态码本且单载波时是 2 bit,多载波时是 4 bit。UE 靠累计计数和总数计数两个值判断自己有没有漏掉 DCI。实测中如果 DAI 配错位宽,表现就是"UE 偶尔不反馈 HARQ",而且概率很低,很难复现,只能靠对的配置比对出来。

2.3 频域资源分配:Type 0、Type 1与那个绕人的RIV

NR 的 FDRA 有两种类型,选哪个由 RRC 参数resourceAllocation决定:

Type 0 是非连续分配,用位图表示 RBG(资源块组)。RBG 大小由 BWP 大小和rbg-Size配置决定,BWP 越大,RBG 越大(比如 100 MHz、273 RB 的 BWP,配置 1 下 RBG 是 16 个 RB)。优点是灵活,缺点是位图长、颗粒度粗,适合大包传输。

Type 1 是连续分配,用 RIV(Resource Indication Value)编码起始 RB 和长度。这个编码方式很多人第一次看会绕晕,我把编解码的数学关系摊开讲。

编码侧,设 BWP 有 N 个 RB:

若 (L - 1) ≤ floor(N / 2): RIV = N × (L - 1) + RB_start 否则: RIV = N × (N - L + 1) + (N - 1 - RB_start)

其中 L 是连续分配的 RB 数,RB_start 是起始 RB。解码侧的 Python 实现如下,这段代码我在离线验证时反复用过,可以直接抄:

def riv_decode(riv, n): """从RIV还原 (rb_start, length),n为BWP内RB数""" x, y = divmod(riv, n) if x <= n // 2 and y <= n - (x + 1): return y, x + 1 # rb_start, L else: return n - 1 - y, n - x + 1 # rb_start, L # 举例:BWP 106 RB,收到 RIV = 2014 print(riv_decode(2014, 106)) # (10, 20) 表示从第10个RB起连续20个RB

验证一下位数:106 个 RB 的全组合数是 106 × 107 / 2 = 5671,取 2 的对数上取整是 13 bit。这就是 DCI 里 FDRA 字段在 Type 1、106 RB BWP 下的大小。反推一下,如果日志里看到 FDRA 字段只有 11 bit,那 BWP 肯定不是 106 RB——这个技巧在逆向推断未知配置时很好用。

**Type 2(Rel-16 引入)**是给 0_1/1_1 用的交织式分配,把虚拟 RB 按规则映射到物理 RB,主要为了频率分集。日常调试遇到的不多。

时间域的 TDRA 也有个类似的编码叫 SLIV,把起始符号 S 和长度 L 打包成一个值:

若 (L - 1) ≤ 7:SLIV = 14 × (L - 1) + S 否则: SLIV = 14 × (14 - L + 1) + (14 - 1 - S)

举例 S = 2、L = 12:因为 L - 1 = 11 > 7,走第二个分支,SLIV = 14 × 3 + 11 = 53。UE 收到 53,反解出从第 2 个符号起连续 12 个符号——典型的 PDSCH 映射类型 B 配置。

2.4 RNTI:用"收件人"把不同业务区分开

UE 之所以能在盲检中确认"这条 DCI 是给我的",靠的是 CRC 用 RNTI 加扰。UE 用自己手上的 RNTI 去解 CRC,对得上才算命中。这套机制把同一条物理信道复用给了完全不同的用途。

RNTI取值用途
SI-RNTI0xFFFF调度SIB1及其他系统消息
P-RNTI0xFFFE寻呼
RA-RNTI计算得出调度随机接入响应RAR
TC-RNTI由RAR分配Msg4调度与冲突解决
C-RNTI由网络分配用户专属调度
CS-RNTI由RRC配置半静态调度激活/释放
MCS-C-RNTI由RRC配置专用MCS表调度
SP-CSI-RNTI由RRC配置半持续CSI上报触发

RA-RNTI 是算出来的,公式是:

RA-RNTI = 1 + s_id + 14 × t_id + 14 × 80 × f_id + 14 × 80 × 8 × ul_carrier_id

其中 s_id 是 PRACH 占用的第一个 OFDM 符号索引(0 到 13),t_id 是 PRACH 所在的时隙索引(0 到 79),f_id 是频域资源索引(0 到 7),ul_carrier_id 区分普通上行和 SUL。这个公式的价值在于:PRACH 资源规划时,如果两个 UE 在同一个 RACH 机会上发了前导,它们的 RA-RNTI 就是一样的,网络必须靠前导索引来区分。规划时把 t_id 和 f_id 拉开,能有效降低 RAR 的碰撞概率。

3. 盲检机制:UE是怎么在不知道位置的情况下找到自己的DCI

3.1 CORESET和搜索空间:把大海捞针变成有限枚举

盲检听起来很暴力,实际上是被约束死的——全靠 CORESET 和搜索空间两层配置把它收窄。

CORESET 管"在哪里",配置项有这么几个关键:

  • frequencyDomainResources:45 bit 位图,每一位代表 6 个 RB 的一组,从频率低到高排列。比如填11111111000...,表示头 8 组共 48 个 RB。
  • duration:符号数,1 到 3。
  • cce-REG-MappingType:交织或非交织。1 个 CCE 固定等于 6 个 REG,1 个 REG 固定等于 1 个 RB × 1 个符号。
  • reg-BundleSize:2、3 或 6,交织映射的捆绑粒度。
  • interleaverSize:2、3 或 6,交织器大小。
  • precoderGranularitysameAsREG-bundleallContiguousRBs,决定预编码能不能跨 REG 捆绑变化。

搜索空间管"怎么找",配置项包括监听周期monitoringSlotPeriodicityAndOffset、监听时长duration(连续多少个时隙)、时隙内监听哪几个符号monitoringSymbolsWithinSlot(14 bit 位图),以及每个聚合等级给多少个候选nrofCandidates

搜索空间分两大类:公共搜索空间 CSS用户专属搜索空间 USS。CSS 里还有细分类型,Type0 管 SIB1,Type0A 管其他系统消息,Type1 管 RAR 和 Msg4,Type2 管寻呼,Type3 伸缩性最大,常用作组公共信令。这五类的监听时机和候选数在协议里都写死了,不能随便改。

提示:monitoringSymbolsWithinSlot是 14 bit 位图,第 0 位对应时隙第一个符号。如果配成只有符号 0 是 1,那么 PDCCH 就固定落在时隙头,跟 LTE 的观感类似;如果配成符号 0 和 7 都是 1,那这个搜索空间一个时隙内要监听两次,盲检次数直接翻倍。

3.2 CCE、聚合等级与候选数量的计算

一个 CCE 等于 6 个 REG。每个 REG 有 12 个 RE,其中 3 个给 DMRS(每 RB 的符号 1、5、9 位置各一个),剩下 9 个承载数据。所以:

1 CCE 的可用比特数 = 6 REG × 9 RE × 2 bit(QPSK) = 108 bit 聚合等级 AL 对应的比特数 E = 108 × AL 扣除 24 bit CRC 后,可承载的 DCI 净荷 ≈ 108 × AL - 24

拿最常用的几个等级算一下:AL1 能装约 84 bit,AL2 约 192 bit,AL4 约 408 bit,AL8 约 840 bit,AL16 约 1512 bit。NR 的 DCI 大小大致在 30 到 140 bit 之间,所以AL1 和 AL2 就能覆盖绝大多数常规调度,AL4 以上主要是为了覆盖和抗干扰,不是为了装更多内容。

聚合等级和候选数的对应关系由nrofCandidates配置,协议里给了一张标准组合表,大致是这样的:

聚合等级典型候选数(USS)消耗CCE数
10 到 60 到 6
20 到 60 到 12
40 到 60 到 24
80 到 60 到 48
160 到 30 到 48

UE 需要在每个配了候选的聚合等级上,把该等级的所有候选位置都试一遍。所以配置表里的数字不是随便填的——每多给一个 AL8 的候选,UE 就多一次盲检、网络侧就多预留 8 个 CCE

3.3 盲检次数上限与Overbooking:为什么UE会"挑着看"

UE 的盲检能力是有硬上限的,协议里按子载波间隔给了明确的两张表:

子载波间隔配置 μSCS单时隙最大盲检候选数单时隙最大非重叠CCE数
015 kHz4456
130 kHz3656
260 kHz2248
3120 kHz2032

注意这两个限制是同时生效的:候选数不能超,占用的非重叠 CCE 数也不能超。SCS 越大,时隙越短,UE 在单位时间内要处理的时隙越多,所以单时隙允许的盲检量反而被压低了——这是给 UE 基带留处理时间的。

如果 RRC 配下来的多个搜索空间集合在某个时隙里加起来超了限额,就出现Overbooking。这时候协议规定 UE 按一定顺序丢弃候选:公共搜索空间优先保留,USS 按聚合等级由高到低优先丢弃,并且还要考虑搜索空间集合的索引顺序。丢候选意味着什么?意味着网侧明明下了调度,UE 压根没去听,表现出来就是"莫名丢包 + HARQ 不反馈"。

注意:Overbooking 的丢弃顺序在 38.213 第 10.1 节有完整描述,具体实现时务必对着协议原文核一遍,不同版本的规则细节有差异。网侧规划时最稳的做法是主动算好每个时隙的总 CCE 占用,别让它触发 Overbooking。

还有一个相关机制叫DCI 尺寸对齐。UE 每监听一种 DCI 尺寸就相当于多一轮盲检,为了压住总量,协议要求对 CSS 和 USS 里尺寸不同的 DCI 做补零对齐,同一个小区里 CSS 的 DCI 尺寸种类和 USS 的尺寸种类都有上限约束。如果网侧配了两套尺寸差异不大的搜索空间却没对齐,UE 的盲检量会明显上升,直接表现就是接入慢、切换慢。

4. 从时频资源到DCI字段:走一遍完整的PDCCH解析流程

4.1 工具链准备:三种路线各管一段

我一般准备三套工具,分别对应不同的调试阶段:

MATLAB 5G Toolbox用来做离线验证。好处是收发链路完整、参数直观,配错一个参数立刻能从星座图或者 BER 上看出来。适合验证 CORESET 交织、聚合等级、DCI 尺寸这些"配错就完全对不上"的环节。

srsRAN 或 OpenAirInterface用来做在线抓取。这两个开源栈都能在 gNB 侧打印出调度信息,包括 RNTI、聚合等级、CCE 起始位置、MCS、HARQ 进程号,字段比仪器还全。

Wireshark + MAC-NR 解析用来做问题定位。物理层解出来的 DCI 最终会变成 MAC 层的调度结果,信令面的时间线能帮你快速判断问题是在控制面还是用户面。

先把 MATLAB 那条路线写出来,这段配置我调过好几遍,属性名请按自己手上的工具箱版本再核一次:

% 1) 载波与BWP carrier = nrCarrierConfig; carrier.SubcarrierSpacing = 30; carrier.NSizeGrid = 273; carrier.NStartGrid = 0; carrier.NSlot = 0; carrier.NFrame = 0; % 2) CORESET:48 RB x 2 符号,交织映射 coreset = nrCORESETConfig; coreset.FrequencyResources = [ones(1,8) zeros(1,37)]; % 8组 x 6RB = 48RB coreset.Duration = 2; coreset.CCEREGMapping = 'interleaved'; coreset.REGBundleSize = 6; coreset.InterleaverSize = 2; coreset.ShiftIndex = 0; % 3) 搜索空间:每时隙监听,符号0开始 ss = nrSearchSpaceConfig; ss.CORESET = coreset; ss.MonitoringSlotPeriodicityAndOffset = 1; ss.MonitoringSymbolsWithinSlot = [1 zeros(1,13)]; % 4) PDCCH 实例 pdcch = nrPDCCHConfig; pdcch.CORESET = coreset; pdcch.SearchSpace = ss; pdcch.RNTI = 4601; pdcch.DCIFormat = 'Format1_0'; pdcch.AggregationLevel = 4; pdcch.AllocatedCandidate = 0; % 5) 发端:DCI 比特 -> PDCCH 符号 dciBits = randi([0 1], 40, 1); sym = nrPDCCH(dciBits, pdcch.RNTI, pdcch); % 6) 收端:先估信道、再解 PDCCH % est 由 nrChannelEstimate / nrPDCCHSpace 给出的资源格获得 % [recBits, crcOk] = nrPDCCHDecode(est, pdcch.RNTI, pdcch);

关键点在第 5 步和第 6 步之间:nrPDCCH内部会自动做完 CRC 加扰、极性编码、速率匹配、加扰、QPSK 调制、RE 映射和交织。真正要你手动确认的是收端资源格的提取范围——也就是nrPDCCHSpace给出的那一片 RE 对不对。收端的 CCE 起始位置只要错一个 REG,CRC 就永远是 fail。

srsRAN 那条路线的日志筛选可以这么干:

# 跑起来先把日志落盘 ./gnb -c gnb.yml 2>&1 | tee gnb.log # 只看调度相关的行,按聚合等级统计 grep -E "PDCCH|DCI" gnb.log | \ awk '{for(i=1;i<=NF;i++) if($i ~ /aggr/) print $i}' | \ sort | uniq -c | sort -rn # 看某个RNTI的连续调度轨迹 grep "rnti=4601" gnb.log | head -50

拿到聚合等级的分布,你就能立刻判断网络当前的覆盖状态:如果 AL8 和 AL16 占比超过三成,说明小区边缘用户多,控制信道的覆盖是瓶颈;如果清一色 AL1,说明大家都在近点,这时候可以适当把 CORESET 收窄来给 PDSCH 腾资源。

4.2 PDCCH的完整处理链路

把发端链路串起来看,PDCCH 的加工顺序是这样的:

  1. DCI 净荷生成,按格式拼字段。
  2. CRC 附着,附 24 bit CRC,并用 RNTI 对 CRC 加扰。
  3. 极性编码。NR 用的是 Polar 码,短码时会有特殊的码率匹配处理。
  4. 速率匹配,输出长度 E = 108 × AL 比特,并对齐到星座点。
  5. 加扰,扰码序列的初始化跟小区 ID 和 RNTI 相关。
  6. QPSK 调制,PDCCH 固定用 QPSK,因为要保证可靠性。
  7. RE 映射与交织。非交织时 CCE j 直接占 REG 6j 到 6j+5;交织时按 REG 捆绑打散到整个 CORESET 上。
  8. DMRS 插入,每个 REG 每个符号的第 1、5、9 个 RE 放 DMRS。

第 7 步的交织是覆盖性能的关键。举个例子:CORESET 有 48 个 RB、2 个符号,总共 96 个 REG、16 个 CCE。如果配非交织,一个 AL4 的 PDCCH 会连续占 24 个 REG,也就是 24 个 RB 宽、2 个符号高的一片连续区域。这片区域如果正好落进一个频域凹陷,整条 DCI 就废了。改成交织映射、REG 捆绑大小 6、交织器大小 2,这 24 个 REG 会被均匀打散到 48 个 RB 上,获得明显的频率分集增益。

代价是什么?UE 需要在整个 CORESET 宽度上做信道估计。CORESET 96 RB 的话,UE 的接收带宽不能小于这个数。如果 UE 的射频能力本来就窄,交织配置会让它吃不消。所以交不交织、交织器给多大,得看你的终端类型混比。

4.3 三个真实解析场景

场景一:用 SI-RNTI 验证整条链路。这是最稳的切入点,因为 SI-RNTI 固定是 0xFFFF,搜索空间固定在 CORESET#0 和 Type0-PDCCH CSS 里,聚合等级只在 4、8、16 里选。SIB1 解不出来的时候,先把这三条路走一遍,能在几分钟内判断是 CORESET#0 配置错了还是信道估计有问题。CORESET#0 的配置藏在 MIB 的pdcch-ConfigSIB1里,高 4 位是controlResourceSetZero(取值范围 0 到 15),低 4 位是searchSpaceZero。这两个索引各自对应 38.213 里的一张表,选错了连 RB 数都对不上。

场景二:跟踪一个 C-RNTI 的连续调度。关注这几个字段的组合:MCS 突然从 20 掉到 5、RV 一直是 0、HARQ 进程号在 0 到 15 之间循环、NDI 反复翻转。如果 NDI 一直是 0 而 RV 在变,说明这条链路在连续重传,PDCCH 本身大概率没问题,问题在 PDSCH 的链路质量或者 MCS 选得过于激进。

场景三:RAR 窗口。随机接入时,UE 发完前导后在 RAR 窗口内监听 RA-RNTI 加扰的 DCI 1_0。这条 DCI 里的 FDRA 字段特别大(因为要覆盖 CORESET#0 的全部 RB),时域上 K0 固定,MCS 是压到最低的那几档。如果 RAR 收不到,先算一遍 RA-RNTI 对不对——PRACH 的 t_id 和 f_id 很容易被规划文档和实际配置搞混,我自己就踩过这个坑,查了两天才发现是 t_id 算错了。

5. 容量估算与参数配置:一个小区到底能塞多少用户

5.1 PDCCH容量估算的三步法

控制信道容量不算清楚,扩容的时候就会一头雾水。我用的三步法很简单:

第一步,算 CORESET 能提供多少 CCE。

总 REG 数 = CORESET 频域 RB 数 × 时域符号数 总 CCE 数 = 总 REG 数 / 6

举两个对比配置。配置 A:48 RB × 2 符号 = 96 REG = 16 CCE。配置 B:96 RB × 3 符号 = 288 REG = 48 CCE。差了 3 倍。

第二步,扣掉公共搜索空间的固定开销。Type0/0A 只在特定时隙出现,Type1 在 RACH 活跃时才有,Type2 按寻呼周期出现,日常稳态下主要是 Type3 和一些周期性公共信令。经验上按总 CCE 的 15% 到 25% 预留比较稳。

第三步,按平均聚合等级折算用户数。

以配置 B、30 kHz SCS 为例:48 CCE,扣 20% 给公共信道,剩约 38 CCE 可用于 USS。假设上下行各一次调度、平均都用 AL4,那么一个用户完成一次完整的上下行调度需要 8 个 CCE。

每秒可用于 USS 的 CCE 数 = 38 × 2000(30kHz SCS 每秒 2000 个时隙) = 76000 VoNR 用户每秒需要的 CCE = 8 CCE / 20 ms = 400 CCE/s 可支撑的 VoNR 用户数 ≈ 76000 / 400 ≈ 190

这个量级跟我见过的实际规格是吻合的。注意这只是 PDCCH 维度的上限,实际还得看 PUSCH 的 PRB 够不够、上行干扰大不大、调度器是不是平均分配。

配置 A 呢?16 CCE × 2000 = 32000 CCE/s,扣 20% 后 25600,除以 400 得到约 64 个 VoNR 用户。差了一倍多。这就是为什么容量规划阶段控制信道必须提前算——它不是"配完再说"的东西。

5.2 参数取舍:几个必须做选择的地方

CORESET 和搜索空间的参数没有"最优解",只有"适合当前场景的解"。下面这几个选择的权衡逻辑,我按实际决策顺序列一下。

参数取值好处代价适用场景
CORESET符号数1数据资源损失小CCE少,容量受限带宽紧张、用户少
2折中需算清PDSCH起始符号大多数常规场景
3CCE多,容量大每个时隙损失3个符号高负载、大量VoNR
CORESET频域宽度窄(12-24RB)资源省,UE接收带宽要求低CCE少,频率分集弱边缘覆盖优先
宽(48-96RB)CCE多,频率分集好UE必须支持宽带监听容量优先
CCE-REG映射非交织信道估计简单无频率分集,怕频选衰落单符号CORESET
交织抗频选衰落需全带宽信道估计多符号CORESET
REG捆绑大小2预编码灵活分集增益一般多波束场景
6分集增益好预编码粒度粗单波束或宽波束
预编码粒度sameAsREG-bundle可逐捆绑换预编码参考信号开销相对高多用户波束赋形
allContiguousRBs整个CORESET一个预编码灵活性差宽波束覆盖

有个约束要记住:非交织映射只在 CORESET 符号数为 1 时才允许用。想用交织,符号数至少是 2。

另外一个容易忽略的点是 CORESET 和 PDSCH 的资源关系。PDCCH 占用的 RE 是不会给 PDSCH 用的,PDSCH 要绕开(rate matching around CORESET)。所以 CORESET 定得越宽、符号数越多,PDSCH 的有效 RE 就越少。在峰值速率测试场景,如果 CORESET 给了 3 个符号,单用户峰值能掉 3% 到 5%,这个损失是实打实的。

5.3 与调度器的联动:PDCCH受限时会发生什么

这是我特别想强调的一点:PDCCH 容量不是独立指标,它会反向改变调度器的行为

当 CCE 接近耗尽时,调度器只有三条路可走:

第一条是降聚合等级。本来该给 AL8 的边缘用户改成 AL4,结果是这条 DCI 的解调成功率下降,HARQ 重传率上升,实际吞吐不升反降。

第二条是推迟调度。用户明明有数据要发,但 CCE 不够,只能排队等下一个时隙。表现出来就是时延抖动变大,VoNR 的 MOS 分会掉,游戏业务的时延尖峰明显。

第三条是降低复用层数。MU-MIMO 需要给每个用户一条 DCI,用户越多 DCI 越多。CCE 不够的时候,空间复用就上不去,小区容量直接受限。这一点在密集城区特别明显。

还有一种更隐蔽的现象叫CCE 阻塞(Blocking)。PDCCH 候选位置的排布是有算法的,某些位置天然更容易被占用。假设两个用户的搜索空间在某些候选项上重叠,其中一个用户先被调度占掉了这些 CCE,另一个用户即使还有足够的空闲 CCE,也可能因为找不到连续的满足聚合等级要求的 CCE 位置而调度失败。这是概率性的,表现出来是"CCE 明明还有空闲,但就是调度不上"。

排查阻塞的实用做法是统计一段时间内每个 CCE 索引的占用频次,做个直方图。如果分布明显不均匀、集中在前半段,那就是搜索空间配置太集中,需要通过调整ShiftIndex或者给不同的搜索空间集合错开监听时机来分散。

另外还有一个跨层的影响:PDCCH 占用的符号数会改变 PDSCH 的起始符号,而 PDSCH 起始符号又通过 K0 和 TDRA 表决定。如果调度器在计算时域分配时没有把 CORESET 的符号数算进去,就会出现 PDSCH 和 PDCCH 撞资源的情况。这类 bug 的表现是"特定 K0 取值下误码率异常",很隐蔽。

6. 常见问题与排查技巧实录

6.1 问题速查表

我把这几年遇到过的 PDCCH 相关问题整理成表,按现象索引比较快。

现象大概率原因排查动作
小区起不来,SIB1解不出CORESET#0索引配错,或pdcch-ConfigSIB1高低位搞反核对高4位/低4位,对照38.213表确认RB数
盲检CRC一直failRNTI用错、CCE起始位置算错、交织参数不一致先用SI-RNTI验证链路,再比对收发端交织配置
偶尔丢调度、HARQ不反馈Overbooking触发候选丢弃统计每时隙总CCE占用,检查是否超限额
边缘用户接入困难聚合等级配置里没有足够的AL8/AL16候选检查nrofCandidates,确认高等级候选数不为0
上行反馈总是冲突隐式PUCCH资源计算导致重叠检查n_CCE分布,必要时缩小PUCCH资源集合
切换后掉线BWP切换后搜索空间未重配核对目标BWP的CORESET和搜索空间配置
特定K0下误码率高PDSCH与PDCCH资源重叠核对TDRA表起始符号与CORESET符号数
盲检功耗异常高DCI尺寸未对齐,尺寸种类过多检查CSS和USS的DCI尺寸种类数

6.2 几个我踩过的坑

坑一:把子载波间隔当成了常数。早期做的一个项目,CORESET 配在 30 kHz、数据在 15 kHz 的 BWP 上,我按 15 kHz 算时隙位置,结果所有监听时机全偏了。NR 里每个 BWP 有自己的 numerology,μ 值不同,一个无线帧里的时隙数差好几倍。现在的习惯是:写任何跟时隙相关的脚本,第一行先打印 μ 和每帧时隙数。

坑二:忽略了 CORESET 频域位图的对齐基准。45 bit 位图的每一 bit 对应 6 个 RB 的一组,分组是从哪个 RB 开始算的,CORESET#0 和普通 CORESET 的处理方式不一样。这个问题会导致 CORESET 的位置整体偏移 6 个 RB 的整数倍,表现出来是"偶尔能解、偶尔不能解",因为偏移量小的时候还在 PDSCH 的容错范围内。核对方法是把预期占用的 RB 范围和实际能量检测结果叠在一起看。

坑三:DCI 尺寸对齐没做,盲检量翻倍。一次测试里 UE 的接入时延比预期高了一倍,查到最后是 USS 里配了两种尺寸相差 3 bit 的 DCI,没有触发对齐规则补零。这两种尺寸导致 UE 的盲检次数几乎翻倍。补零对齐之后,接入时延回到正常水平。这个坑的教训是:配搜索空间的时候先数一数 DCI 尺寸种类,超过两类就要警惕

坑四:REG 捆绑大小和 UE 的信道估计能力不匹配。用了 REG 捆绑大小 2、交织器大小 6,理论分集增益很好,但测试用的终端在小带宽下信道估计跟不上,误码率反而比非交织配置还高。后来改成捆绑 6、交织 2,问题解决。参数不是越"优化"越好,得跟终端能力匹配。

6.3 几条实操上省时间的技巧

先能量检测,再解调。拿到一段空口数据,不要急着往解码链路里塞。先对每个符号做能量统计,找出哪些符号的能量明显高于纯数据区,那就是 PDCCH 的位置。这一步能快速确认 CORESET 的符号数配得对不对,比反复调解码参数快得多。

用 SI-RNTI 做第一个验证点。0xFFFF 是固定的,搜索空间是固定的,聚合等级范围是有限的,三个条件一锁,剩下的变量就很少了。任何 PDCCH 相关的调试,我都从这一步开始,成功率最高。

把 AL 分布当健康度指标。长期采集 AL 分布,AL1/AL2 占比超过七成说明覆盖良好,AL8 以上超过三成说明边缘压力大。这个指标比看 RSRP 分布更直接,因为它反映的是"控制信道实际用了多少资源才把用户捞上来"。

盲检失败先怀疑交织,再怀疑信道估计。交织参数不匹配会导致 REG 位置完全错位,CRC 必然 fail,而且现象和"信道质量差"一模一样。判断方法是把交织和非交织两种配置都跑一遍,如果只有一种能解出来,那就是映射类型的问题。

做容量规划时留 25% 的 CCE 余量。按我的经验,理论算出来的 CCE 容量打个七五折,才是实际能稳定支撑的用户数。剩下的余量要留给突发负载、RACH 密集期和公共信令的波动。算得太满的规划,上线之后一定会遇到偶发的调度失败,而且很难定位。

关于 BWP 切换,多留一份配置清单。每个 BWP 的 CORESET 和搜索空间我都建议单独存一份配置记录,包含频域位图、符号数、监听周期、每个 AL 的候选数。切换出问题的时候,直接两份清单一对比,差异点一目了然,比翻配置文件快得多。

我个人在实际操作中的体会是,PDCCH 这块的调试和参数规划,难的地方从来不是协议本身有多复杂,而是它的"隐性耦合"太多——CORESET 的符号数会影响 PDSCH 的资源格,PDCCH 的 CCE 位置会决定 PUCCH 用哪个资源,搜索空间的候选数会决定 UE 的盲检上限,聚合等级的配置会决定边缘用户能不能接进来。这些关系理清楚之后,你会发现大部分"玄学问题"其实都有明确的因果链,只是需要你把链路上下游一起看。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询