PDSCH Waveform generation
outPath = fileparts(matlab.desktop.editor.getActiveFilename);
disp(outPath);
/Users/shahab/code/Fireball/OpenSource/onGithub/Tests/Wireless/NewProject/OnGit/neoradium/Playground/CompareWithMatlab/PDSCH/MatlabFiles
Carrier Configuration
Specify the number of transmit antennas and create a carrier configuration object. This object controls the size of the resource grid. For simplicity, use the default carrier configuration object.
carrier = nrCarrierConfig;
carrier.SubcarrierSpacing=30
carrier =
nrCarrierConfig with properties:
NCellID: 1
SubcarrierSpacing: 30
CyclicPrefix: 'normal'
NSizeGrid: 52
NStartGrid: 1
NSlot: 0
NFrame: 0
IntraCellGuardBands: [0×2 double]
Read-only properties:
SymbolsPerSlot: 14
SlotsPerSubframe: 2
SlotsPerFrame: 20
PDSCH and PDSCH DM-RS Configuration
Create a PDSCH configuration object. This object specifies PDSCH-related parameters. Specify 16-QAM modulation, two layers, and full band allocation. This configuration maps the PDSCH into a bandwidth part (BWP) of equal size to the carrier. You can also use this object to specify other time-allocation parameters and DM-RS settings.
pdsch.Modulation = "16QAM";
pdsch.PRBSet = 0:carrier.NSizeGrid-1; % Full band allocation
pdsch.VRBToPRBInterleaving = 1;
pdsch.PRBSetType = "PRB"; % NOTE: Remark out this line if using Matlab 2022b or older
Display the PDSCH and PDSCH DM-RS parameters.
pdsch.DMRS
ans =
nrPDSCHDMRSConfig with properties:
DMRSConfigurationType: 1
DMRSReferencePoint: 'CRB0'
DMRSTypeAPosition: 2
DMRSAdditionalPosition: 0
DMRSLength: 1
CustomSymbolSet: []
DMRSPortSet: []
NIDNSCID: []
NSCID: 0
NumCDMGroupsWithoutData: 2
DMRSDownlinkR16: 0
Read-only properties:
CDMGroups: [0 0]
DeltaShifts: [0 0]
FrequencyWeights: [2×2 double]
TimeWeights: [2×2 double]
DMRSSubcarrierLocations: [6×2 double]
CDMLengths: [2 1]
PDSCH Generation
Generate indices to map the PDSCH to the grid.
[pdschIndices,pdschInfo] = nrPDSCHIndices(carrier,pdsch);
Generate and map random PDSCH bits to PDSCH symbols. The input argument pdschInfo.G specifies the bit capacity of the PDSCH, which is the length of the codeword from the channel coding stages. pdschInfo.G takes into account the resource elements (REs) available for PDSCH transmission. For simplicity, this example does not include downlink shared channel (DL-SCH) modeling.
% Unremark this to generate random bits
pdschBits = randi([0 1],pdschInfo.G,1);
save(strcat(outPath,'/pdschBits.mat'),'pdschBits');
% Load random bits from file for deterministic results
pdschBits = load(strcat(outPath,'/pdschBits.mat')).pdschBits;
Generate PDSCH symbols. The PDSCH symbols are stored in a matrix of size
-by-ν, where
is the number of symbols and ν is the number of layers. pdschSymbols = nrPDSCH(carrier,pdsch,pdschBits);
save(strcat(outPath,'/pdschSymbols.mat'),'pdschSymbols');
pdschSymbols(1:20,1)
-0.3162 + 0.3162i
-0.9487 + 0.9487i
-0.3162 + 0.3162i
0.3162 - 0.3162i
0.9487 - 0.3162i
-0.3162 + 0.9487i
-0.9487 - 0.9487i
0.9487 + 0.3162i
0.9487 + 0.9487i
0.3162 - 0.3162i
PDSCH DM-RS Generation
Generate DM-RS symbols and indices.
dmrsSymbols = nrPDSCHDMRS(carrier,pdsch);
dmrsIndices = nrPDSCHDMRSIndices(carrier,pdsch);
save(strcat(outPath,'/dmrsSymbols.mat'),'dmrsSymbols');
dmrsSymbols(1:10,1)
0.7071 - 0.7071i
0.7071 + 0.7071i
0.7071 - 0.7071i
-0.7071 - 0.7071i
-0.7071 + 0.7071i
0.7071 + 0.7071i
0.7071 + 0.7071i
0.7071 + 0.7071i
0.7071 + 0.7071i
0.7071 + 0.7071i
MIMO Precoding and Mapping to the Resource Grid
Apply precoding. Channel measurements determine the precoding weights (also referred to as beamforming weights). However, this example does not model the propagation channel. This example assumes that the precoding weights are known.
W = fft(eye(nTxAnts))/sqrt(nTxAnts); % Unitary precoding matrix
w = W(1:pdsch.NumLayers,:)/sqrt(pdsch.NumLayers); % Normalize by number of layers
Precode the PDSCH symbols.
pdschSymbolsPrecoded = pdschSymbols*w;
size(pdschSymbolsPrecoded)
Generate an empty resource grid. This grid spans one slot.
pdschGrid = nrResourceGrid(carrier,nTxAnts);
[~,pdschAntIndices] = nrExtractResources(pdschIndices,pdschGrid);
pdschGrid(pdschAntIndices) = pdschSymbolsPrecoded;
Precode and map the DM-RS symbols to the grid. Similar to the PDSCH indices, the DM-RS indices refer to layers. To convert these layers to multiantenna indices, use the nrExtractResources function again.
% PDSCH DM-RS precoding and mapping
for p = 1:size(dmrsSymbols,2)
[~,dmrsAntIndices] = nrExtractResources(dmrsIndices(:,p),pdschGrid);
pdschGrid(dmrsAntIndices) = pdschGrid(dmrsAntIndices) + dmrsSymbols(:,p)*w(p,:);
save(strcat(outPath,'/pdschGrid.mat'),'pdschGrid');
pdschGrid(1:10,1,1)
0.2236 + 0.4472i
-0.2236 + 0.2236i
-0.4472 + 0.2236i
0.4472 + 0.2236i
0.6708 - 0.2236i
0.2236 + 0.2236i
-0.6708 + 0.0000i
0.2236 + 0.4472i
0.4472 + 0.2236i
0.4472 - 0.2236i
Display the resource grid for the first antenna.
imagesc([0 carrier.SymbolsPerSlot-1],[0 carrier.NSizeGrid*12-1],abs(pdschGrid(:,:,1)));
axis xy;title("Resource Grid (First Antenna) - PDSCH and PDSCH DM-RS");
xlabel("OFDM Symbol");ylabel("Subcarrier")
OFDM Modulation
OFDM-modulate the resource grid and display the time-domain waveform for the first antenna.
[txWaveform,waveformInfo] = nrOFDMModulate(carrier,pdschGrid);
save(strcat(outPath,'/txWaveform.mat'),'txWaveform');
txWaveform(1:10,1)
0.0091 + 0.0032i
0.0105 + 0.0007i
-0.0014 + 0.0021i
-0.0019 + 0.0060i
0.0111 + 0.0053i
0.0150 - 0.0004i
0.0033 - 0.0066i
-0.0085 - 0.0111i
-0.0107 - 0.0064i
-0.0072 + 0.0088i
plot(abs(txWaveform(:,1)));title("Time Domain Waveform (First Antenna)");xlabel("Sample Number");ylabel("Magnitude")
The waveformInfo output contains information about the time-domain waveform, such as the sampling rate.