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 ?
- Overview on Configuration
- RRC Parameters for Two Step RACH Process
- Example
- 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.

< Frame structure of two-step RACH and 4-step RACH >

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)
Possible Drawback of 2 step RACH
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
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.
RRC Parameters for Two Step RACH Process
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
...
}
GroupB-ConfiguredTwoStepRA-r16 ::= SEQUENCE {
ra-MsgA-SizeGroupA ENUMERATED {b56, b144, b208, b256, b282, b480, b640, b800,
b1000, b72, spare6, spare5, spare4, spare3, spare2, spare1},
messagePowerOffsetGroupB ENUMERATED {minusinfinity, dB0, dB5, dB8, dB10, dB12, dB15, dB18},
numberOfRA-PreamblesGroupA INTEGER (1..64)
}
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
...
}
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
]]
}
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)
},
...
}
CFRA-SSB-Resource ::= SEQUENCE {
ssb SSB-Index,
ra-PreambleIndex INTEGER (0..63),
...,
[[
msgA-PUSCH-Resource-Index-r16 INTEGER (0..3071) OPTIONAL -- Cond 2StepCFRA
]]
}
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),
...
}
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 R
msgA-DataScramblingIndex-r16 INTEGER (0..1023) OPTIONAL, -- Need S
msgA-DeltaPreamble-r16 INTEGER (-1..6) OPTIONAL -- Need R
}
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, -- Need R
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
...
}
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
Example 01 : FDD, UL 2x2
Thus example is from the test with Amarisoft Callbox and Amarisoft UEsim.

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
},
timeAlignmentTimerCommon infinity
},
...
}
Message: sequence_index=20 ta=1 prb=7:6 two_steps=1 snr=29.2
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
Message: MSGB: uecri=0x1453233e84e6 mac_sdu=1
uecri=0x1453233e84e6
ta=1
harq_feedback_timing_ind=1
pucch_rsc_ind=0
pucch_tpc_command=0
mac_sdu=1
Message: harq=si prb=2:16 symb=1:13 CW0: tb_len=317 mod=2 rv_idx=0 cr=0.66
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