Demystifying numCdmGroupsWithoutData
This notebook shows how to set the numCdmGroupsWithoutData parameter to let the PDSCH know how to allocate the resource elements around DMRS resources in different DMRS ports. numCdmGroupsWithoutData specifies how many CDM groups in each RB are treated as reserved for DM-RS and therefore unavailable for payload data (e.g., PDSCH). By default, NeoRadium derives a default value from the number of active DM-RS ports and the configured DM-RS symbol length. This default value ensures
there is no interference between DMRS signals in different ports/layers.
[1]:
import numpy as np
import scipy.io
from neoradium import BandwidthPart, PDSCH
[2]:
# First, create a bandwidth part with 5 resource blocks and 30 kHz subcarrier spacing
bwp = BandwidthPart(numRbs=5, spacing=30)
bwp.print()
Bandwidth Part Properties:
Resource Blocks: 5 RBs starting at 0 (60 subcarriers)
Subcarrier Spacing: 30 kHz
CP Type: normal
Interleaving: No
Bandwidth: 1.8 MHz
symbolsPerSlot: 14
slotsPerSubFrame: 2
nFFT: 1024
frameNo: 0
slotNo: 0
[3]:
# Create a 2-layer PDSCH with Mapping Type A (default) using All Symbols and PRBs in the BWP (default)
pdsch = PDSCH(bwp, numLayers=2)
# This PDSCH is using CDM group 0 only. (2 layers -> 2 ports -> one CDM group)
pdsch.setDMRS()
pdsch.print()
# Initialize the resource grid of the PDSCH object. This creates an internal Grid object and
# populates it with the DMRS and PTRS values
pdsch.initGrid()
# Print some statistics about the PDSCH resource grid
stats = pdsch.grid.getStats()
print("Number of resource elements:")
for key, value in stats.items(): print(" %-15s %d"%(key+":", value))
print(f"\nnumCdmGroupsWithoutData: {pdsch.dmrs.numCdmGroupsWithoutData}\n")
# Draw grid map for both layers
pdsch.grid.drawMap(pdsch.portSet);
# Note that in this case:
# - We only have one CDM group
# - By default, `numCdmGroupsWithoutData` is set to 1.
# - There are no resource elements marked as "NO_DATA"
# - There is no interference between DMRS and PDSCH resources
PDSCH Properties:
mappingType: A
nID: 1
rnti: 1
numLayers: 2
numCodewords: 1
modulation: 16QAM
PRG Size: Wideband
portSet: 0 1
symSet: 0 1 2 3 4 5 6 7 8 9 10 11 12 13
prbSet: 0 1 2 3 4
DMRS:
configType: 1
nIDs: []
scID: 0
sameSeq: True
symbols: Single
typeA1stPos: 2
additionalPos: 0
cdmGroups (port:cdm): 0:0 1:0
deltaShifts (port:cdm): 0:0 1:0
numCdmGroupsWithoutData: 1
symSet: 2
REs (before shift): 0 2 4 6 8 10
epreRatioDb: 0 (dB)
Number of resource elements:
GridSize: 1680
PDSCH: 1620
DMRS: 60
numCdmGroupsWithoutData: 1
[4]:
# Now let's create a 4-layer PDSCH (using all default settings)
pdsch = PDSCH(bwp, numLayers=4)
pdsch.setDMRS()
pdsch.print()
# Initialize the resource grid of the PDSCH object.
pdsch.initGrid()
# Print some statistics about the PDSCH resource grid
stats = pdsch.grid.getStats()
print("Number of resource elements:")
for key, value in stats.items(): print(" %-15s %d"%(key+":", value))
# Draw grid map for both layers
pdsch.grid.drawMap(pdsch.portSet);
# Note that in this case:
# - We have two CDM groups
# - By default, `numCdmGroupsWithoutData` is set to 2. This ensures no DMRS interference.
# - The resource elements between the DMRS REs are marked as "NO_DATA" and therefore
# not available for PDSCH.
# - There is no interference between DMRS and PDSCH resources
PDSCH Properties:
mappingType: A
nID: 1
rnti: 1
numLayers: 4
numCodewords: 1
modulation: 16QAM
PRG Size: Wideband
portSet: 0 1 2 3
symSet: 0 1 2 3 4 5 6 7 8 9 10 11 12 13
prbSet: 0 1 2 3 4
DMRS:
configType: 1
nIDs: []
scID: 0
sameSeq: True
symbols: Single
typeA1stPos: 2
additionalPos: 0
cdmGroups (port:cdm): 0:0 1:0 2:1 3:1
deltaShifts (port:cdm): 0:0 1:0 2:1 3:1
numCdmGroupsWithoutData: 2
symSet: 2
REs (before shift): 0 2 4 6 8 10
epreRatioDb: -3 (dB)
Number of resource elements:
GridSize: 3360
NO_DATA: 120
PDSCH: 3120
DMRS: 120
[5]:
# Now let's use a different DMRS configuration where we set the 'numCdmGroupsWithoutData' to 1:
pdsch.setDMRS(numCdmGroupsWithoutData=1)
pdsch.print()
# Re-initialize the resource grid since we have new DMRS configuration
pdsch.initGrid()
# Print some statistics about the PDSCH resource grid
stats = pdsch.grid.getStats()
print("Number of resource elements:")
for key, value in stats.items(): print(" %-15s %d"%(key+":", value))
# Draw grid map for both layers
pdsch.grid.drawMap(pdsch.portSet);
# Note that in this case:
# - We have two CDM groups
# - Since numCdmGroupsWithoutData = 1, the first CDM group has REs marked as
# "NO_DATA" (see this in ports 2 and 3 below).
# - Since numCdmGroupsWithoutData = 1, the second CDM group is now available
# for PDSCH (see this in ports 0 and 1 below).
# - This means there will be some interference between the DMRS signals in
# layers 2 and 3 and the PDSCH data in layers 0 and 1. This interference
# can be minimized using spatial diversity between different layers of
# PDSCH in Multi-User MIMO configurations.
PDSCH Properties:
mappingType: A
nID: 1
rnti: 1
numLayers: 4
numCodewords: 1
modulation: 16QAM
PRG Size: Wideband
portSet: 0 1 2 3
symSet: 0 1 2 3 4 5 6 7 8 9 10 11 12 13
prbSet: 0 1 2 3 4
DMRS:
configType: 1
nIDs: []
scID: 0
sameSeq: True
symbols: Single
typeA1stPos: 2
additionalPos: 0
cdmGroups (port:cdm): 0:0 1:0 2:1 3:1
deltaShifts (port:cdm): 0:0 1:0 2:1 3:1
numCdmGroupsWithoutData: 1
symSet: 2
REs (before shift): 0 2 4 6 8 10
epreRatioDb: 0 (dB)
Number of resource elements:
GridSize: 3360
NO_DATA: 60
PDSCH: 3180
DMRS: 120
[6]:
# Now we create a 6-Layer PDSCH
pdsch = PDSCH(bwp, numLayers=6)
# Use a DMRS with configType 2 and double symbols:
pdsch.setDMRS(configType=2, symbols=2)
pdsch.print()
pdsch.initGrid()
# Print some statistics about the PDSCH resource grid
stats = pdsch.grid.getStats()
print("Number of resource elements:")
for key, value in stats.items(): print(" %-15s %d"%(key+":", value))
# Draw grid map for both layers
pdsch.grid.drawMap(pdsch.portSet);
# Note that in this case:
# - We have three CDM groups
# - By default, `numCdmGroupsWithoutData` is set to 3.
# - The resource elements between the DMRS REs are marked as "NO_DATA" and therefore
# not available for PDSCH.
# - There is no interference between DMRS and PDSCH resources
PDSCH Properties:
mappingType: A
nID: 1
rnti: 1
numLayers: 6
numCodewords: 2
modulation: 16QAM
PRG Size: Wideband
portSet: 0 1 2 3 4 5
symSet: 0 1 2 3 4 5 6 7 8 9 10 11 12 13
prbSet: 0 1 2 3 4
DMRS:
configType: 2
nIDs: []
scID: 0
sameSeq: True
symbols: Double
typeA1stPos: 2
additionalPos: 0
cdmGroups (port:cdm): 0:0 1:0 2:1 3:1 4:2 5:2
deltaShifts (port:cdm): 0:0 1:0 2:2 3:2 4:4 5:4
numCdmGroupsWithoutData: 3
symSet: 2 3
REs (before shift): 0 1 6 7
epreRatioDb: -4.77 (dB)
Number of resource elements:
GridSize: 5040
NO_DATA: 480
PDSCH: 4320
DMRS: 240
[7]:
# Now lets set 'numCdmGroupsWithoutData' to 1
pdsch.setDMRS(configType=2, symbols=2, numCdmGroupsWithoutData=1)
pdsch.print()
pdsch.initGrid()
# Print some statistics about the PDSCH resource grid
stats = pdsch.grid.getStats()
print("Number of resource elements:")
for key, value in stats.items(): print(" %-15s %d"%(key+":", value))
# Draw grid map for both layers
pdsch.grid.drawMap(pdsch.portSet);
# Note that in this case:
# - We have three CDM groups
# - Since numCdmGroupsWithoutData = 1, the first CDM group has REs marked as
# "NO_DATA" (see this in ports 2, 3, 4, and 5 below).
# - Since numCdmGroupsWithoutData = 1, the second and third CDM groups are
# now available for PDSCH (see this in ports 0, 1, 2, and 3 below).
# - This means there will be some interference between the DMRS signals and
# PDSCH data in different layers. This interference may be minimized using
# spatial diversity between different layers of PDSCH in Multi-User MIMO
# configurations.
PDSCH Properties:
mappingType: A
nID: 1
rnti: 1
numLayers: 6
numCodewords: 2
modulation: 16QAM
PRG Size: Wideband
portSet: 0 1 2 3 4 5
symSet: 0 1 2 3 4 5 6 7 8 9 10 11 12 13
prbSet: 0 1 2 3 4
DMRS:
configType: 2
nIDs: []
scID: 0
sameSeq: True
symbols: Double
typeA1stPos: 2
additionalPos: 0
cdmGroups (port:cdm): 0:0 1:0 2:1 3:1 4:2 5:2
deltaShifts (port:cdm): 0:0 1:0 2:2 3:2 4:4 5:4
numCdmGroupsWithoutData: 1
symSet: 2 3
REs (before shift): 0 1 6 7
epreRatioDb: 0 (dB)
Number of resource elements:
GridSize: 5040
NO_DATA: 160
PDSCH: 4640
DMRS: 240
[7]:
# With the same 6-layer PDSCH, we now set 'numCdmGroupsWithoutData' to 2:
pdsch.setDMRS(configType=2, symbols=2, numCdmGroupsWithoutData=2)
pdsch.print()
pdsch.initGrid()
# Print some statistics about the PDSCH resource grid
stats = pdsch.grid.getStats()
print("Number of resource elements:")
for key, value in stats.items(): print(" %-15s %d"%(key+":", value))
# Draw grid map for both layers
pdsch.grid.drawMap(pdsch.portSet);
# Note that in this case:
# - We have three CDM groups
# - Since numCdmGroupsWithoutData = 2, the first and second CDM groups have
# REs marked as "NO_DATA".
# - Since numCdmGroupsWithoutData = 2, the third CDM group is now available
# for PDSCH (see this in ports 0, 1, 2, and 3 below).
# - This means there will be some interference between the DMRS signals in
# the third CDM group (in ports 4,5) and the PDSCH at those locations
# in ports 0,1,2, and 3.
PDSCH Properties:
mappingType: A
nID: 1
rnti: 1
numLayers: 6
numCodewords: 2
modulation: 16QAM
PRG Size: Wideband
portSet: 0 1 2 3 4 5
symSet: 0 1 2 3 4 5 6 7 8 9 10 11 12 13
prbSet: 0 1 2 3 4
DMRS:
configType: 2
nIDs: []
scID: 0
sameSeq: True
symbols: Double
typeA1stPos: 2
additionalPos: 0
cdmGroups (port:cdm): 0:0 1:0 2:1 3:1 4:2 5:2
deltaShifts (port:cdm): 0:0 1:0 2:2 3:2 4:4 5:4
numCdmGroupsWithoutData: 2
symSet: 2 3
REs (before shift): 0 1 6 7
epreRatioDb: -3 (dB)
Number of resource elements:
GridSize: 5040
NO_DATA: 320
PDSCH: 4480
DMRS: 240
[ ]:
[ ]: