As the term implies 2 Step RACH indicates a type of RACH procedure that are complete in 2 steps. To be honest, the number of steps would look differently depending on how to split the whole procedure into smaller steps. Highlevel view of the 2step RACH can be illustrated as below.
- Overall Procedure
- Why 2 step RACH ?
- Possible Drawback of 2 step RACH
- Overview on Configuration
- RRC Parameters for Two Step RACH Process
- Example
- Reference
- Get the Test Procedure and Log / Amarisoft TechAcademy
Overall Procedure
I think the biggest difference between the two step RACH and regular (existing, conventional) rach is with step 1. In two step RACH, PUSCH can be transmitted at the very first step whereas a PUSCH can be transmitted at step 3 in regular RACH.
The sequence below is the whole procedure on one screen, and the two blue boxes on the right are what makes it worth reading twice. They list the RRC that has to be in place before any of it can run, and almost all of that configuration belongs to Step 1.

Step 1 is two transmissions, not one : B is the preamble and C is the PUSCH, and the brace on the left groups both into MsgA. That is the whole idea of two step RACH.System information comes first : A carries the configuration, so the UE cannot attempt MsgA until it has read SIB1.The configuration is lopsided : the upper box lists thirteen parameters for Step 1 and the lower box lists one, msgB-ResponseWindow, for Step 2.MsgB arrives on PDCCH and PDSCH : D is scheduled the same way an ordinary downlink transmission is. The log further down therefore shows a PDCCH row beside the PDSCH row.
< Frame structure of two-step RACH and 4-step RACH >
The drawing below sets the two procedures side by side on the same six PRBs, which is the fairest way to compare them. The upper half is two step RACH and the lower half is four step, and the caption of each states the condition being assumed.

