NR SA PUSCH Transform Precoding
The purpose of this tutorial is to show you how to configure and verify PUSCH Transform Precoding. In LTE, we use the different waveform for DL and UL by default in which OFDMA is for DL and SC-FDMA(Single Carrier-FDMA) is used for UL. However in NR, we use the same type of waveform OFDM for both DL and UL in most of the default configuration. The reason why we use SC-FDMA in LTE UL is to decrease PAPR (Peak to Average Power Ratio). It implies that UL PAPR would be larger in NR default configuration comparing to LTE UL. For some specific case where low PAPR is necessary in NR, NR support a specific parameter to use SC-FDMA for UL and it is called 'Transform Precoding'. You may think of Transform Precoding as another name for SC-FDMA. There are two stages of applying the Transform Precoding in NR as listed below.
- Apply Transform Precoding only for msg3. You can configure this in SIB1
- Apply Transform Precoding for all other UL except msg3. You can configure this in RRCSetup or RRCReconfiguration.
You can enable both of them or enable only one of the options as you like.
Table of Contents
Introduction
PUSCH (Physical Uplink Shared Channel) Transform Precoding is a key technique in the 5G New Radio (NR) air interface, designed to optimize uplink transmission characteristics, particularly in scenarios demanding low Peak-to-Average Power Ratio (PAPR). In legacy LTE systems, OFDMA (Orthogonal Frequency Division Multiple Access) is employed in the downlink, while SC-FDMA (Single Carrier Frequency Division Multiple Access) is used in the uplink to address the high PAPR challenge, which is critical for power-limited User Equipment (UE). With 5G NR, OFDM (Orthogonal Frequency Division Multiplexing) is adopted for both downlink and uplink by default, providing increased flexibility, spectral efficiency, and simplified transceiver design. However, OFDM inherently exhibits higher PAPR, which can be detrimental for uplink transmissions—particularly for battery-powered devices. To address this, NR introduces Transform Precoding as an optional feature that effectively reintroduces SC-FDMA-like characteristics into the uplink waveform by applying a Discrete Fourier Transform (DFT) prior to subcarrier mapping. This architectural option allows NR to strike a balance between flexibility and power efficiency, enabling operators and device manufacturers to tailor uplink performance to specific scenarios, such as coverage enhancement or IoT applications. Transform Precoding can be selectively enabled at different stages—such as for initial random access (msg3) or for all subsequent uplink transmissions—via parameters configured in SIB1 or RRC signaling. Its significance lies in providing a standards-compliant method to lower PAPR, ensuring robust uplink performance, extending UE battery life, and supporting diverse deployment requirements within the broader 5G ecosystem.
-
Context of PUSCH Transform Precoding in 5G NR
- 5G NR adopts OFDM for both uplink and downlink by default, differing from LTE's use of SC-FDMA in the uplink to reduce PAPR.
- High PAPR in uplink can negatively impact UE battery life and coverage, especially for power-constrained devices.
- Transform Precoding enables a DFT operation prior to subcarrier mapping, emulating SC-FDMA behavior and reducing PAPR.
- The feature can be configured at various protocol stages, including initial access (msg3) and subsequent uplink transmissions.
-
Relevance and Importance of the Tutorial Topic
- Understanding and configuring Transform Precoding is essential for optimizing uplink performance in scenarios where low PAPR is critical.
- The tutorial addresses practical steps for parameter configuration and verification, which are vital for network engineers, system integrators, and device developers.
- Proper configuration impacts device battery longevity, uplink coverage, and overall network efficiency.
-
Learning Outcomes
- Gain a clear understanding of Transform Precoding’s role and benefits in 5G NR uplink transmissions.
- Acquire practical knowledge of how to configure Transform Precoding for different uplink scenarios.
- Learn to verify the correct application of Transform Precoding through relevant configuration parameters.
- Be able to assess when and why to enable Transform Precoding based on deployment needs.
-
Prerequisite Knowledge or Skills
- Familiarity with fundamental wireless communication concepts, especially OFDM and SC-FDMA.
- Basic understanding of LTE and 5G NR protocol architecture and signaling procedures.
- Experience with network configuration, radio resource management, and 3GPP standards is beneficial.
Summary of the Tutorial
This tutorial demonstrates the procedure for testing transform precoding (SC-FDMA) enabled for both Msg3 and subsequent PUSCH transmissions in a 5G NR Standalone (SA) environment using Amarisoft’s UEsim and Callbox (gNB simulator).
-
Test Setup:
- The test configuration involves Amarisoft UEsim as the UE and Callbox as the gNB, connected as depicted in the referenced diagram.
-
Key Configuration Parameters:
- tf_precoding: Enables transform precoding for all PUSCH transmissions after Msg3.
- msg3_tf_precoding: Enables transform precoding specifically for Msg3.
-
Test 1: Transform-Precoding enabled for both Msg3 and PUSCH afterwards
-
Configuration Steps:
- Ensure proper alignment between UEsim and Callbox configuration files. The tutorial uses default configurations (ue.default.cfg and enb.default.cfg) without modification.
- For UEsim, use ue-nr-sa.cfg as-is.
- For the Callbox (gNB), use gnb-sa-tf-precode.cfg (a copy of gnb-sa.cfg).
- The test operates in TDD mode with NR_TDD_CONFIG 2. SRS is disabled for simplicity (USE_SRS 0).
- Band n78 with 30 kHz subcarrier spacing is used, but any band/frequency can be selected.
- msg3_tf_precoding and tf_precoding are both set to true to enable transform precoding for Msg3 and all PUSCH.
- Ensure UE bandwidth and subcarrier spacing in UEsim (BANDWIDTH 20, band:78, subcarrier_spacing:30) match gNB settings.
-
Performing the Test:
- Validate Callbox (gNB) configuration using 'cell phy' and 'cell' commands.
- Power on the UE on UEsim after confirming gNB configuration.
- Confirm successful call setup using the 't' command.
-
Log Analysis:
- Confirm msg3 transform precoding is enabled by inspecting the msg3-transformPrecoder information element (IE) in SIB1.
- Verify transform precoding for PUSCH after Msg3 by checking the transformPrecodingEnabled flag in the RRC Setup message.
- Ensure all PUSCH transmissions are properly received and decoded by the gNB. Note that PUSCH logs do not directly indicate transform precoding status.
-
Configuration Steps:
The methodology focuses on aligning UE and gNB configurations, enabling and verifying transform precoding features for initial and subsequent uplink transmissions, and confirming correct operation through configuration checks and log analysis.
Test Setup
Setup A
Test setup for this tutorial is as shown below.

