☰
5G NR PRACH规划全解:ZC序列、Ncs计算与根序列分配要点
2026/9/27 4:45:57 网站建设 项目流程

简介:面向5G网络优化工程师、无线网规网优人员及NR学习者的一份PRACH规划知识整理,聚焦物理随机接入信道在接入流程、Preamble序列生成与格式选择上的核心机制。资源从ZC序列长度(839/139)、循环移位、CP/GP设计出发,说明Preamble由循环前缀、前导序列与保护间隔组成,逐项比较long preamble的format0/1/2/3与short preamble的A/B/C系列共13种Format,解释不同CP和GP长度对应的小区半径、弱覆盖及高速移动场景,并结合邻区同频前导干扰、根序列规划、Ncs取值及TA调整给出可落地的优化思路。Preamble中保护间隔GP的长度决定小区接入覆盖半径,基站还会根据收到的Preamble估算UE上行时延并下发TA命令,使UE完成上行同步。压缩包仅1个PDF文件,大小2.22MB,形式为PDF讲义,适合放在手边随时查阅公式与参数表格。目前已吸引647人学习,对需要掌握5G随机接入原理、开展PRACH参数规划和接入问题定位的读者有直接参考价值。

1. 5G NR PRACH接入信号到底在规划什么:序列、时频位置与覆盖三者联动

做5G网络优化,白天被客户问“PRACH虚检率怎么又上去了”,晚上对着小区半径和ZC根规划表发呆,这是很多网优工程师的日常。PRACH前导序列本质上是一段Zadoff-Chu序列,长度要么839要么139,通过不同的根序列和循环移位组合出64个Preamble,再配上循环前缀CP和保护间隔GP,映射到特定的时频资源上。UE能在多远的距离发起接入,取决于CP和GP的长度;邻区之间会不会互相干扰,取决于根序列规划和频域位置是否错开。规划得好,UE毫秒级完成随机接入;规划得不好,边缘用户反复重发、切换接入失败、虚检率居高不下。这篇笔记把PRACH接入信号规划的完整逻辑拆开讲:从64个Preamble怎么生成,到长码短码怎么选,再到Ncs和根序列怎么算,最后落在频域位置和常见坑上,给一份可复现的规划方法。

2. Preamble从ZC序列到64条:生成原理、DFT映射与组成结构

2.1 ZC序列的数学来历与为什么选它

PRACH Preamble从数学上看就是一个长度为LRA的Zadoff-Chu序列,LRA只取839或139两种值。ZC序列的定义是x_u(i) = e^(-jπui(i+1)/LRA),其中i从0取到LRA-1,u是根序列序号。之所以选ZC序列,是因为它有两条非常关键的性质:恒定幅度,时域和频域都是恒定的包络,峰均比低,适合功率放大器的线性工作区间;理想自相关和低互相关,同一个根的循环移位序列之间正交性很好,不同根的序列之间互相关也低。这两条直接决定了PRACH检测的成功率——基站侧用本地序列做相关检测,干扰小、峰明显,识别就准。

这里有个初学者经常忽略的细节:ZC序列生成时,u和LRA必须互质。如果u和LRA存在公因子,生成的序列周期性变差,自相关旁瓣会抬高,直接表现为PRACH虚检概率上升。做根序列规划时,u的取值不是随便从表里挑,而是由logical root sequence index按协议表格映射出来的,这也是为什么规划时总是一组一组地分配根序列,而不是随手填一个数。

2.2 64个Preamble的两种生成手段:不同根与循环移位

有了基础ZC序列,终端要生成64个Preamble。产生不同序列只有两种手段:一种是用不同的根序列u直接生成,另一种是同一个根序列上做循环移位。循环移位的公式是x_{u,v}(n) = x_u((n + C_v) mod LRA),C_v就是循环移位量,协议38.211有明确规定:先在一个根序列上循环移位,凑不够64个再换下一个根序列,直到凑满为止。

