Main Content

NR PUSCH Throughput with Transport Block over Multiple Slots

R2026b
Since R2026b

This example shows how to measure the physical uplink shared channel (PUSCH) throughput of a 5G New Radio (NR) link with transport block processing over multiple slots (TBoMS). You can perform perfect or practical synchronization and channel estimation. To reduce the total simulation time, you can execute the signal-to-noise ratio (SNR) points in the SNR loop in parallel by using the Parallel Computing Toolbox™ software.

Introduction

This example measures the PUSCH throughput of a 5G link using TBoMS, as defined in 3GPP TS 38.211, TS 38.212, TS 38.213, and TS 38.214.

3GPP Release 17 introduced TBoMS as part of the NR coverage enhancements work item (TS 38.212, TS 38.214). A single transport block (TB) is transmitted across multiple slots. The number of slots is configured by the numberOfSlotsTBoMS RRC parameter, as defined in TS 38.331. The TB is encoded into a single LDPC code block. This figure shows the uplink shared channel (UL-SCH) rate matching with TBoMS. Each slot starts reading the LDPC buffer at the point where the previous slot finished reading. HARQ operates on the TB across multiple slots as a single entity.

Block diagram of UL-SCH rate matching with TBoMS, showing the rate matching circular buffer and slots. The diagram illustrates how each slot starts reading the buffer at the point where the previous slot finished reading.

The example models these 5G NR features:

  • UL-SCH transport channel processing with TBoMS

  • PUSCH type-A repetition

  • PUSCH and PUSCH DM-RS generation

  • Variable subcarrier spacing and frame numerologies (2n×15 kHz)

  • Normal and extended cyclic prefix

  • TDL and CDL propagation channel models

Other features of the simulation are:

  • Optional PUSCH transform precoding

  • Slot-wise and non-slot-wise PUSCH and DM-RS mapping

  • Perfect or practical synchronization and channel estimation

  • HARQ operation

To reduce the total simulation time, you can use the Parallel Computing Toolbox software to execute the SNR points of the SNR loop in parallel.

Simulation Length and SNR Points

Set the length of the simulation in terms of the number of 10 ms frames. To produce meaningful throughput results, update NFrames to a large number. Set the SNR points to simulate. The example defines SNR per RE and applies the SNR to each receive antenna. For an explanation of the SNR definition that this example uses, see SNR Definition Used in Link Simulations.

simParameters = struct();                     % Create a structure to contain all key simulation parameters
simParameters.NFrames = 2; % Number of 10 ms frames
simParameters.SNRIn   = [-5 0 5]; % SNR range (dB)

Channel Estimator Configuration

Use the PerfectChannelEstimator variable to control channel estimation and synchronization behavior. When set to true, the example uses perfect channel estimation and synchronization. Otherwise, the example uses practical channel estimation and synchronization based on the values of the received PUSCH DM-RS.

simParameters.PerfectChannelEstimator = true;

Simulation Diagnostics

Use the DisplaySimulationInformation variable to control the display of simulation information such as the HARQ process ID used for each slot. In case of a CRC error, the example also displays the value of the index to the RV sequence.

simParameters.DisplaySimulationInformation = true;

Carrier Configuration

Set the carrier resource grid parameters. This example uses the parameters from TS 38.104 Table 8.2.12-1 as the default.

simParameters.Carrier                   = nrCarrierConfig;      % Carrier resource grid configuration
simParameters.Carrier.NSizeGrid         = 5; % Bandwidth in number of resource blocks (5 RBs at 15 kHz SCS)
simParameters.Carrier.SubcarrierSpacing = 15; % Subcarrier spacing (kHz)
simParameters.Carrier.CyclicPrefix      = 'Normal';             % 'Normal' or 'Extended' (Extended CP is relevant for 60 kHz SCS only)
simParameters.Carrier.NCellID           = 0;                    % Cell identity

PUSCH Configuration

Set the PUSCH parameters including resource allocation, modulation, and DM-RS. This example assumes fixed PUSCH configuration across all simulated slots.

simParameters.PUSCH = nrPUSCHConfig;

Set the PUSCH time-frequency resource allocation per slot to a single full grid BWP.

simParameters.PUSCH.PRBSet =  0:simParameters.Carrier.NSizeGrid-1;
simParameters.PUSCH.SymbolAllocation = [0,simParameters.Carrier.SymbolsPerSlot];

Set the mapping type, scrambling identifiers, transform precoding, and modulation scheme.

simParameters.PUSCH.MappingType = 'A';   % 'A'(slot-wise), 'B'(non-slot-wise)
simParameters.PUSCH.NID = simParameters.Carrier.NCellID;
simParameters.PUSCH.RNTI = 1;
simParameters.PUSCH.TransformPrecoding = false;
simParameters.PUSCH.Modulation = 'QPSK'; % 'pi/2-BPSK', 'QPSK', '16QAM', '64QAM', '256QAM'

Configure the PUSCH DM-RS.

simParameters.PUSCH.DMRS.DMRSTypeAPosition = 2;       % Mapping type A only. First DM-RS symbol position (2, 3)
simParameters.PUSCH.DMRS.DMRSLength = 1;              % Number of front-loaded DM-RS symbols (1(single symbol), 2(double symbol))
simParameters.PUSCH.DMRS.DMRSAdditionalPosition = 1;  % Additional DM-RS symbol positions (max range 0...3)
simParameters.PUSCH.DMRS.DMRSConfigurationType = 1;   % DM-RS configuration type (1, 2)
simParameters.PUSCH.DMRS.NumCDMGroupsWithoutData = 2; % Number of CDM groups without data
simParameters.PUSCH.DMRS.NIDNSCID = 0;                % Scrambling identity (0...65535)
simParameters.PUSCH.DMRS.NSCID = 0;                   % Scrambling initialization (0, 1)
simParameters.PUSCH.DMRS.NRSID = 0;                   % Scrambling ID for low-PAPR sequences (0...1007)
simParameters.PUSCH.DMRS.GroupHopping = 0;            % Group hopping (0, 1)
simParameters.PUSCH.DMRS.SequenceHopping = 0;         % Sequence hopping (0, 1)
simParameters.PUSCH.DMRS.DMRSPortSet = [];            % Use this to specify explicit DM-RS port numbers (TS 38.212 Section 7.3.1.1). Empty corresponds to the first NumLayers valid ports

UL-SCH Configuration

Set the UL-SCH transport channel processing parameters including the TBoMS and HARQ parameters.

simParameters.PUSCHExtension = struct();
simParameters.PUSCHExtension.NumberOfSlotsTBoMS = 4; % Number of slots for transport block processing
simParameters.PUSCHExtension.NumRepetitionTypeA = 4; % Number of Type-A repetitions
simParameters.PUSCHExtension.RVSequence         = [0 2 3 1];            % RV sequence for repetition
simParameters.PUSCHExtension.TargetCodeRate     = 193 / 1024; % Target code rate of the whole block
simParameters.PUSCHExtension.XOverhead          = 0;                    % Rate matching overhead for TBS (Xoh)

Set HARQ parameters.

simParameters.PUSCHExtension.NHARQProcesses = 16; % Number of parallel HARQ processes to use
simParameters.PUSCHExtension.EnableHARQ = true;   % Enable retransmissions for each process, using RV sequence [0 2 3 1]

Antenna Geometry and Propagation Channel

Set the number of receive antennas. This example supports single-input multiple-output (SIMO) configurations where a signal from a single transmit antenna is received by one or more receive antennas.

simParameters.NRxAnts = 2; % Number of receive antennas

Configure a CDL or TDL propagation channel model. Set DelayProfile to 'None' to disable channel impairments. For CDL channels, the example converts the number of antenna elements into an antenna panel configuration.

simParameters.DelayProfile        = 'TDL-B'; % 'TDL-A', ..., 'TDL-E', 'CDL-A', ..., 'CDL-E', 'None'
simParameters.DelaySpread         = 100e-9;
simParameters.MaximumDopplerShift = 400;

% Cross-check parameters before simulation
validateNumLayers(simParameters);

waveformInfo = nrOFDMInfo(simParameters.Carrier);
[channel,simParameters] = createChannel(simParameters,waveformInfo);

% Get the maximum channel delay
chInfo     = info(channel);
maxChDelay = chInfo.MaximumChannelDelay;

Processing Loop

