Main Content

nrPUSCHDecode

Decode PUSCH modulation symbols

Description

[cw,symbols] = nrPUSCHDecode(sym,mod,nid,rnti) returns soft bits cw and constellation symbols symbols resulting from the inverse operation of physical uplink shared channel (PUSCH) processing from TS 38.211 Section 6.3.1 [1]. The decoding consists of layer demapping, demodulation of symbols sym with modulation scheme mod, and descrambling with scrambling identity nid. The input rnti is the radio network temporary identifier (RNTI) of the user equipment (UE). In this syntax, multi-input multi-output (MIMO) deprecoding and transform deprecoding are disabled and the function assumes that the input symbols contain data symbols only.

example

[cw,symbols] = nrPUSCHDecode(sym,mod,nid,rnti,nVar) also specifies the noise variance scaling factor of the soft bits in the PUSCH demodulation. When you use this syntax, the function assumes the input symbols contain data symbols only.

[cw,symbols] = nrPUSCHDecode(sym,mod,nid,rnti,nVar,transformPrecode,mrb) also specifies transform deprecoding as a logical value and the number of allocated PUSCH resource blocks. When transformPrecode is set to true, the function applies the inverse of transform precoding defined in TS 38.211 Section 6.3.1.4. mrb specifies the allocated number of PUSCH resource blocks. The MIMO deprecoding is disabled. When you use this syntax, the function assumes the input symbols contain data symbols only.

[cw,symbols] = nrPUSCHDecode(sym,mod,nid,rnti,nVar,transformPrecode,mrb,txScheme,nLayers,tpmi) also specifies the transmission scheme. When txScheme is set to 'codebook', the function performs MIMO deprecoding based on the specified number of transmission layers nLayers and transmitted precoding matrix indicator (TPMI) tpmi. When you use this syntax, the function assumes the input symbols contain data symbols only.

example

[cw,symbols] = nrPUSCHDecode(carrier,pusch,sym,nVar) returns soft bits cw and constellation symbols symbols for the specified carrier configuration carrier and PUSCH configuration pusch. The input sym is the received PUSCH symbols for each layer and nVar specifies the noise variance scaling factor of the soft bits. When you use this syntax with transform precoding, the function assumes the input symbols contain data and PT-RS symbols (if applicable) and uses only data symbols for further processing.

example

[cw,symbols] = nrPUSCHDecode(carrier,pusch,tcr,tbs,oack,ocsi1,ocsi2,sym,nVar) specifies target code rate tcr, transport block size tbs, and uplink control information. oack is the hybrid automatic repeat request acknowledgment (HARQ-ACK) payload length. ocsi1 is the channel state information (CSI) part 1 payload length. ocsi2 is the CSI part 2 payload length. When you use this syntax with transform precoding, the function assumes that the input symbols contain data and PT-RS symbols (if applicable) and uses only data symbols for further processing. The function also handles the UCI placeholders when descrambling.

example

[cw,symbols] = nrPUSCHDecode(___,UniformCellOutput=celloutput) specifies the format of the cw and symbols outputs in addition to the input arguments in any of the previous syntaxes. Use this syntax with UniformCellOutput=true to enable C++ code generation when the number of layers is greater than 4. In this case, the function returns cw and symbols as a cell array irrespective of the number of layers. (since R2024a)

Examples

collapse all

Specify a random sequence of binary values corresponding to a codeword of 8064 bits.

cw = randi([0 1],8064,1);

Using 256-QAM modulation, generate PUSCH modulation symbols for the specified physical layer cell identity number, RNTI, and two transmission layers. By default, this function disables transform precoding and noncodebook-based transmission.

modulation = '256QAM';
nlayers = 2;
ncellid = 17;
rnti = 111;
sym = nrPUSCH(cw,modulation,nlayers,ncellid,rnti)
sym = 504×2 complex

  -0.9971 - 0.8437i   0.0767 + 0.2301i
   0.3835 + 0.2301i   0.9971 - 0.5369i
  -0.3835 - 1.1504i  -0.3835 + 0.9971i
   0.5369 + 0.0767i  -0.9971 + 0.8437i
   1.1504 - 0.9971i  -0.8437 - 0.6903i
  -0.6903 + 0.0767i   1.1504 - 0.3835i
   0.8437 + 0.6903i   1.1504 + 0.2301i
  -0.6903 - 0.2301i  -0.8437 + 1.1504i
   0.0767 + 0.8437i  -0.0767 + 0.6903i
   0.3835 - 0.8437i   0.3835 + 0.9971i
      ⋮

