Main Content

This example measures the throughput performance of the Physical Uplink Shared Channel (PUSCH) with closed-loop spatial multiplexing using the LTE Toolbox™ under a 2-codeword Release 10 UL-MIMO scenario, based on conformance test conditions as defined in Table 8.2.1.1-7 of TS 36.104.

TS 36.104, Table 8.2.1.1-7 [ 1 ] defines a minimum fraction of 70% throughput for a physical uplink shared channel (PUSCH) transmission for a given signal-to-noise ratio (SNR) assuming hybrid automatic repeat request (HARQ) retransmissions. A normal cyclic prefix, Extended Pedestrian A (EPA5) propagation channel and Fixed Reference Channel (FRC) A3-2 are used, but amended to transmit two identically-configured codewords in parallel. In order to assist Precoding Matrix Indicator (PMI) selection for closed-loop spatial multiplexing, the Sounding Reference Signal (SRS) is transmitted which allows full-rank channel estimation even when the PUSCH is being transmitted with fewer transmit layers than transmit antennas.

If SRS is used the PUSCH capacity is shorted as the last symbol of the subframe where SRS is transmitted is not used for PUSCH in any User Equipment (UE) in the cell.

The example is executed for a simulation length of 10 frames at an SNR of -0.1 dB as per TS 36.104, Table 8.2.1.1-7 [ 1 ]. A large number of `NFrames`

should be used to produce meaningful throughput results. `SNRIn`

can be an array of values or a scalar.

NFrames = 10; % Number of frames SNRIn = -0.1; % SNR range in dB

User Equipment (UE) settings are specified in a structure.

frc.RC = 'A3-2'; % FRC number frc.DuplexMode = 'FDD'; % Duplex mode frc.TotSubframes = 1; % Total number of subframes to generate frc.NCellID = 10; % Cell identity frc.CyclicPrefixUL = 'Normal'; % Uplink cyclic prefix length frc.CyclicPrefix = 'Normal'; % Downlink cyclic prefix length frc.NTxAnts = 4; % Number of transmit antennas

Configure SRS within UE configuration to allow for channel estimation.

frc.SRS.SubframeConfig = 1; % Cell-specific schedule: 2 ms periodicity frc.SRS.NTxAnts = frc.NTxAnts; % Configure SORTD same as no of UE antennas frc.SRS.BWConfig = 7; % Cell-specific SRS bandwidth frc.SRS.BW = 0; % UE-specific SRS bandwidth frc.SRS.ConfigIdx = 0; % UE-specific schedule: 2ms periodicity frc.SRS.CyclicShift = 0; % Cyclic shift 0 frc.SRS.SeqGroup = 0; % Sequence group 0 frc.SRS.SeqIdx = 0; % Base sequence 0 frc.SRS.TxComb = 0; % Transmission comb 0 frc.SRS.FreqPosition = 0; % Frequency-domain position 0 frc.SRS.HoppingBW = 0; % Disable hopping (as HoppingBW >=0 BW)

Set the PMI delay for the closed-loop spatial multiplexing. This is the delay of a PMI being passed from UE to eNodeB.

pmiDelay = 8;

Propagation channel model characteristics are set using a structure containing the fields specified below. These are set according to TS 36.104, Table 8.2.1.1-7 [ 1 ].

chcfg.NRxAnts = 4; % Number of receive antennas chcfg.DelayProfile = 'EPA'; % Delay profile chcfg.DopplerFreq = 5.0; % Doppler frequency chcfg.MIMOCorrelation = 'Low'; % MIMO correlation chcfg.Seed = 9; % Channel seed chcfg.NTerms = 16; % Oscillators used in fading model chcfg.ModelType = 'GMEDS'; % Rayleigh fading model type chcfg.InitPhase = 'Random'; % Random initial phases chcfg.NormalizePathGains = 'On'; % Normalize delay profile power chcfg.NormalizeTxAnts = 'On'; % Normalize for transmit antennas

The variable `perfectChanEstimator`

controls channel estimator behavior. Valid values are `true`

or `false`

. When set to `true`

a perfect channel estimator is used otherwise an imperfect estimate of the channel is used, based on the values of received pilot signals.

% Controls channel estimator behavior perfectChanEstimator = false; % Valid values are true or false reference = 'Antennas'; % Channel reference

Imperfect channel estimation is configured using a structure `cec`

. Here cubic interpolation will be used with an averaging window of 12-by-1 Resource Elements (REs). This configures the channel estimator to use a special mode which ensures the ability to despread and orthogonalize the different overlapping PUSCH transmissions.

% Channel estimator configuration cec.PilotAverage = 'UserDefined'; % Type of pilot symbol averaging cec.FreqWindow = 12; % Frequency averaging window in REs (special mode) cec.TimeWindow = 1; % Time averaging window in REs (special mode) cec.InterpType = 'Cubic'; % 2D interpolation type

To generate the uplink Reference Model Channel (RMC) the LTE Toolbox functions `lteRMCUL`

and `lteRMCULTool`

are used. `lteRMCULTool`

creates a configuration structure for given UE settings; specific to a given Fixed Reference Channel (FRC). This configuration structure is constructed as per TS 36.104, Annex A [ 1 ] and is used by `lteRMCULTool`

to generate an SC-FDMA modulated waveform. The sub-structure `PUSCH`

defines the parameters associated with PUSCH and contains the vector defining the transport data capacity per subframe. These lengths are used when decoding Uplink Shared Channel (UL-SCH).

In this example two codewords are used for the PUSCH. The size of four parameters depend on the number of codewords used:

- Each cell contains the modulation scheme for a codeword.`frc.PUSCH.Modulation`

- Each row contains the transport block sizes for a codeword.`frc.PUSCH.TrBlkSizes`

- Each row contains the coded transport block sizes for a codeword.`frc.PUSCH.CodedTrBlkSizes`

- Each row contains the Redundancy Versions (RVs) for a codeword.`frc.PUSCH.RVSeq`

% Generate parameter structure for single codeword A3-2 FRC frc = lteRMCUL(frc); % Then update Physical Uplink Shared Channel (PUSCH) parameters to define % two identically configured single layer codewords frc.PUSCH.NLayers = 2; % the layers are shared across the 2 codewords frc.PUSCH.Modulation = repmat({frc.PUSCH.Modulation}, 1, 2); frc.PUSCH.TrBlkSizes = repmat(frc.PUSCH.TrBlkSizes, 2, 1); frc.PUSCH.RVSeq = repmat(frc.PUSCH.RVSeq, 2, 1); % Record transport block sizes for each subframe in a frame trBlkSizes = frc.PUSCH.TrBlkSizes; % The number of codewords is the number of transport block sizes ncw = size(trBlkSizes,1); % Record RV sequence rvSequence = frc.PUSCH.RVSeq;

The sampling rate for the channel model is set using the value returned from `lteSCFDMAInfo`

.

dims = lteSCFDMAInfo(frc); chcfg.SamplingRate = dims.SamplingRate;

The conformance test may be carried out over a number of SNR points. To determine the throughput at each SNR point, the PUSCH data is analyzed on a subframe by subframe basis using the following steps:

*Update Current HARQ Process.*The HARQ process either carries new transport data or a retransmission of previously sent transport data depending upon the Acknowledgment (ACK) or Negative Acknowledgment (NACK) based on CRC results. All this is handled by the HARQ scheduler, hHARQScheduling.m. The PUSCH data is updated based on the HARQ state.

*Set PMI.*A PMI is taken sequentially from a set of PMIs,`txPMIs`

, each subframe and used by the eNodeB to select a precoding matrix. When a PMI is used by the eNodeB for a transmission it is replaced with a PMI selected by the UE. This PMI is then used to select a precoding matrix after`pmiDelay`

subframes. Initially a set of`pmiDelay`

random PMIs is used.

*Create Transmit Waveform.*The data generated by the HARQ process is passed to`lteRMCULTool`

, which produces an OFDM modulated waveform, containing the physical channels and signals.

*Noisy Channel Modeling.*The waveform is passed through a fading channel and Additive White Gaussian Noise (AWGN) noise added. The noise power is normalized to take account of the sampling rate.

*Synchronization and SC-FDMA Demodulation.*The received symbols are offset to account for a combination of implementation delay and channel delay spread. The symbols are then SC-FDMA demodulated.

*Channel Estimation.*The channel response and noise are estimated using either a perfect or imperfect channel estimator. These estimates are used to aid the soft decoding of the PUSCH. If imperfect channel estimation is used, the SRS is utilized to enhance estimation. This information is passed in the variable`refGrid`

which contains known transmitted SRS symbols in their correct locations. All other locations are represented by a`NaN`

.

*Equalization, Combining and PUSCH Decoding.*The equalization is performed using`lteEqualizeMMSE`

and then`ltePUSCHDecode`

completes the reception processing under the assumption that the input is already equalized.

*UL-SCH Decoding.*The vector of decoded soft bits is passed to`lteULSCHDecode`

; this decodes the codewords and returns the block CRC error used to determine the throughput of the system. The contents of the new soft buffer,`harqProc(harqID).decState`

, is available at the output of this function to be used for the next subframe.

*Update PMI.*A PMI is selected and fed back to the eNodeB for use in future subframes. For perfect channel estimation the PMI is updated every subframe. For imperfect channel estimation a PMI update only occurs when when an SRS transmission occurs and therefore a full-rank channel estimate is available, from which PMI can be estimated and selected.

% Store results for each SNR point and each subframe containing data for % the whole simulation nDataTBS = sum(trBlkSizes(:)~=0)*NFrames; crc = zeros(numel(SNRIn), nDataTBS); % Total block CRC error vector tput = zeros(numel(SNRIn), nDataTBS); % Total throughput vector ResultIndex = 1; % SNR point result index for SNRdB = SNRIn % Configure random number generators rng('default'); % Noise configuration fprintf('\nSimulating at %gdB SNR for a total %d Frame(s)', ... SNRdB, NFrames); SNR = 10^(SNRdB/20); N = 1/(SNR*sqrt(double(dims.Nfft)))/sqrt(2.0*frc.NTxAnts); % Initialize state of all HARQ processes harqProcesses = hNewHARQProcess(frc); % Initialize HARQ process IDs to 1 as the first non-zero transport % block will always be transmitted using the first HARQ process. This % will be updated with the full sequence output by lteRMCULTool after % the first call to the function harqProcessSequence = 1; % Use random PMIs for the first 'pmiDelay' subframes until feedback is % available from the UE if multiple transmit antennas are used if (frc.NTxAnts>1) pmidims = lteULPMIInfo(frc, frc.PUSCH); txPMIs = randi([0 pmidims.MaxPMI], pmidims.NSubbands, pmiDelay); end % Initialize result store for SNR point tested crcSNR = zeros(nDataTBS/ncw, ncw); % Intermediate block CRC tputSNR = zeros(nDataTBS/ncw, ncw); % Intermediate throughput dataSubframeIndex = 1; % Loop for all subframes at this SNR offsetused = 0; for subframeNo = 0:(NFrames*10-1) % Update subframe number frc.NSubframe = mod(subframeNo, 10); % If this is an uplink subframe duplexDims = lteDuplexingInfo(frc); if(strcmp(duplexDims.SubframeType,'Uplink')==1) % Get HARQ process ID for the subframe from HARQ process sequence harqID = harqProcessSequence(mod(subframeNo, length(harqProcessSequence))+1); % If there is a transport block scheduled in the current subframe % (indicated by non-zero 'harqID'), perform transmission and % reception. Otherwise continue to the next subframe if harqID == 0 continue; end % Update current HARQ process harqProcesses(harqID) = hHARQScheduling( ... harqProcesses(harqID), subframeNo, rvSequence); % Update the PUSCH transmission config with HARQ process state frc.PUSCH = harqProcesses(harqID).txConfig; data = harqProcesses(harqID).data; % Set the PMI to the appropriate value in the delay queue (if % multiple antennas are being used) if (frc.NTxAnts>1) pmiIdx = mod(subframeNo, pmiDelay); frc.PUSCH.PMI = txPMIs(:, pmiIdx+1); end % Create transmit waveform and get the HARQ scheduling ID % sequence from 'frcOut' structure output which also contains % the waveform configuration and OFDM modulation parameters [txWaveform,~,frcOut] = lteRMCULTool(frc, data); % Add 25 sample padding. This is to cover the range of delays % expected from channel modeling (a combination of % implementation delay and channel delay spread) txWaveform = [txWaveform; zeros(25, frc.NTxAnts)]; %#ok<AGROW> % Get the HARQ ID sequence from 'frcOut' for HARQ processing harqProcessSequence = frcOut.PUSCH.HARQProcessSequence; % Pass data through the fading channel model. The % initialization time for channel modeling is set each subframe % to simulate a continuously varying channel. chcfg.InitTime = subframeNo/1000; rxWaveform = lteFadingChannel(chcfg, txWaveform); % Add noise at the receiver noise = N*complex(randn(size(rxWaveform)), ... randn(size(rxWaveform))); rxWaveform = rxWaveform + noise; % Calculate synchronization offset offset = lteULFrameOffset(frc, frc.PUSCH, rxWaveform); if (offset < 25) offsetused = offset; end % SC-FDMA demodulation rxSubframe = lteSCFDMADemodulate(frc, rxWaveform... (1+offsetused:end, :)); % Mark this subframe as not being involved in PMI update updatePMI = false; % Channel and noise estimation if (perfectChanEstimator) % Create reference grid - not required for perfect channel % estimator, but needed as an input to lteULPMISelect to % match call with imperfect channel estimator. refGrid = NaN(lteULResourceGridSize(frc)); %#ok % Perfect channel estimation, perfect knowledge of all REs % and perfect knowledge of channel noise estChannelGrid = lteULPerfectChannelEstimate( ... frc, chcfg, offsetused); n = lteSCFDMADemodulate(frc, noise(1+offsetused:end, :)); noiseEst = var(reshape(n, numel(n), 1)); updatePMI = true; else % Use imperfect channel estimator with support from the SRS % if available if (strcmpi(reference, 'Antennas')==1 || ... (frc.NTxAnts == frc.PUSCH.NLayers)) refGrid = NaN(lteULResourceGridSize(frc)); if (isfield(frc, 'SRS')) [srsIndices, srsIndicesDims] = lteSRSIndices( ... frc, frc.SRS); if (~isempty(srsIndices)) srsSymbols = lteSRS(frc, frc.SRS); refGrid(srsIndices) = srsSymbols; updatePMI = true; end end end cec.Reference = reference; [estChannelGrid, noiseEst] = lteULChannelEstimate( ... frc, frc.PUSCH, cec, rxSubframe, refGrid); end % Shorten PUSCH capacity shortening as appropriate if (isfield(frc, 'SRS')) srsDims = lteSRSInfo(frc, frc.SRS); frc.Shortened = srsDims.IsSRSSubframe; else frc.Shortened = 0; end % Set up variable indicating the current transport block sizes TBSs = trBlkSizes(:, mod(subframeNo, 10)+1).'; % Extract REs corresponding to the PUSCH from the given % subframe across all receive antennas and channel estimates. puschIndices = ltePUSCHIndices(frc, frc.PUSCH); [puschRx, puschEstCh] = lteExtractResources( ... puschIndices, rxSubframe, estChannelGrid); % Equalization and combining, layer demapping, transform % deprecoding, demodulation and descrambling of the received % data ulschDims = lteULSCHInfo(frc, frc.PUSCH, TBSs, 'chsconcat'); rxSymbols = lteEqualizeMMSE(puschRx, puschEstCh, noiseEst); rxEncodedBits = ltePUSCHDecode(frc, ulschDims, rxSymbols); % UL-SCH transport decoding [rxdata, harqProcesses(harqID).blkerr, ... harqProcesses(harqID).decState] = lteULSCHDecode( ... frc, ulschDims, TBSs, rxEncodedBits, ... harqProcesses(harqID).decState); % Store block CRC and throughput results for subframes % containing transport data crcSNR(dataSubframeIndex, :) = harqProcesses(harqID).blkerr; tputSNR(dataSubframeIndex, :) = TBSs.* ... (1-harqProcesses(harqID).blkerr); dataSubframeIndex = dataSubframeIndex + 1; % Provide PMI feedback (if multiple antennas are being used) if (frc.NTxAnts>1) if (~any(TBSs) || ~updatePMI) % Use previous PMI value if in a subframe not used for % uplink in TDD, or if PMI update is not configured for % this subframe. PMI = txPMIs(:, mod(pmiIdx-1, pmiDelay)+1); else % Update PMI estimate. If not using the perfect channel % estimator, redo channel estimation using only the SRS % for PMI selection purposes. if (~perfectChanEstimator) cec.Reference = 'None'; [estChannelGrid, noiseEst] = ... lteULChannelEstimate(frc, frc.PUSCH, cec, ... rxSubframe, refGrid); end PMI = lteULPMISelect(frc, frc.PUSCH, ... estChannelGrid, noiseEst, refGrid, cec); end txPMIs(:, pmiIdx+1) = PMI; end end end % Record the block CRC error and bit throughput for the total number of % frames simulated at an SNR point crc(ResultIndex, :) = crcSNR(:); tput(ResultIndex, :) = tputSNR(:); ResultIndex = ResultIndex + 1; disp(' '); end

Simulating at -0.1dB SNR for a total 10 Frame(s)

The throughput results for the simulation are contained in `crc`

and `tput`

. `crc`

is a matrix where each row contains the results of decoding the CRC for a particular SNR. Each column contains the CRC result for a transport block containing PUSCH data at an SNR. `tput`

is a matrix where each row contains the bit throughput per subframe for a particular SNR. Each column contains the throughput result for a transport block containing PUSCH data at an SNR.

The throughput results are plotted as a percentage of total capacity and actual bit throughput for the range of SNR values input using hMultiCodewordPUSCHResults.m.

hMultiCodewordPUSCHResults(SNRIn, NFrames, trBlkSizes, crc, tput);

This example uses these helper functions.

3GPP TS 36.104 "Base Station (BS) radio transmission and reception"