Main Content

NR Sidelink Vector Waveform Generation

Since R2024b

This example shows how to configure and generate a 5G NR V2X sidelink baseband waveform containing a sequence of physical sidelink control channel (PSCCH) and physical sidelink shared channel (PSSCH) transmissions, including sidelink control information (SCI) and SL-SCH transport channel coding.

Introduction

This example shows how to parameterize and generate a 5G NR sidelink baseband waveform using the 5G Toolbox™ product. The generated waveform contains a sequence of consecutive data transmissions. Each transmission comprises these channels and signals:

  • PSCCH and its associated DM-RS

  • PSSCH and its associated DM-RS

The waveform is based on the PSSCH reference measurement channels (RMCs) defined in TS 38.101-4 Annex A.6.2. However, you can parameterize the waveform for an arbitrary resource pool and PSSCH configuration.

For the physical layer procedures and processing, like the LTE sidelink, the NR sidelink uses the concept of resource pools to configure specific resources for transmission and reception on a sidelink carrier. Each data transmission comprises a PSCCH transmission and an associated PSSCH transmission. Unlike LTE, NR uses two-stage sidelink control information (SCI), where the 1st-stage SCI part (SCI1) is sent on the PSCCH and the 2nd-stage SCI part (SCI2) is multiplexed with SL-SCH transport data and sent on the associated PSSCH.

For LTE sidelink waveform generation, see Sidelink Channels (LTE Toolbox).

Waveform and Resource Pool Configuration

To define an NR sidelink resource pool within a BWP in an SCS carrier, this example uses the MATLAB® class NRSidelinkResourcePool. This class is parameterized in terms of a subset of the SL-ResourcePool-r16 RRC information element fields (TS 38.331). The class provides a method to transmit PSCCH and PSSCH into the resource pool, creating a baseband IQ waveform for each slot. The class also provides a method to receive PSCCH and PSSCH in the resource pool. In addition, the class has methods that return PSCCH and PSSCH resource information and provide resource mapping visualization. The NRSidelinkResourcePool class supports PSSCH transmission shortening for periodic PSFCH opportunities, but it does not create PSFCH instances.

The NRSidelinkResourcePool class includes a static method that returns a preconfigured resource pool and PSCCH parameter configurations for the TS 38.101-4 PSSCH RMCs. These RMC pools are defined with HARQ enabled and have a 4-slot PSFCH period, meaning that every fourth slot is shortened by two symbols to make transmission resources available for PSFCH candidates.

The waveform construction process comprises these steps:

  • Get the PSSCH RMC-based resource pool and PSSCH transmission parameters as an initial template. If required, reconfigure for an arbitrary pool and PSSCH.

  • Specify the length of the waveform in number of slots.

  • If open-loop SL-SCH transport block retransmissions are required in the waveform, specify the number of HARQ processes and the shared RV sequence to cycle through.

  • Construct the full baseband waveform by creating a pair of PSCCH and PSSCH transmissions in each slot.

  • The SCI1 and SCI2 payloads and SL-SCH transport blocks come from separate PN23 data streams. The SL-SCH transport blocks are sourced according to the specified HARQ processes and RV sequences.

In addition to the baseband IQ waveform, the example creates the associated resource element grid for the component carrier. It also creates an array of structures that contain detailed information about the intermediate data processing vectors, DM-RS signals, and all resource indices for each of the PSCCH and PSSCH transmission pairs in all the slots.

Use the following section to set the parameters for the waveform and resource pool configuration.

% Define all top-level waveform configuration parameters in a single 'waveconfig' structure
waveconfig = struct();

% Use the PSSCH RMC configurations as an initial parameter template for 
% the sequence of PSCCH and PSSCH transmissions in the waveform
% TS 38.101-4 Section 11, V2X requirements and A.6, SL reference measurements channels