To determine the throughput at each SNR point, the example analyzes PUSCH data on a per-slot basis. Each TBoMS bundle, consisting of a given number of slots (NumberOfSlotsTBoMS), shares a single transport block and HARQ entity. Physical channel processing is independent per slot:

  • Update current HARQ process: Determine whether a new transport block or a retransmission is required in the first slot of every TBoMS bundle.

  • UL-SCH encoding: On the first slot of the bundle, encode and rate-match the transport block across all slots in the bundle. The first slot starts at the RV-indicated circular buffer position; subsequent slots continue from where the previous slot left off.

  • Generate grid and waveform: Modulate the coded bits onto PUSCH resource elements and OFDM-modulate the resource grid.

  • Model noisy channel: Pass the waveform through a CDL or TDL fading channel and add AWGN.

  • Perform synchronization and OFDM demodulation: For perfect synchronization, reconstruct the channel impulse response to synchronize the received waveform. For practical synchronization, correlate the received waveform with the PUSCH DM-RS. Then OFDM demodulate the synchronized signal.

  • Perform channel estimation and equalization: For perfect channel estimation, reconstruct the channel impulse response and perform OFDM demodulation. For practical channel estimation, use the PUSCH DM-RS. MMSE equalize the channel by using the nrEqualizeMMSE function.

  • Decode the PUSCH: Demodulate and descramble the recovered PUSCH symbols along with a noise estimate by using the nrPUSCHDecode function.

  • UL-SCH decoding: Rate-recover and accumulate soft bits into the N-domain soft buffer every slot. The decoder attempts LDPC decoding only when it receives all slots in the bundle.

To reduce the total simulation time, you can execute the processing loop in parallel by using the Parallel Computing Toolbox software. For parallel processing, comment out the for statement and uncomment the parfor statement. If Parallel Computing Toolbox is not installed, parfor defaults to the traditional for statement. Because parfor-loop iterations are executed in parallel in a nondeterministic order, the simulation information displayed for each SNR point can be intertwined. To switch off simulation information display, set the DisplaySimulationInformation variable to false.

% Array to store the maximum throughput for all SNR points
maxThroughput = zeros(length(simParameters.SNRIn),1); 
% Array to store the simulation throughput for all SNR points
simThroughput = zeros(length(simParameters.SNRIn),1);

% Define RV at first occurrence and use RV only here
if simParameters.PUSCHExtension.EnableHARQ
    rvSeq  = simParameters.PUSCHExtension.RVSequence;
    % Expand RV sequence to match its length to the number of Type-A repetitions
    numRVs = numel(rvSeq);
    numRep = simParameters.PUSCHExtension.NumRepetitionTypeA;
    rvSeq = rvSeq(mod((0:numRep-1),numRVs)+1);
else
    % HARQ disabled - single transmission with RV=0, no retransmissions
    rvSeq = 0;
end

% Calculate the number of RBs in one slot, transport block size, and
% aggregated bit capacity of the multiple slots. Also calculate PUSCH
% indices in each slot as PUSCH configuration is fixed in all slots.
[puschIndices,puschIndicesInfo] = nrPUSCHIndices(simParameters.Carrier,simParameters.PUSCH);
MRB = numel(puschIndicesInfo.PRBSet);
trBlkSize = nrTBS(simParameters.PUSCH.Modulation,simParameters.PUSCH.NumLayers, ...
    MRB*simParameters.PUSCHExtension.NumberOfSlotsTBoMS,puschIndicesInfo.NREPerPRB, ...
    simParameters.PUSCHExtension.TargetCodeRate,simParameters.PUSCHExtension.XOverhead);
GBundle = simParameters.PUSCHExtension.NumberOfSlotsTBoMS*puschIndicesInfo.G;