这里就能看出Ncs的份量了。Ncs是循环移位的最小间隔,决定了同一个根序列上能挤出多少个Preamble。Ncs越大,间隔越大,能挤出的Preamble越少,比如格式0、Ncs=32时,839长度的序列最多产生floor(839/32)=26个Preamble;Ncs=0时一个根序列只能产生1个Preamble。这是整个PRACH规划的第一个约束条件:64个Preamble总量不变,Ncs越大,需要的根序列数量越多,而根序列总数有限,复用距离就得缩小。

提示:ZC序列的循环移位间隔Ncs不是越大越好。它需要大于等于小区最大往返时延TRTD与多径时延扩展TMD之和,否则基站侧做相关检测时,远端UE的Preamble峰会落到相邻循环移位窗口里,造成检测错误。Ncs取值是“够用就行”的原则,不是越大越安全。

2.3 时域信号做完DFT后的频域结构

在5G里终端发送的是时域信号x_{u,v}(n),但基站检测和资源映射都离不开频域。时域序列做离散傅里叶变换后得到长度同样为LRA点的序列y_{u,v}(n),可以理解为PRACH在频域上占用了LRA个子载波。子载波间隔不同,实际占用的频域宽度就不同:格式0用1.25kHz子载波间隔,839个子载波只占约1.048MHz;短码格式C2用30kHz或120kHz子载波间隔,139个子载波占约4.17MHz或16.68MHz。这也是为什么短码格式在高频大带宽场景下更常用——它和PUSCH的子载波间隔天然对齐,频域调度更灵活。

频域结构还有个特点:PRACH的频域位置由msg1-FrequencyStart和msg1-FDM两个参数决定。msg1-FrequencyStart控制PRACH起始位置相对BWP起点的偏移,以RB为单位;msg1-FDM控制同一时刻在频域上映射多少个PRACH资源。规划频域位置时,不光要看PRACH自己占用多少RB,还要看它是否和PUSCH的RB分配冲突,以及邻区之间是否错开。

2.4 Preamble的组成三个段:CP、序列与GP各管什么

一个完整的PRACH时域由CP加Preamble序列再加GP构成。CP的作用是抵抗多径时延扩展,免得前一个符号的多径拖尾污染后一个符号;GP是保护间隔,避免不同UE的Preamble在时间上重叠到达基站。CP和GP的长度决定了小区覆盖半径的上限——CP越长,能容忍的时延越大;GP越长,覆盖半径越大。这就是为什么格式1的CP是格式0的将近三倍,能支持超过100公里的小区半径。

但要理解这里的取舍:CP和GP越长,PRACH占用的时域资源越多,能容纳的接入时隙密度就越低。城市密集区要的是高并发接入能力,农村广覆盖要的是大半径,这是长码format 0到format 3存在的意义。短码的139序列则更极端,CP和GP都很短,覆盖范围小,但时频资源占用少,能塞进高频段的灵活帧结构里。规划的核心就是在这两者之间找平衡点。

3. 长码839还是短码139:format选型、覆盖半径表与场景映射

3.1 Long Preamble四种格式的覆盖半径解读

先看长码。长码即839长度的ZC序列,子载波间隔固定1.25kHz或5kHz,对应四种格式:format 0/1/2/3。它们的CP长度、GP长度、最大小区半径和适用场景差异非常明显:

FormatSCS(kHz)CP(km)GP(km)最大小区半径(km)适用场景
01.2515.4714.5314.53常规半径
11.25102.66107.34102.66超远覆盖
21.2522.86142.7222.86弱覆盖
351410214超高速

这张表里最值得玩味的是format 2:CP半径只有22.86公里,但GP半径高达142.72公里。它的设计意图是每个PRACH时隙里Preamble重复发送多次,增强覆盖和抗干扰能力,但对远处的UE来说,GP足够长,不会和后续子帧冲突。format 3则是为高速场景设计的,5kHz子载波间隔,序列时域长度缩短,多普勒频移的容忍度更好,但代价是覆盖半径退回14公里。

从网规视角看,长码format的选择基本就是先看覆盖目标再看移动性:目标半径10公里以下用format 0;海上、草原这类超远覆盖用format 1;有弱覆盖但半径要求不高用format 2;高铁沿线用format 3。注意format 3的SCS是5kHz,和格式0/1/2的1.25kHz不一样,这直接影响了时隙长度和PRACH配置索引的选择,千万别搞混。