% Select PSSCH reference measurement channel to start
% All PSSCH RMC below are defined for 20 MHz BW @ 30 kHz SCS (10 PRB subchannels)
% 'R.PSSCH.2-1.1' - 20 PRB (2 subchannels), QPSK,  TCR=308/1024
% 'R.PSSCH.2-1.2' - 20 PRB (2 subchannels), 16QAM, TCR=378/1024
% 'R.PSSCH.2-1.3' - 10 PRB (1 subchannel),  64QAM, TCR=438/1024
% 'R.PSSCH.2-1.4' - 10 PRB (1 subchannel),  QPSK,  TCR=308/1024
% 'R.PSSCH.2-1.5' - 10 PRB (1 subchannel),  64QAM, TCR=910/1024
rmc   = "R.PSSCH.2-1.2";   % RMC selection
bwscs = [20 30];   % Release 16 NR sidelink is specified to operate in FR1 at 10, 20, 30, 40 MHz BW

% Get PSCCH and PSSCH channel and sidelink pool parameters
bw = bwscs(1); 
scs = bwscs(2);
[waveconfig.SLTransmission,waveconfig.Pool] = NRSidelinkResourcePool.rmcTestConfiguration(rmc,bw,scs);

% Reconfigure any required pool and channel parameters here for the generated waveform
% For example:
% Uncomment to turn off PSFCH symbol reservation in the resource pool
% waveconfig.Pool.sl_PSFCH_Period_r16 = 0;  % In terms of L3 protocol, this is signalling no HARQ enabled in the pool
% Uncomment to move the PSSCH allocation up by one subchannel
% waveconfig.SLTransmission.SubchannelAllocation = waveconfig.SLTransmission.SubchannelAllocation + [1 0]; 

% Visually crosscheck the PSCCH and PSSCH resources configured for the sequence of transmissions in the carrier waveform
disp(waveconfig.Pool)
  NRSidelinkResourcePool with properties:

                   SCSCarrier: [1x1 nrCarrierConfig]
                    NStartBWP: []
                     NSizeBWP: []
           sl_StartSymbol_r16: 0
         sl_LengthSymbols_r16: 14
        sl_SubchannelSize_r16: 10
    sl_StartRB_Subchannel_r16: 0
         sl_NumSubchannel_r16: 5
            sl_X_Overhead_r16: 0
               sl_Scaling_r16: 1
     sl_TimeResourcePSCCH_r16: 2
     sl_FreqResourcePSCCH_r16: 10
       sl_DMRS_ScrambleID_r16: 0
          sl_PSFCH_Period_r16: 4
            MaxNumSubchannels: 5
                  IsPSFCHSlot: 0
disp(waveconfig.SLTransmission)
    SubchannelAllocation: [0 2]
               NumLayers: 1
              Modulation: '16QAM'
        NumDMRSPositions: 3
    NumDMRSPositionsList: [2 3]
          TargetCodeRate: 0.3691
          BetaSCI2Offset: 5
                   OSCI2: 35
                    NXID: []
       RedundancyVersion: 0
           HARQProcessID: 0
           PSFCHOverhead: 0
                   OSCI1: 26
displayTransmissionResources(waveconfig.Pool,waveconfig.SLTransmission);

Figure contains an axes object. The axes object with title PSCCH and PSSCH Resource Mapping, xlabel Symbols in Slot, ylabel Resource Elements contains 7 objects of type image, line. These objects represent PSCCH (SCI1), PSCCH DM-RS, PSSCH (SCI2), PSSCH (SL-SCH), PSSCH DM-RS, Repeated symbol.

% Waveform length
waveconfig.NumSlots = 20;        % Number of transmission slots in the waveform (20 slots = 1ms subframe @ 30 kHz SCS)

% SL-SCH HARQ-related parameters
waveconfig.NHARQProcesses = 4;   % Number of independent parallel HARQ processes to use (up to 16 processes available (4 bits available for HARQ ID in SCI2))
waveconfig.RVSequence = [0];     % Sequence of RV indices for a TB (initial transmission and any potential retransmissions, for full HARQ the sequence [0 2 3 1] is performant)