for snrIdx = 1:numel(simParameters.SNRIn)    % comment out for parallel computing
% parfor snrIdx = 1:numel(simParameters.SNRIn) % uncomment for parallel computing
    
    % Reset the random number generator so that each SNR point will
    % experience the same noise realization
    rng('default');
    
    % Take full copies of the simulation-level parameter structures so that they are not 
    % PCT broadcast variables when using parfor 
    simLocal = simParameters;
    waveinfoLocal = waveformInfo;
    
    % Take copies of channel-level parameters to simplify subsequent parameter referencing 
    carrier = simLocal.Carrier;
    pusch = simLocal.PUSCH;
    puschextra = simLocal.PUSCHExtension;

    % Prepare simulation for new SNR point
    SNRdB = simLocal.SNRIn(snrIdx);
    fprintf('\nSimulating (1x%d) SCS=%dkHz with %s channel at %gdB SNR for %d 10ms frame(s)\n', ...
        simLocal.NRxAnts,carrier.SubcarrierSpacing,simLocal.DelayProfile,SNRdB,simLocal.NFrames);

    % Specify the fixed order for the HARQ process IDs to cycle through
    harqSequence = 0:puschextra.NHARQProcesses-1;

    % Initialize the state of all HARQ processes
    harqEntity = HARQEntity(harqSequence,rvSeq,pusch.NumCodewords);

    % Reset the channel so that each SNR point will experience the same
    % channel realization
    reset(channel);
    
    % Total number of slots in the simulation period
    NSlots = simLocal.NFrames * carrier.SlotsPerFrame;

    % Timing offset, updated in every slot for perfect synchronization and
    % when the correlation is strong for practical synchronization
    offset = 0;

    % Noise power, normalized by the IFFT size used in OFDM modulation, as
    % the OFDM modulator applies this normalization to the transmitted
    % waveform. Also normalize by the number of receive antennas, as the
    % channel model applies this normalization to the received waveform
    % by default
    SNR = 10^(SNRdB/10);
    N0 = 1/sqrt(simLocal.NRxAnts*waveinfoLocal.Nfft*SNR);
    nVar = N0^2*waveinfoLocal.Nfft;

    % Initialize the array to store the decoder states and transport blocks
    % for each HARQ process
    initCell      = repmat({[]},puschextra.NHARQProcesses,1);
    nSlotInBundle = 0;        % TBoMS slot number counter inside the bundle
    dstate        = initCell; % Decoder states
    trBlk         = initCell; % Transport block

    % Loop over the entire waveform length
    for nslot = 0:NSlots-1

        % Update the carrier slot numbers for new slot
        carrier.NSlot = nslot;

        % At the first slot of each TBoMS slot bundle, create a new UL-SCH
        % transport block if this is the initial transmission of the
        % current HARQ process. Encode once and rate-match across all slots
        % in the bundle.
        if nSlotInBundle == 0
            if harqEntity.NewData
                % New transmission: reset decoder state completely
                dstate{harqEntity.HARQProcessID+1} = [];
                % Create new UL-SCH transport block
                trBlk{harqEntity.HARQProcessID+1} = randi([0 1],trBlkSize,1);
            else
                % Retransmission: keep soft buffer for combining, clear
                % buffered LLRs from previous bundle attempt
                dstate{harqEntity.HARQProcessID+1}.SlotLLRs = [];
            end

            % UL-SCH encoding: perform LDPC encoding on the whole transport
            % block and per-slot rate matching. Store the encoded bits for
            % each slot in a matrix
            codedSlots = hULSCHEncode( ...
                trBlk{harqEntity.HARQProcessID+1},pusch.Modulation, ...
                puschIndicesInfo.G,puschextra.TargetCodeRate, ...
                harqEntity.RedundancyVersion,puschextra.NumberOfSlotsTBoMS);
        end

        % Select coded bits for current slot in the bundle
        codedTrBlock = codedSlots(:,nSlotInBundle+1);

        % Create resource grid for a slot
        puschGrid = nrResourceGrid(carrier);

        % PUSCH modulation and mapping to resource grid
        puschSymbols = nrPUSCH(carrier,pusch,codedTrBlock);
        puschGrid(puschIndices) = puschSymbols;

        % Generate PUSCH DM-RS symbols and map to resource grid
        dmrsSymbols = nrPUSCHDMRS(carrier,pusch);
        dmrsIndices = nrPUSCHDMRSIndices(carrier,pusch);
        puschGrid(dmrsIndices) = dmrsSymbols;

        % OFDM modulation
        txWaveform = nrOFDMModulate(carrier,puschGrid);

        % Pass data through channel model. Append zeros at the end of the
        % transmitted waveform to flush channel content. These zeros take
        % into account any delay introduced in the channel. This is a mix
        % of multipath delay and implementation delay. This value may 
        % change depending on the sampling rate, delay profile, and delay
        % spread. The channel model also returns the OFDM channel response
        % and timing offset for the specified carrier
        txWaveform = [txWaveform; zeros(maxChDelay,size(txWaveform,2))]; %#ok<AGROW>
        [rxWaveform,ofdmResponse,timingOffset] = channel(txWaveform,carrier);
        
        % Add AWGN to the received time-domain waveform
        noise = N0*randn(size(rxWaveform),"like",rxWaveform);
        rxWaveform = rxWaveform + noise;

        if (simLocal.PerfectChannelEstimator)
            % For perfect synchronization, use the timing offset obtained
            % from the channel
            offset = timingOffset;
        else
            % Practical synchronization. Correlate the received waveform 
            % with the PUSCH DM-RS to give timing offset estimate 't' and
            % correlation magnitude 'mag'. The function
            % hSkipWeakTimingOffset is used to update the receiver timing
            % offset. If the correlation peak in 'mag' is weak, the current
            % timing estimate 't' is ignored and the previous estimate
            % 'offset' is used
            [t,mag] = nrTimingEstimate(carrier,rxWaveform,dmrsIndices,dmrsSymbols);
            offset = hSkipWeakTimingOffset(offset,t,mag);
            % Display a warning if the estimated timing offset exceeds the
            % maximum channel delay
            if offset > maxChDelay
                warning(['Estimated timing offset (%d) is greater than the maximum channel delay (%d).' ...
                    ' This will result in a decoding failure. This may be caused by low SNR,' ...
                    ' or not enough DM-RS symbols to synchronize successfully.'],offset,maxChDelay);
            end
        end
        rxWaveform = rxWaveform(1+offset:end,:);

        % Perform OFDM demodulation on the received data to recreate the
        % resource grid, including padding, when practical synchronization
        % results in an incomplete slot being demodulated
        rxGrid = nrOFDMDemodulate(carrier,rxWaveform);
        [K,L,R] = size(rxGrid);
        if (L < carrier.SymbolsPerSlot)
            rxGrid = cat(2,rxGrid,zeros(K,carrier.SymbolsPerSlot-L,R));
        end
        
        if (simLocal.PerfectChannelEstimator)
            % For perfect channel estimate, use the OFDM channel response
            % obtained from the channel
            estChannelGrid = ofdmResponse;

            % Use the precalculated noise variance as the perfect noise
            % estimate
            noiseEst = nVar;
        else
            % Practical channel estimation using the PUSCH DM-RS
            dmrsLayerSymbols = nrPUSCHDMRS(carrier,pusch);
            dmrsLayerIndices = nrPUSCHDMRSIndices(carrier,pusch);
            [estChannelGrid,noiseEst] = nrChannelEstimate(carrier,rxGrid,dmrsLayerIndices,dmrsLayerSymbols,'CDMLengths',pusch.DMRS.CDMLengths);
        end
        
        % Get PUSCH resource elements from the received grid
        [puschRx,puschHest] = nrExtractResources(puschIndices,rxGrid,estChannelGrid);
        
        % Equalization
        [puschEq,csi] = nrEqualizeMMSE(puschRx,puschHest,noiseEst);

        % Decode PUSCH physical channel
        [ulschLLRs,rxSymbols] = nrPUSCHDecode(carrier,pusch,puschEq,noiseEst);

        % Apply channel state information (CSI) produced by the equalizer,
        % including the effect of transform precoding if enabled
        if (pusch.TransformPrecoding)
            MSC = MRB * 12;
            csi = nrTransformDeprecode(csi,MRB) / sqrt(MSC);
            csi = repmat(csi((1:MSC:end).'),1,MSC).';
            csi = reshape(csi,size(rxSymbols));
        end
        Qm = length(ulschLLRs) / length(rxSymbols);
        csi = reshape(repmat(csi.',Qm,1),[],1);
        ulschLLRs = ulschLLRs .* csi;
        
        % UL-SCH decoding. Rate recover and accumulate soft bits every slot.
        % LDPC decoding is only attempted once all TBoMS slots in a bundle
        % have been received.
        lastSlotInBundle = (nSlotInBundle == puschextra.NumberOfSlotsTBoMS-1);
        [decbits,blkerr,dstate{harqEntity.HARQProcessID+1}] = hULSCHDecode(ulschLLRs,pusch.Modulation, ...
            harqEntity.RedundancyVersion,trBlkSize,puschextra.TargetCodeRate, ...
            dstate{harqEntity.HARQProcessID+1},lastSlotInBundle);

        % Update HARQ process with transport block CRC error at the last
        % slot in each bundle
        if lastSlotInBundle
            % Store values to calculate throughput
            simThroughput(snrIdx) = simThroughput(snrIdx) + (~blkerr * trBlkSize);
            maxThroughput(snrIdx) = maxThroughput(snrIdx) + trBlkSize;

            % Update current process with CRC error and advance to next process
            procstatus = updateAndAdvance(harqEntity,blkerr,trBlkSize,GBundle);
            if (simLocal.DisplaySimulationInformation)
                firstSlot = nslot-puschextra.NumberOfSlotsTBoMS+1;
                fprintf('\n(%3.2f%%) NSlot=%d:%d, %s', ...
                    100*(nslot+1)/NSlots,firstSlot,nslot,procstatus);
            end
        end

        % Advance TBoMS slot counter
        nSlotInBundle = mod(nSlotInBundle+1,puschextra.NumberOfSlotsTBoMS);

    end
    
    % Display the results dynamically in the command window
    if (simLocal.DisplaySimulationInformation)
        fprintf('\n');
    end
    fprintf('\nThroughput (Mbps) for %d frame(s) = %.4f\n',simLocal.NFrames,1e-6*simThroughput(snrIdx)/(simLocal.NFrames*10e-3));
    fprintf('Throughput (%%) for %d frame(s) = %.4f\n',simLocal.NFrames,simThroughput(snrIdx)*100/maxThroughput(snrIdx));

end
Simulating (1x2) SCS=15kHz with TDL-B channel at -5dB SNR for 2 10ms frame(s)
(20.00%) NSlot=0:3, HARQ Proc 0: CW0: Initial transmission passed  (TBS=1128,RV=0,CR=0.195833).
(40.00%) NSlot=4:7, HARQ Proc 1: CW0: Initial transmission passed  (TBS=1128,RV=0,CR=0.195833).
(60.00%) NSlot=8:11, HARQ Proc 2: CW0: Initial transmission failed  (TBS=1128,RV=0,CR=0.195833).
(80.00%) NSlot=12:15, HARQ Proc 3: CW0: Initial transmission failed  (TBS=1128,RV=0,CR=0.195833).
(100.00%) NSlot=16:19, HARQ Proc 4: CW0: Initial transmission failed  (TBS=1128,RV=0,CR=0.195833).
Throughput (Mbps) for 2 frame(s) = 0.1128
Throughput (%) for 2 frame(s) = 40.0000
Simulating (1x2) SCS=15kHz with TDL-B channel at 0dB SNR for 2 10ms frame(s)
(20.00%) NSlot=0:3, HARQ Proc 0: CW0: Initial transmission passed  (TBS=1128,RV=0,CR=0.195833).
(40.00%) NSlot=4:7, HARQ Proc 1: CW0: Initial transmission passed  (TBS=1128,RV=0,CR=0.195833).
(60.00%) NSlot=8:11, HARQ Proc 2: CW0: Initial transmission passed  (TBS=1128,RV=0,CR=0.195833).
(80.00%) NSlot=12:15, HARQ Proc 3: CW0: Initial transmission passed  (TBS=1128,RV=0,CR=0.195833).
(100.00%) NSlot=16:19, HARQ Proc 4: CW0: Initial transmission passed  (TBS=1128,RV=0,CR=0.195833).
Throughput (Mbps) for 2 frame(s) = 0.2820
Throughput (%) for 2 frame(s) = 100.0000
Simulating (1x2) SCS=15kHz with TDL-B channel at 5dB SNR for 2 10ms frame(s)
(20.00%) NSlot=0:3, HARQ Proc 0: CW0: Initial transmission passed  (TBS=1128,RV=0,CR=0.195833).
(40.00%) NSlot=4:7, HARQ Proc 1: CW0: Initial transmission passed  (TBS=1128,RV=0,CR=0.195833).
(60.00%) NSlot=8:11, HARQ Proc 2: CW0: Initial transmission passed  (TBS=1128,RV=0,CR=0.195833).
(80.00%) NSlot=12:15, HARQ Proc 3: CW0: Initial transmission passed  (TBS=1128,RV=0,CR=0.195833).
(100.00%) NSlot=16:19, HARQ Proc 4: CW0: Initial transmission passed  (TBS=1128,RV=0,CR=0.195833).
Throughput (Mbps) for 2 frame(s) = 0.2820
Throughput (%) for 2 frame(s) = 100.0000

Results

Display the measured throughput. The example calculates the throughput as the percentage of the maximum possible throughput of the link given the available resources for data transmission.

plotResults(simParameters,simThroughput,maxThroughput);

Figure contains an axes object. The axes object with title CP-OFDM / NRB=5 / SCS=15kHz / QPSK 193/1024 / 1x2 / TB over 4 Slots, xlabel SNR (dB), ylabel Throughput (%) contains an object of type line.

% Bundle key parameters and results into a combined structure for recording
simResults.simParameters = simParameters;
simResults.simThroughput = simThroughput;
simResults.maxThroughput = maxThroughput;

References

[1] 3GPP TS 38.211. "NR; Physical channels and modulation." 3rd Generation Partnership Project; Technical Specification Group Radio Access Network.

[2] 3GPP TS 38.212. "NR; Multiplexing and channel coding." 3rd Generation Partnership Project; Technical Specification Group Radio Access Network.

[3] 3GPP TS 38.213. "NR; Physical layer procedures for control." 3rd Generation Partnership Project; Technical Specification Group Radio Access Network.

[4] 3GPP TS 38.214. "NR; Physical layer procedures for data." 3rd Generation Partnership Project; Technical Specification Group Radio Access Network.

[5] 3GPP TS 38.331. "NR; Radio Resource Control (RRC); Protocol specification." 3rd Generation Partnership Project; Technical Specification Group Radio Access Network.

[6] 3GPP TS 38.104. "NR; Base Station (BS) radio transmission and reception." 3rd Generation Partnership Project; Technical Specification Group Radio Access Network.

Local Functions

function validateNumLayers(simParameters)
% Validate the number of layers relative to the antenna geometry

    validateattributes(simParameters.PUSCHExtension.NumberOfSlotsTBoMS, ...
        {'numeric'},{'integer','positive'},'','NumberOfSlotsTBoMS');
    numlayers = simParameters.PUSCH.NumLayers;
    if numlayers ~= 1
        error('The number of layers (%d) must be 1. This example only supports single-layer PUSCH.', ...
            numlayers);
    end

end

function [channel,simParameters] = createChannel(simParameters,waveformInfo)
% Construct the CDL or TDL channel model object

    if contains(simParameters.DelayProfile,'CDL','IgnoreCase',true)
        channel = nrCDLChannel; % CDL channel object

        % Swap transmit and receive sides as the default CDL channel is
        % configured for downlink transmissions.
        swapTransmitAndReceive(channel);

        % Turn the number of antennas into antenna panel array layouts. If
        % NRxAnts is not one of (1,2,4,8,16,32,64,128,256,512,1024), its value
        % is rounded up to the nearest value in the set.
        channel = hArrayGeometry(channel,1,simParameters.NRxAnts,'uplink');
        simParameters.NRxAnts = prod(channel.ReceiveAntennaArray.Size);
    else
        channel = nrTDLChannel; % TDL channel object

        % Configure the channel to automatically select a sample rate for
        % generating channel coefficients
        channel.PathGainSampleRate = 'auto';

        % Swap transmit and receive sides as the default TDL channel is
        % configured for downlink transmissions
        swapTransmitAndReceive(channel);

        % Set the channel geometry
        channel.NumTransmitAntennas = 1;
        channel.NumReceiveAntennas = simParameters.NRxAnts;
    end

    % Assign simulation channel parameters and waveform sample rate to the
    % object, and specify OFDM channel response as the channel response output
    % so that perfect channel estimate is calculated while filtering the signal
    channel.DelayProfile = simParameters.DelayProfile;
    if ~strcmp(channel.DelayProfile,"None")
        channel.DelaySpread = simParameters.DelaySpread;
        channel.MaximumDopplerShift = simParameters.MaximumDopplerShift;
        channel.SampleRate = waveformInfo.SampleRate;
    end
    channel.ChannelResponseOutput = 'ofdm-response';
end

function plotResults(simParameters,simThroughput,maxThroughput)
% Plot the simulation results

    figure;
    plot(simParameters.SNRIn,simThroughput*100./maxThroughput,'o-.')
    xlabel('SNR (dB)'); ylabel('Throughput (%)'); grid on;
    if (simParameters.PUSCH.TransformPrecoding)
        ofdmType = 'DFT-s-OFDM';
    else
        ofdmType = 'CP-OFDM';
    end
    title(sprintf('%s / NRB=%d / SCS=%dkHz / %s %d/1024 / 1x%d / TB over %d Slots', ...
        ofdmType,simParameters.Carrier.NSizeGrid,simParameters.Carrier.SubcarrierSpacing, ...
        simParameters.PUSCH.Modulation, ...
        round(simParameters.PUSCHExtension.TargetCodeRate*1024), ...
        simParameters.NRxAnts, ...
        simParameters.PUSCHExtension.NumberOfSlotsTBoMS));
end

See Also

| | | | | |

See Also

Topics