3.2 Short Preamble的九种格式与城市场景选型

短码即139长度的ZC序列,有A1/A2/A3、B1/B2/B3/B4、C0/C2九种格式。短码的子载波间隔可以是15/30/60/120kHz,覆盖半径普遍在两三公里以内。从目前运营商的配置习惯看,密集城区普遍用B系列,郊区用C系列,这和屠龙刀与倚天剑的区别有点像——各有各的用途。

FormatSCS(kHz)CP(km)GP(km)最大小区半径(km)适用场景
A1150.70360.46850.4685Small Cell
A2301.40721.05451.0545Normal Cell
A3302.07061.75751.7575Normal Cell
B1300.52730.17580.1758Small Cell
B2300.87920.52750.5275Normal Cell
B3301.23100.87930.8793Normal Cell
B4302.28641.93461.9346Normal Cell
C0303.05692.70192.7019Normal Cell
C2302.66513.78952.6651Normal Cell

注意A系列和B系列的区别:A格式的Preamble序列没有重复,B格式有重复段。B格式靠序列重复增强检测灵敏度,但代价是CP和GP的可用时间变短,覆盖半径反而更小。C系列则是在B系列基础上进一步增大了序列长度和重复次数,适合覆盖和抗干扰要求都高的场景。

3.3 邻区Preamble格式相同时会发生什么

PRACH规划里的一个经典问题是:如果邻近小区的Preamble格式、频域起始位置、ZC根序列都相同,会出现什么?结果是Preamble虚检。本小区的检测窗里可能收到邻区UE的Preamble,基站侧相关检测出现假峰,误以为有UE接入,于是分配上行授权、发起随机接入响应,但实际没有对应终端,浪费调度资源;更严重的是,真实UE的Preamble反而可能被淹没在干扰里。

这就是为什么要做根序列规划。64个Preamble由根序列和循环移位共同产生,只要邻区间使用不同的ZC根序列分组,即使时频位置部分重叠,相关检测也不会互相干扰。规划目标说白了就是:在给定复用距离下,让相邻小区尽量错开根序列,同时保证每个小区都能凑够64个Preamble。

注意:Preamble格式的选择还会反过来影响根序列规划的结果。长码格式的Ncs支持的小区半径大,但每个根序列能产生的Preamble数少;短码格式的Ncs支持半径小,但根序列复用度高。选格式的时候就要把根序列资源够不够用一并考虑,不要格式选完了才发现可用根序列组撑不住。

4. Ncs与ZC根分配:四步计算的完整流程与Python实现

4.1 Step 1:由小区半径反推Ncs的原理与计算

PRACH的Ncs满足一个核心不等式:Ncs·Ts > TRTD + TMD + TAdsch。其中Ts是ZC序列的抽样间隔,TRTD是信号往返时延,等于2倍小区半径除以光速,TMD是最大多径时延扩展,TAdsch是下行同步误差。把这个不等式展开看,Ncs的本质就是给PRACH相关的循环移位窗口留出足够的“时间净空”,让窗口内的检测不会串扰。

具体计算时,Ts = 1000 / (SCS(kHz)·LRA) 微秒。格式0、SCS=1.25kHz、LRA=839时,Ts约0.9535微秒;格式C2、SCS=30kHz、LRA=139时,Ts约0.4796微秒。然后按目标半径算出TRTD = 2·Radius / 0.3 微秒。例如目标半径24.6公里,TRTD约164微秒,加上TMD约2.345微秒,TAdsch短码取0,算出的Ncs·Ts约166.5微秒,反推Ncs约347,查表找到最接近的大值,也就是Ncs=349。这里有个常见误操作:直接用表格里的Ncs值去匹配半径,而不是从半径算出Ncs再查表,顺序反了会导致选出来的Ncs过紧,边缘UE反复接入失败。

4.2 Step 2至Step 4:根序列需求量、分组与复用距离

Ncs定了以后,每个根序列能产生的Preamble数就确定了。对Unrestricted类型小区,公式是Num_Preamble_Per_ZC_Root = floor(LRA / Ncs),LRA=839或139。然后算每个小区需要的根序列个数:Num_Root_Per_Group = ceil(64 / Num_Preamble_Per_ZC_Root)。根序列总数是838个,可用分组数就是floor(838 / 每个小区所需根数),分组数越多,复用距离越大,邻区错开越容易。

Ncs的具体查表值如下(部分行),Unrestricted Set用于低速场景,Restricted Set A用于高速,Restricted Set B用于超高速:

NcsFormat0(km) UnrestrictedFormat0(km) Restricted AFormat0(km) Restricted B
0151515
2181818
4222222
6262626
8323232
10383838
12464646
13595959
15828282

短码格式下Ncs查表逻辑相同,但支持的小区半径随子载波间隔增大而急剧缩小。120kHz子载波间隔下Unrestricted Set最大只支持约1.15公里的小区半径,这决定了高频段宏站覆盖不可能靠短码格式撑大。做一个Python脚本把这四步串起来,就完全可以落地到日常规划里:

def pranch_planning(lra, scs, target_radius_km, tmd_us=2.345, t_adsch_us=0): # 计算ZC序列抽样间隔 ts_us = 1000 / (scs * lra) # 往返时延:半径(km) -> 微秒,光速0.3km/us trtd_us = 2 * target_radius_km / 0.3 # 核心不等式:Ncs * Ts > TRTD + TMD + TAdsch ncs_floor = (trtd_us + tmd_us + t_adsch_us) / ts_us # 按协议表向上取最近的合法Ncs值 ncs_table = [0, 2, 4, 6, 8, 10, 12, 13, 15, 17, 19, 21, 23, 25, 27, 29, 32, 34, 38, 42, 46, 49, 54, 59, 64, 71, 76, 82, 89, 96, 102, 109, 116, 123, 131, 139, 147, 155, 163, 172, 181, 190, 200, 210, 221, 232, 243, 255, 267, 279, 292, 305, 319, 334, 349, 365, 382, 400] ncs = min([v for v in ncs_table if v >= ncs_floor]) # 每个根序列能产生的preamble数 pra_per_root = lra // ncs if ncs > 0 else 1 # 每个小区需要的根序列数 root_per_cell = (64 + pra_per_root - 1) // pra_per_root avail_group = 838 // root_per_cell return ncs, ncs_floor, pra_per_root, root_per_cell, avail_group # 示例:格式C2,SCS=30kHz,LRA=139,目标半径24.6km ncs, ncs_floor, pra_per_root, root_per_cell, avail_group = \ pranch_planning(139, 30, 24.6) print(f"Ncs={ncs}, 最小需求={ncs_floor:.2f}, 每根preamble数={pra_per_root}") print(f"每小区需{root_per_cell}个根序列,可用根组={avail_group}组")

这个脚本把Ncs计算、根序列需求量、复用分组一次算全。注意ncs_table列表是从协议表格手工录入的,不同format的合法Ncs值不完全一样,实际使用时应该以对应表为准。算出来Ncs需求量是347,查表向上取349,这就是前面手算的结果。

4.3 实际算一遍:64个Preamble从439到441的三级跳

把上面四步落到具体例子里。已知prach-ConfigurationIndex=2,preamble format是format 0,SCS=1.25kHz,zeroCorrelationZoneConfig=6,查表Ncs=32。restrictedSetConfig=unrestricted。第一步logical root sequence index=439,查表得sequence number=662,循环移位Cv从0开始,步进32,依次得到Cv=0/32/64/96...直到Cv=800,一共floor(839/32)=26个Preamble,编号0到25。

26个远远不够64个。第二步logical root sequence index=440,查表得sequence number=196,再在196这个根上循环移位,又得到26个Preamble,编号26到51。还差12个。第三步logical root sequence index=441,查表得sequence number=643,这一次只需要12个Preamble,Cv从0取到352,编号52到63。到这里64个Preamble全部产生。