Key Configuration Parameters
Followings are important configuration parameters for this tutorial. You may click on the items for the descriptions from Amarisoft documents.
Test 1 : Transform-Precoding enabled for both Msg3 and PUSCH afterwards
In this test I will show you how to apply transform precoding (SC-FDMA) to Msg3 and all the PUSCH after the msg3.
Configuration
An important thing in using UE sim is to do proper matching between UE sim configuration and Call box configuration In this tutorial, I used the ue.default.cfg and and enb.default.cfg without any change
If you use other Network (e.g, other network simulator or real network), you have to make it sure to configure UE sim according to the settings on network side
I used ue-nr-sa.cfg. as it is

I used gnb-sa-tf-precode.cfg which is copied from gnb-sa.cfg.

The configuration in gnb-sa-tf-precode.cfg (Callbox) is set as follows. In this test, TDD is used and one of the default TDD config (NR_TDD_CONFIG 2) is applied. And SRS is disabled (USE_SRS 0) for simplicity.

It doesn't matter whatever band and frequency is used for transform precoding. In this test, n78 (band :78) with SCS 30 Khz (subcarrier_spacing 30) is used.

These are the main configuration parameter for transform preconding. Transform Precoding is applied to msg3 by setting msg3_tf_precoding to true and applied to all the PUSCH by setting tf_precoding to true.

The configuration in ue-nr-sa.cfg (UEsim) is set as follows. TDD is used for UEsim to be aligned to Callbox (gNB) configuration. BANDWIDTH 20 and band :78, subcarrier_spacing:30 are configured to get aligned to gNB configuration.

