Main Content

ACS Test Waveform Generation for 5G NR Receiver Testing

Since R2024b

This example provides a framework that enables you to generate a waveform for the adjacent channel selectivity (ACS) receiver test, as specified in TS 38.141-1, Section 7.4.1, to test a 5G NR receiver. The framework provides a simplified receiver model for the test. However, you can replace this simplified model by an arbitrary receiver model that measures throughput and EVM.

Introduction

The aim of this example is to provide a framework for you to simulate the ACS test on your receiver model. To illustrate the workflow, the example provides a simplified receiver model that you can replace with your receiver model under test.

The ACS test requires a reference measurement channel, as a signal of interest, and an interference in an adjacent frequency. The example generates these waveforms at an oversampled rate Fs=NFsnom, where N is the oversampling ratio and Fsnom is the nominal sampling rate of the signal of interest. The example then uses the simplified receiver model to measure the EVM and throughput of the received signal. To pass the test, the receiver under tests must have a throughput greater than or equal to 95% of the maximum throughput of the reference measurement channel.

The addition of reference measurement channel and interference is fed to the receiver under test.

Set Waveform Parameters

Select a reference measurement channel from TS 38.141-1, Table 7.2.5-1. The example displays the valid bandwidth and subcarrier spacing values for the selected reference channel.

signalDefinition.ulnrref = "G-FR1-A1-1";
ACSTestExampleHelpers.displayBWSCS(signalDefinition.ulnrref)
Possible BW for G-FR1-A1-1: [5 10 15] (MHz)
Possible SCS for G-FR1-A1-1: 15 (kHz)

Specify the bandwidth and subcarrier spacing.

signalDefinition.BW  = 5;        % Bandwidth (MHz)
signalDefinition.SCS = 15;        % Subcarrier spacing (kHz)

Specify the value of reference sensitivity power level (Prefsens) in dBm. Prefsens is a function of the reference measurement channel and the carrier frequency for a wide area base station, as defined in TS 38.141-1, Table 7.2.5-1.

ACSTestExampleHelpers.displayValidSensitivityPowerLevels();
    Ref. channel    Prefsens (dBm) f<=3 GHz    Prefsens (dBm) 3 GHz<f<=4.2 GHz    Prefsens (dBm) 4.2<f<=6 GHz
    ____________    _______________________    _______________________________    ___________________________

    "G-FR1-A1-1"              -101                         -100.7                           -100.5           
    "G-FR1-A1-2"            -101.1                         -100.8                           -100.6           
    "G-FR1-A1-3"             -98.2                          -97.9                            -97.7           
    "G-FR1-A1-4"             -94.6                          -94.3                            -94.1           
    "G-FR1-A1-5"             -94.9                          -94.6                            -94.4           
    "G-FR1-A1-6"               -95                          -94.7                            -94.5           
signalDefinition.Prefsens = -101;    % dBm

Specify the duplexing mode and the resource block (RB) allocation offset.

signalDefinition.dm       = "FDD";    % Duplexing mode
signalDefinition.rbOffset = 0;    % RB offset (allocation offset)
ACSTestExampleHelpers.validateParameters(signalDefinition);
Reference measurement channel: G-FR1-A1-1
Modulation: QPSK
Bandwidth (RBs): 25
Allocated RBs: 25
RB offset: 0

Specify the simulation length in number of frames to calculate the throughput.

simulationLengthInFrames = 5;      % Number of frames to simulate

Calculate Sampling Rate

Calculate the sampling rate of the signal of interest and the interference. Both signals are sampled at the same rate, Fs=NFsnom, before aggregation. N is the oversampling ratio. Fsnom is the nominal sampling rate of the signal of interest and is a function of the bandwidth and subcarrier spacing of the signal of interest.

Specify the oversampling ratio as a power of two. The filtering stages of the simplified receiver model requires the oversampling ratio to be at least 8. If necessary, adjust this value according to your receiver model.

N = 16; % Oversampling ratio

Calculate the sampling rate, Fs. The calculateFs helper function performs the following operations:

  • Checks that the bandwidth and subcarrier spacing combination is defined according to TS 38.101-1, Tables 5.3.2-1 and 5.3.2-2.

  • Checks that the oversampling ratio, N, is a power of two equal to or greater than 8.

  • Calculates the nominal sampling rate of the signal of interest, Fsnom, and checks that Fs=NFsnom is sufficient to represent the aggregation of the signal of interest and the interference.

  • Calculates the center frequency offset of the interfering signal from the center of the signal of interest band, iFoffset, as specified in TS 38.141-1, Table 7.4.1.5-2.

[Fs,iFoffset] = ACSTestExampleHelpers.calculateFs(signalDefinition.BW,signalDefinition.SCS,N);
Fs = 122.88 MHz = 16*7.68 MHz
Fs_nominal = 7.68 MHz
BW = 5 MHz. iBW = 5 MHz
iFoffset = 5.0025 MHz