# 展示64个preamble生成的完整逻辑 lra = 839 # format 0长码 ncs = 32 # 由zeroCorrelationZoneConfig=6查表得到 preamble_needed = 64 # 从logical root index 439开始,查表得到实际sequence number root_seq_map = {439: 662, 440: 196, 441: 643} preamble_idx = 0 for logical_idx, seq_num in root_seq_map.items(): cv = 0 while preamble_idx < preamble_needed and cv < lra: print(f"preamble[{preamble_idx}]: root={seq_num}, Cv={cv}") preamble_idx += 1 cv += ncs

跑出来的结果和协议流程完全一致:每个根序列最多生成26个Preamble,第三个根序列只需要12个,第64个Preamble的Cv停在352。这说明64个Preamble生成中最核心的逻辑就是根序列接力加循环移位分块,理解了这个,做根序列分配时就不会对着参数表发懵。

提示:logical root sequence index映射到sequence number u的规则是协议里的一张表,l839和l139是两套不同的映射表。实际规划中一定要确认配置的是长码还是短码索引,同一个索引值在两张表里映射出的u完全不同,搞错了整个小区的PRACH检测都会异常。

5. PRACH频域时域配置与常见问题排查:五个真实原因定到位

5.1 频域位置解析:msg1-FrequencyStart、msg1-FDM与RB占用

PRACH频域资源由两个参数控制:msg1-FrequencyStart决定PRACH起始位置相对BWP起点的偏移,msg1-FDM决定频域上并行映射的PRACH资源数量。具体占多少个RB,取决于PRACH的子载波间隔、序列长度以及PUSCH的子载波间隔三者。以139短码、30kHz PRACH间隔为例,如果PUSCH也是30kHz,139个子载波除以12约等于12个RB;如果PUSCH是15kHz,则是6个RB。长码839序列对应1.25kHz间隔时,占104个RB左右,但带宽实际只有1.048MHz,因为RB带宽是15kHz,104个RB计算的却是小间隔下的窄带宽。

频域规划有个容易翻车的细节:msg1-FrequencyStart的取值范围是0到36,但单位是RB,所以它表达的其实是PRACH起始点相对BWP起点的偏移。真正计算绝对频域位置时,还要叠加BWP本身的起始位置。遇到PRACH和PUSCH资源冲突时,最常见的做法是先调msg1-FrequencyStart把PRACH挪到频带边缘,再检查msg1-FDM是否有多个PRACH资源并行挤在一起。频域上PRACH占用的RB越分散,后续PUSCH调度的灵活性越好。

5.2 时域位置解析:PRACH Configuration Index与机会密度

时域配置由prach-ConfigurationIndex决定。以FR1、非成对频谱为例,PRACH Configuration Index=94配置的是format A2,30kHz子载波间隔,奇数帧的第4和第9个时隙里每个子帧包含6次PRACH机会,20毫秒周期内共12个PRACH机会。查表可得nSFN mod x=2,y=1,slot number为7和9,起始符号为0,每个PRACH slot里包含4个时域PRACH机会。

时域位置规划的核心是匹配接入需求密度。Preambles机会多,则UE可以更快发起随机接入;但机会太密,PRACH占用的时域资源多,下行和上行数据传输资源就少了。一般商用网里接入用户量大的区域,会适当增加PRACH时域机会的密度,边缘覆盖区域则更关注格式本身的覆盖能力,机会密度反而次要。

5.3 问题排查清单:虚检、接入失败、根序列冲突的真实案例

PRACH问题排查时,如果只看KPI一个指标,很容易被带偏。我按踩过的坑列个排查顺序,每一条都是可以独立验证的:

现象一:Preamble虚检率飙升但上行干扰并无明显抬升。原因:邻区Preamble格式、频域起始位置或ZC根序列与本小区配置重叠。如果在参数核查里发现邻区配置的prach-RootSequenceIndex落在同一个根序列分组内,且msg1-FrequencyStart偏移量一致,基本就是根序列复用距离不够。解决:调整邻区的逻辑根序列索引,让相邻小区的根序列在838个根里错开一定间隔,间隔越大越安全;同时对比msg1-FDM配置,确保频域错开。

