Matlab Toolbox - 4G/LTE

 

 

 

PDCCH

 

The PDCCH carries the DCI, which tells each UE where its data is and how to decode it. Unlike the PCFICH, PHICH and PBCH, the PDCCH has no fixed position: the UE has to search for it among several candidates. This page follows a Format 1A DCI from its bits to its resource elements, in seven steps.

If you don't know what PDCCH(Physical Downlink Control Channel) is, refer to Physical Layer Channel : Downlink : PDCCH (Physical Downlink Control Channel) page first.

Followings are the topics to be covered in this page.

DCI Message Bit Generation

First step for creating PDCCH is to generate bit stream (informations) to be carried by PDCCH. As you know, PDCCH is the channel carrying the DCI information. So the first step is basically defining a specific DCI informations.

    % First you have to define properites of a eNodeB.  

    % NDLRB indicate System Bandwith in the unit of RBs.

    % NDLRB 6 = 1.4 Mhz, NDLRB 15 = 3.0 Mhz, NDLRB 25 = 5.0 Mhz,

    % NDLRB 50 = 10 Mhz, NDLRB 75 = 15 Mhz, NDLRB 100 = 20 Mhz

    % CellRefP indicate number of downlink Antenna. CellRefP = 1 means 1 transmission antenna (SISO)

    % NCellID indicate PCI (Physical Cell Identity) of the Cell

    % NSubframe indicate the subframe number.

    enb.CyclicPrefix = 'Normal';

    enb.PHICHDuration = 'Normal';

    enb.Ng = 'Sixth';

    enb.NDLRB = 6;

    enb.CellRefP = 1;

    enb.DuplexMode = 'FDD';

     

    enb.NCellID = 0;

    enb.NSubframe = 0;

    enb.CFI = 3;

     

     

    % Now populate all the information in DCI field as you like. Understanding details of DCI is also pretty huge topics.

    % You would need separate page for DCI for the details.

     

    dci.NDLRB = enb.NDLRB;

    dci.DCIFormat = 'Format1A';

    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;

     

    % once you defined all the detailed fields of DCI, just pass it to lteDCI() function with eNB info as follows,

    % then you will get the bit stream for the DCI.

     

    [dciMessage,dciMessageBits] = lteDCI(enb,dci);

     

    % Following shows one example the DCI bits generated by lteDCI(). This bit stream is the input to the step (1)

    % of the procedure described in Physical Layer Channel : Downlink : PDCCH (Physical Downlink Control Channel)

     

    dci.NDLRB = enb.NDLRB;

    dci.DCIFormat = 'Format1A';

    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;

     

    dciMessageBits(21 bits) = 1  0  1  0  0  1  0  0  1  0  1  0  0  0  0  0  0  0  0  0  0

The 21 bits are the Format 1A payload for NDLRB = 6 and FDD, with the fields in the order that lteDCI sets them. The bit count depends on the bandwidth, because the resource allocation field grows with the number of RB. The DCI page explains the fields of each format in detail.

  • lteDCI builds the payload : from the dci structure and the bandwidth in enb.
  • 21 bits for Format 1A at 1.4 MHz : the size grows with NDLRB.

DCI Channel Coding

The DCI payload is too small and too fragile to transmit as it is. The next step adds a CRC, protects the bits with a convolutional code, and stretches or cuts the result to fit the chosen aggregation level.

This section will show the result of steps (1)~(3) described in Physical Layer Channel : Downlink : PDCCH (Physical Downlink Control Channel).

    % First you have to define properites of a eNodeB.  

    % NDLRB indicate System Bandwith in the unit of RBs.

    % NDLRB 6 = 1.4 Mhz, NDLRB 15 = 3.0 Mhz, NDLRB 25 = 5.0 Mhz,

    % NDLRB 50 = 10 Mhz, NDLRB 75 = 15 Mhz, NDLRB 100 = 20 Mhz

    % CellRefP indicate number of downlink Antenna. CellRefP = 1 means 1 transmission antenna (SISO)

    % NCellID indicate PCI (Physical Cell Identity) of the Cell

    % NSubframe indicate the subframe number.

    enb.CyclicPrefix = 'Normal';

    enb.PHICHDuration = 'Normal';

    enb.Ng = 'Sixth';

    enb.NDLRB = 6;

    enb.CellRefP = 1;

    enb.DuplexMode = 'FDD';

     

    enb.NCellID = 0;

    enb.NSubframe = 0;

    enb.CFI = 3;

     

     

    % Now populate all the information in DCI field as you like. Understanding details of DCI is also pretty huge topics.

    % You would need separate page for DCI for the details.

     

    dci.NDLRB = enb.NDLRB;

    dci.DCIFormat = 'Format1A';

    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;

     

    % once you defined all the detailed fields of DCI, just pass it to lteDCI() function with eNB info as follows,

    % then you will get the bit stream for the DCI.

     

    [dciMessage,dciMessageBits] = lteDCI(enb,dci);

    % for this step, you need to set a couple of additional parameters as shown below. C_RNTI will be XORed to CRC bits

    % PDCCHFormat will determined Aggregation Level.

    %          PDCCHFormat 0 indicate Aggregation Level 1

    %          PDCCHFormat 1 indicate Aggregation Level 2

    %          PDCCHFormat 2 indicate Aggregation Level 4

    %          PDCCHFormat 3 indicate Aggregation Level 8

     

    C_RNTI = 100;                         

    pdcchConfig.RNTI = C_RNTI;            

    pdcchConfig.PDCCHFormat = 0;          

     

    % then pass dciMessageBits and pdcchConfig to lteDCIEncode, the you would get the encoded bitstream.

     

    codedDciBits = lteDCIEncode(pdcchConfig, dciMessageBits);

     

    % Following is one example of channel coding for DCI.

     

    dci.NDLRB = enb.NDLRB;

    dci.DCIFormat = 'Format1A';

    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;

     

    C_RNTI = 100;                         

    pdcchConfig.RNTI = C_RNTI;            

    pdcchConfig.PDCCHFormat = 0;

     

    codedDciBits (72 bits) =

      1  1  1  0  1  0  0  1  1  1  1  1  0  1  1  1  0  1  1  1  0  0  0  0  0  0  1  1  0  0  1  0  0  1  0  1  

      1  0  1  1  0  0  1  0  1  1  1  1  1  0  1  1  0  0  1  0  0  0  1  1  1  0  0  1  0  1  1  0  1  1  0  0

     

    dci.NDLRB = enb.NDLRB;

    dci.DCIFormat = 'Format1A';

    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;

     

    C_RNTI = 100;                         

    pdcchConfig.RNTI = C_RNTI;            

    pdcchConfig.PDCCHFormat = 1;

     

    codedDciBits (144 bits) =

      1  1  1  0  1  0  0  1  1  1  1  1  0  1  1  1  0  1  1  1  0  0  0  0  0  0  1  1  0  0  1  0  0  1  0  1  

      1  0  1  1  0  0  1  0  1  1  1  1  1  0  1  1  0  0  1  0  0  0  1  1  1  0  0  1  0  1  1  0  1  1  0  0

      0  0  1  1  0  1  0  0  0  1  1  0  1  1  1  1  0  1  0  0  1  1  0  0  0  0  1  0  1  0  1  1  0  1  0  0

      0  1  1  1  1  1  0  1  0  0  1  1  1  1  1  0  1  1  1  0  1  1  1  0  0  0  0  0  0  1  1  0  0  1  0  0

     

    dci.NDLRB = enb.NDLRB;

    dci.DCIFormat = 'Format1A';

    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;

     

    C_RNTI = 100;                         

    pdcchConfig.RNTI = C_RNTI;            

    pdcchConfig.PDCCHFormat = 2;

     

    codedDciBits (288 bits) =

      1  1  1  0  1  0  0  1  1  1  1  1  0  1  1  1  0  1  1  1  0  0  0  0  0  0  1  1  0  0  1  0  0  1  0  1  

      1  0  1  1  0  0  1  0  1  1  1  1  1  0  1  1  0  0  1  0  0  0  1  1  1  0  0  1  0  1  1  0  1  1  0  0

      0  0  1  1  0  1  0  0  0  1  1  0  1  1  1  1  0  1  0  0  1  1  0  0  0  0  1  0  1  0  1  1  0  1  0  0

      0  1  1  1  1  1  0  1  0  0  1  1  1  1  1  0  1  1  1  0  1  1  1  0  0  0  0  0  0  1  1  0  0  1  0  0

      1  0  1  1  0  1  1  0  0  1  0  1  1  1  1  1  0  1  1  0  0  1  0  0  0  1  1  1  0  0  1  0  1  1  0  1

      1  0  0  0  0  1  1  0  1  0  0  0  1  1  0  1  1  1  1  0  1  0  0  1  1  0  0  0  0  1  0  1  0  1  1  0

      1  0  0  0  1  1  1  1  1  0  1  0  0  1  1  1  1  1  0  1  1  1  0  1  1  1  0  0  0  0  0  0  1  1  0  0

      1  0  0  1  0  1  1  0  1  1  0  0  1  0  1  1  1  1  1  0  1  1  0  0  1  0  0  0  1  1  1  0  0  1  0  1

     

    dci.NDLRB = enb.NDLRB;

    dci.DCIFormat = 'Format1A';

    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;

     

    C_RNTI = 100;                         

    pdcchConfig.RNTI = C_RNTI;            

    pdcchConfig.PDCCHFormat = 3;

     

    codedDciBits (576 bits) =

      1  1  1  0  1  0  0  1  1  1  1  1  0  1  1  1  0  1  1  1  0  0  0  0  0  0  1  1  0  0  1  0  0  1  0  1

      1  0  1  1  0  0  1  0  1  1  1  1  1  0  1  1  0  0  1  0  0  0  1  1  1  0  0  1  0  1  1  0  1  1  0  0

      0  0  1  1  0  1  0  0  0  1  1  0  1  1  1  1  0  1  0  0  1  1  0  0  0  0  1  0  1  0  1  1  0  1  0  0

      0  1  1  1  1  1  0  1  0  0  1  1  1  1  1  0  1  1  1  0  1  1  1  0  0  0  0  0  0  1  1  0  0  1  0  0

      1  0  1  1  0  1  1  0  0  1  0  1  1  1  1  1  0  1  1  0  0  1  0  0  0  1  1  1  0  0  1  0  1  1  0  1

      1  0  0  0  0  1  1  0  1  0  0  0  1  1  0  1  1  1  1  0  1  0  0  1  1  0  0  0  0  1  0  1  0  1  1  0

      1  0  0  0  1  1  1  1  1  0  1  0  0  1  1  1  1  1  0  1  1  1  0  1  1  1  0  0  0  0  0  0  1  1  0  0

      1  0  0  1  0  1  1  0  1  1  0  0  1  0  1  1  1  1  1  0  1  1  0  0  1  0  0  0  1  1  1  0  0  1  0  1

      1  0  1  1  0  0  0  0  1  1  0  1  0  0  0  1  1  0  1  1  1  1  0  1  0  0  1  1  0  0  0  0  1  0  1  0

      1  1  0  1  0  0  0  1  1  1  1  1  0  1  0  0  1  1  1  1  1  0  1  1  1  0  1  1  1  0  0  0  0  0  0  1

      1  0  0  1  0  0  1  0  1  1  0  1  1  0  0  1  0  1  1  1  1  1  0  1  1  0  0  1  0  0  0  1  1  1  0  0

      1  0  1  1  0  1  1  0  0  0  0  1  1  0  1  0  0  0  1  1  0  1  1  1  1  0  1  0  0  1  1  0  0  0  0  1

      0  1  0  1  1  0  1  0  0  0  1  1  1  1  1  0  1  0  0  1  1  1  1  1  0  1  1  1  0  1  1  1  0  0  0  0

      0  0  1  1  0  0  1  0  0  1  0  1  1  0  1  1  0  0  1  0  1  1  1  1  1  0  1  1  0  0  1  0  0  0  1  1

      1  0  0  1  0  1  1  0  1  1  0  0  0  0  1  1  0  1  0  0  0  1  1  0  1  1  1  1  0  1  0  0  1  1  0  0

      0  0  1  0  1  0  1  1  0  1  0  0  0  1  1  1  1  1  0  1  0  0  1  1  1  1  1  0  1  1  1  0  1  1  1  0

36.212 v19.3.0 clause 5.3.3 defines the three steps. A 16-bit CRC is added to the 21 DCI bits, and the CRC is scrambled with the RNTI, 100 in this example. So only the UE with that RNTI finds a valid CRC. The 37 bits then go through the rate 1/3 tail-biting convolutional code, which gives 111 bits. Rate matching finally cuts or repeats them to 72 bits per CCE: 72, 144, 288 or 576 bits for aggregation levels 1, 2, 4 and 8.

The outputs above show the effect of the rate matching. The first 72 bits of every codeword are the same, because the rate matching always reads the same circular buffer from the same starting point. Aggregation level 1 punctures the 111 bits down to 72, and the higher levels repeat them. More repetition means more energy per DCI bit, which is how a UE at the cell edge still decodes its DCI.

  • CRC scrambled by the RNTI : the UE finds a valid CRC only for its own DCI.
  • 37 bits become 111 : the rate 1/3 tail-biting convolutional code.
  • 72 bits per CCE : aggregation level 1 punctures, and higher levels repeat.
  • Same first 72 bits at every level : the circular buffer is read from the same start.

Calculation of Available Resources

This section shows how to figure out the amount of resources that can be allocated for PDCCH transmission. The amount of the resources for PDCCH is determined mainly by System Bandwidth and CFI which are the attribute of eNB.

    % First you have to define properites of a eNodeB.  

    % NDLRB indicate System Bandwith in the unit of RBs.

    % NDLRB 6 = 1.4 Mhz, NDLRB 15 = 3.0 Mhz, NDLRB 25 = 5.0 Mhz,

    % NDLRB 50 = 10 Mhz, NDLRB 75 = 15 Mhz, NDLRB 100 = 20 Mhz

    % CellRefP indicate number of downlink Antenna. CellRefP = 1 means 1 transmission antenna (SISO)

    % NCellID indicate PCI (Physical Cell Identity) of the Cell

    % NSubframe indicate the subframe number.

    enb.CyclicPrefix = 'Normal';

    enb.PHICHDuration = 'Normal';

    enb.Ng = 'Sixth';

    enb.NDLRB = 6;

    enb.CellRefP = 1;

    enb.DuplexMode = 'FDD';

    enb.NCellID = 0;

    enb.NSubframe = 0;

    enb.CFI = 3;

     

    % If you pass the enb into ltePDCCHInfo() function, it will give you the amount of resources that can be allocated

    % for PDCCH allocation. This is not the amount of resource for only one DCI. It will give you the total/maximum

    % amount of the resources that can be allocated for PDCCH.

     

    pdcchDims = ltePDCCHInfo(enb);

     

    C_RNTI = 100;                         

    pdcchConfig.RNTI = C_RNTI;            

    pdcchConfig.PDCCHFormat = 0;

     

    pdcchDims =

            NREG: 59

             NRE: 236

            NCCE: 6

        NREGUsed: 54

         NREUsed: 216

            MTot: 472

        NSymbols: 4

These numbers can be counted by hand. With NDLRB = 6 and CFI = 3, the control region has 4 OFDM symbols, because a bandwidth of 10 RB or less adds one symbol to the CFI. Symbol 0 has 12 REGs, because the RS take 2 of every 6 subcarriers, and symbols 1 to 3 have 18 REGs each. The total of 66 REGs loses 4 to the PCFICH and 3 to the PHICH, which leaves NREG = 59 and NRE = 236.

A CCE is 9 REGs, so the 59 REGs give NCCE = 6 CCEs, and 6 CCEs use NREGUsed = 54 REGs. The other 5 REGs stay empty. MTot = 472 is the number of bits the 236 REs can carry with QPSK, and it is the length of the bit vector that ltePDCCH expects later.

  • 4 control symbols : CFI = 3 plus 1, because NDLRB is 10 or less.
  • 59 REGs : 66 minus 4 for the PCFICH and 3 for the PHICH.
  • 6 CCEs of 9 REGs : 5 REGs are left over.
  • MTot = 472 bits : 236 REs with 2 bits each.

Locate PDCCH Candidates

This section would show PDCCH Candidate. This is not specific to each DCI, it is about the all the possible spaces that can carry on PDCCH, so you don't need to specify any specific DCI at this step.

    % First you have to define properites of a eNodeB.  

    % NDLRB indicate System Bandwith in the unit of RBs.

    % NDLRB 6 = 1.4 Mhz, NDLRB 15 = 3.0 Mhz, NDLRB 25 = 5.0 Mhz,

    % NDLRB 50 = 10 Mhz, NDLRB 75 = 15 Mhz, NDLRB 100 = 20 Mhz

    % CellRefP indicate number of downlink Antenna. CellRefP = 1 means 1 transmission antenna (SISO)

    % NCellID indicate PCI (Physical Cell Identity) of the Cell

    % NSubframe indicate the subframe number.

    enb.CyclicPrefix = 'Normal';

    enb.PHICHDuration = 'Normal';

    enb.Ng = 'Sixth';

    enb.NDLRB = 6;

    enb.CellRefP = 1;

    enb.DuplexMode = 'FDD';

     

    enb.NCellID = 0;

    enb.NSubframe = 0;

    enb.CFI = 3;

     

    % for this step, you need to set a couple of additional parameters as shown below. C_RNTI will be XORed to CRC bits

    % PDCCHFormat will determined Aggregation Level.

    %          PDCCHFormat 0 indicate Aggregation Level 1

    %          PDCCHFormat 1 indicate Aggregation Level 2

    %          PDCCHFormat 2 indicate Aggregation Level 4

    %          PDCCHFormat 3 indicate Aggregation Level 8

     

    C_RNTI = 100;                         

    pdcchConfig.RNTI = C_RNTI;            

    pdcchConfig.PDCCHFormat = 0;          

     

    % If you pass the enb into ltePDCCHInfo() function, it will give you the amount of resources that can be allocated

    % for PDCCH allocation. This is not the amount of resource for only one DCI. It will give you the total/maximum

    % amount of the resources that can be allocated for PDCCH.

    % the output of ltePDCCHInfo() will be used ltePDCCHSpace() in next step to calculate PDCCH Space.

     

    pdcchDims = ltePDCCHInfo(enb);

     

    % With ltePDCCHSpace, you can get the list of all the possible spaces that can carry PDCCH. In this example,

    % the space were shown in the unit of bits.

     

    pdcchBits = -1*ones(pdcchDims.MTot, 1);

    candidates = ltePDCCHSpace(enb, pdcchConfig, {'bits', '1based'});

     

    % Followings are not required information in this post, but I put this as a additional reference for your study.

    % If you want to calculate the PDCCH space manually to understand details of 3GPP specification.

    % this can be a good information to verify your own calculation.

     

    candidatesRE = ltePDCCHSpace(enb, pdcchConfig, {'re', '1based'});

    candidatesREG = ltePDCCHSpace(enb, pdcchConfig, {'reg', '1based'});

     

     

    enb.NDLRB = 6;

    enb.CFI = 3;

     

    C_RNTI = 100;                         

    pdcchConfig.RNTI = C_RNTI;            

    pdcchConfig.PDCCHFormat = 0;

     

    candidates =

             145         216  ==> 72 bits

             217         288  ==> 72 bits

             289         360  ==> 72 bits

             361         432  ==> 72 bits

               1          72  ==> 72 bits

              73         144  ==> 72 bits

     

    candidatesRE =

              73         108  ==> 36 REs

             109         144  ==> 36 REs

             145         180  ==> 36 REs

             181         216  ==> 36 REs

               1          36  ==> 36 REs

              37          72  ==> 36 REs

     

    candidatesREG =

              19          27  ==> 9 REG

              28          36  ==> 9 REG

              37          45  ==> 9 REG

              46          54  ==> 9 REG

               1           9  ==> 9 REG

              10          18  ==> 9 REG

     

    enb.NDLRB = 6;

    enb.CFI = 3;

     

    C_RNTI = 100;                         

    pdcchConfig.RNTI = C_RNTI;            

    pdcchConfig.PDCCHFormat = 1;

     

    candidates =

             289         432  ==> 144 bits

               1         144  ==> 144 bits

             145         288  ==> 144 bits

             289         432  ==> 144 bits

               1         144  ==> 144 bits

             145         288  ==> 144 bits

     

    candidatesRE =

             145         216  ==> 72 RE

               1          72  ==> 72 RE

              73         144  ==> 72 RE

             145         216  ==> 72 RE

               1          72  ==> 72 RE

              73         144  ==> 72 RE

     

    candidatesREG =

              37          54  ==> 18 REG

               1          18  ==> 18 REG

              19          36  ==> 18 REG

              37          54  ==> 18 REG

               1          18  ==> 18 REG

              19          36  ==> 18 REG

     

    enb.NDLRB = 6;

    enb.CFI = 3;

     

    C_RNTI = 100;                         

    pdcchConfig.RNTI = C_RNTI;            

    pdcchConfig.PDCCHFormat = 2;

     

    candidates =

               1         288  ==> 288 bits

               1         288  ==> 288 bits

     

    candidatesRE =

               1         144  ==> 144 RE

               1         144  ==> 144 RE

     

    candidatesREG =

               1          36  ==> 36 REG

               1          36  ==> 36 REG

     

    enb.NDLRB = 6;

    enb.CFI = 3;

     

    C_RNTI = 100;                         

    pdcchConfig.RNTI = C_RNTI;            

    pdcchConfig.PDCCHFormat = 3;

     

    candidates =

               Not Applicable

     

    candidatesRE =

               Not Applicable

     

    candidatesREG =

               Not Applicable

The candidate lists follow 36.213 v19.4.0 clause 9.1.1 for the UE-specific search space. A UE monitors 6, 6, 2 and 2 candidates at aggregation levels 1, 2, 4 and 8. The first CCE of candidate m is L x ((Yk + m) mod ⌊NCCE/L⌋), where Yk is a hash of the RNTI and the subframe. For RNTI 100 in subframe 0, Y0 = 39827 x 100 mod 65537 = 50480.