Generate Signal of Interest and Interference

Generate the signal of interest at the sampling rate Fs and with the required power.

rng("default")                                 % Reset the random number generator
numSubframes = 10*simulationLengthInFrames+1;  % Add an extra subframe to allow for delay caused by filters
[waveform,carrier,pusch,puschExt,frcResourceInfo] =  ACSTestExampleHelpers.generateSignalOfInterest(signalDefinition,Fs,numSubframes);
disp("Signal power: "+(10*log10(rms(waveform)^2)+30)+" dBm")
Signal power: -95 dBm

Generate the interfering signal, as defined in TS 38.141-1, Table 7.4.1.5-2. This interference has the same sampling rate and length as the signal of interest.

powerInterf = ACSTestExampleHelpers.getInterferencePowerLevel();
[interfWaveform,interfDefinition]= ACSTestExampleHelpers.generateInterference(signalDefinition.BW,numSubframes,Fs,powerInterf);
disp("Interference power: "+(10*log10(rms(interfWaveform)^2)+30)+" dBm")
Interference power: -52 dBm

Combine Signal of Interest and Interference

Use the multiband combiner to apply a frequency offset to the interfering signal. Then add the interfering signal to the signal of interest. Both signals are sampled at the same rate of Fs Hz.

sigAggregator = comm.MultibandCombiner(InputSampleRate = Fs, ...
    FrequencyOffsets = [0 iFoffset], OutputSampleRateSource = 'Property', ...
    OutputSampleRate = Fs);
aggregatedWaveform = sigAggregator([waveform interfWaveform]);

% Plot spectrum of aggreggated signal
 saCombined = spectrumAnalyzer("SampleRate",Fs,"Title","Aggregated Waveform");
 saCombined(aggregatedWaveform);

Simplified Receiver Model

The simplified receiver model of this example adds thermal noise, then performs the filtering and resampling stages. The sampling rate of the resulting signal is Fsnom.

The simplified receiver model consists of thermal noise, two cascaded half-band filters, and a resampling stage with a lowpass filter.

The digital front-end model includes:

  • Two cascaded identical halfband filters to decrease the sampling rate by a factor of 4.

  • FIR lowpass filter to decrease the sampling rate to Fsnom.

You can replace this simplified model by your receiver model and study the effect the receiver has on the throughput and EVM of the decoded signal.

Design the receiver filters.

[halfbandDecimator1,halfbandDecimator2,firFilter] = ACSTestExampleHelpers.designFilters(carrier,Fs,interfDefinition,iFoffset);

Display the FIR filter response.

filterAnalyzer(firFilter,SampleRates=Fs/4,FilterNames="FIR", Analysis="magnitude",OverlayAnalysis="phase")

Create the thermal noise object and apply noise to the received signal.

noiseFloor = comm.ThermalNoise("NoiseMethod","Noise temperature","NoiseTemperature",290,"SampleRate",Fs);
rxWaveform = noiseFloor(aggregatedWaveform);

Apply halfband filters and visualize the spectrum of the resulting signal.

filteredWaveform = halfbandDecimator1(rxWaveform);
filteredWaveform = halfbandDecimator2(filteredWaveform);

% Spectrum analyzer to visualize output of halfband filters
saHalfBand = spectrumAnalyzer("SampleRate",Fs/4,"Title","Halfband Filters Output");
saHalfBand(filteredWaveform);

Apply FIR filtering and visualize the spectrum of the resampled signal.

% FIR filering and resampling stage
filteredWaveform  = resample(filteredWaveform,1,N/4,firFilter.Numerator);
% Normalise received signal
filteredWaveform = filteredWaveform/(rms(filteredWaveform));

% Spectrum analyzer to visualize output of FIR filter
saResampled = spectrumAnalyzer("SampleRate",Fs/N,"Title","Resampled Signal");
% Plot spectrum of filtered signal
saResampled(filteredWaveform);

Synchronize and apply OFDM demodulation.

% Synchronize
timingOffset = nrTimingEstimate(carrier,filteredWaveform,frcResourceInfo.ResourceGrids.ResourceGridBWP,"SampleRate",Fs/N);
filteredWaveform = filteredWaveform(1+timingOffset:end,:);  

% OFDM Demodulation
carrier.NFrame = 0;
carrier.NSlot = 0;
rxGrid = nrOFDMDemodulate(carrier,filteredWaveform,"SampleRate",Fs/N);

Decode all slots, then measure the throughput and the EVM of the received signal.

% Number of symbols per slot
symPerSlot = frcResourceInfo.ResourceGrids.Info.SymbolsPerSlot;
% Number of slots in signal of interest, ignore the last slot as it may not
% be complete due to delay in the filters
numSlots = numSubframes*frcResourceInfo.ResourceGrids.Info.SlotsPerSubframe-1;