The same six PRBs are spent differently : the two step case puts a preamble beside two PUSCH occasions of three PRBs each. The four step case gives one PRB to each of six UEs.Two step trades users for latency : six PRBs carry two msgA payloads in the upper half and six Msg3 payloads in the lower half. The capacity per occasion is lower.The time axis is where it is won : the four step case needs a RAR window and then a Msg3 in Subframe #(n+1). The two step case has already sent its payload in Subframe #2.Evaluation BW is a subset of System BW : the left hand panel marks the six PRBs inside the wider carrier, so neither scheme uses the whole band for random access.
Source : Figure 18 of Power Saving Techniques for 5G and Beyond (Ref [1])
Why 2 step RACH ?
I think the main purpose of 2 step RACH is to reduce the overall latency caused by RACH procedure. 2 Step RACH would reduce the delay in two ways.
- Reduce the number of signaling steps for RACH procedure (4 steps to 2 steps) ==> reduce the control signal overhead
- Reduce the latency
- Allowing PUSCH transmission at the very first step
- If it is used in Unlicensed spectrum, it can reduce the number of LBT(Listen Before Talk) attempt
- Power Saving : By reducing the number of signaling steps, it can reduce the power consumption (For more about NR power saving techniques, refer to this note)
Latency is the point, and it is bought twice : once by removing two signalling steps, and again by letting the payload travel with the preamble rather than after it.Unlicensed spectrum benefits most : each transmission needs its own listen before talk, so halving the transmissions halves the number of times the UE has to win the channel.Power follows from the same saving : fewer transmissions and a shorter procedure mean the receiver spends less time awake waiting for a response.It does not replace four step RACH : msgA-RSRP-Threshold-r16 in the listing further down is what selects between them, so a cell can offer both and let signal strength decide.
Possible Drawback of 2 step RACH
Sending the payload before the network has replied costs something, and the two problems below are both consequences of that. Neither of them exists in four step RACH, because there the network has already measured the preamble and told the UE how to correct itself.
Some possible drawback of 2 Step RACH is mentioned in the Introduction of this paper as follows :
- The demodulation performance degradation observed without time offset compensation at the base station (gNB), specially for MR(mid range) or WA(wide area) cells
- In the case that all preambles from multiple users (UEs) trying to perform the initial access are mapped to the same PUSCH physical resources, the associated data parts overlap and may result in unsuccessful decoding ==> There is therefore a trade-off between the collision probability of the PUSCH part of MsgA and the resource overhead for 2SR
The timing advance arrives too late to help : in four step RACH the RAR carries a timing advance and Msg3 uses it. In two step RACH the PUSCH has already been sent, so it must be decoded without that correction.Cell size is therefore the limit : the degradation is described for mid range and wide area deployments. There the round trip delay is large enough for the uncorrected offset to matter.Shared PUSCH resources create a second contention : two UEs can pick different preambles and still land on the same PUSCH resource. Resolving the preamble collision does not resolve the payload collision.Both are why the RSRP threshold exists : restricting two step RACH to UEs with good signal keeps the procedure inside the range where these two effects stay small.
Overview on Configuration
In terms of RRC, you would see the huge list of parameters specified for 2step RACH as listed in RRC Parameters for Two Step RACH Process, but in terms of physical layer point of view the basic concept of each configuration almost same as existing RACH and PUSCH. I would not exaplain much of the physical layer parameters in this note. I would recommend you to refer to existing notes on PHY aspect of RACH and PUSCH linked below.
The split is worth stating plainly. Two step RACH adds a large number of RRC parameters and almost no new physical layer machinery, because MsgA is an ordinary preamble followed by an ordinary PUSCH. What is new is the configuration that ties the two together, and that is what the listings in the next section carry.
The physical layer is reused : the preamble is generated the way any RACH preamble is, and the payload is a PUSCH, so the pages linked above still apply unchanged.The new work is in RRC : MsgA-PUSCH-Resource-r16 alone carries nineteen members, because the network has to describe a PUSCH the UE will send before it has any grant.One parameter binds preamble to payload : msgA-PUSCH-TimeDomainOffset-r16 fixes how many slots after the preamble the PUSCH goes out, which is what removes the need for a grant.
RRC Parameters for Two Step RACH Process
Three groups sit in the listings below. RACH-ConfigCommonTwoStepRA-r16 and its generic half are broadcast and describe the preamble side. The MsgA-PUSCH family describes the payload side. CFRA-TwoStep-r16 is the dedicated case, where the network hands one UE its own resources.
Following is based on
RACH-ConfigCommonTwoStepRA-r16 ::= SEQUENCE {
rach-ConfigGenericTwoStepRA-r16 RACH-ConfigGenericTwoStepRA-r16,
msgA-TotalNumberOfRA-Preambles-r16 INTEGER (1..63) OPTIONAL, -- Need S
msgA-SSB-PerRACH-OccasionAndCB-PreamblesPerSSB-r16 CHOICE {
oneEighth ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32,n36,n40,n44,n48,n52,n56,n60,n64},
oneFourth ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32,n36,n40,n44,n48,n52,n56,n60,n64},
oneHalf ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32,n36,n40,n44,n48,n52,n56,n60,n64},
one ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32,n36,n40,n44,n48,n52,n56,n60,n64},
two ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32},
four INTEGER (1..16),
eight INTEGER (1..8),
sixteen INTEGER (1..4)
} OPTIONAL, -- Cond 2StepOnly
msgA-CB-PreamblesPerSSB-PerSharedRO-r16 INTEGER (1..60) OPTIONAL, -- Cond SharedRO
msgA-SSB-SharedRO-MaskIndex-r16 INTEGER (1..15) OPTIONAL, -- Need S
groupB-ConfiguredTwoStepRA-r16 GroupB-ConfiguredTwoStepRA-r16 OPTIONAL, -- Need S
msgA-PRACH-RootSequenceIndex-r16 CHOICE {
l839 INTEGER (0..837),
l139 INTEGER (0..137),
l571 INTEGER (0..569),
l1151 INTEGER (0..1149)
} OPTIONAL, -- Cond 2StepOnly
msgA-TransMax-r16 ENUMERATED {n1, n2, n4, n6, n8, n10, n20, n50, n100, n200} OPTIONAL, -- Need R
msgA-RSRP-Threshold-r16 RSRP-Range OPTIONAL, -- Cond 2Step4Step
msgA-RSRP-ThresholdSSB-r16 RSRP-Range OPTIONAL, -- Need R
msgA-SubcarrierSpacing-r16 SubcarrierSpacing OPTIONAL, -- Cond 2StepOnlyL139
msgA-RestrictedSetConfig-r16 ENUMERATED {unrestrictedSet, restrictedSetTypeA,
restrictedSetTypeB} OPTIONAL, -- Cond 2StepOnly
ra-PrioritizationForAccessIdentityTwoStep-r16 SEQUENCE {
ra-Prioritization-r16 RA-Prioritization,
ra-PrioritizationForAI-r16 BIT STRING (SIZE (2))
} OPTIONAL, -- Cond InitialBWP-Only
ra-ContentionResolutionTimer-r16 ENUMERATED {sf8, sf16, sf24, sf32, sf40, sf48, sf56, sf64} OPTIONAL, -- Cond 2StepOnly
...,
[[
ra-PrioritizationForSlicingTwoStep-r17 RA-PrioritizationForSlicing-r17 OPTIONAL, -- Cond InitialBWP-Only
featureCombinationPreamblesList-r17 SEQUENCE (SIZE(1..maxFeatureCombPreamblesPerRACHResource-r17)) OF FeatureCombinationPreambles-r17 OPTIONAL -- Cond AdditionalRACH
]]
}
Following is based on
GroupB-ConfiguredTwoStepRA-r16 ::= SEQUENCE { ra-MsgA-SizeGroupA-r16 ENUMERATED {b56, b144, b208, b256, b282, b480, b640, b800, b1000, b72, spare6, spare5, spare4, spare3, spare2, spare1}, messagePowerOffsetGroupB-r16 ENUMERATED {minusinfinity, dB0, dB5, dB8, dB10, dB12, dB15, dB18}, numberOfRA-PreamblesGroupA-r16 INTEGER (1..64) }
Following is based on
RACH-ConfigGenericTwoStepRA-r16 ::= SEQUENCE { msgA-PRACH-ConfigurationIndex-r16 INTEGER (0..262) OPTIONAL, -- Cond 2StepOnly msgA-RO-FDM-r16 ENUMERATED {one, two, four, eight} OPTIONAL, -- Cond 2StepOnly msgA-RO-FrequencyStart-r16 INTEGER (0..maxNrofPhysicalResourceBlocks-1) OPTIONAL, -- Cond 2StepOnly msgA-ZeroCorrelationZoneConfig-r16 INTEGER (0..15) OPTIONAL, -- Cond 2StepOnly msgA-PreamblePowerRampingStep-r16 ENUMERATED {dB0, dB2, dB4, dB6} OPTIONAL, -- Cond 2StepOnlyNoCFRA msgA-PreambleReceivedTargetPower-r16 INTEGER (-202..-60) OPTIONAL, -- Cond 2StepOnlyNoCFRA msgB-ResponseWindow-r16 ENUMERATED {sl1, sl2, sl4, sl8, sl10, sl20, sl40, sl80, sl160, sl320} OPTIONAL, -- Cond NoCFRA preambleTransMax-r16 ENUMERATED {n3, n4, n5, n6, n7, n8, n10, n20, n50, n100, n200} OPTIONAL, -- Cond 2StepOnlyNoCFRA ..., [[ msgB-ResponseWindow-v1700 ENUMERATED {sl240, sl640, sl960, sl1280, sl1920, sl2560} OPTIONAL -- Cond NoCFRA2 ]] }
Following is based on
RACH-ConfigDedicated ::= SEQUENCE {
cfra CFRA OPTIONAL, -- Need S
ra-Prioritization RA-Prioritization OPTIONAL, -- Need N
...,
[[
ra-PrioritizationTwoStep-r16 RA-Prioritization OPTIONAL, -- Need N
cfra-TwoStep-r16 CFRA-TwoStep-r16 OPTIONAL -- Need S
]]
}
Following is based on
CFRA-TwoStep-r16 ::= SEQUENCE { occasionsTwoStepRA-r16 SEQUENCE { rach-ConfigGenericTwoStepRA-r16 RACH-ConfigGenericTwoStepRA-r16, ssb-PerRACH-OccasionTwoStepRA-r16 ENUMERATED {oneEighth, oneFourth, oneHalf, one, two, four, eight, sixteen} } OPTIONAL, -- Need S msgA-CFRA-PUSCH-r16 MsgA-PUSCH-Resource-r16, msgA-TransMax-r16 ENUMERATED {n1, n2, n4, n6, n8, n10, n20, n50, n100, n200} OPTIONAL, -- Need S resourcesTwoStep-r16 SEQUENCE { ssb-ResourceList SEQUENCE (SIZE(1..maxRA-SSB-Resources)) OF CFRA-SSB-Resource, ra-ssb-OccasionMaskIndex INTEGER (0..15) }, ... }
Following is based on
CFRA-SSB-Resource ::= SEQUENCE {
ssb SSB-Index,
ra-PreambleIndex INTEGER (0..63),
...,
[[
msgA-PUSCH-Resource-Index-r16 INTEGER (0..3071) OPTIONAL -- Cond 2StepCFRA
]]
}
Following is based on
CFRA-CSIRS-Resource ::= SEQUENCE {
csi-RS CSI-RS-Index,
ra-OccasionList SEQUENCE (SIZE(1..maxRA-OccasionsPerCSIRS)) OF INTEGER (0..maxRA-Occasions-1),
ra-PreambleIndex INTEGER (0..63),
...
}
Following is based on
MsgA-PUSCH-Config-r16 ::= SEQUENCE { msgA-PUSCH-ResourceGroupA-r16 MsgA-PUSCH-Resource-r16 OPTIONAL, -- Cond InitialBWPConfig msgA-PUSCH-ResourceGroupB-r16 MsgA-PUSCH-Resource-r16 OPTIONAL, -- Cond GroupBConfigured msgA-TransformPrecoder-r16 ENUMERATED {enabled, disabled} OPTIONAL, -- Need S msgA-DataScramblingIndex-r16 INTEGER (0..1023) OPTIONAL, -- Need S msgA-DeltaPreamble-r16 INTEGER (-1..6) OPTIONAL -- Need R }
Following is based on
MsgA-PUSCH-Resource-r16 ::= SEQUENCE { msgA-MCS-r16 INTEGER (0..15), nrofSlotsMsgA-PUSCH-r16 INTEGER (1..4), nrofMsgA-PO-PerSlot-r16 ENUMERATED {one, two, three, six}, msgA-PUSCH-TimeDomainOffset-r16 INTEGER (1..32), msgA-PUSCH-TimeDomainAllocation-r16 INTEGER (1..maxNrofUL-Allocations) OPTIONAL, -- Need S startSymbolAndLengthMsgA-PO-r16 INTEGER (0..127) OPTIONAL, -- Need S mappingTypeMsgA-PUSCH-r16 ENUMERATED {typeA, typeB} OPTIONAL, -- Need S guardPeriodMsgA-PUSCH-r16 INTEGER (0..3) OPTIONAL, -- Need R guardBandMsgA-PUSCH-r16 INTEGER (0..1), frequencyStartMsgA-PUSCH-r16 INTEGER (0..maxNrofPhysicalResourceBlocks-1), nrofPRBs-PerMsgA-PO-r16 INTEGER (1..32), nrofMsgA-PO-FDM-r16 ENUMERATED {one, two, four, eight}, msgA-IntraSlotFrequencyHopping-r16 ENUMERATED {enabled} OPTIONAL, -- Need R msgA-HoppingBits-r16 BIT STRING (SIZE(2)) OPTIONAL, -- Cond FreqHopConfigured msgA-DMRS-Config-r16 MsgA-DMRS-Config-r16, nrofDMRS-Sequences-r16 INTEGER (1..2), msgA-Alpha-r16 ENUMERATED {alpha0, alpha04, alpha05, alpha06, alpha07, alpha08, alpha09, alpha1} OPTIONAL, -- Need S interlaceIndexFirstPO-MsgA-PUSCH-r16 INTEGER (1..10) OPTIONAL, -- Need R nrofInterlacesPerMsgA-PO-r16 INTEGER (1..10) OPTIONAL, -- Need R ... }
Following is based on
MsgA-DMRS-Config-r16 ::= SEQUENCE { msgA-DMRS-AdditionalPosition-r16 ENUMERATED {pos0, pos1, pos3} OPTIONAL, -- Need S msgA-MaxLength-r16 ENUMERATED {len2} OPTIONAL, -- Need S msgA-PUSCH-DMRS-CDM-Group-r16 INTEGER (0..1) OPTIONAL, -- Need S msgA-PUSCH-NrofPorts-r16 INTEGER (0..1) OPTIONAL, -- Need S msgA-ScramblingID0-r16 INTEGER (0..65535) OPTIONAL, -- Need S msgA-ScramblingID1-r16 INTEGER (0..65535) OPTIONAL -- Need S }
Example
The trace below is one complete two step attempt, captured end to end. Read it against the sequence diagram at the top of this page, because the six numbered markers in the log line up with the lettered arrows in that drawing.
Example 01 : FDD, UL 2x2
What identifies this as a two step attempt is one field in one row. The PRACH line carries two_steps=1, and everything after it follows from that. The six numbered markers group the rows into the two steps.
Thus example is from the test with Amarisoft Callbox and Amarisoft UEsim.

