Physical Channels
Physical Downlink Shared Channel
The module pdsch.py implements the PDSCH class which encapsulates the Physical Downlink Shared Channel.
It is a downlink channel that delivers user data from gNB to UE. PDSCH occupies a grid of Resource Blocks (RBs) within
a slot. Usually, one or more OFDM symbols are used by the PDCCH, and the remaining resources are available for the
PDSCH.
The gNB schedules PDSCH resources for UEs based on their channel quality, data requirements, and fairness considerations. PDSCH uses LDPC (Low-Density Parity-Check) coding to provide forward error correction, enhancing the robustness of data transmission over the wireless channel.
In Multiple Input, Multiple Output (MIMO) systems, a PDSCH is distributed among multiple layers. PDSCH includes
Demodulation Reference Signals (DMRS) to assist the UE in channel estimation and
demodulation, ensuring accurate data reception. It may also include Phase Tracking Reference Signals
(PTRS) which enable suppression of phase noise and common phase error, particularly
important at high carrier frequencies such as millimeter-wave bands.
- class neoradium.pdsch.PDSCH(bwp, **kwargs)
This class encapsulates the configuration and functionality of a Physical Downlink Shared Channel (PDSCH), that delivers user data transmitted from gNB to UE.
- Parameters:
bwp (
BandwidthPart) – TheBandwidthPartobject that represents the resources used by thisPDSCHfor transmission of user data from gNB to UE.kwargs (dict) –
A set of optional arguments.
- mappingType:
The mapping type used by this PDSCH and its associated
DMRSobject. It is a text string that can be either'A'or'B'. The default is'A'.In mapping type
'A', the first DMRS OFDM symbol index is 2 or 3 and DMRS is mapped relative to the start of slot boundary, regardless of where in the slot the actual data transmission starts. The user data in this case usually occupies most of the slot.In mapping type
'B', the first DMRS OFDM symbol is the first OFDM symbol of the data allocation, that is, the DMRS location is not given relative to the slot boundary but relative to where the user data is located. The user data in this case usually occupies a small fraction of the slot to support very low latency.- numLayers:
The number of transmission layers for this
PDSCH. It must be an integer from 1 to 8, with 1 as the default.- modulation:
A text string or a tuple or list of 2 text strings specifying the modulation scheme used for data transmitted in this
PDSCHbased on 3GPP TR 38.211, Table 7.3.1.2-1. The default is'16QAM'. Here is a list of supported modulation schemes:Modulation Scheme
Modulation Order (
qm)BPSK
1
QPSK
2
16QAM
4
64QAM
6
256QAM
8
1024QAM
10
If
modulationis a text string and there are two codewords in thisPDSCH, the same modulation scheme is used for both codewords. If there are two codewords in thisPDSCH, and you want to use different modulation schemes for the two codewords, you can specify two different modulation schemes in a tuple or list of text strings. For example:# Using "QPSK" for the first codeword and "16QAM" for the second codeword modulation = ("QPSK", "16QAM")
The specified modulation scheme(s) are used to create one or two
Modemobjects.- reservedRbSets:
A list of
ReservedRbSetobjects that are used to reserve the specified resource blocks (RBs) at the specified OFDM symbols based on the patterns defined in theReservedRbSetobjects. The default is an empty list which means no reserved RBs.- reservedReMap:
The map of additional reserved resource elements (REs) as a 3D list of the form
portNo x symNo x reNo. The default is an empty list which means no reserved REs. The following additional rules makes configuring reserved REs both easy and flexible.If
reservedReMaphas data for only one port, it means that the map is the same for all ports.If in a port, the reserved REs are given only for a single symbol, it is assumed the same REs are reserved in all symbols.
Here are some examples:
# REs 5, 17, and 29 are reserved on all ports and all symbols reservedReMap = [[[5,17,29]]] # REs 5, 17, and 29 are reserved on all ports for OFDM symbol 2 only reservedReMap = [[ [], [], [5,17,29], [], [], [], [], [], [], [], [], [], [], [] ]] # REs 5, 17, and 29 are reserved on all symbols of port index 1 (assuming we have 3 ports) reservedReMap = [[], [[5,17,29]], []]
- sliv:
Start and Length Indicator Value. If specified, it is used to determine the start and length of consecutive OFDM symbols used by this
PDSCHbased on 3GPP TS 38.214, Section 5.1.2.1. The default is None. See Specifying the OFDM symbols below for more information.- symStart:
The index of the first OFDM symbol used for this
PDSCH. The default is None. See Specifying the OFDM symbols below for more information.- symLen:
The number of consecutive OFDM symbols used by this
PDSCHstarting atsymStart. The default is None. See Specifying the OFDM symbols below for more information.- symSet:
A list of OFDM symbol indices that are used by this
PDSCH. See Specifying the OFDM symbols below for more information.- prbSet:
The list of physical resource blocks (PRBs) used by this
PDSCH. The default is all the RBs in theBandwidthPartobjectbwp.- interleavingBundleSize:
The bundle size of interleaving process. It can be one of 0 (default), 2, or 4. The value 0 means interleaving is disabled (default). See 3GPP TS 38.211, Section 7.3.1.6 for more information.
- rnti:
The Radio Network Temporary Identifier. The default is 1. It is used with
nIDbelow to initialize a golden sequence used for the scrambling process. See 3GPP TS 38.211, Section 7.3.1.1 for more information.- nID:
The scrambling identity. The default is 1. It is used with
rntito initialize a golden sequence used for the scrambling process. See 3GPP TS 38.211, Section 7.3.1.1 for more information.- prgSize:
The size of Precoding RB Groups (PRGs). It can be one of 0 (default), 2, or 4. The value 0 means Wideband Precoding which means the same precoding is used for the whole bandwidth of this
PDSCH. See 3GPP TS 38.214, Section 5.1.2.3 for more information.
Specifying the OFDM symbols:
You can specify the OFDM symbols used by this
PDSCHin different ways:If
slivis specified, it is used to determine the start and length of consecutive OFDM symbols used by thisPDSCHbased on 3GPP TS 38.214, Section 5.1.2.1. In this case, the parameterssymStart,symLen, andsymSetare ignored.If
slivis not specified and bothsymStartandsymLenare specified, they are used to determine the OFDM symbols used by thisPDSCH. In this case the parametersymSetis ignored.If
sliv,symStart, andsymLenare not specified butsymSetis specified, it is used to determine the OFDM symbols used by thisPDSCH.If neither of
sliv,symStart,symLen, andsymSetare specified, the OFDM symbols are automatically assigned based onmappingTypeandcpTypeparameter of theBandwidthPartobjectbwp.
Other Properties:
- numCW:
The number of codewords derived from the
numLayersparameter. It is either 1 or 2.- modems:
A list of one or two (depending on
numCW)Modemobject(s) used internally for modulation/demodulation of the codewords.- dmrs:
The
DMRSobject associated with thisPDSCH. You can usesetDMRS()method to set theDMRSobject associated with thisPDSCH.- portSet:
The list of ports used by this
PDSCHand its associatedDMRSobject. By default, this is set to the number of layers specified bynumLayers. This can be changed by theDMRSconfiguration.- slotNo:
This returns the
slotNoproperty of theCarrierobject containingbwp.- frameNo:
This returns the
frameNoproperty of theCarrierobject containingbwp.- slotNoInFrame:
This returns the
slotNoInFrameproperty of theCarrierobject containingbwp.- slotMap:
This is the map of resource blocks used for each OFDM symbol in this
PDSCHin the form of a 2D list (A list of lists). Each element in the list corresponds to one OFDM symbol. If an OFDM symbol has no resource blocks allocation in thisPDSCH, its corresponding element is an empty list. Otherwise, it is a list of indices of all resource blocks used in that OFDM symbol in the order they should be allocated (based on the interleaving process). Note that the reserved resource blocks specified byreservedRbSetsabove are not included in theslotMap.
The notebook PDSCH end-to-end communication shows how to create an end-to-end pipeline of PDSCH communication.
- print(indent=0, title='PDSCH Properties:', getStr=False)
Prints the properties of this
PDSCHobject.- Parameters:
indent (int) – The number of indentation characters.
title (str) – If specified, it is used as a title for the printed information.
getStr (Boolean) – If True, returns a text string instead of printing it.
- Returns:
If the
getStrparameter is True, then this function returns the information in a text string. Otherwise, nothing is returned.- Return type:
None or str
- setDMRS(**kwargs)
Creates and initializes a
DMRSobject associated with thisPDSCHobject.- Parameters:
kwargs (dict) – A dictionary of parameters passed directly to the constructor of the
DMRSclass. Please refer to this class for a list of parameters that can be used to configure DMRS.
- setPTRS(**kwargs)
Creates and initializes a
PTRSobject associated with thisPDSCHobject. Please note that you must first use thesetDMRS()function to initialize theDMRSobject before calling this function.- Parameters:
kwargs (dict) – A dictionary of parameters passed directly to the constructor of the
PTRSclass. Please refer to this class for a list of parameters that can be used to configure PTRS.
- getGrid(useReDesc=False)
Creates a
Gridobject for thisPDSCHand a populates it with the configuredDMRSandPTRSreference signals. It also marks all the resources corresponding to thereservedRbSetsandreservedReMapparameters as reserved in the newly created resource grid.The returned resource grid contains all reference signals and is ready to be populated with the user data (See
populateGrid()method).- Parameters:
useReDesc (Boolean) – If True, the resource grid will also include additional fields that describe the content of each resource element (RE). This can be used during the debugging to make sure the resources are allocated correctly.
- Returns:
A
Gridobject representing the resource grid for thisPDSCHpre-populated with reference signals.- Return type:
- getReIndexes(grid, reTypeStr)
Returns the indices of all resource elements of the specified resource grid that are allocated for this
PDSCHwith the content type specified by thereTypeStr.This is similar to the
getReIndexes()of theGridclass with two main differences:This function considers only the resource elements in
gridthat are assigned to thisPDSCH.The indices are ordered based on the interleaving configuration given by
interleavingBundleSizeaccording to 3GPP TS 38.214, Section 5.1.4.1.
For example, the following code first gets the indices of all DMRS values in
myPdschand uses the returned indices to retrieve the DMRS values.myGrid = myPdsch.getGrid() dmrsIdx = myPdsch.getReIndexes(myGrid, "DMRS") # Get the indices of all DMRS values dmrsValues = myGrid[indexes] # Get all DMRS values as a 1-D array.
- Parameters:
grid (
Grid) – The resource grid associated with thisPDSCH. This can be obtained using thegetGridfunction for example.reTypeStr (str) –
The content type of the desired resource elements in
gridthat are used by thisPDSCH. Here is a list of values that can be used:- ”UNASSIGNED”:
The un-assigned resource elements.
- ”RESERVED”:
The reserved resource elements. This includes the REs reserved by
reservedRbSetsorreservedReMapparameters of thisPDSCH.- ”NO_DATA”:
The resource elements that should not contain any data. For example when the corresponding REs in a different layer is used for transmission of data for a different UE. (See
otherCdmGroupsparameter ofDMRSclass)- ”DMRS”:
The resource elements used for
DMRS.- ”PTRS”:
The resource elements used for
PTRS.- ”CSIRS_NZP”:
The resource elements used for Zero-Power (ZP) CSI-RS (See
csirs).- ”CSIRS_ZP”:
The resource elements used for Non-Zero-Power (NZP) CSI-RS (See
csirs).- ”PDSCH”:
The resource elements used for user data in a Physical Downlink Shared Channel (
PDSCH)- ”PDCCH”:
The resource elements used for user data in a Physical Downlink Control Channel (
PDCCH)- ”PUSCH”:
The resource elements used for user data in a Physical Uplink Shared Channel (
PUSCH)- ”PUCCH”:
The resource elements used for user data in a Physical Uplink Control Channel (
PUCCH)
- Returns:
A tuple of three 1-D NumPy arrays specifying a list of locations in
grid. This value can be used directly to access the REs at the specified locations. (see example above)- Return type:
3-tuple
- getNumREsFromIndexes(indexes)
Returns the number of resource elements included in
indexesfor each codeword. The returned value is a list of one or two integers depending on number of codewords (numCW).- Parameters:
indexes (3-tuple) – A tuple of 3 lists specifying locations of a set of resource elements in the resource grid. For example this can be obtained using the
getReIndexes()function.- Returns:
A list of one or two integers depending on the number of codewords (
numCW), indicating the number of resource elements (REs) included inindexesfor each codeword.- Return type:
list
- getBitSizes(grid, reTypeStr='PDSCH')
Returns total number of bits corresponding to the resource elements in
gridassigned to thisPDSCHwith content type specified byreTypeStrfor each codeword. The returned value is a list of one or two integers depending on the number of codewords (numCW).The default value of
reTypeStr="PDSCH"is for a common use case where we want to get total number of bits available in thisPDSCHfor user data after setting aside the REs for DMRS, PTRS, and the reserved resources.- Parameters:
grid (
Grid()) – The resource grid associated with thisPDSCH. This can be obtained using thegetGrid()function for example.reTypeStr (str) – The content type of the desired resource elements used to count the returned number of bits. The default values of
"PDSCH"causes this function to return total number of (unassigned) bits that are available for user data. Please refer to thegetReIndexes()function for a list of values that can used forreTypeStr.
- Returns:
A list of one or two integers depending on the number of codewords (
numCW), indicating the number of bits allocated forreTypeStrfor each codeword.- Return type:
list
- populateGrid(grid, bits=None)
Populates the resource grid specified by
gridwith the user data provided inbits.This function performs the following operations:
- Scrambling:
Scrambling of the specified
bitsusing therntiandnIDproperties of thisPDSCH. These properties are used to initialize a golden sequence which is then used for the scrambling process according to 3GPP TS 38.211, Section 7.3.1.1. The data bits for each codeword are scrambled separately.- Modulation:
Converting the scrambled binary data stream into complex symbols for each resource elements assigned for user data. The modulation process is performed by the
Modemobjects in themodemslist of thisPDSCH. The modulation for each codeword is performed separately by its own dedicatedModemobject.- Layer Mapping:
Distributing the modulated complex symbols across one or more transmission layers of this
PDSCHaccording to 3GPP TS 38.211, Section 7.3.1.3.- Interleaving:
Converting Virtual Resource Blocks (VRBs) to Physical Resource Blocks (PRBs). If enabled, the resources are re-ordered based on the interleaving configuration given by
interleavingBundleSizeaccording to 3GPP TS 38.214, Section 5.1.4.1.
- Parameters:
grid (
Grid) – TheGridobject that gets populated with the user data bits.bits (list, tuple, NumPy array, or None) –
Specifies the user data bits that are used to populate the specified resource grid. It can be one of the following:
- tuple of NumPy arrays:
Depending on the number of codewords (
numCW), the tuple can have one or two 1D NumPy arrays of bits each specifying the user data bits for each codeword.- NumPy array:
A one or two dimensional NumPy array. It is a 1D array, only if we have one codeword and the given NumPy array is used for the single codeword. The 2D NumPy array can be used for one or two codeword cases. The first dimension of the NumPy array in this case should match the number of codewords (
numCW).- list of NumPy arrays:
Depending on the number of codewords (
numCW), the list can have one or two 1D NumPy arrays of bits each specifying the user data bits for each codeword.- None:
If this is None,
griddata is not updated. This is used for the (rare) case where we only want to update the resource element descriptions in thegridobject. See theuseReDescparameter of theGridclass for more information.
- getLLRsFromGrid(rxGrid, pdschIndexes, llrScales=None, noiseVar=None, useMax=True)
This method is used at the receiving side where the Log-likelihood-Ratios (LLRs) are extracted from the received resource grid
rxGrid. This is in some sense the opposite of thepopulateGrid()method since it does the following:- Deinterleaving:
Converting Physical Resource Blocks (PRBs) to Virtual Resource Blocks (VRBs). If enabled, the resources are re-ordered based on the interleaving configuration given by
interleavingBundleSizeaccording to 3GPP TS 38.214, Section 5.1.4.1 so get the data in its original order.- Layer Demapping:
Extracting the modulated complex symbols for each codeword from different layers of this
PDSCHaccording to 3GPP TS 38.211, Section 7.3.1.3.- Demodulation:
Converting complex symbols to Log-likelihood-Ratios (LLRs) using the
Modemobjects in themodemslist of thisPDSCH. The demodulation for each codeword is performed separately by its own dedicatedModemobject. This produces one or two sets of LLRs for each codeword.- Descrambling:
The descrambling of the demodulated LLRs using the
rntiandnIDproperties of thisPDSCH. These properties are used to initialize a golden sequence which is then used for the descrambling process according to 3GPP TS 38.211, Section 7.3.1.1. The LLRs for each codeword are descrambled separately.
This function returns a list of one or two NumPy arrays representing the LLRs for each codeword.
- Parameters:
rxGrid (
Grid) – The equalized received resource grid associated with thisPDSCH. Usually this is theGridobject obtained after equalization in the receiver pipeline (See theequalize()function).pdschIndexes (3-tuple) – A tuple of 3 lists specifying locations of the set of resource elements in
rxGridthat are assigned to the user data. The functiongetReIndexes()is typically used to obtain this.llrScales (3-D NumPy array) – The Log-Likelihood Ratios (LLR) scaling factors which are used by demodulating process when extracting Log-Likelihood Ratios (LLRs) from the equalized resource grid. The shape of this array must be the same shape as
rxGrid.noiseVar (float or None) – The variance of the Additive White Gaussian Noise (AWGN) present in the received resource grid. If this is not provided (
noiseVar=None), This function uses thenoiseVarproperty of therxGridobject.useMax (Boolean) – If True, this implementation uses the
Maxfunction in the calculation of the LLR values. This is faster but uses an approximation and is slightly less accurate than the actual Log Likelihood method which uses logarithm and exponential functions. If False, the slower more accurate method is used.
- Returns:
A list of one or two NumPy arrays each representing the LLRs for each codeword.
- Return type:
list
- getHardBitsFromGrid(rxGrid, pdschIndexes, llrScales=None, noiseVar=None, useMax=True)
This method first calls the
getLLRsFromGrid()function above and then uses hard-decisions on the returned LLRs to get the output user bits.This can be used when there is no channel coding in the communication pipeline. It returns a list of one or two NumPy arrays of bits for each codeword.
- Parameters:
rxGrid (
Grid) – The equalized received resource grid associated with thisPDSCH. Usually this is theGridobject obtained after equalization in the receiver pipeline (See theequalize()function).pdschIndexes (3-tuple) – A tuple of 3 lists specifying locations of the set of resource elements in
rxGridthat are assigned to the user data. The functiongetReIndexes()is typically used to obtain this.llrScales (3-D NumPy array) – The Log-Likelihood Ratios (LLR) scaling factors which are used by demodulating process when extracting Log-Likelihood Ratios (LLRs) from the equalized resource grid. The shape of this array must be the same shape as
rxGrid.noiseVar (float or None) – The variance of the Additive White Gaussian Noise (AWGN) present in the received resource grid. If this is not provided (
noiseVar=None), This function uses thenoiseVarproperty of therxGridobject.useMax (Boolean) – If True, this implementation uses the
Maxfunction in the calculation of the LLR values. This is faster but uses an approximation and is slightly less accurate than the actual Log Likelihood method which uses logarithm and exponential functions. If False, the slower more accurate method is used.
- Returns:
A list of one or two NumPy arrays of bits for each codeword.
- Return type:
list
- getDataSymbols(grid)
This is a helper function that returns the modulated complex symbols for all user data in
gridfor thisPDSCHobject. The following code shows two different ways to do this:# Getting the indices of user data in "grid" and then using them to get "dataSymbols1": dataReIndexes = myPdsch.getReIndexes(grid, "PDSCH") dataSymbols1 = grid[ dataReIndexes ] # Using the "getDataSymbols" function: dataSymbols2 = myPdsch.getDataSymbols(grid) assert np.all(dataSymbols1==dataSymbols2) # The results are the same
- getPrecodingMatrix(channelMatrix)
This function calculates the precoding matrix that can be applied to a resource grid. This function supports Precoding RB groups (PRGs) which means different precoding matrices could be applied to different groups of subcarriers in the resource grid. See 3GPP TS 38.214, Section 5.1.2.3 for more details. The
prgSizeproperty ofPDSCHdetermines what type of precoding matrix is returned by this function:- Wideband:
If
prgSizeis set to zero, a singleNt x Nl, matrix is returned whereNtis the number of transmitter antenna andNlis the number of layers in thisPDSCH. In this case the same precoding is applied to all subcarriers of the resource grid.- Using PRGs:
If
prgSizeis set to 2 or 4, a list of tuples of the form (groupRBs,groupF) is returned. For each entry in the list, theNt x Nlprecoding matrixgroupFis applied to all subcarriers of the resource blocks listed ingroupRBs.
Note
It is assumed that the
channelMatrixis obtained based on the sameBandwidthPartobject as the one used by thisPDSCH.- Parameters:
channelMatrix (NumPy array) – An
L x K x Nr x Ntcomplex NumPy array representing the channel matrix. It can be the actual channel matrix obtained directly from a channel model using thegetChannelMatrix()method (perfect estimation), or an estimated channel matrix obtained using theestimateChannelLS()method.- Returns:
Depending on the
prgSizeproperty of thisPDSCH, the returned value can be:- NumPy Array:
If
prgSizeis set to zero, a single WidebandNt x Nl, matrix is returned whereNtis the number of transmitter antenna andNlis the number of layers in thisPDSCH. In this case the same precoding is applied to all subcarriers of the resource grid.- list of tuples:
If
prgSizeis set to 2 or 4, a list of tuples of the form (groupRBs,groupF) is returned. For each entry in the list, theNt x Nlprecoding matrixgroupFis applied to all subcarriers of the resource blocks listed ingroupRBs.
- Return type:
NumPy array or list of tuples
- getTxBlockSize(codeRates, xOverhead=0, scaleFactor=1.0)
This function calculates the transport block size based on the desired code rate (
codeRates), the number of additional overhead resource elements (xOverhead), and the scaling factor (scaleFactor). It returns a list of one or two integer values specifying the size of transport blocks for each codeword. This implementation is based on 3GPP TS 38.214, Section 5.1.3.2.- Parameters:
codeRates (float, list, NumPy array, or tuple) – If
codeRatesis a float value, it specifies the same code rate for all codewords. If it is a list, NumPy array, or tuple, it should contain one or two code rate values for each codeword. This is the value \(R\) in 3GPP TS 38.214, Section 5.1.3.2.xOverhead (int) – The number of additional overhead resource elements (REs) that should be considered when calculating the transport block size. This is the value \(N^{PRB}_{oh}\) in 3GPP TS 38.214, Section 5.1.3.2.
scaleFactor (float) – The scaling factor, which must be one of: 0.25, 0.5, or 1.0. This is the value \(S\) in 3GPP TS 38.214, Table 5.1.3.2-2.
- Returns:
A list of one or two integers depending on the number of codewords (
numCW), indicating the transport block size for each codeword.- Return type:
list