Decode the PUSCH modulation symbols.

demod = nrPUSCHDecode(sym,modulation,ncellid,rnti)
demod = 8064×1
1010 ×

   -1.1529
   -0.8471
    0.2118
   -0.0941
   -0.0235
    0.0235
    0.0235
   -0.0235
   -0.0235
   -0.0941
      ⋮

Perform hard decision on the soft metric.

rxcw = double(demod<0)
rxcw = 8064×1

     1
     1
     0
     1
     1
     0
     0
     1
     1
     1
      ⋮

Compare the result with the original codeword.

isequal(cw,rxcw)
ans = logical
   1

Specify a random sequence of binary values corresponding to a codeword of 8064 bits.

cw = randi([0 1],8064,1);

Using QPSK modulation, generate PUSCH modulation symbols for the specified physical layer cell identity number, RNTI, bandwidth, and one transmission layer. Enable transform precoding and codebook-based transmission based on the specified PUSCH bandwidth, TPMI, and four antennas.

modulation = 'QPSK';
ncellid = 17;
rnti = 111;
nlayers = 1;
transformPrecode = true;
txScheme = 'codebook';
mrb = 6;
tpmi = 1;
nports = 4;
sym = nrPUSCH(cw,modulation,nlayers,ncellid,rnti,transformPrecode,mrb,txScheme,nports,tpmi)
sym = 4032×4 complex

   0.0000 + 0.0000i  -0.1667 + 0.0833i   0.0000 + 0.0000i   0.0000 + 0.0000i
   0.0000 + 0.0000i  -0.0632 - 0.2911i   0.0000 + 0.0000i   0.0000 + 0.0000i
   0.0000 + 0.0000i  -0.1519 - 0.0450i   0.0000 + 0.0000i   0.0000 + 0.0000i
   0.0000 + 0.0000i   0.3677 + 0.3664i   0.0000 + 0.0000i   0.0000 + 0.0000i
   0.0000 + 0.0000i  -0.3079 - 0.5027i   0.0000 + 0.0000i   0.0000 + 0.0000i
   0.0000 + 0.0000i  -0.8082 - 0.1640i   0.0000 + 0.0000i   0.0000 + 0.0000i
   0.0000 + 0.0000i  -0.0640 - 0.2388i   0.0000 + 0.0000i   0.0000 + 0.0000i
   0.0000 + 0.0000i   0.3936 - 0.4160i   0.0000 + 0.0000i   0.0000 + 0.0000i
   0.0000 + 0.0000i   0.0851 - 0.4625i   0.0000 + 0.0000i   0.0000 + 0.0000i
   0.0000 + 0.0000i   0.0345 - 0.3333i   0.0000 + 0.0000i   0.0000 + 0.0000i
      ⋮

Decode the PUSCH modulation symbols assuming zero noise variance.

nVar = 0;
demod = nrPUSCHDecode(sym,modulation,ncellid,rnti,nVar,transformPrecode,mrb,txScheme,nlayers,tpmi)
demod = 8064×1
1010 ×

   -2.0000
   -2.0000
    2.0000
   -2.0000
   -2.0000
    2.0000
    2.0000
   -2.0000
   -2.0000
   -2.0000
      ⋮

Perform hard decision on the soft metric.

rxcv = double(demod<0)
rxcv = 8064×1

     1
     1
     0
     1
     1
     0
     0
     1
     1
     1
      ⋮

Compare the result with the original codeword.

isequal(cw,rxcv)
ans = logical
   1

Create a carrier configuration object with physical layer cell identity as 42.

carrier = nrCarrierConfig;
carrier.NCellID = 42;

Create a PUSCH configuration object with these properties.

pusch = nrPUSCHConfig;
pusch.Modulation = '256QAM';
pusch.NumLayers = 2;
pusch.RNTI = 111;
pusch.TransformPrecoding = 0;
pusch.TransmissionScheme = 'nonCodebook';
pusch.NID = []; % Use empty to be equal to NCellID of carrier
pusch.NSizeBWP = 25;
pusch.NStartBWP = 10;
pusch.PRBSet = 0:pusch.NSizeBWP-1; % Occupy entire bandwidth part

Generate PUSCH symbols for a single codeword of 8064 bits with the specified carrier configuration and uplink shared channel configuration.

cw = randi([0 1],8064,1);
sym = nrPUSCH(carrier,pusch,cw)
sym = 504×2 complex

  -0.3835 - 0.8437i  -1.1504 - 0.3835i
   0.6903 + 0.6903i   0.0767 + 0.3835i
  -1.1504 - 0.2301i  -1.1504 + 0.2301i
   0.9971 - 0.6903i  -0.2301 - 0.8437i
  -0.0767 + 0.2301i   0.2301 + 0.8437i
  -0.6903 + 1.1504i   0.8437 + 0.3835i
  -0.0767 + 0.8437i  -0.3835 + 0.5369i
   0.3835 + 0.5369i  -0.8437 - 1.1504i
   0.3835 + 0.2301i  -1.1504 - 0.8437i
   0.2301 - 0.0767i  -0.3835 + 1.1504i
      ⋮

Add an additive white Gaussian noise (AWGN) to the PUSCH symbols. Then demodulate to produce soft bit estimates.

SNR = 30; % SNR in dB
rxsym = awgn(sym,SNR);
demod = nrPUSCHDecode(carrier,pusch,rxsym)
demod = 8064×1
1010 ×

   -0.2106
   -0.8061
    0.0949
   -0.0805
   -0.0231
    0.0304
    0.0239
   -0.0167
   -1.4588
   -0.2063
      ⋮

Perform hard decision on the soft metric.

rxcw = double(demod<0);

Compare the result with the original codeword.

isequal(cw,rxcw)
ans = logical
   1

Create a carrier configuration object with 15 kHz subcarrier spacing and 10 MHz transmission bandwidth.

carrier = nrCarrierConfig;
carrier.SubcarrierSpacing = 15;
carrier.CyclicPrefix = 'normal';
carrier.NSizeGrid = 52;

Create a physical uplink shared channel (PUSCH) configuration object with a QPSK modulation scheme and no frequency hopping. Set the beta offset factor for hybrid automatic repeat request acknowledgment (HARQ-ACK) to 20, and set the beta offset factor for channel state information (CSI) part 1 and CSI part 2 to 6.5 each. Specify the scaling factor as 0.8, which limits the number of resource elements (REs) assigned for the UCI.

pusch = nrPUSCHConfig;
pusch.Modulation = 'QPSK';
pusch.FrequencyHopping = 'neither';
pusch.BetaOffsetACK = 20;
pusch.BetaOffsetCSI1 = 6.5;
pusch.BetaOffsetCSI2 = 6.5;
pusch.UCIScaling = 0.8;

Set the target code rate, payload lengths of the uplink shared channel (UL-SCH) data, HARQ-ACK, CSI part 1, and CSI part 2.

tcr = 0.65;   % Target code rate
tbs = 900;    % Payload length of UL-SCH data (transport block size)
oack = 1;     % Payload length of HARQ-ACK
ocsi1 = 55;   % Payload length of CSI part 1
ocsi2 = 72;   % Payload length of CSI part 2

Get the rate-matched lengths of the data, HARQ-ACK, CSI part 1, and CSI part 2.

rmInfo = nrULSCHInfo(pusch,tcr,tbs,oack,ocsi1,ocsi2);

Create the random payload bits for the UL-SCH data, HARQ-ACK, CSI part 1, and CSI part 2.

data = randi([0 1],tbs,1);
ack  = randi([0 1],oack,1);
csi1 = randi([0 1],ocsi1,1);
csi2 = randi([0 1],ocsi2,1);

Create a UL-SCH encoder System object™.

encUL = nrULSCH;

Load the transport block into the UL-SCH encoder.

setTransportBlock(encUL,data);

Get the coded bits of length rmInfo.GULSCH by calling the encoder.

rv = 0;  % Redundancy version 0
culsch = encUL(pusch.Modulation,pusch.NumLayers,rmInfo.GULSCH,rv);

Encode the random payload of the HARQ-ACK, CSI part 1, and CSI part 2 for the rate-matched output lengths obtained from the rmInfo structure.