That value reproduces every list above. At level 1, 50480 mod 6 = 2, so the candidates start at CCE 2, 3, 4, 5, 0 and 1, which are bits 145, 217, 289, 361, 1 and 73. At level 2, only 3 positions exist, so the 6 candidates cover each position twice. At level 4, only 1 position exists, and both candidates are the same. Level 8 needs 8 CCEs, and this bandwidth has only 6, so it has no candidate at all.

  • Yk from the RNTI : each UE searches in a different place.
  • 6, 6, 2 and 2 candidates : for aggregation levels 1, 2, 4 and 8.
  • Repeated candidates at levels 2 and 4 : 6 CCEs leave only 3 and 1 distinct positions.
  • No level 8 at 1.4 MHz with CFI 3 : only 6 CCEs exist.

Allocate the codedBits to one of the Candidates

In this section, I would create a long bit string that can contain all the possible PDCCH and then allocated the PDCCH codeBits to one of the candidate area.

    % First you have to define properites of a eNodeB.  

    % NDLRB indicate System Bandwith in the unit of RBs.

    % NDLRB 6 = 1.4 Mhz, NDLRB 15 = 3.0 Mhz, NDLRB 25 = 5.0 Mhz,

    % NDLRB 50 = 10 Mhz, NDLRB 75 = 15 Mhz, NDLRB 100 = 20 Mhz

    % CellRefP indicate number of downlink Antenna. CellRefP = 1 means 1 transmission antenna (SISO)

    % NCellID indicate PCI (Physical Cell Identity) of the Cell

    % NSubframe indicate the subframe number.

    enb.CyclicPrefix = 'Normal';

    enb.PHICHDuration = 'Normal';

    enb.Ng = 'Sixth';

    enb.NDLRB = 6;

    enb.CellRefP = 1;

    enb.DuplexMode = 'FDD';

     

    enb.NCellID = 0;

    enb.NSubframe = 0;

    enb.CFI = 3;

     

    % Now populate all the information in DCI field as you like. Understanding details of DCI is also pretty huge topics.

    % You would need separate page for DCI for the details.

     

    dci.NDLRB = enb.NDLRB;

    dci.DCIFormat = 'Format1A';

    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;

     

    % once you defined all the detailed fields of DCI, just pass it to lteDCI() function with eNB info as follows,

    % then you will get the bit stream for the DCI.

     

    [dciMessage,dciMessageBits] = lteDCI(enb,dci);

     

    % for this step, you need to set a couple of additional parameters as shown below. C_RNTI will be XORed to CRC bits

    % PDCCHFormat will determined Aggregation Level.

    %          PDCCHFormat 0 indicate Aggregation Level 1

    %          PDCCHFormat 1 indicate Aggregation Level 2

    %          PDCCHFormat 2 indicate Aggregation Level 4

    %          PDCCHFormat 3 indicate Aggregation Level 8

     

    C_RNTI = 100;                         

    pdcchConfig.RNTI = C_RNTI;            

    pdcchConfig.PDCCHFormat = 0;          

     

    % Then if you pass the dciMessageBits and pdcchConfig into lteDCIEncode(), it will generated codedDciBits.

     

    codedDciBits = lteDCIEncode(pdcchConfig, dciMessageBits);

    pdcchDims = ltePDCCHInfo(enb);

     

    % generate an array with the length that can accommodate all the possible PDCCH bits.

     

    pdcchBits = -1*ones(pdcchDims.MTot, 1);

     

    % With ltePDCCHSpace, you can get the list of all the possible spaces that can carry PDCCH. In this example,

    % the space were shown in the unit of bits.

    candidates = ltePDCCHSpace(enb, pdcchConfig, {'bits', '1based'});

     

    % select one of the candidate bitSection and assign the codedDcitBits. You can select any candidate bit section,

    % but in this example, I selected the first candidate section.

     

    pdcchBits ( candidates(1, 1) : candidates(1, 2) ) = codedDciBits;

The code fills the 472-bit vector with -1 and writes the 72 coded bits into the first candidate, bits 145 to 216. The -1 marks bits that carry no DCI, and ltePDCCH turns them into zero-power symbols. A real eNB fills several candidates in the same subframe, one for each scheduled UE, and the search space hashing keeps their candidates apart.

  • -1 marks unused bits : they become zero-power symbols.
  • First candidate: bits 145 to 216 : CCE 2 for RNTI 100 in subframe 0.

Generating PDCCH Symbols

The bit vector now becomes symbols. The function ltePDCCH scrambles the bits, modulates them with QPSK, and interleaves the result, so the symbols of one DCI no longer sit next to each other. The plot below shows how far apart they end up.

In this section, I will generate the modulated symbol (a bit string modulated by QPSK) for PDCCH.

    % First you have to define properites of a eNodeB.  

    % NDLRB indicate System Bandwith in the unit of RBs.

    % NDLRB 6 = 1.4 Mhz, NDLRB 15 = 3.0 Mhz, NDLRB 25 = 5.0 Mhz,

    % NDLRB 50 = 10 Mhz, NDLRB 75 = 15 Mhz, NDLRB 100 = 20 Mhz

    % CellRefP indicate number of downlink Antenna. CellRefP = 1 means 1 transmission antenna (SISO)

    % NCellID indicate PCI (Physical Cell Identity) of the Cell

    % NSubframe indicate the subframe number.

    enb.CyclicPrefix = 'Normal';

    enb.PHICHDuration = 'Normal';

    enb.Ng = 'Sixth';

    enb.NDLRB = 6;

    enb.CellRefP = 1;

    enb.DuplexMode = 'FDD';

     

    enb.NCellID = 0;

    enb.NSubframe = 0;

    enb.CFI = 3;

     

    % Now populate all the information in DCI field as you like. Understanding details of DCI is also pretty huge topics.

    % You would need separate page for DCI for the details.

     

    dci.NDLRB = enb.NDLRB;

    dci.DCIFormat = 'Format1A';

    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;

     

    % once you defined all the detailed fields of DCI, just pass it to lteDCI() function with eNB info as follows,

    % then you will get the bit stream for the DCI.

     

    [dciMessage,dciMessageBits] = lteDCI(enb,dci);

     

    % for this step, you need to set a couple of additional parameters as shown below. C_RNTI will be XORed to CRC bits

    % PDCCHFormat will determined Aggregation Level.

    %          PDCCHFormat 0 indicate Aggregation Level 1

    %          PDCCHFormat 1 indicate Aggregation Level 2

    %          PDCCHFormat 2 indicate Aggregation Level 4

    %          PDCCHFormat 3 indicate Aggregation Level 8

     

    C_RNTI = 100;                         

    pdcchConfig.RNTI = C_RNTI;            

    pdcchConfig.PDCCHFormat = 0;          

     

    % Then if you pass the dciMessageBits and pdcchConfig into lteDCIEncode(), it will generated codedDciBits.

     

    codedDciBits = lteDCIEncode(pdcchConfig, dciMessageBits);

    pdcchDims = ltePDCCHInfo(enb);

     

    % generate an array with the length that can accommodate all the possible PDCCH bits.

     

    pdcchBits = -1*ones(pdcchDims.MTot, 1);

     

    % With ltePDCCHSpace, you can get the list of all the possible spaces that can carry PDCCH. In this example,

    % the space were shown in the unit of bits.

     

    candidates = ltePDCCHSpace(enb, pdcchConfig, {'bits', '1based'});

     

    % select one of the candidate bitSection and assign the codedDcitBits. You can select any candidate bit section,

    % but in this example, I selected the first candidate section.

     

    pdcchBits ( candidates(1, 1) : candidates(1, 2) ) = codedDciBits;

     

    % if pass the encodedBits into ltePDCCH(), it will generate the modulated physical layer symbols.

     

    pdcch_sym = ltePDCCH(enb, pdcchBits);

    pdcch_sym_arrayIndex = 0:length(pdcch_sym)-1;

     

    % Now I will plot the modulated symbol in two forms. Constellation in the left side and I/Q in bit sequence on the

    % right side.

     

    subplot(1,3,1);

    plot(real(pdcch_sym),imag(pdcch_sym),'ro','MarkerFaceColor',[1 0 0]);

    title('Constellation');

     

    subplot(1,3,[2 3]);

    plot(pdcch_sym_arrayIndex,real(pdcch_sym),'ro-',pdcch_sym_arrayIndex,imag(pdcch_sym),'bo-');

    xlim([0 max(pdcch_sym_arrayIndex)]);

    title('PDCCH index vs PDCCH value. Red -> real, Blue -> Imaginary');

     

    enb.NCellID = 0;

    enb.NSubframe = 0;

    enb.CFI = 3;

     

    dci.NDLRB = enb.NDLRB;

    dci.DCIFormat = 'Format1A';

    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;

     

    C_RNTI = 100;                

    pdcchConfig.RNTI = C_RNTI;   

    pdcchConfig.PDCCHFormat = 0;  

     

    Constellation and values of the 236 PDCCH symbols with one Format 1A DCI at aggregation level 1

     

236 symbol positions. Only 36 are non-zero, in 9 groups of 4, one group for each REG of the single CCE.

The 72 coded bits give 36 QPSK symbols, and the other 200 positions carry the zero-power symbols. The 36 symbols appear as 9 separate groups of 4, spread over the whole plot. 36.211 v19.3.0 clause 6.8.5 applies a sub-block interleaver and a cell-specific cyclic shift to the REG quadruplets, so one CCE is spread over the whole control region. That spreading gives the PDCCH frequency diversity and averages the interference between neighbouring cells.

  • 36 QPSK symbols per CCE : 72 bits, 2 per symbol.
  • 9 groups of 4 : one quadruplet per REG.
  • Interleaved over the control region : frequency diversity for every PDCCH.

Displaying PDCCH Region : RE Mapping for PDCCH

The last step places the symbols in the grid, and it shows how CFI changes the size of the control region. The grids below compare CFI 1 and CFI 3 at two bandwidths, first for the whole PDCCH region and then for the single DCI.

This the last step allocating each physical layer symbols to corresponding resource elements in a subframe.

    % First you have to define properites of a eNodeB.  

    % NDLRB indicate System Bandwith in the unit of RBs.

    % NDLRB 6 = 1.4 Mhz, NDLRB 15 = 3.0 Mhz, NDLRB 25 = 5.0 Mhz,

    % NDLRB 50 = 10 Mhz, NDLRB 75 = 15 Mhz, NDLRB 100 = 20 Mhz

    % CellRefP indicate number of downlink Antenna. CellRefP = 1 means 1 transmission antenna (SISO)

    % NCellID indicate PCI (Physical Cell Identity) of the Cell

    % NSubframe indicate the subframe number.

    enb.CyclicPrefix = 'Normal';

    enb.PHICHDuration = 'Normal';

    enb.Ng = 'Sixth';

    enb.NDLRB = 6;

    enb.CellRefP = 1;

    enb.DuplexMode = 'FDD';

     

    enb.NCellID = 0;

    enb.NSubframe = 0;

    enb.CFI = 1;

     

    % following is PHICH parameters that will be used ltePHICH() function in later step.

     

    PHICH_Group_Index = 0;

    PHICH_Sequence_Index = 1;

    HARQ_Indicator_Value = 0; % 0 = NACK, 1 = ACK

     

    % Now populate all the information in DCI field as you like. Understanding details of DCI is also pretty huge topics.

    % You would need separate page for DCI for the details.

     

    dci.NDLRB = enb.NDLRB;

    dci.DCIFormat = 'Format1A';

    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;

     

    % once you defined all the detailed fields of DCI, just pass it to lteDCI() function with eNB info as follows,

    % then you will get the bit stream for the DCI.

     

    [dciMessage,dciMessageBits] = lteDCI(enb,dci);

     

    % for this step, you need to set a couple of additional parameters as shown below. C_RNTI will be XORed to CRC bits

    % PDCCHFormat will determined Aggregation Level.

    %          PDCCHFormat 0 indicate Aggregation Level 1

    %          PDCCHFormat 1 indicate Aggregation Level 2

    %          PDCCHFormat 2 indicate Aggregation Level 4

    %          PDCCHFormat 3 indicate Aggregation Level 8

     

    C_RNTI = 100;                         

    pdcchConfig.RNTI = C_RNTI;            

    pdcchConfig.PDCCHFormat = 0;          

     

    % Then if you pass the dciMessageBits and pdcchConfig into lteDCIEncode(), it will generated codedDciBits.

     

    codedDciBits = lteDCIEncode(pdcchConfig, dciMessageBits);

     

    pdcchDims = ltePDCCHInfo(enb);

     

    % generate an array with the length that can accommodate all the possible PDCCH bits.

     

    pdcchBits = -1*ones(pdcchDims.MTot, 1);

     

    % With ltePDCCHSpace, you can get the list of all the possible spaces that can carry PDCCH. In this example,

    % the space were shown in the unit of bits.

     

    candidates = ltePDCCHSpace(enb, pdcchConfig, {'bits', '1based'});

     

    % select one of the candidate bitSection and assign the codedDcitBits. You can select any candidate bit section,

    % but in this example, I selected the first candidate section.

     

    pdcchBits ( candidates(1, 1) : candidates(1, 2) ) = codedDciBits;

     

    % if pass the encodedBits into ltePDCCH(), it will generate the modulated physical layer symbols.

     

    pdcch_sym = ltePDCCH(enb, pdcchBits);

     

    % now figure out all the RE (Resource Element) indices for the PDCCH.

     

    pdcch_sym_ind = ltePDCCHIndices(enb,{'1based','re'});

    pdcch_sym_arrayIndex = 0:length(pdcch_sym)-1;

     

    % Following is to create an empty resource grid for one subframe.

     

    resourceGrid = lteDLResourceGrid(enb);

     

    % Following is to create symbols for Cell Specific Reference Signal and make a list of resource index for the

    % reference signal.

     

    rsAnt0 = lteCellRS(enb,0);

    indAnt0 = lteCellRSIndices(enb,0);

    resourceGrid(indAnt0) = rsAnt0;

     

    % Following is to create symbols for PBCH and make a list of resource index for the signal (channel)

     

    mib_bits = lteMIB(enb);

    bch_cw = lteBCH(enb,mib_bits);

     

    pbch_sym = ltePBCH(enb,bch_cw);

    pbch_sym_arrayIndex = 0:length(pbch_sym)-1;

    pbch_sym_ind = ltePBCHIndices(enb,{'1based','re'});

     

    % Following is to create symbols for PSS and make a list of resource index for the signal

     

    pss = ltePSS(enb);

    pss_arrayIndex = 0:length(pss)-1;

    pss_sym_ind = ltePSSIndices(enb,0,{'1based','re'});

     

    % Following is to create symbols for SSS and make a list of resource index for the signal

     

    sss = lteSSS(enb);

    sss_arrayIndex = 0:length(sss)-1;

    sss_sym_ind = lteSSSIndices(enb,0,{'1based','re'});

     

    % Following is to create symbols for PCFICH and make a list of resource index for the signal

     

    cfi_cw = lteCFI(enb);

    pcfich_sym = ltePCFICH(enb,cfi_cw);

    pcfich_sym_arrayIndex = 0:length(pcfich_sym)-1;

    pcfich_sym_ind = ltePCFICHIndices(enb,{'1based','re'});

     

    % Following is to create symbols for PHICH and make a list of resource index for the signal

     

    phich_sym = ltePHICH(enb,[PHICH_Group_Index,PHICH_Sequence_Index,HARQ_Indicator_Value]);

    phich_sym_arrayIndex = 0:length(phich_sym)-1;

    phich_sym_ind = ltePHICHIndices(enb,{'1based','re'});

     

     

    % Following part is filling the resource grid with each of the signal.. but if you see carefully I didn't fill this

    % with real symbol number, I just filled it with a constant that I arbitrarily set. This is just for visualization..

    % just to allocate constant/outstanding color for each signal. When you  use this resource grid for real

    % transmission (not for visualization), fill the resourceGrid with real symbol value you generated above.

     

    pss_scale = 0.2;

    sss_scale = 0.4;

    phich_scale = 0.7;

    pcfich_scale = 0.5;

    pbch_scale = 0.7;

    pdcch_scale = 0.9;

     

    resourceGrid(pss_sym_ind) = pss_scale;

    resourceGrid(sss_sym_ind) = sss_scale;

    resourceGrid(pcfich_sym_ind) = pcfich_scale;

    resourceGrid(phich_sym_ind) = phich_scale;

    resourceGrid(pbch_sym_ind) = pbch_scale;

    resourceGrid(pdcch_sym_ind) = pdcch_scale;

     

    % Following is to display the resource grid. I didn't find any proper functions in the toolbox to display

    % one subframe grid as I like. So I used a little bit of tricks. First I plot 3D surface graph with the grid and

    % move the view point right on top of the plot so that it looks like plane 2D grid.

     

    xStep = 0:13;

    yStep = 0:(enb.NDLRB*12-1);

    surface(xStep,yStep,abs(resourceGrid));

    axis([0 13 0 (enb.NDLRB*12-1) 0 1]);

    view([0,90]);

    set(gca,'xtick',[0 6 7 13]);

    set(gca,'ytick',[[0:12:enb.NDLRB*12-1] [enb.NDLRB*12-1]]);

     

The first set of examples shows the location of PDCCH Resource Elements in 1.4 Mhz BW. The orange REs in the symbol 0~1 in left side and 0~3 symbols in right side represents PDCCH.

enb.NCellID = 0;

enb.CellRefP = 1;

enb.PHICHDuration = 'Normal';

enb.Ng = 'Sixth';

enb.NDLRB = 6;

enb.CFI = 1;

enb.NCellID = 0;

enb.CellRefP = 1;

enb.PHICHDuration = 'Normal';

enb.Ng = 'Sixth';

enb.NDLRB = 6;

enb.CFI = 3;

Subframe grid with NDLRB 6 and CFI 1 showing the PDCCH region in symbols 0 and 1

Subframe grid with NDLRB 6 and CFI 3 showing the PDCCH region in symbols 0 to 3

1.4 MHz. CFI 1 gives 2 control symbols and CFI 3 gives 4, because the bandwidth is 10 RB or less.

The second set of examples shows the location of PDCCH Resource Elements in 5.0 Mhz BW. The orange REs in the symbol 0 in left side and 0~2 symbols in right side represents PDCCH.

enb.NCellID = 0;

enb.CellRefP = 1;

enb.PHICHDuration = 'Normal';

enb.Ng = 'Sixth';

enb.NDLRB = 25;

enb.CFI = 1;

enb.NCellID = 0;

enb.CellRefP = 1;

enb.PHICHDuration = 'Normal';

enb.Ng = 'Sixth';

enb.NDLRB = 25;

enb.CFI = 3;

Subframe grid with NDLRB 25 and CFI 1 showing the PDCCH region in symbol 0

Subframe grid with NDLRB 25 and CFI 3 showing the PDCCH region in symbols 0 to 2

5 MHz. CFI 1 gives 1 control symbol and CFI 3 gives 3.

The previous example shows the all the possible PDCCH REs, if you modify just one line as shown below. you can display the REs that are allocated for the specific PDCCH.

    pss_scale = 0.2;

    sss_scale = 0.4;

    phich_scale = 0.7;

    pcfich_scale = 0.5;

    pbch_scale = 0.7;

    pdcch_scale = 0.9;

     

    resourceGrid(pss_sym_ind) = pss_scale;

    resourceGrid(sss_sym_ind) = sss_scale;

    resourceGrid(pcfich_sym_ind) = pcfich_scale;

    resourceGrid(phich_sym_ind) = phich_scale;

    resourceGrid(pbch_sym_ind) = pbch_scale;

    resourceGrid(pdcch_sym_ind) = pdcch_scale .* pdcch_sym;

     

    xStep = 0:13;

    yStep = 0:(enb.NDLRB*12-1);

    surface(xStep,yStep,abs(resourceGrid));

    axis([0 13 0 (enb.NDLRB*12-1) 0 1]);

    view([0,90]);

    set(gca,'xtick',[0 6 7 13]);

    set(gca,'ytick',[[0:12:enb.NDLRB*12-1] [enb.NDLRB*12-1]]);

The first set of examples shows the location of PDCCH Resource Elements in 1.4 Mhz BW. The orange REs in the symbol 0~1 in left side and 0~3 symbols in right side represents PDCCH.

enb.NCellID = 0;

enb.CellRefP = 1;

enb.PHICHDuration = 'Normal';

enb.Ng = 'Sixth';

enb.NDLRB = 6;

enb.CFI = 1;

 

dci.NDLRB = enb.NDLRB;

dci.DCIFormat = 'Format1A';

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;

enb.NCellID = 0;

enb.CellRefP = 1;

enb.PHICHDuration = 'Normal';

enb.Ng = 'Sixth';

enb.NDLRB = 6;

enb.CFI = 3;

 

dci.NDLRB = enb.NDLRB;

dci.DCIFormat = 'Format1A';

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;

Subframe grid with NDLRB 6 and CFI 1 showing only the REs of one PDCCH

Subframe grid with NDLRB 6 and CFI 3 showing only the REs of one PDCCH

Only the REs of the single DCI are coloured here. Its 9 REGs are scattered over the control symbols, as the interleaving in the previous section predicts.

36.211 clause 6.7 sets the number of control symbols to CFI when the bandwidth is more than 10 RB, and to CFI + 1 when it is 10 RB or less. That is why the same CFI gives one more symbol at 1.4 MHz than at 5 MHz. The small bandwidth has so few REs per symbol that it needs the extra symbol to carry even a few DCIs.

  • CFI + 1 symbols at 10 RB or less : 2 and 4 symbols at 1.4 MHz.
  • CFI symbols above 10 RB : 1 and 3 symbols at 5 MHz.
  • One DCI is scattered : its 9 REGs spread over the whole control region.

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.211 v19.3.0 - clause 6.8, Physical downlink control channel

[2] 3GPP TS 36.212 v19.3.0 - clause 5.3.3, Downlink control information

[3] 3GPP TS 36.213 v19.4.0 - clause 9.1.1, PDCCH assignment procedure

[4] Physical Layer Channel : Downlink : PDCCH