Waveform Generation

Create a baseband IQ waveform that contains a sequence of the previously configured PSCCH and PSSCH transmissions.

% Take a copy of the resource pool and PSSCH transmission parameters for ease of reference in the code
pool = waveconfig.Pool;
sltransmission = waveconfig.SLTransmission;

% Use a SL-SCH HARQ entity object to control the HARQ process and RV scheduling 
% of the SL-SCH transport encoding, across the series of PSSCH transmissions in the waveform
blindharq = 1;  % Use open-loop RV sequencing across the series of PSSCH instances
harqEntity = HARQEntitySL(0:waveconfig.NHARQProcesses-1,waveconfig.RVSequence,1,blindharq);

% Set up SL-SCH transport channel processing
slschtx = nrULSCH("MultipleHARQProcesses",true);     % SL-SCH transport channel encoder (same processing as UL-SCH, but with I_BIL = 0 always)
slschtx.TargetCodeRate = sltransmission.TargetCodeRate;

% Create a set of PN23 data sources to stream the SL-SCH, SCI1, and SCI2 payloads 
% across the sequence of transmissions
slschdatasource = createPN23DataSource();
sci1datasource = createPN23DataSource();
sci2datasource = createPN23DataSource();

% Create a pair of PSSCH DM-RS position configurations, the first one for a PSFCH candidate slot
% and the second one for a normal slot
if isempty(sltransmission.NumDMRSPositionsList)
    dmrspositionset = ones(1,2)*sltransmission.NumDMRSPositions;
else
    [dmrspositionset(1), dmrspositionset(2)] = bounds(sltransmission.NumDMRSPositionsList);
end

% Create variables for the basestation waveform and related outputs
waveform = [];
resourcegrid = [];
waveformresources = [];

% Start the waveform construction at slot 0
pool.SCSCarrier.NSlot = 0; 

% Slot-wise loop to build the complete waveform from the sequence of individual PSCCH and PSSCH transmissions
for ns=1:waveconfig.NumSlots

    % PSFCH slot related adjustments to the PSSCH transmission parameters
    sltransmission.PSFCHOverhead = pool.IsPSFCHSlot;
    sltransmission.NumDMRSPositions = dmrspositionset(2 - pool.IsPSFCHSlot);

    % SL-SCH transport block data
    if harqEntity.NewData   % Is this a new data opportunity for the current HARQ process or a retransmission?

        % Calculate the SL-SCH TBS from the PSSCH transmission and pool parameters
        tbs = getTBS(pool,sltransmission);

        % Get a new transport block for this PSSCH transmission
        trBlk = slschdatasource(tbs);

        % Set the transport block into the SL-SCH encoder
        setTransportBlock(slschtx,trBlk,harqEntity.HARQProcessID);
    end

    % Update dynamic HARQ related transmission parameters for the SL-SCH part of this PSSCH transmission
    sltransmission.HARQProcessID = harqEntity.HARQProcessID;
    sltransmission.RedundancyVersion = harqEntity.RedundancyVersion;

    % SCI1 and SCI2 payload data 
    % 
    % 1st-stage SCI information bits for PSCCH
    sci1infobits = sci1datasource(sltransmission.OSCI1);
    % 2nd-stage SCI information bits for transmission on PSSCH, multiplexed with SL-SCH data
    sci2infobits = sci2datasource(sltransmission.OSCI2);

    % Transmit PSCCH and PSSCH pair in the resource pool
    % Input is the separate control information bits (SCI1 and SCI2) and transport channel object
    % Output is the slot waveform, plus intermediate processing symbols and resource information
    [basebandiq,sld,slo] = transmitInPool(pool,sltransmission,sci1infobits,sci2infobits,slschtx);

    % Append latest slot IQ samples onto the baseband waveform array
    waveform = [waveform;basebandiq];               
    resourcegrid = [resourcegrid, sld.ResourceGrid];
    % Push data and info structures onto 'waveformresources' structure array
    waveformresources = [waveformresources struct(NSlot=pool.SCSCarrier.NSlot,DataVectors=sld,ResourceIndices=slo)];

    % Move on to next HARQ process for the next transmission
    advanceToNextProcess(harqEntity);

    % Move on to next available transmission slot in the resource pool (this updates the slot number)
    [pool,nslotsadvanced] = advanceToNextSlot(pool);