cack  = nrUCIEncode(ack,rmInfo.GACK,pusch.Modulation);
ccsi1 = nrUCIEncode(csi1,rmInfo.GCSI1,pusch.Modulation);
ccsi2 = nrUCIEncode(csi2,rmInfo.GCSI2,pusch.Modulation);

Get the codeword from the coded bits of the UL-SCH and the coded bits of UCI types.

[cw,info] = nrULSCHMultiplex(pusch,tcr,tbs,culsch,cack,ccsi1,ccsi2)
cw = 16224x1 int8 column vector

   0
   1
   0
   1
   1
   0
   0
   0
   0
   0
      ⋮

info = struct with fields:
    ULSCHIndices: [3244x1 uint32]
      ACKIndices: [338x1 uint32]
     CSI1Indices: [7252x1 uint32]
     CSI2Indices: [5390x1 uint32]
     UCIXIndices: [0x1 uint32]
     UCIYIndices: [169x1 uint32]
            QUCI: 0

Get the PUSCH symbols.

sym = nrPUSCH(carrier,pusch,cw);

Decode the PUSCH symbols.

rxcw = nrPUSCHDecode(carrier,pusch,tcr,tbs,oack,ocsi1,ocsi2,sym);

Check that the received soft bits are equal at the locations other than the UCI placeholders.

indNoPlaceHolder = setdiff(1:length(cw),[info.UCIXIndices;info.UCIYIndices]);
isequal(cw(indNoPlaceHolder),int8(rxcw(indNoPlaceHolder)<0))
ans = logical
   1

Demultiplex the coded UL-SCH and coded UCI types from the received codeword.

[rxculsch,rxcack,rxccsi1,rxccsi2] = nrULSCHDemultiplex(pusch,tcr,tbs,oack,ocsi1,ocsi2,rxcw);

Decode the UL-SCH bits.

decUL = nrULSCHDecoder;
decUL.TransportBlockLength = tbs;
decUL.TargetCodeRate = tcr;
[decULBits,blkErr] = decUL(rxculsch,pusch.Modulation,pusch.NumLayers,rv);

Decode the HARQ-ACK, CSI part 1, and CSI part 2 bits.

decack = nrUCIDecode(rxcack,oack,pusch.Modulation);
deccsi1 = nrUCIDecode(rxccsi1,ocsi1,pusch.Modulation);
deccsi2 = nrUCIDecode(rxccsi2,ocsi2,pusch.Modulation);

Check the decoded bits of the UL-SCH, HARQ-ACK, CSI part 1, and CSI part 2.

isequal(data,decULBits)
ans = logical
   1

isequal(decack,ack)
ans = logical
   1

isequal(deccsi1,csi1)
ans = logical
   1

isequal(deccsi2,csi2)
ans = logical
   1

Input Arguments

collapse all

Received PUSCH modulation symbols, specified as a complex matrix of size NRE-by-NLAYERS. NRE is the number of symbols in resource elements. NLAYERS is the number of layers.

Data Types: single | double
Complex Number Support: Yes

Modulation scheme, specified as 'pi/2-BPSK', 'QPSK', '16QAM', '64QAM', or '256QAM'. This modulation scheme determines the modulation type and number of bits used per modulation symbol.

Modulation SchemeNumber of Bits Per Symbol
'pi/2-BPSK'1
'QPSK'2
'16QAM'4
'64QAM'6
'256QAM'8

Data Types: char | string

Scrambling identity, specified as an integer from 0 to 1023. nid is higher layer parameter dataScramblingIdentityPUSCH, ranging from 0 to 1023, if the higher layer parameter is configured. Otherwise, nid is physical layer cell identity number NCellID, ranging from 0 to 1007. For more information, see TS 38.211 Section 6.3.1.1.

Data Types: double

RNTI of the UE, specified as an integer from 0 to 65,535.

Data Types: double

Noise variance, specified as a nonnegative numeric scalar. The soft bits are scaled with the variance of additive white Gaussian noise (AWGN). The default value corresponds to an SNR of 100 dB, assuming unit signal power.

Note

The default value assumes the decoder and coder are connected back-to-back, where the noise variance is zero. To avoid -Inf or +Inf values in the output, the function uses 1e-10 as the default value for noise variance. To get appropriate results when the signal is transmitted through a noisy channel, adjust the noise variance accordingly.

Data Types: double

