1. 从一条调度日志说起:PDSCH时域资源到底在调什么
第一次接触5G NR物理层调度的人,多半会被一堆以字母开头的参数砸晕:K0、K1、SLIV、TDRA、Type A、Type B……单独看每个词都能查到定义,可一旦放进一条真实的DCI里,就完全不知道基站到底想干什么。我最初调PDSCH时域资源的时候,就是盯着一条DCI格式1_1的日志看了整整一个下午,明明每个字段都认识,却说不清这个用户的数据究竟被安排在了哪几个符号上。
这篇内容就围绕5G NR PDSCH时域资源调度展开,把时域资源分配这条链路从头到尾拆一遍。核心要回答的问题很具体:基站通过哪些参数告诉终端"你的数据在哪个时隙、哪几个符号上";这些参数之间怎么配合;实际调测时哪些地方最容易出错。适合已经了解NR基本帧结构、正在做物理层调度或者终端侧解析的同行参考,也适合想从"背协议"进阶到"看懂调度意图"的读者。
需要先明确一个边界:PDSCH的调度分频域和时域两条线,频域管的是"用哪些RB",时域管的是"用哪个时隙的哪些符号"。两者在DCI里是分开编码的,但实际生效时又互相约束。这篇只聚焦时域这条线,频域分配、MCS、HARQ这些只在必要的时候带一句,不展开。
时域资源调度之所以值得单独拿出来讲,是因为它直接决定了调度灵活性和信令开销之间的平衡。NR相比LTE最大的变化之一,就是时域分配从"固定几种图案"变成了"一张可配置的表格",基站可以按需配置十几甚至几十种时域资源分配方案,再用一个索引去指。灵活是灵活了,但配置错了、索引对不上、参考点搞混,终端就会直接解不出数据。下面按实际调测的顺序,一层层往下拆。
2. 时域资源分配的三个坐标:参考点、偏移量、符号位置
要讲清楚PDSCH时域调度,得先建立三个坐标概念。任何一次PDSCH传输,本质上都是在回答三个问题:从哪个时间点开始算、往后偏移多少、占用多长。这三个问题对应到协议里,就是参考点(Reference Point)、时隙偏移K0、起始符号与长度(SLIV)。
2.1 参考点为什么是第一个必须钉死的坐标
参考点是整个时域分配的"原点"。原点选错,后面所有偏移全部作废。NR里PDSCH的时域分配参考点,通常落在承载调度DCI的那个PDCCH所在时隙的边界上,但具体是哪个边界、和CORESET、搜索空间怎么关联,是有讲究的。
我习惯把参考点理解成"发令枪响的那一刻"。基站先在某个时隙的PDCCH上把DCI发出去,这个PDCCH所在的时隙就是发令枪的位置。终端收到DCI后,要回到这个时隙边界,以此为起点,加上K0个时隙,再落到具体的符号上。如果终端把参考点理解成了"收到DCI的那个符号",那算出来的位置就会整体偏移,数据自然解不出来。
这里有个容易忽略的点:参考点和公共搜索空间、UE专属搜索空间的配置有关。不同搜索空间对应的监测时机不同,DCI出现的时隙位置也不同,参考点随之变化。调测时如果发现同一套TDRA配置在某个搜索空间下正常、换一个就错位,八成是参考点没对齐。
2.2 K0:跨时隙调度的那个"往后推几步"
K0是PDSCH相对于调度DCI所在时隙的时隙偏移。K0等于0,表示PDSCH和PDCCH在同一个时隙;K0等于1,表示PDSCH在下一个时隙,以此类推。这个参数是跨时隙调度的核心,也是NR相比LTE更灵活的地方。
K0的取值不是随便来的,它由高层参数配置的一个集合决定,DCI里用若干比特去索引这个集合。集合里可以配0、1、2、3……具体能配到多大,取决于子载波间隔和协议规定的范围。我实测下来,K0配得越大,调度器留给自己的处理时间越充裕,但代价是时延增加。所以K0的选择本质上是处理时延和调度时延之间的权衡。
提示:K0等于0并不意味着"零时延",它只是说PDSCH和PDCCH同处一个时隙,具体符号位置还要看SLIV。很多新手会把K0=0理解成"立刻开始传数据",这是误解。
2.3 SLIV:把起始符号和长度压进一个数值
SLIV是Start and Length Indicator Value的缩写,它把"起始符号S"和"连续符号长度L"这两个信息编码成一个整数。终端拿到SLIV后,通过一套固定的解码规则反推出S和L。这样做的目的是省信令比特——本来要传两个数,现在传一个数就够了。
SLIV的解码规则和**PDSCH映射类型(Mapping Type A / Type B)**强相关。Type A的起始符号相对时隙边界,通常从符号0开始,适合长传输;Type B的起始符号相对PDSCH起始位置,更灵活,适合短传输和低时延场景。两种类型下S和L的取值范围不同,SLIV的计算公式也不同。
我踩过的一个坑是:配置表里明明写了某个SLIV对应S=2、L=12,结果终端解出来是S=0、L=10。排查半天发现是映射类型配错了,Type A和Type B的SLIV解码表根本不是一套。这个坑后面还会细说。
| 坐标 | 作用 | 典型取值 | 出错后果 |
|---|---|---|---|
| 参考点 | 确定时间原点 | PDCCH所在时隙边界 | 整体偏移,全错 |
| K0 | 时隙级偏移 | 0、1、2、3 | 落到错误时隙 |
| SLIV | 符号级位置 | 编码S和L | 符号错位或长度错 |
这三个坐标是层层递进的关系:参考点定原点,K0定哪个时隙,SLIV定时隙内哪几个符号。任何一层出错,最终位置都不对。理解了这三层,再看TDRA表格就不会觉得是一堆无意义的数字了。
3. TDRA表格:一张把灵活性装进索引的配置表
时域资源分配(Time Domain Resource Allocation,TDRA)在NR里是通过一张高层配置的表格来实现的。这张表最多可以配16行,每行描述一种时域资源分配方案,DCI里用4比特去索引。理解这张表的结构,是看懂PDSCH时域调度的关键。
3.1 表格每一行到底装了哪些信息
TDRA表格的每一行,本质上是一个"套餐",里面打包了这样几样东西:K0、映射类型、起始符号S、长度L,有的还带PDSCH聚合因子。终端拿到DCI里的索引后,直接查表,把这一行的参数全部取出来用。
这里的设计思路值得说一下。为什么要把这些参数打包成一行,而不是每个参数单独用DCI字段传?因为单独传的话,DCI开销会非常大。打包成表格后,DCI只需要4比特索引,剩下的信息基站和终端通过高层配置提前约定好。这是典型的用配置换信令的思路,NR里到处都是这种设计。
我实际配置这张表的时候,习惯按用途分组。比如前几行配K0=0的短传输,用于低时延业务;中间几行配K0=1、2的中等偏移,用于常规调度;后面几行配大K0,用于跨时隙的预调度。这样调度器在选索引的时候,逻辑清晰,不容易乱。
3.2 默认表格和自定义表格的取舍
协议里定义了几套默认的TDRA表格,终端在还没收到高层配置的时候,用默认表工作。一旦高层配置下发,就切换到自定义表。默认表的好处是"开箱即用",坏处是它为了兼容各种场景,配得比较保守,灵活性有限。
自定义表就自由多了,基站可以根据自己的调度策略、业务类型、覆盖情况去配。但自由也意味着责任——配错了没人帮你兜底。我见过一个案例,自定义表里某行的L配成了14,但映射类型是Type B,而Type B下L的最大值受起始符号约束,结果这一行永远无法被正确解析。这种错误在默认表里不会出现,因为默认表是经过验证的。
注意:自定义TDRA表时,每一行的S和L组合必须满足映射类型的约束条件,不是随便填的。填之前先把Type A和Type B的合法组合范围查清楚。
3.3 索引冲突和覆盖问题
TDRA表最多16行,DCI里4比特刚好能索引0到15。但实际配置时,不一定16行都用满。用不满没关系,问题是不同行之间不能有歧义。如果两行配了完全相同的参数,那索引到哪一行结果都一样,虽然不报错,但浪费了表项。
更隐蔽的问题是跨配置的覆盖。比如切换搜索空间、切换BWP的时候,TDRA表可能会重新配置。如果终端还在用旧表的索引去查新表,就会查到完全不同的参数。这种问题在移动性场景下特别容易出现,表现是"切换后偶尔解不出数据",很难复现。
我的经验是,每次重配TDRA表之后,都要确认终端侧的表已经同步更新。可以在调测工具里把当前生效的TDRA表打印出来,和基站侧配置逐行比对。这个动作花不了几分钟,但能省掉大量排查时间。
4. 映射类型A和B:同一个SLIV,两种截然不同的解读
映射类型是PDSCH时域调度里最容易被低估的一个参数。很多人觉得它只是个"模式选择",实际上它决定了SLIV怎么解、解调参考信号怎么放、甚至影响终端能不能按时完成信道估计。这一节把Type A和Type B的差异彻底讲透。
4.1 Type A:从时隙边界起步的长传输
Type A的特点是PDSCH的起始符号相对时隙边界来定,通常从符号0开始。它的设计目标是支持长传输,一次占用较多符号,适合eMBB这类追求吞吐的业务。
Type A下,解调参考信号(DM-RS)的位置是相对固定的,通常放在时隙的前几个符号。这样终端一收到数据就能先做信道估计,后续符号直接用估计结果解调。这种"前置参考信号"的设计,对长传输很友好,因为信道估计只做一次,开销摊薄了。
但Type A的灵活性差一些。起始符号基本固定在时隙开头,如果PDCCH占用了前几个符号,PDSCH就得往后让,实际可用的起始位置受限。所以在PDCCH符号数较多的时候,Type A的调度空间会被压缩。
4.2 Type B:贴着调度位置起步的短传输
Type B的起始符号是相对PDSCH的起始位置来定的,更准确地说,它允许PDSCH从时隙内的任意符号开始。这让它特别适合短传输、低时延业务,比如URLLC场景下那种几个符号就传完的小包。
Type B下DM-RS的位置也更灵活,可以跟着PDSCH的起始位置走。好处是短传输也能有合适的信道估计,坏处是参考信号开销占比变高——传的符号本来就少,再扣掉参考信号,有效数据更少。
我实测下来,Type B在符号数少于7的时候优势明显,超过7之后Type A反而更划算。所以调度器选类型的时候,不能只看业务类型,还要看这次要传多少符号。
4.3 两种类型下SLIV解码的差异
这是最容易出错的地方。SLIV的解码公式里,S和L的取值范围是跟映射类型绑定的。Type A下,S的取值通常从0开始,L的范围也更大;Type B下,S可以从任意位置开始,但L受S约束,必须保证S+L不超过时隙边界。
举个具体的例子。假设SLIV解出来是S=0、L=14,这在Type A下是合法的,表示占满整个时隙。但同样的数值放到Type B下,如果PDSCH的起始参考位置不在时隙开头,就可能越界。反过来,Type B下常见的S=8、L=4这种组合,放到Type A下又不符合它的起始约束。
| 对比项 | Type A | Type B |
|---|---|---|
| 起始参考 | 时隙边界 | PDSCH起始位置 |
| 典型起始符号 | 0 | 任意 |
| DM-RS位置 | 相对固定 | 跟随起始位置 |
| 适用场景 | 长传输、eMBB | 短传输、低时延 |
| SLIV约束 | S从0起,L范围大 | S+L不越界 |
提示:调测时如果发现SLIV解出来的S和L"看起来不对",先别怀疑公式,先确认映射类型。十次里有八次是类型配错了。
5. 从DCI到实际符号:一次完整调度的推演过程
光讲参数还是抽象,这一节用一个完整的推演,把DCI里的时域字段一步步变成实际的符号位置。这个过程走通了,时域调度就算真正入门了。
5.1 拿到DCI后先看哪几个字段
终端收到DCI格式1_1后,和时域相关的字段主要有两个:一个是时域资源分配索引,4比特;另一个是PDSCH到HARQ反馈的定时指示,也就是K1。K1管的是反馈时机,不属于PDSCH本身的时域位置,但和时域调度紧密相关,这里先记着,后面单独说。
拿到4比特索引后,第一步是查当前生效的TDRA表,取出对应行的K0、映射类型、S、L。这一步的关键是"当前生效"——如果表刚重配过,一定要确认用的是新表。
5.2 参考点加K0,定位到时隙
假设DCI在时隙n的PDCCH上收到,K0取出来是1,那么PDSCH所在的时隙就是n+1。这一步看似简单,但参考点的确认不能省。要确认PDCCH所在的时隙边界,而不是DCI解码完成的时刻。
这里有个细节:如果PDCCH和PDSCH跨了帧边界,时隙编号要按帧结构重新算。NR的帧结构里,一个无线帧10毫秒,子载波间隔不同,一个帧里的时隙数也不同。15kHz下10个时隙,30kHz下20个,60kHz下40个。跨帧的时候,n+1可能落到下一帧的时隙0,这个要算对。
5.3 SLIV解码加映射类型,落到具体符号
定位到时隙后,用SLIV解码出S和L,再结合映射类型确定实际符号范围。Type A下,S是相对时隙边界的;Type B下,S是相对PDSCH起始位置的。这一步做完,PDSCH占用的符号就完全确定了。
我习惯在调测时把这个过程写成一个小脚本,输入DCI字段和TDRA表,输出实际的符号范围。这样每次怀疑调度位置不对,跑一下脚本就能验证,比手工推算快得多,也不容易算错。
5.4 一个完整的数值推演
假设条件如下:子载波间隔30kHz,一个帧20个时隙;DCI在时隙5收到;TDRA表第3行配置为K0=1、Type A、S=2、L=11;SLIV按Type A公式编码。
推演过程:参考点是时隙5的边界;加K0=1,落到时隙6;Type A下S=2表示从时隙6的第2个符号开始,L=11表示连续占11个符号,即符号2到符号12。最终PDSCH占用时隙6的符号2到12。
如果同样的SLIV放到Type B下,且PDSCH起始参考位置是符号4,那S=2就表示从符号4往后数2个,即符号6开始,占11个符号到符号16——但一个时隙只有14个符号,这就越界了。这个对比很直观地说明了映射类型的影响。
6. 调测中最容易翻车的几个点
参数讲完了,推演也走了一遍,但真正上手调的时候,坑还是在所难免。这一节把我在实际项目里踩过的、以及看别人踩过的坑整理出来,都是能直接对照排查的。
6.1 K0配了但没生效:检查DCI字段宽度
有一次配置里明明写了K0=2,终端解出来却是0。排查发现是DCI里时域资源分配字段的比特宽度和TDRA表的行数不匹配。表里只配了4行,理论上2比特就够索引,但基站侧按4比特发了,终端按2比特解,高位被截断,索引值就错了。
这个问题的根因是基站和终端对字段宽度的理解不一致。协议规定字段宽度由TDRA表的行数决定,但实际实现里,如果配置更新和字段宽度更新不同步,就会出现这种错位。解决办法是每次改TDRA表行数后,确认DCI字段宽度同步调整。
6.2 SLIV解出来越界:映射类型和S、L不匹配
前面提过这个坑,这里展开说排查链路。现象是终端报告PDSCH解码失败,日志里SLIV解出来的S+L超过了时隙符号数。第一步查映射类型,确认基站配的和终端理解的是否一致;第二步查S、L的合法范围,Type A和Type B的范围不同;第三步查SLIV编码公式,确认用的是对应类型的公式。
我遇到的那次,是基站侧配置工具默认用了Type A的公式去编码Type B的参数,编码出来的SLIV终端按Type B解就错了。这种工具层面的坑最隐蔽,因为参数本身没错,错在编码环节。
6.3 跨时隙调度时延对不上:K0和K1要一起看
跨时隙调度时,PDSCH在一个时隙,HARQ反馈在另一个时隙,中间隔着K0和K1。如果只调K0不管K1,可能出现反馈时隙落在PDSCH之前的情况,逻辑上就不成立。
正确的做法是把K0和K1放在一起算:PDSCH时隙等于DCI时隙加K0,反馈时隙等于PDSCH时隙加K1。反馈时隙必须晚于PDSCH时隙,这是硬约束。调测时如果发现反馈定时异常,先检查这个不等式是否成立。
6.4 重配TDRA表后的"幽灵索引"
这个坑前面提过一句,这里说完整。场景是终端在连接态下,基站重配了TDRA表,但终端侧因为某种原因没有及时更新,仍然用旧表的索引去查。结果就是索引值合法,但查出来的参数完全不对。
排查方法是抓取重配前后的DCI,对比同一索引值对应的实际调度位置。如果位置变了但索引没变,基本可以确定是表没同步。解决办法是在重配流程里加确认机制,确保终端侧表更新完成后再用新索引调度。
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
| K0不生效 | 字段宽度不匹配 | 查DCI字段宽度和表行数 |
| SLIV越界 | 映射类型或公式错 | 查类型、S/L范围、编码公式 |
| 反馈时延异常 | K0和K1不匹配 | 验证反馈时隙晚于PDSCH |
| 索引查出错参数 | TDRA表未同步 | 对比重配前后同索引结果 |
7. 把时域调度讲清楚之后,还剩什么
时域资源调度这条链路,从参考点、K0、SLIV三个坐标,到TDRA表格的配置,再到映射类型的差异,最后落到实际符号位置的推演,环环相扣。任何一个环节理解不到位,调测时就会卡住。我自己的体会是,与其死记协议条文,不如把"参考点加K0定位时隙、SLIV加映射类型定位符号"这个主线刻在脑子里,遇到问题顺着主线往回查,基本都能定位到。
还有一点值得说:时域调度和频域调度、MCS选择、HARQ时序是联动的。这篇只讲了时域这一条线,但实际调度器做决策时,这几个维度是一起考虑的。比如选了一个大K0,频域上可能就要相应调整RB分配,因为跨时隙的信道变化需要更保守的MCS。这些联动关系,等时域这条线吃透了,再往上看会顺很多。
最后分享一个我常用的自查习惯:每次配置完TDRA表,先不急着跑业务,而是用几组边界值(K0取最小和最大、S取0和最大值、L取最小和最大)手工推演一遍,确认每一组都能落到合法符号范围内。这个动作花十分钟,能挡掉后面大部分的诡异问题。时域调度这东西,配置阶段多花的时间,都会在调测阶段省回来。