Marker 2 is the preamble : the PRACH row at SFN 929.1 reads sequence_index=20 ta=1 prb=7:6 two_steps=1 snr=29.2, so preamble 20 was sent on six PRBs starting at PRB 7.Marker 3 is the payload of the same MsgA : a PUSCH at SFN 929.5, four slots later, carrying tb_len=12 with QPSK. The RRC setup request sits inside it.Step 1 spans both : the bracket on the left covers markers 2 and 3 together, which is the log showing what the sequence diagram calls MsgA.Marker 4 is MsgB : the MAC row reads MSGB: uecri=0x1453233e84e6 mac_sdu=1, and the decoded box below it shows the C-RNTI of 0x8c01 being handed over.Markers 5 and 6 are how MsgB travelled : a PDSCH and the PDCCH that scheduled it, both at SFN 929.9 on RNTI 0x460f. That is the MsgB-RNTI rather than the C-RNTI.The C-RNTI takes over afterwards : every row below marker 6 uses 0x8c01, the value MsgB assigned, so the random access procedure is finished at that point.
Decoded RRC,
message c1: systemInformationBlockType1: {
....
uplinkConfigCommon {
...
initialUplinkBWP {
genericParameters {
locationAndBandwidth 28875,
subcarrierSpacing kHz15
},
rach-ConfigCommon setup: {
rach-ConfigGeneric {
prach-ConfigurationIndex 16,
msg1-FDM one,
msg1-FrequencyStart 7,
zeroCorrelationZoneConfig 15,
preambleReceivedTargetPower -110,
preambleTransMax n7,
powerRampingStep dB4,
ra-ResponseWindow sl10
},
ssb-perRACH-OccasionAndCB-PreamblesPerSSB one: n8,
ra-ContentionResolutionTimer sf64,
prach-RootSequenceIndex l839: 1,
restrictedSetConfig unrestrictedSet
},
pusch-ConfigCommon setup: {
pusch-TimeDomainAllocationList {
{
k2 4,
mappingType typeA,
startSymbolAndLength 41
},
{
k2 4,
mappingType typeA,
startSymbolAndLength 27
}
},
p0-NominalWithGrant -84
},
...
msgA-ConfigCommon-r16 setup: {
rach-ConfigCommonTwoStepRA-r16 {
rach-ConfigGenericTwoStepRA-r16 {
msgB-ResponseWindow-r16 sl40
},
msgA-CB-PreamblesPerSSB-PerSharedRO-r16 16,
msgA-RSRP-Threshold-r16 56
},
msgA-PUSCH-Config-r16 {
msgA-PUSCH-ResourceGroupA-r16 {
msgA-MCS-r16 5,
nrofSlotsMsgA-PUSCH-r16 1,
nrofMsgA-PO-PerSlot-r16 one,
msgA-PUSCH-TimeDomainOffset-r16 4,
startSymbolAndLengthMsgA-PO-r16 27,
mappingTypeMsgA-PUSCH-r16 typeA,
guardBandMsgA-PUSCH-r16 0,
frequencyStartMsgA-PUSCH-r16 7,
nrofPRBs-PerMsgA-PO-r16 1,
nrofMsgA-PO-FDM-r16 four,
msgA-DMRS-Config-r16 {
msgA-PUSCH-NrofPorts-r16 1
},
nrofDMRS-Sequences-r16 1
},
msgA-TransformPrecoder-r16 disabled
}
}
},
timeAlignmentTimerCommon infinity
},
...
}
Log capture. Field values are from a live capture, not from the specification.
Message: sequence_index=20 ta=1 prb=7:6 two_steps=1 snr=29.2
Log capture. Field values are from a live capture, not from the specification.
Message: harq=0 prb=7 symb=0:14 CW0: tb_len=12 mod=2 rv_idx=0 cr=0.37 retx=0 crc=OK snr=35.4 epre=-76.1 ta=0.9
Log capture. Field values are from a live capture, not from the specification.
Message: MSGB: uecri=0x1453233e84e6 mac_sdu=1 uecri=0x1453233e84e6 ta=1 harq_feedback_timing_ind=1 pucch_rsc_ind=0 pucch_tpc_command=0c-rnti=0x8c01 mac_sdu=1
Log capture. Field values are from a live capture, not from the specification.
Message: harq=si prb=2:16 symb=1:13 CW0: tb_len=317 mod=2 rv_idx=0 cr=0.66
Log capture. Field values are from a live capture, not from the specification.
Message: ss_id=1 cce_index=0 al=4 dci=1_0 rb_alloc=0x5a0 time_domain_rsc=0 vrb_to_prb_map=0 mcs=9 tb_scaling=0 lsb_sfn=1
Reference
[1] Power Saving Techniques for 5G and Beyond