Transform deprecoding, specified as false or true. For more information, see TS 38.211 Section 6.3.1.4.

Data Types: double | logical

Number of allocated PUSCH resource blocks, specified as an integer from 1 to 275. For more information, see TS 38.214 Section 6.1.2.

Data Types: double

Transmission scheme, specified as one of these values:

  • 'nonCodebook' — Use this option to disable MIMO deprecoding.

  • 'codebook' — Use this option for codebook-based transmission using MIMO deprecoding.

For more information, see TS 38.211 Section 6.3.1.4.

Data Types: char | string

Number of transmission layers, specified as an integer from 1 to 4. For more information, see TS 38.211 Section 6.3.1.3.

Data Types: double

Transmitted precoding matrix indicator, specified as an integer from 0 to 27. The valid range of tpmi depends on the specified number of transmission layers nLayers and the number of ports. For more information, see TS 38.211 Tables 6.3.1.5-1 to 6.3.1.5-7.

Data Types: double

Carrier configuration parameters for a specific OFDM numerology, specified as an nrCarrierConfig object. This function uses only these properties of the nrCarrierConfig object.

PUSCH configuration parameters for a specific OFDM numerology, specified as an nrPUSCHConfig object. This function uses only these properties of the nrPUSCHConfig object.

For operation with shared spectrum channel access for frequency range 1 (FR1), set the Interlacing property to true, then use the RBSetIndex and InterlaceIndex object properties to specify the allocated frequency resources. (since R2023b)

Target code rate for the codewords in the UL-SCH transmission, specified as a scalar in the range (0, 1) or a two-element vector of numeric values in the range (0, 1) for two codewords. When you specify this input as a scalar and there are two codewords, the specified scalar applies to both codewords.

Data Types: double

Transport block size associated with the codewords in the UL-SCH transmission, specified as a nonnegative integer or a two-element vector of nonnegative integers for two codewords. When you specify this input as a nonnegative integer and there are two codewords, the specified value applies to both codewords. A value of 0 indicates no transport block or no UL-SCH transmission on the PUSCH.

Data Types: double

Payload length of the HARQ-ACK bits, specified as a nonnegative integer. A value of 0 indicates no HARQ-ACK transmission.

Data Types: double

Payload length of the CSI part 1 bits, specified as a nonnegative integer. A value of 0 indicates no CSI part 1 transmission.

Data Types: double

Payload length of the CSI part 2 bits, specified as a nonnegative integer. A value of 0 indicates no CSI part 2 transmission. Nominally, CSI part 2 is present only when CSI part 1 is present.

Data Types: double

Since R2024a

Enable cell format for the cw and symbols outputs, irrespective of the number of codewords, specified as one of these logical values.

  • 0 (false) — This option corresponds to the default behavior of the function in which the cw and symbols outputs are returned as column vectors for a single codeword or as cell arrays for two codewords.

  • 1 (true) — The function returns cw and symbols as cell arrays irrespective of the number of codewords. Use this option to enable C++ code generation when the number of layers is greater than 4.

Data Types: logical | double

Output Arguments

collapse all

Approximate log-likelihood ratio (LLR) soft bits, corresponding to the UL-SCH codewords defined in TS 38.212 Section 6.2.6, returned as a real column vector or a cell array of one or two real column vectors.

  • For the function syntaxes that use the carrier and pusch inputs, cw is a column vector or a cell array of one column vector, representing one codeword, or a cell array of two column vectors, representing two codewords.

  • For all the other function syntaxes, cw is a column vector, representing one codeword.

cw inherits the data type of sym. Sign represents hard bits.

Data Types: double | single

Constellation symbols for cw, returned as a complex column vector or a cell array of one or two complex column vectors.

  • For the function syntaxes that use the carrier and pusch inputs, symbols is a column vector or a cell array of one column vector, corresponding to one codeword, or a cell array of two column vectors, corresponding to two codewords.

  • For all the other function syntaxes, symbols is a column vector, corresponding to one codeword.

symbols inherits the data type of sym.

Data Types: double | single
Complex Number Support: Yes

References

[1] 3GPP TS 38.211. “NR; Physical channels and modulation.” 3rd Generation Partnership Project; Technical Specification Group Radio Access Network.

Extended Capabilities

Version History

Introduced in R2019a

expand all