end

Display the baseband sidelink waveform and associated carrier resource grid.

% Plot the complete baseband IQ waveform
figure;
plot(abs(waveform(:,1)))
title('Magnitude of 5G Sidelink Baseband Waveform');
subtitle('PSCCH and PSSCH transmissions');
xlabel('Sample Index');
ylabel('Magnitude');

Figure contains an axes object. The axes object with title Magnitude of 5G Sidelink Baseband Waveform, xlabel Sample Index, ylabel Magnitude contains an object of type line.

% Plot the complete resource grid usage
figure;
image(100*abs(resourcegrid(:,:,1)))
axis('xy');
title('Sidelink Carrier Resource Grid');
subtitle('PSCCH and PSSCH Transmissions');
xlabel('Symbols');
ylabel('Subcarriers');

Figure contains an axes object. The axes object with title Sidelink Carrier Resource Grid, xlabel Symbols, ylabel Subcarriers contains an object of type image.

Display the PSCCH and PSSCH intermediate processing vectors and the resource usage information for individual transmission instances in the waveform.

% Display the PSCCH and PSSCH intermediate processing vectors and the resource usage information 
% for individual transmission instances in the waveform
transmissionnumber = 1;
fprintf('PHY processing data vectors associated with PSCCH and PSSCH transmission #%d:\n%s',transmissionnumber,...
    formattedDisplayText(waveformresources(transmissionnumber).DataVectors));
PHY processing data vectors associated with PSCCH and PSSCH transmission #1:
             SCI1Bits: [26x1 double]
            PSCCHBits: [360x1 double]
         PSCCHSymbols: [180x1 double]
    PSCCHDMRSOCCIndex: 0
                 NXID: 6912148
             SCI2Bits: [35x1 double]
            SLSCHBits: [1800x1 int8]
        PSSCHSCI2Bits: [816x1 double]
       PSSCHSLSCHBits: [5088x1 int8]
         PSSCHSymbols: [1680x1 double]
         ResourceGrid: [612x14 double]
% Display the PSCCH and PSSCH intermediate processing vectors and the resource usage information 
% for individual transmission instances in the waveform
fprintf('Resource indices and DM-RS associated with PSCCH and PSSCH transmission #%d:\n%s',transmissionnumber,...
    formattedDisplayText(waveformresources(transmissionnumber).ResourceIndices));
Resource indices and DM-RS associated with PSCCH and PSSCH transmission #1:
         PSCCHIndices: [180x1 double]
     PSCCHDMRSIndices: [60x1 double]
            PSCCHDMRS: [60x1 double]
              PSCCHGd: 180
               PSCCHG: 360
         PSSCHIndices: [1680x1 double]
    PSSCHIndicesSplit: {[408x1 double]  [1272x1 double]}
     PSSCHDMRSIndices: [240x1 double]
            PSSCHDMRS: [240x1 double]
              PSSCHGd: [408 1272]
               PSSCHG: [816 5088]
                Gamma: 8

Local Functions

function ds = createPN23DataSource()  
% Create a PN23 sequence generator (ITU-T 0.150)
    poly = [23 5 0];
    shiftreglength = 23;
    initialstateBin = ones(1, shiftreglength);
    maxSize = [2745600 1]; 
    ds = comm.PNSequence('Polynomial',poly,'InitialConditions',initialstateBin, ...
        'Mask',[zeros(1,shiftreglength-1) 1], 'VariableSizeOutput', true, 'MaximumOutputSize', maxSize);
end
%#ok<*NBRAK2>
%#ok<*AGROW>

Related Topics