Matlab Toolbox - 4G/LTE
These RMCs use 2 or 4 cell-specific antenna ports, so every antenna carries its own CRS pattern and part of every channel. They test transmit diversity and closed-loop spatial multiplexing. This page generates R.10 to R.14 from 36.101 Tables A.3.3.2.1-1 and A.3.3.2.2-1, and shows the grid of each antenna side by side.
Followings are the topics to be covered in this page.
- Generating RMC Downlink Signal
- Two antenna port RMCs R.10 and R.11
- Four antenna port RMCs R.12, R.13 and R.14
- Checking the RMCs against 36.101
- Reference
Generating RMC Downlink Signal
The code follows the single antenna RMC page, with one extra problem to solve: each channel now has one set of REs per antenna. It selects one antenna with TxAntIndex, and it picks the column of each Indices output that belongs to that antenna.
rc = 'R.10';
rmc = lteRMCDL(rc)
pdsch = rmc.PDSCH
txData = [0;0;0;0];
[txWaveform, txGrid, rmcCfgOut] = lteRMCDLTool(rmc, txData);
SF_RE_NUM = rmc.NDLRB*12*14;
TxAntIndex = 0;
TxAnt = TxAntIndex + 1;
txGrid = txGrid(:,:,TxAnt);
txGridChMap = txGrid(:,:,1);
crs_scale = 0.2;
pss_scale = 0.3;
sss_scale = 0.3;
phich_scale = 0.7;
pcfich_scale = 0.8;
pbch_scale = 0.7;
pdcch_scale = 0.5;
pdsch_scale = 0.4;
noPdschSubframe = [5];
for i=0:9
rmc.NSubframe = i;
pdsch = rmc.PDSCH;
indexOffset = (rmc.NDLRB * 12 * 14) * rmc.NSubframe;
crs_sym_ind = lteCellRSIndices(rmc);
if rmc.CellRefP == 2
crs_sym_ind = reshape(crs_sym_ind,[length(crs_sym_ind)/2, 2]);
crs_sym_ind_p0 = crs_sym_ind(:,1);
crs_sym_ind_p1 = crs_sym_ind(:,2);
elseif rmc.CellRefP == 4
crs_sym_ind = reshape(crs_sym_ind,[length(crs_sym_ind)/3, 3]);
crs_sym_ind_p0 = crs_sym_ind(:,1);
crs_sym_ind_p1 = crs_sym_ind(:,2);
crs_sym_ind_p2_3 = crs_sym_ind(:,3);
crs_sym_ind_p2_3 = reshape(crs_sym_ind_p2_3,[length(crs_sym_ind_p2_3)/2, 2]);
crs_sym_ind_p2 = crs_sym_ind_p2_3(:,1);
crs_sym_ind_p3 = crs_sym_ind_p2_3(:,2);
end
if (i == 0) || (i == 5)
pss_sym_ind = ltePSSIndices(rmc)+indexOffset;
sss_sym_ind = lteSSSIndices(rmc)+indexOffset;
end
pcfich_sym_ind = ltePCFICHIndices(rmc)+indexOffset;
phich_sym_ind = ltePHICHIndices(rmc)+indexOffset;
if i == 0
pbch_sym_ind = ltePBCHIndices(rmc)+indexOffset;
end
dci.NDLRB = rmc.NDLRB;
dci.DCIFormat = pdsch.DCIFormat;
dci.AllocationType = 0;
dci.Allocation.RIV = 18;
dci.ModCoding = 10;
dci.HARQNo = 0;
dci.NewData = 0;
dci.TPCPUCCH = 0;
dci.DuplexMode = 'FDD';
dci.NTxAnts = 1;
[dciMessage,dciMessageBits] = lteDCI(rmc,dci);
pdcchConfig.RNTI = pdsch.RNTI;
pdcchConfig.PDCCHFormat = pdsch.PDCCHFormat;
codedDciBits = lteDCIEncode(pdcchConfig, dciMessageBits);
pdcchDims = ltePDCCHInfo(rmc);
pdcchBits = -1*ones(pdcchDims.MTot, 1);
candidates = ltePDCCHSpace(rmc, pdcchConfig);
pdcchBits ( candidates(1, 1) : candidates(1, 2) ) = codedDciBits;
pdcch_sym = ltePDCCH(rmc, pdcchBits);
pdcch_sym_ind = ltePDCCHIndices(rmc)+indexOffset;
if ismember(i,noPdschSubframe) == false
if iscell(pdsch.PRBSet) == true
[pdsch_sym_ind,pdschIndInfo] = ltePDSCHIndices(rmc,pdsch,cell2mat(pdsch.PRBSet(i+1)));
else
[pdsch_sym_ind,pdschIndInfo] = ltePDSCHIndices(rmc,pdsch,pdsch.PRBSet);
end
pdsch_sym_ind = pdsch_sym_ind + indexOffset;
end
if TxAntIndex == 0
txGridChMap(crs_sym_ind_p0-SF_RE_NUM*TxAntIndex) = crs_scale;
elseif TxAntIndex == 1
txGridChMap(crs_sym_ind_p1-SF_RE_NUM*TxAntIndex) = crs_scale;
elseif TxAntIndex == 2
txGridChMap(crs_sym_ind_p2-SF_RE_NUM*TxAntIndex) = crs_scale;
elseif TxAntIndex == 3
txGridChMap(crs_sym_ind_p3-SF_RE_NUM*TxAntIndex) = crs_scale;
end
if TxAntIndex == 0
txGridChMap(pss_sym_ind) = pss_scale;
txGridChMap(sss_sym_ind) = sss_scale;
end
txGridChMap(pcfich_sym_ind(:,TxAnt)-SF_RE_NUM*TxAntIndex) = pcfich_scale;
txGridChMap(phich_sym_ind(:,TxAnt)-SF_RE_NUM*TxAntIndex) = phich_scale;
txGridChMap(pbch_sym_ind(:,TxAnt)-SF_RE_NUM*TxAntIndex) = pbch_scale;
txGridChMap(pdcch_sym_ind(:,TxAnt)-SF_RE_NUM*TxAntIndex) = pdcch_scale .* pdcch_sym(:,TxAnt);
if ismember(i,noPdschSubframe) == false
txGridChMap(pdsch_sym_ind(:,TxAnt)-SF_RE_NUM*TxAntIndex) = pdsch_scale;
end
end
ylabelText = {'0','1','2','3','4','5','6','7','8','9', ...
'10','11','12','13','14','15','16','17','18','19', ...
'20','21','22','23','24','25','26','27','28','29', ...
'30','31','32','33','34','35','36','37','38','39', ...
'40','41','42','43','44','45','46','47','48','49', ...
'50','51','52','53','54','55','56','57','58','59', ...
'60','61','62','63','64','65','66','67','68','69', ...
'70','71','72','73','74','75','76','77','78','79', ...
'80','81','82','83','84','85','86','87','88','89', ...
'90','91','92','93','94','95','96','97','98','99'};
ytick = 7:12:(rmc.NDLRB*12);
subplot(2,2,1);
imagesc(abs(txGrid));
axis xy;
xlabel('Subframe');
ylabel('RB');
set(gca,'xtick',8:14:140);
set(gca,'xticklabel',{'0','1','2','3','4','5','6','7','8','9','10'});
set(gca,'ytick',ytick);
set(gca,'yticklabel',ylabelText);
subplot(2,2,3);
imagesc(abs(txGridChMap));
axis xy;
xlabel('Subframe');
ylabel('RB');
set(gca,'xtick',8:14:140);
set(gca,'xticklabel',{'0','1','2','3','4','5','6','7','8','9','10'});
set(gca,'ytick',ytick);
set(gca,'yticklabel',ylabelText);
subplot(2,2,[2 4]);
imagesc(abs(txGridChMap));
axis xy;
xlabel('Symbol');
ylabel('RB');
xlim([0.5 14.5]);
ylim([0.5 12*rmc.NDLRB]);
set(gca,'xtick',1:14);
set(gca,'xticklabel',{'0','1','2','3','4','5','6','7','8','9','10','11','12','13'});
set(gca,'ytick',ytick);
set(gca,'yticklabel',ylabelText);
mymap = [0.0 0.0 0.0
1.0 1.0 0.0
1.0 0.0 0.0
0.5 0.0 0.0
0.0 1.0 0.0
0.0 0.5 0.0
0.0 0.0 1.0
0.0 0.0 0.5
0.0 1.0 1.0
1.0 0.0 1.0
1.0 1.0 1.0];
colormap(mymap);
set(gcf, 'Position', [200, 200, 800, 700])
The CRS needs the most work. The function lteCellRSIndices returns the indices of all ports together. The code splits them into ports 0 to 3 and marks only the port of the selected antenna. The PSS and SSS are marked only for antenna 0, because the toolbox writes them on the first antenna only. The PBCH, PCFICH, PHICH, PDCCH and PDSCH have one column per antenna, and the code subtracts SF_RE_NUM times TxAntIndex to bring each column back into the grid of one antenna.
One Indices column per antenna : TxAntIndex selects the column.CRS split by port : each antenna shows only its own CRS.PSS and SSS on antenna 0 only : the other antennas leave those REs empty.
Two antenna port RMCs R.10 and R.11
R.10 and R.11 use two CRS ports and transmit diversity on 50 RB, with QPSK at a target code rate of 1/3 and 16QAM at 1/2. The two antennas carry the same channels, but each carries a different CRS pattern and a different half of the SFBC pair.
|
rc = 'R.10'; TxAntIndex = 0 |
36.101 v14.4 - Table A.3.3.2.1-1: Fixed Reference Channel two antenna ports |
|
|
|
|
rc = 'R.10'; TxAntIndex = 1 |
|
![]() |
|
|
rmc =
struct with fields:
RC: 'R.10' NDLRB: 50 CellRefP: 2 NCellID: 0 CyclicPrefix: 'Normal' CFI: 2 PCFICHPower: 0 Ng: 'Sixth' PHICHDuration: 'Normal' HISet: [112×3 double] PHICHPower: 0 NFrame: 0 NSubframe: 0 TotSubframes: 10 Windowing: 0 DuplexMode: 'FDD' PDSCH: [1×1 struct] OCNGPDCCHEnable: 'Off' OCNGPDCCHPower: 0 OCNGPDSCHEnable: 'Off' OCNGPDSCHPower: 0 OCNGPDSCH: [1×1 struct]
pdsch =
struct with fields:
TxScheme: 'TxDiversity' Modulation: {'QPSK'} NLayers: 2 Rho: 0 RNTI: 1 RVSeq: [0 1 2 3] RV: 0 NHARQProcesses: 8 NTurboDecIts: 5 PRBSet: [50×1 double] TargetCodeRate: 0.3333 ActualCodeRate: [0.3566 0.3345 0.3345 0.3345 0.3345 0 0.3345 0.3345 0.3345 0.3345] TrBlkSizes: [4392 4392 4392 4392 4392 0 4392 4392 4392 4392] CodedTrBlkSizes: [12384 13200 13200 13200 13200 0 13200 13200 13200 13200] DCIFormat: 'Format1' PDCCHFormat: 2 PDCCHPower: 0 CSIMode: 'PUSCH 1-2' PMIMode: 'Wideband'
|
|
R.10. Antenna 0 on the left carries the PSS and SSS in subframe 0, and antenna 1 on the right leaves them empty. Both antennas carry the PBCH, the control channels and the PDSCH.
|
rc = 'R.11'; TxAntIndex = 0 |
36.101 v14.4 - Table A.3.3.2.1-1: Fixed Reference Channel two antenna ports |
|
|
|
|
rc = 'R.11'; TxAntIndex = 1 |
|
![]() |
|
|
rmc =
struct with fields:
RC: 'R.11' NDLRB: 50 CellRefP: 2 NCellID: 0 CyclicPrefix: 'Normal' CFI: 2 PCFICHPower: 0 Ng: 'Sixth' PHICHDuration: 'Normal' HISet: [112×3 double] PHICHPower: 0 NFrame: 0 NSubframe: 0 TotSubframes: 10 Windowing: 0 DuplexMode: 'FDD' PDSCH: [1×1 struct] OCNGPDCCHEnable: 'Off' OCNGPDCCHPower: 0 OCNGPDSCHEnable: 'Off' OCNGPDSCHPower: 0 OCNGPDSCH: [1×1 struct]
pdsch =
struct with fields:
TxScheme: 'TxDiversity' Modulation: {'16QAM'} NLayers: 2 Rho: 0 RNTI: 1 RVSeq: [0 1 2 3] RV: 0 NHARQProcesses: 8 NTurboDecIts: 5 PRBSet: [50×1 double] TargetCodeRate: 0.5000 ActualCodeRate: [0.5271 0.4945 0.4945 0.4945 0.4945 0 0.4945 0.4945 0.4945 0.4945] TrBlkSizes: [12960 12960 12960 12960 12960 0 12960 12960 12960 12960] CodedTrBlkSizes: [24768 26400 26400 26400 26400 0 26400 26400 26400 26400] DCIFormat: 'Format1' PDCCHFormat: 2 PDCCHPower: 0 CSIMode: 'PUSCH 3-1' PMIMode: 'Wideband'
|
|
R.11. The same REs as R.10, now carrying 16QAM.
With two ports, the CRS of both ports are excluded from the PDSCH on both antennas, because one port has to stay silent where the other transmits its reference signal. In symbols 4, 7 and 11, each PRB pair loses 4 REs instead of 2. So a PRB pair carries 144 - 12 = 132 PDSCH REs with CFI 2, and 50 RB give 6600 REs. QPSK then gives the 13200 coded bits of R.10, and 16QAM the 26400 of R.11.
In subframe 0, the central 6 RB lose 144 REs to the PSS and SSS and 264 REs to the PBCH, beyond the CRS already counted. That leaves 6192 REs, which are 12384 coded bits for R.10 and 24768 for R.11. Transmit diversity sends one codeword, so NLayers = 2 here counts the two SFBC branches, not two independent streams.
132 PDSCH REs per PRB pair : the CRS of both ports are excluded.One codeword on two antennas : SFBC transmit diversity.PSS and SSS on antenna 0 only : as the grids for antenna 1 show.
Four antenna port RMCs R.12, R.13 and R.14
R.12, R.13 and R.14 use four CRS ports. Ports 2 and 3 add reference signals in symbols 1 and 8, so the PDSCH loses more REs than with two ports. The three RMCs also use three different schemes: transmit diversity, spatial multiplexing with one layer, and spatial multiplexing with two layers.
|
rc = 'R.12'; TxAntIndex = 0 |
36.101 v14.4 - Table A.3.3.2.2-1: Fixed Reference Channel four antenna ports |
|
|
|
|
rc = 'R.12'; TxAntIndex = 1 |
|
![]() |
|
|
rc = 'R.12'; TxAntIndex = 2 |
|
![]() |
|
|
rc = 'R.12'; TxAntIndex = 3 |
|
![]() |
|
|
rmc =
struct with fields:
RC: 'R.12' NDLRB: 6 CellRefP: 4 NCellID: 0 CyclicPrefix: 'Normal' CFI: 3 PCFICHPower: 0 Ng: 'Sixth' PHICHDuration: 'Normal' HISet: [112×3 double] PHICHPower: 0 NFrame: 0 NSubframe: 0 TotSubframes: 10 Windowing: 0 DuplexMode: 'FDD' PDSCH: [1×1 struct] OCNGPDCCHEnable: 'Off' OCNGPDCCHPower: 0 OCNGPDSCHEnable: 'Off' OCNGPDSCHPower: 0 OCNGPDSCH: [1×1 struct]
pdsch =
struct with fields:
TxScheme: 'TxDiversity' Modulation: {'QPSK'} NLayers: 4 Rho: 0 RNTI: 1 RVSeq: [0 1 2 3] RV: 0 NHARQProcesses: 8 NTurboDecIts: 5 PRBSet: [6×1 double] TargetCodeRate: 0.3333 ActualCodeRate: [0.3667 0.3462 0.3462 0.3462 0.3462 0 0.3462 0.3462 0.3462 0.3462] TrBlkSizes: [152 408 408 408 408 0 408 408 408 408] CodedTrBlkSizes: [480 1248 1248 1248 1248 0 1248 1248 1248 1248] DCIFormat: 'Format1' PDCCHFormat: 2 PDCCHPower: 0 CSIMode: 'PUCCH 1-1' PMIMode: 'Wideband' |
|
R.12, 6 RB, transmit diversity. Antennas 2 and 3 carry their CRS in symbols 1 and 8. In subframe 0, the PDSCH keeps only symbols 4, 11, 12 and 13.
|
rc = 'R.13'; TxAntIndex = 0 |
36.101 v14.4 - Table A.3.3.2.2-1: Fixed Reference Channel four antenna ports |
|
|
|
|
rc = 'R.13'; TxAntIndex = 1 |
|
![]() |
|
|
rc = 'R.13'; TxAntIndex = 2 |
|
![]() |
|
|
rc = 'R.13'; TxAntIndex = 3 |
|
![]() |
|
|
rmc =
struct with fields:
RC: 'R.13' NDLRB: 50 CellRefP: 4 NCellID: 0 CyclicPrefix: 'Normal' CFI: 2 PCFICHPower: 0 Ng: 'Sixth' PHICHDuration: 'Normal' HISet: [112×3 double] PHICHPower: 0 NFrame: 0 NSubframe: 0 TotSubframes: 10 Windowing: 0 DuplexMode: 'FDD' PDSCH: [1×1 struct] OCNGPDCCHEnable: 'Off' OCNGPDCCHPower: 0 OCNGPDSCHEnable: 'Off' OCNGPDSCHPower: 0 OCNGPDSCH: [1×1 struct]
pdsch =
struct with fields:
TxScheme: 'SpatialMux' Modulation: {'QPSK'} NLayers: 1 Rho: 0 RNTI: 1 RVSeq: [0 1 2 3] RV: 0 NHARQProcesses: 8 NTurboDecIts: 5 PRBSet: [50×1 double] TargetCodeRate: 0.3333 ActualCodeRate: [0.3032 0.3450 0.3450 0.3450 0.3450 0 0.3450 0.3450 0.3450 0.3450] TrBlkSizes: [3624 4392 4392 4392 4392 0 4392 4392 4392 4392] CodedTrBlkSizes: [12032 12800 12800 12800 12800 0 12800 12800 12800 12800] DCIFormat: 'Format2' PDCCHFormat: 2 PDCCHPower: 0 CSIMode: 'PUSCH 1-2' PMIMode: 'Wideband' PMISet: 0 |
|
R.13, 50 RB, spatial multiplexing with one layer and PMI 0. Each antenna carries its own CRS, and all four carry the PDSCH.
|
rc = 'R.14'; TxAntIndex = 0 |
36.101 v14.4 - Table A.3.3.2.2-1: Fixed Reference Channel four antenna ports |
|
|
|
|
rc = 'R.14'; TxAntIndex = 1 |
|
![]() |
|
|
rc = 'R.14'; TxAntIndex = 2 |
|
![]() |
|
|
rc = 'R.14'; TxAntIndex = 3 |
|
![]() |
|
|
rmc =
struct with fields:
RC: 'R.14' NDLRB: 50 CellRefP: 4 NCellID: 0 CyclicPrefix: 'Normal' CFI: 2 PCFICHPower: 0 Ng: 'Sixth' PHICHDuration: 'Normal' HISet: [112×3 double] PHICHPower: 0 NFrame: 0 NSubframe: 0 TotSubframes: 10 Windowing: 0 DuplexMode: 'FDD' PDSCH: [1×1 struct] OCNGPDCCHEnable: 'Off' OCNGPDCCHPower: 0 OCNGPDSCHEnable: 'Off' OCNGPDSCHPower: 0 OCNGPDSCH: [1×1 struct]
pdsch =
struct with fields:
TxScheme: 'SpatialMux' Modulation: {'16QAM' '16QAM'} NLayers: 2 Rho: 0 RNTI: 1 RVSeq: [2×4 double] RV: [0 0] NHARQProcesses: 8 NTurboDecIts: 5 PRBSet: [50×1 double] TargetCodeRate: 0.5000 ActualCodeRate: [2×10 double] TrBlkSizes: [2×10 double] CodedTrBlkSizes: [2×10 double] DCIFormat: 'Format2' PDCCHFormat: 2 PDCCHPower: 0 CSIMode: 'PUSCH 1-2' PMIMode: 'Wideband' PMISet: 0 |
|
R.14, 50 RB, spatial multiplexing with two layers and two 16QAM codewords. The RE map is the same as for R.13.
With four ports and CFI 2, a PRB pair loses 12 REs to ports 0 and 1 and 4 more to ports 2 and 3 in symbol 8. That leaves 128 PDSCH REs, and 50 RB give 6400 REs, which are the 12800 coded bits of R.13 with QPSK. R.12 has 6 RB and CFI 3, so its control region takes 4 symbols. It keeps 104 REs per PRB pair, 1248 coded bits with QPSK, and only 480 in subframe 0.
R.13 and R.14 use Format 2 and codebook index 0 on four ports, as the Precoding - Downlink page shows for that codebook. R.13 sends one layer. R.14 sends two layers, one codeword on each, so its toolbox output lists two rows of sizes, shown in the dump above as a 2 by 10 array. 36.101 gives 11448 bits for subframe 0 and 12960 bits for the other subframes, per codeword.
128 PDSCH REs per PRB pair with 4 ports : CRS in symbols 4, 7, 8 and 11.R.12 transmit diversity, R.13 one layer, R.14 two layers : all on four antennas.R.14 carries two codewords : each with 12960 bits in subframes 1 to 9.
Checking the RMCs against 36.101
Are these values still the ones in the current specification? The page cites 36.101 v14.4, and the table below compares the toolbox output with 36.101 v20.0.0 Tables A.3.3.2.1-1 and A.3.3.2.2-1.
RMC | Scheme | TBS, subframe 0 | TBS, other subframes | Coded bits, subframe 0 | Coded bits, other subframes | 36.101 v20.0.0 |
R.10 | TxDiversity, 2 ports | 4392 | 4392 | 12384 | 13200 | match |
R.11 | TxDiversity, 2 ports | 12960 | 12960 | 24768 | 26400 | match |
R.12 | TxDiversity, 4 ports | 152 | 408 | 480 | 1248 | match |
R.13 | SpatialMux, 1 layer | 3624 | 4392 | 12032 | 12800 | match |
R.14 | SpatialMux, 2 layers | 11448 per codeword | 12960 per codeword | 24064 | 25600 | not shown in the dump |
The ActualCodeRate values in the dumps follow from the same numbers. Each transport block gets a 24-bit CRC, and each code block another 24 bits when there is more than one. So R.10 gives (4392 + 24) / 13200 = 0.3345, and R.11, with 3 code blocks, gives (12960 + 24 + 3 x 24) / 26400 = 0.4945, as the toolbox reports.
The four RMCs with visible values all match. For R.14, the toolbox dump shows the sizes only as a 2 by 10 array, so the page cannot confirm them, and the table gives the 36.101 values.
R.10 to R.13 match 36.101 v20.0.0 : transport blocks and coded bits.R.14 sizes hidden in the dump : 36.101 gives 11448 and 12960 bits per codeword.
Disclaimer !
This page is only to show you the overall logics and visualization for various LTE physical layer channels. I haven't investigated much about verifying about the accuracy.
If you think the code is not so efficient, it is 100% my fault. I haven't made any effort for effiecient code. I just tried to create code as simple as possible for the readers. As you know, easy-to-read code is not always efficient for a specific chipset.
If you find any mistake in terms of accuracy, it is also very highly likely be my fault. Not the problem of Matlab tool box itself.
Any comment and corrections if you find any mistake will be welcome and appreciated.
Reference
[1] 3GPP TS 36.101 v20.0.0 - Tables A.3.3.2.1-1 and A.3.3.2.2-1, Fixed Reference Channels for two and four antenna ports
[2] 3GPP TS 36.211 v19.3.0 - clause 6.3.4, Precoding, and clause 6.10.1, Cell-specific reference signals