Perform the Test
check if callbox confgiuration (gNB configuration) is properly set as you intended by the command 'cell phy' and 'cell'.

If gNB configuration is done as you desire, power on UE on UEsim.

Make it sure that call setup is properly established using 't' command.

Log Analysis
You can confirm that msg3 transform precoding is enabled by checking out msg3-transformPrecoder IE in SIB1.

Transform Precoding for PUSCH after msg3 can be confirmed by checking out transformPrecodingEnabled in RRC Setup. If transformPrecodingEnabled exists, it indicates transform precoding is enabled.

Make it sure that all the PUSCH are properly received and decoded by gNB. PUSCH log print itself does not print any specific information about transform precoding.

RRC / NAS Signaling
SIB1 (SA)
: This is the SIB1 message sent by gNB to enable transform precoding for msg1. (
{
message c1: systemInformationBlockType1: {
cellSelectionInfo {
...
},
cellAccessRelatedInfo {
...
},
connEstFailureControl {
...
},
servingCellConfigCommon {
downlinkConfigCommon {
frequencyInfoDL {
...
},
initialDownlinkBWP {
genericParameters {
locationAndBandwidth 13750,
subcarrierSpacing kHz30
},
pdcch-ConfigCommon setup: {
...
},
pdsch-ConfigCommon setup: {
...
}
},
bcch-Config {
...
},
pcch-Config {
...
}
},
uplinkConfigCommon {
frequencyInfoUL {
scs-SpecificCarrierList {
{
offsetToCarrier 0,
subcarrierSpacing kHz30,
carrierBandwidth 51
}
}
},
initialUplinkBWP {
genericParameters {
locationAndBandwidth 13750,
subcarrierSpacing kHz30
},
rach-ConfigCommon setup: {
rach-ConfigGeneric {
prach-ConfigurationIndex 160,
msg1-FDM one,
msg1-FrequencyStart 3,
zeroCorrelationZoneConfig 15,
preambleReceivedTargetPower -110,
preambleTransMax n7,
powerRampingStep dB4,
ra-ResponseWindow sl20
},
ssb-perRACH-OccasionAndCB-PreamblesPerSSB one: n8,
ra-ContentionResolutionTimer sf64,
prach-RootSequenceIndex l139: 1,
msg1-SubcarrierSpacing kHz30,
restrictedSetConfig unrestrictedSet,
msg3-transformPrecoder enabled
},
pusch-ConfigCommon setup: {
...
},
pucch-ConfigCommon setup: {
...
}
},
timeAlignmentTimerCommon infinity
},
ssb-PositionsInBurst {
...
},
ssb-PeriodicityServingCell ms20,
tdd-UL-DL-ConfigurationCommon {
...
},
...
},
ue-TimersAndConstants {
...
RrcSetup (SA)
: This is the RrcSetup message sent by gNB to enable transform precoding for PUSCH after msg1. (
{
message c1: rrcSetup: {
rrc-TransactionIdentifier 0,
criticalExtensions rrcSetup: {
radioBearerConfig {
...
},
masterCellGroup {
...
},
physicalCellGroupConfig {
...
},
spCellConfig {
spCellConfigDedicated {
initialDownlinkBWP {
pdcch-Config setup: {
...
},
pdsch-Config setup: {
...
},
firstActiveDownlinkBWP-Id 0,
uplinkConfig {
initialUplinkBWP {
pucch-Config setup: {
...
},
pusch-Config setup: {
txConfig codebook,
dmrs-UplinkForPUSCH-MappingTypeA setup: {
dmrs-AdditionalPosition pos1,
transformPrecodingEnabled {
}
},
pusch-PowerControl {
...
},
resourceAllocation resourceAllocationType1,
codebookSubset nonCoherent,
maxRank 1,
uci-OnPUSCH setup: {
...
}
},
srs-Config setup: {
...
}
},
firstActiveUplinkBWP-Id 0,
pusch-ServingCellConfig setup: {
}
},
pdcch-ServingCellConfig setup: {
},
pdsch-ServingCellConfig setup: {
...
},
csi-MeasConfig setup: {
...