% Create DL-SCH object
decodeULSCH = nrULSCHDecoder;
decodeULSCH.TargetCodeRate = puschExt.TargetCodeRate;
decodeULSCH.LDPCDecodingAlgorithm = 'Normalized min-sum';

% Initialize variables and storage
txedTrBlkSizes = [];                % Vector of transport block sizes
slotThPut = [];                     % Instantaneous throughput per slot
runningSimThPut = nan(1,numSlots);  % Accumulated throughput per slot
runningMaxThPut = nan(1,numSlots);  % Accumulated maximum throughput per slot
symIdx = 1;                         % OFDM symbol index

% EVM object
evm = comm.EVM();
evmV = [];  % vector of EVM values

% List of active slots for TDD
activeSlots = [frcResourceInfo.WaveformResources.PUSCH.Resources.NSlot];

% Process all slots, skip the last slot, it may not be complete due to delay in the filters
for slotNum = 0:numSlots-1

    % Extract slot of interest
    gridSlot = rxGrid(:,symIdx:symIdx+symPerSlot-1,:); 

    if any(activeSlots == slotNum) % skip inactive slots
        carrier.NSlot = slotNum;   % new slot number

        % DM-RS and PUSCH resources for current slot (used for channel estimation)
        resIdx = find(activeSlots == slotNum); % resources index
        dmrsIndices = frcResourceInfo.WaveformResources.PUSCH.Resources(resIdx).DMRSIndices;
        dmrsSymbols = frcResourceInfo.WaveformResources.PUSCH.Resources(resIdx).DMRSSymbols;
        puschIndices= frcResourceInfo.WaveformResources.PUSCH.Resources(resIdx).ChannelIndices;
        puschSymbols=frcResourceInfo.WaveformResources.PUSCH.Resources(resIdx).ChannelSymbols;
        trBlkSize = frcResourceInfo.WaveformResources.PUSCH.Resources(resIdx).TransportBlockSize;

        % Channel estimation
        [estChannelGrid,noiseEst] = nrChannelEstimate(carrier,gridSlot,dmrsIndices,dmrsSymbols,'CDMLengths',frcResourceInfo.WaveformResources.PUSCH.CDMLengths);

        % Get PDSCH resource elements from the received grid and channel estimate
        [puschRx,puschHest] = nrExtractResources(puschIndices,gridSlot,estChannelGrid);

        % Equalization
        [puschEq,csi] = nrEqualizeMMSE(puschRx,puschHest,noiseEst);

        % EVM measurement
        evmV = [evmV evm(puschEq,puschSymbols)];

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

        % Appply csi (scale ulsch LLRs)
        csi = nrLayerDemap(csi);
        Qm = length(ulschLLRs) / length(rxSymbols);
        csi = reshape(repmat(csi{1}.',Qm,1),[],1);
        ulschLLRs = ulschLLRs .* csi;

        % Decode the UL-SCH transport channel
        decodeULSCH.TransportBlockLength = trBlkSize;
        [decbits,blkerr] = decodeULSCH(ulschLLRs,pusch.Modulation,pusch.NumLayers,puschExt.RVSequence);
        decodeULSCH.resetSoftBuffer(); % No HARQ, reset buffer manually
        if blkerr
            disp("CRC error in slot: "+slotNum)
        end

        % Store results
        if any(trBlkSize) % only for slots with data
            txedTrBlkSizes = [txedTrBlkSizes trBlkSize];
            slotThPut = [slotThPut trBlkSize.*(1-blkerr)];
        end
        runningSimThPut(slotNum+1) = sum(slotThPut,2);
        runningMaxThPut(slotNum+1) = sum(txedTrBlkSizes,2);
    end
    % Update OFDM symbol index
    symIdx = symIdx+symPerSlot;
end

Display Results

Plot the accumulated throughput and display the final throughput and EVM values.

% Plot running throughput
figure; plot(runningSimThPut*100./runningMaxThPut,'.-')
ylabel('Throughput (%)');
xlabel('Slot');
title('Throughput');
grid on; hold on
idx1 = find(~isnan(runningSimThPut),1,'last');
idx2 = find(~isnan(runningMaxThPut),1,'last');
finalThroughput = runningSimThPut(idx1)*100./runningMaxThPut(idx2);
plot([1 length(runningSimThPut)],finalThroughput*[1 1],'x:')
legend("Throughput","Final throughput")

Figure contains an axes object. The axes object with title Throughput, xlabel Slot, ylabel Throughput (%) contains 2 objects of type line. These objects represent Throughput, Final throughput.

disp("Final throughput: "+finalThroughput+"%")
Final throughput: 100%
disp("EVM post equalization: "+evmV(end)+" %")
EVM post equalization: 32.424 %

The EVM degradation is primarily due to the aliasing of the interfering signal after filtering and resampling. However, the EVM degradation does not affect the overall throughput because the QPSK modulation of the signal of interest, combined with the LDPC decoding, ensures that the decoded signal is robust against errors.

See Also

Functions