NR V2X Sidelink PSCCH and PSSCH Throughput
This reference simulation measures the link-level throughput and BLER of the NR V2X physical sidelink control channel (PSCCH) and physical sidelink shared channel (PSSCH), including sidelink control information (SCI) and SL-SCH transport channel coding.
Introduction
Release 16 of the 3GPP NR specification introduces the sidelink PC5 interface to the 5G mobile system, specifically for cellular V2X applications. This addition to NR extends the range of use cases that were previously supported by LTE V2X, for example, to include advanced and remote driving scenarios and platooning.
In terms of 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), whereby 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. Unlike LTE, the NR sidelink can support HARQ feedback for unicast and groupcast communications via the physical sidelink feedback channel (PSFCH).
In terms of 3GPP test specification, the NR sidelink channel minimum performance requirements are defined in TS 38.101-4 and the conformance performance specifications are defined in TS 38.521-4. This reference simulation is set up to perform the PSSCH demodulation requirement tests described in TS 38.101-4 Section 11.1.2. However, the example can be parameterized for an arbitrary resource pool and PSSCH configuration. In addition to measuring PSSCH throughput, the simulation also calculates the SCI1 (PSCCH) and SCI2 BLER.
For LTE sidelink link-level simulations, D2D and V2X, see Sidelink Channels (LTE Toolbox) in the LTE Toolbox™ documentation.
Simulation Configuration
This simulation uses the MATLAB® class, NRSidelinkResourcePool
, to define an NR sidelink resource pool within a BWP in an SCS carrier. 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, and provides a method to receive PSCCH and PSSCH in the resource pool. In addition, the class has methods which 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.
All TS 38.101-4 PSSCH demodulation tests use a resource pool configured with PSFCH resources on a four-slot periodicity. The tests do not use any HARQ retransmissions. However, the simulation allows you to enable both closed-loop and open-loop blind HARQ retransmissions. For closed-loop HARQ, the ACK-NACK error result is fed back to the transmitting process immediately and there is no signalling latency.
The simulation supports both TDL and CDL propagation channel models as well as perfect and DM-RS-based channel estimation. The simulation runs for a small number of slots. For accurate BLER results, however, increase the number of slots.
To reduce the total simulation time, you can execute the SNR points in the SNR loop in parallel by using parfor
from the Parallel Computing Toolbox™ product.
% Use the PSSCH RMC test configurations as initial parameter templates for the simulation, % TS 38.101-4 Section 11, V2X requirements and A.6, SL reference measurements channels % Select PSSCH demodulation test % 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, TDLA30-2700 % 'R.PSSCH.2-1.2' - 20 PRB (2 subchannels), 16QAM, TCR=378/1024, TDLA30-1400 % 'R.PSSCH.2-1.3' - 10 PRB (1 subchannel), 64QAM, TCR=438/1024, TDLA30-180 rmc = "R.PSSCH.2-1.1"; % RMC and test selection bwscs = [20 30]; % Release 16 NR sidelink is specified to operate in FR1 at 10, 20, 30, 40 MHz BW % Get PSCCH/PSSCH channel and sidelink pool parameters bw = bwscs(1); scs = bwscs(2); [sltransmission,pool,testconfig] = NRSidelinkResourcePool.rmcTestConfiguration(rmc,bw,scs); % Reconfigure any required pool and channel parameters here for the throughput/BLER simulation % For example: % pool.sl_PSFCH_Period_r16 = 0; % Uncomment to turn off PSFCH symbol reservation in the resource pool (in terms of L3 protocol, no HARQ enabled in the pool) % Visually crosscheck the PSCCH and PSSCH transmission resources configured for simulation pool
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
sltransmission
sltransmission = struct with fields:
SubchannelAllocation: [0 2]
NumLayers: 1
Modulation: 'QPSK'
NumDMRSPositions: 4
NumDMRSPositionsList: [3 4]
TargetCodeRate: 0.3008
BetaSCI2Offset: 3.5000
OSCI2: 35
NXID: []
RedundancyVersion: 0
HARQProcessID: 0
PSFCHOverhead: 0
OSCI1: 26
displayTransmissionResources(pool,sltransmission);
% Define all top-level simulation parameters in a single 'simParameters' structure simParameters = struct(); simParameters.Pool = pool; simParameters.SLTransmission = sltransmission; % From TS 38.101-4 Section 11, V2X requirements tests % Reconfigure the propagation channel parameters, as required simParameters.DelayProfile = testconfig.DelayProfile; simParameters.MaximumDopplerShift = testconfig.MaximumDopplerShift; % Antenna geometry simParameters.NTxAnts = sltransmission.NumLayers; simParameters.NRxAnts = 2; % Simulation length parameters simParameters.SNRIn = testconfig.ReferenceSNR + (-5:5); % Create an SNR range around the test target reference SNR simParameters.NumSlots = 100; % Number of transmission slots to simulate, per SNR point % HARQ-related parameters simParameters.NHARQProcesses = max(1,pool.sl_PSFCH_Period_r16); % Number of independent parallel HARQ processes to simulate (up to 16 processes available (4 bits available for HARQ ID in SCI2)) simParameters.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) simParameters.BlindHARQ = 0; % Enable blind open-loop retransmissions, according to the above specified RV sequence % General algorithmic parameters simParameters.PerfectChannelEstimator = 1; % Use perfect channel estimate; otherwise, use a DM-RS-based estimate simParameters.NXIDPassthrough = 1; % Pass the transmission PSSCH scrambling NXID value directly to the receiver % Simulation diagnostics simParameters.DisplaySimulationInformation = 0; % Display information about each transmission event
% Create and configure the propagation channel model object for the simulation if contains(simParameters.DelayProfile,'CDL','IgnoreCase',true) propchannel = nrCDLChannel('DelayProfile',simParameters.DelayProfile); % CDL uses the antenna panel array sizing, rather than just the total number of antennas, so conversion is required [propchannel.TransmitAntennaArray,simParameters.NTxAnts] = ueArrayGeometry(propchannel.TransmitAntennaArray,simParameters.NTxAnts); [propchannel.ReceiveAntennaArray,simParameters.NRxAnts] = ueArrayGeometry(propchannel.ReceiveAntennaArray,simParameters.NRxAnts); else propchannel = nrTDLChannel('DelayProfile',simParameters.DelayProfile); propchannel.NumTransmitAntennas = simParameters.NTxAnts; % Configure the number of transmit antennas for the transmitting UE propchannel.NumReceiveAntennas = simParameters.NRxAnts; % Configure the number of receive antennas for the receiving UE end propchannel.MaximumDopplerShift = simParameters.MaximumDopplerShift; waveinfo = getWaveformInfo(simParameters.Pool); % Get details of the OFDM baseband IQ that will be transmitted in the pool propchannel.SampleRate = waveinfo.SampleRate; % Align propagation channel with sample rate of baseband transmission
% Start of main BLER simulation body % Array to store the maximum SL-SCH throughput for all SNR points maxThroughput = zeros(length(simParameters.SNRIn),1); % Array to store the simulation SL-SCH throughput for all SNR points simThroughput = zeros(length(simParameters.SNRIn),1); % Record the control/data information block errors for each SNR point simEtotals = repmat(struct('SCI1',0,'SCI2',0,'SLSCH',0,'TxCount',0),1,length(simParameters.SNRIn)); % Set up SL-SCH transport channel processing slschtxProto = nrULSCH("MultipleHARQProcesses",true); % SL-SCH transport channel encoder (same processing as UL-SCH, but with I_BIL = 0 always) slschrxProto = nrULSCHDecoder("MultipleHARQProcesses",true,'LDPCDecodingAlgorithm','Normalized min-sum'); % SL-SCH decoder % Use fixed target code rate for all processes and throughout the simulation slschtxProto.TargetCodeRate = simParameters.SLTransmission.TargetCodeRate; slschrxProto.TargetCodeRate = simParameters.SLTransmission.TargetCodeRate; % Loop through each SNR point in overall simulation for snrIdx = 1:numel(simParameters.SNRIn) % Serializing the execution of the SNR points % parfor snrIdx = 1:numel(simParameters.SNRIn) % Uncomment to parallelize the SNR points using the Parallel Computing Toolbox parfor % Accessing properties in objects/structures defined outside of the parfor body % may result in broadcast variable warnings, so take a local copy of the entire variable simParametersLocal = simParameters; % Using a locally created copy of the pool ensures that the pool state (e.g., current slot number) % starts the same for each SNR point run pool = simParametersLocal.Pool; pool.SCSCarrier.NSlot = 0; % Take a copy of the PSCCH/PSSCH transmission parameters for ease of reference sltransmission = simParametersLocal.SLTransmission; % Take a copy of the transport encoder/decoder handles to help PCT with classification of variables slschtx = slschtxProto; slschrx = slschrxProto; reset(slschrx); % Reset SL-SCH decoder at the start of each SNR point (explicitly required for serial 'for' loop) % Get the SNR value for this run SNRdB = simParametersLocal.SNRIn(snrIdx); % Print summary of overall configuration for this run fprintf('\nSimulating PSCCH/PSSCH at %gdB SNR (%d/%d) with %s-%d channel (%dx%d) for %d slots \n', ... SNRdB,snrIdx,numel(simParametersLocal.SNRIn), ... simParametersLocal.DelayProfile,simParametersLocal.MaximumDopplerShift,simParametersLocal.NTxAnts,simParametersLocal.NRxAnts, ... simParametersLocal.NumSlots); % Reset the random number generator so that each SNR point experiences % the same noise realization rng(0,'twister'); % Reset the propagation channel state so that each SNR point experiences % the same channel realization reset(propchannel); % Get local copy of info about the baseband waveform to be simulated waveinfo = getWaveformInfo(pool); % Use a locally created SL-SCH HARQ entity object to ensure independence between SNR points % This object controls the use and HARQ scheduling of the SL-SCH transport encoder harqEntity = HARQEntitySL(0:simParametersLocal.NHARQProcesses-1,simParametersLocal.RVSequence,1,simParametersLocal.BlindHARQ); % Up to 16 processes available (4 bits for HARQ ID in SCI2) % Record the control/data information block errors for this SNR point etotals = simEtotals(snrIdx); % Simulation loop for a single SNR point for nslot=1:simParametersLocal.NumSlots % Prepare transport/control data for transmission % PSFCH slot related adjustments to the PSSCH transmission parameters sltransmission.PSFCHOverhead = pool.IsPSFCHSlot; if pool.IsPSFCHSlot && ~isempty(sltransmission.NumDMRSPositionsList) sltransmission.NumDMRSPositions = min(sltransmission.NumDMRSPositionsList); else sltransmission.NumDMRSPositions = max(sltransmission.NumDMRSPositionsList); end % SL-SCH transport data if harqEntity.NewData % Is this a new data opportunity for the current process? % Calculate the SL-SCH TBS from the transmission and pool parameters tbs = getTBS(pool,sltransmission); % Transmit side SL-SCH preparation trBlk = randi([0 1],tbs,1); setTransportBlock(slschtx,trBlk,harqEntity.HARQProcessID); % Receive side SL-SCH preparation slschrx.TransportBlockLength = tbs; resetSoftBuffer(slschrx,harqEntity.HARQProcessID); % Reset the process soft buffer if transmitting new data on latest process end % Update dynamic transmission parameters for the SL-SCH part on PSSCH transmission sltransmission.HARQProcessID = harqEntity.HARQProcessID; sltransmission.RedundancyVersion = harqEntity.RedundancyVersion; sltransmission.NXID = []; % Ensure there is no external overridding of the PSSCH NXID value in the transmission % SCI1 and SCI2 data % % 1st-stage SCI information bits for PSCCH sci1infobits = randi([0 1],sltransmission.OSCI1,1); % 2nd-stage SCI information bits for transmission on PSSCH, multiplexed with SL-SCH data sci2infobits = randi([0 1],sltransmission.OSCI2,1); % Transmit PSCCH/PSSCH in the resource pool (baseband) % Input is the separate control information bits (SCI1 and SCI2) and transport channel processing object % Output is the slot waveform, plus intermediate processing symbols and resource information [basebandiq,sld,slo] = transmitInPool(pool,sltransmission,sci1infobits,sci2infobits,slschtx); % Pass baseband waveform through propagation channel [basebandiq,pathGains,sampleTimes] = propchannel(basebandiq); % Add AWGN to the received time domain waveform % Normalize noise power 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(size(basebandiq,2)*double(waveinfo.Nfft)*SNR); noise = N0*randn(size(basebandiq),"like",basebandiq); basebandiq = basebandiq + noise; % Parameterize the decoder algorithm decalgo = struct('PerfectChannelEstimator',simParametersLocal.PerfectChannelEstimator, ... % Control whether to use perfect or DM-RS-based channel estimation 'DecodeSLSCH',~harqEntity.TransmissionSuccess); % Control whether to decode the SL-SCH transport block if decalgo.PerfectChannelEstimator % If perfect channel estimation, then use the value of the path gains % provided by the propagation channel pathFilters = getPathFilters(propchannel); % Get path filters for perfect channel estimation decalgo.estChannelGrid = nrPerfectChannelEstimate(pool.SCSCarrier,pathGains,pathFilters,0,sampleTimes); % Get perfect noise estimate (from the noise realization) noiseGrid = nrOFDMDemodulate(pool.SCSCarrier,noise); decalgo.noiseEst = var(noiseGrid(:)); end % Pass the transmitted PSCCH NXID value to the receiver, if required % This operation allows the PSSCH decoding to be independent of the PSCCH decoding success if simParametersLocal.NXIDPassthrough sltransmission.NXID = sld.NXID; end % Receive the transmission in the current slot of the pool [eset,sldr,slor] = receiveInPool(pool,sltransmission,basebandiq,slschrx,decalgo); % Accumulate the transmission block error results for efn = string(fieldnames(eset))' em = eset.(efn); if (efn=="SLSCH") && (harqEntity.TransmissionNumber == harqEntity.MinNumTransmissions-1) % Is this the first SL-SCH transmission event for error accounting % Record error if this transmission is in error and there have been no passes before on the open process % and then scale error count so that it aligns with overall TxCount em = (em && ~harqEntity.TransmissionSuccess)*harqEntity.MinNumTransmissions; end etotals.(efn) = etotals.(efn) + em; % Accumulate error status into error total end etotals.TxCount = etotals.TxCount + 1; % Keep a total event count, needed for the block error rate % Get the SL-SCH reception result for SL-SCH transmit HARQ management blkerr = eset.SLSCH; G = slo.PSSCHG(2); % G is bit capacity (codeword size) of transmission resources for SL-SCH on PSSCH % Update current HARQ process state with the results of the associated SL-SCH/PSSCH transmission % and advance to next process tbs = length(getTransportBlock(slschtx,harqEntity.HARQProcessID)); slschrxreport = updateAndAdvance(harqEntity,blkerr,tbs,G); % Print out transmission status if simParameters.DisplaySimulationInformation etext = ["passed" "FAILED"]; fprintf('\n%s %s %s %s', ... pad(sprintf('(%3.2f%%)',100*nslot/simParametersLocal.NumSlots),9), ... % Percentage of simulate complete pad(sprintf('NSlot=%d,',pool.SCSCarrier.NSlot),10), ... % Absolute slot number sprintf('SCI1=%s, SCI2=%s,',etext(1+eset.SCI1),etext(1+eset.SCI2)), ... % SCI error status slschrxreport); % SL-SCH HARQ information end % Move on to next available slot in the resource pool [pool,nslotsadvanced] = advanceToNextSlot(pool); end % For the current SNR point, % record the control/data information block errors simEtotals(snrIdx) = etotals; % Store values to calculate SL-SCH throughput simThroughput(snrIdx) = harqEntity.SuccessfulBitsAllProcesses; maxThroughput(snrIdx) = harqEntity.TotalBitsAllProcesses; end
Simulating PSCCH/PSSCH at -1.6dB SNR (1/11) with TDLA30-2700 channel (1x2) for 100 slots Simulating PSCCH/PSSCH at -0.6dB SNR (2/11) with TDLA30-2700 channel (1x2) for 100 slots Simulating PSCCH/PSSCH at 0.4dB SNR (3/11) with TDLA30-2700 channel (1x2) for 100 slots Simulating PSCCH/PSSCH at 1.4dB SNR (4/11) with TDLA30-2700 channel (1x2) for 100 slots Simulating PSCCH/PSSCH at 2.4dB SNR (5/11) with TDLA30-2700 channel (1x2) for 100 slots Simulating PSCCH/PSSCH at 3.4dB SNR (6/11) with TDLA30-2700 channel (1x2) for 100 slots Simulating PSCCH/PSSCH at 4.4dB SNR (7/11) with TDLA30-2700 channel (1x2) for 100 slots Simulating PSCCH/PSSCH at 5.4dB SNR (8/11) with TDLA30-2700 channel (1x2) for 100 slots Simulating PSCCH/PSSCH at 6.4dB SNR (9/11) with TDLA30-2700 channel (1x2) for 100 slots Simulating PSCCH/PSSCH at 7.4dB SNR (10/11) with TDLA30-2700 channel (1x2) for 100 slots Simulating PSCCH/PSSCH at 8.4dB SNR (11/11) with TDLA30-2700 channel (1x2) for 100 slots
Results
Display the SL-SCH throughput, relative to the maximum possible for the link, and the SCI1, SCI2, and SL-SCH BLER.
plotResults(simParameters,simEtotals,simThroughput,maxThroughput);
Local Functions
function [antArray,nants] = ueArrayGeometry(antArray,nUeAnts) % Turn scalar 'number of antennas' into an antenna panel/panel array dimensions % The target panel array is a single panel comprising a row of antenna elements % of dual polarization (when the number of antennas specified is greater that 1) % % The antenna array is defined in terms of the number of rows and columns of a single antenna panel, % the number of polarizations, and the number of rows and columns in the overall array of individual panels arraySize = [ceil(nUeAnts/2),1,1+(nUeAnts>1),1,1]; nants = prod(arraySize); % Final number of antenna elements in overall array antArray.Size = arraySize; antArray.Element = 'isotropic'; end function plotResults(simParameters,simEtotals,simThroughput,maxThroughput) % Display simulation BLER and throughput results in a new figure figure; channelestlabel = ["Practical" "Perfect"]; sgtitle(sprintf('PSCCH/PSSCH Performance (%s, %s-%d, %dx%d)',channelestlabel(1+logical(simParameters.PerfectChannelEstimator)),simParameters.DelayProfile,simParameters.MaximumDopplerShift,simParameters.NTxAnts,simParameters.NRxAnts)); epn = 1; [snrlb, snrub]=bounds(simParameters.SNRIn); % Plot the BLER for SCI1, SCI2, and SL-SCH for efn = string(fieldnames(simEtotals))' subplot(2,2,epn); semilogy(simParameters.SNRIn,[simEtotals.(efn)]./[simEtotals.TxCount],'o'); if snrub > snrlb ax = axis; axis([snrlb snrub ax(3:4)]); % Fix the range of the SNR x-axis (semilogy might have rescaled it for SNR points with no errors) end grid on; xlabel('SNR (dB)'); ylabel('Block Error Rate'); title(strcat(efn,' BLER')); epn = epn + 1; end % Plot throughput for SL-SCH plot(simParameters.SNRIn,simThroughput*100./maxThroughput,'o-.') if snrub > snrlb ax = axis; axis([snrlb snrub ax(3:4)]); % Fix the range of the SNR x-axis end grid on; xlabel('SNR (dB)'); ylabel('Throughput (%)'); title('SLSCH Throughput'); % Reannotate the SL-SCH plots with the TCR and modulation for i = [3 4] subplot(2,2,i) subtitle(sprintf('TCR = %.3f, Mod = %s',simParameters.SLTransmission.TargetCodeRate,simParameters.SLTransmission.Modulation)); end % Reannotate the SCI2 plot with the beta offset value subplot(2,2,2) subtitle(sprintf('TCR = %.3f, Beta = %.3f',simParameters.SLTransmission.TargetCodeRate,simParameters.SLTransmission.BetaSCI2Offset)); end %#ok<*NBRAK2>
Related Examples
More About
- Sidelink Channels (LTE Toolbox)