现象二:远点UE接入成功率低,但近点用户感知正常。原因:Preamble format选择与小区半径不匹配,CP或GP长度不够。比如目标覆盖半径2公里却选了B1格式,最大只支持0.17公里,自然是远处UE接入失败。解决:先按目标半径反查CP和GP支持的半径表,如果半径要求1.5公里,选择C0格式或B4格式,而不是B2/B1。同时检查zeroCorrelationZoneConfig配置的Ncs值,确认循环移位窗口能够覆盖最大时延。

现象三:高速场景下Preamble检测峰飘移,多普勒频移导致误检。原因:Unrestricted Set只适用于低速场景,高速场景下的多普勒频移会让ZC序列的相关峰发生偏移,循环移位窗口不够时会检测失败。解决:把restrictedSetConfig配置改为Restricted Set Type A或B,同时重新计算对应的Ncs表;Type A和B为高速场景准备了不同的循环移位限制,从根本上规避多普勒模糊问题。

现象四:PRACH频域资源和PUSCH冲突,接入突发时段PUSCH解调失败。原因:msg1-FrequencyStart配置的偏移量过小,PRACH的频域位置落到PUSCH的常用调度区间内。尤其是短码格式带宽较大时,139序列在30kHz间隔下占12个RB,如果配置在BWP中带,几乎必然和PUSCH的RB抢占冲突。解决:把msg1-FrequencyStart调大,将PRACH资源推到BWP边缘,并用msg1-FDM把多个PRACH机会均匀展开,降低对PUSCH连续调度的干扰。

现象五:同一个小区改了PRACH配置后,突发大量接入失败。原因:prach-ConfigurationIndex变更后,时域位置和format跟着变了,但邻区的PRACH配置还是旧的。格式不同时CP和GP占用的时域符号数不同,深处时隙交织后互相干扰,甚至导致邻区基站收不到本小区的Preamble。解决:全网搜索PRACH配置不一致的目标小区,把格式、Ncs、根序列索引、频域起始位置四个维度全部对齐再观察。

6. 用PRACH参数反推接入覆盖边界:手工验算与邻区复核的小技巧

PRACH规划做完之后,验证是必不可少的一环。我习惯在每次参数变更后做一遍“反推验算”:从配置参数出发,用手工计算推回预期的覆盖半径,再和路测或MR数据里的实际接入距离对比。这个动作几乎每次都值回票价。

反推的第一步是读prach-ConfigurationIndex,得到Preamble format和SCS。第二步读zeroCorrelationZoneConfig,查表得到Ncs。第三步按Ncs反算可以支持的往返时延上限:T = Ncs·Ts - TMD - TAdsch,再换算成半径R = T·0.3 / 2。这里的Ts按SCS和LRA计算,短码TAdsch取0,长码按实际下行同步精度填入。如果算出来的理论半径比预期的规划半径小,那说明配置有问题,要往回查格式和Ncs选择。

然后是邻区复核。每改完一个站的PRACH参数,我会把邻区列表拉出来,逐个比对本小区和邻区的四个维度:Preamble format是否相同,频率起始位置是否错开,根序列分组是否重叠,Ncs是否一致。这四维比对可以在网管工具里写成核查模板,每次批量刷参数后跑一遍,把冲突小区直接打标。跑出来的冲突清单里,重点看组团基站之间是否存在连续覆盖关系,如果是,调整逻辑根序列索引错开即可;如果不是连续覆盖而是跨区域复用,则检查复用距离是否小于隔离要求。

还有一个习惯值得分享:5G的PRACH规划是典型的“牵一发动全身”,Preamble format一变,Ncs支持半径就变,根序列需求量也变,频域占用RB数同样变;msg1-FrequencyStart一变,PUSCH调度范围就跟着动。所以我在每次开站或扩容前,都会强制走一遍完整的四步规划流程——量半径、选格式、算Ncs、排根序列——再叠加时频位置复核,全部通过后才下发参数。这套流程跑熟了,PRACH相关的虚检和接入失败问题基本能消灭在规划阶段。从那以后,我每次给一线同事做PRACH参数修改,都会强制输出一份覆盖半径反推表和邻区复核记录,确认无误再上站执行。PRACH规划没有黑匣子,每一步都能算出来、查得到、验得清,希望帮到你。

本文还有配套的精品资源,点击获取

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

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

立即咨询