Main Content

TDD Reciprocity-Based PDSCH MU-MIMO Using SRS

This example implements downlink multiuser multiple-input multiple-output (MU-MIMO) by exploiting channel reciprocity in a time division duplex (TDD) scenario. The example shows how to determine beamforming weights for physical downlink shared channel (PDSCH) transmission by using channel estimates based on uplink sounding reference signals (SRS) transmitted for each user, and how to schedule PDSCHs for multiple users in the same time and frequency resources.

Introduction

TDD systems use the same frequency band for uplink (UL) and downlink (DL) transmissions. The radio channel is reciprocal because it has the same characteristics in both UL and DL directions. Exploiting this reciprocity, you can use a UL transmission to obtain a channel estimate and then use this channel estimate to calculate parameters, including beamforming, for a DL transmission. This method is known as reciprocity-based beamforming.

This example implements downlink MU-MIMO by calculating a channel estimate for multiple users based on their SRS transmissions. Assuming reciprocity, the example then uses these channel estimates to select a set of users to be scheduled for PDSCH transmission and calculates DL beamforming weights for PDSCH transmissions to those users. When the base station has a sufficient number of antennas, it is possible to beamform PDSCH transmissions for a set of users in the same time and frequency resources such that the users suffer little interference from each other.

This example schedules SRS transmissions for all UEs in the UL part of the special slot, and schedules PDSCH transmissions for UEs chosen by the user selection algorithm in DL slots and the DL part of special slots.

TDDReciprocityBasedBeamforming.png

The example offers a choice of MU-MIMO precoding algorithms and allows the number of layers scheduled in the same time and frequency resources to be configured. Finally, the example measures the capacity of the overall cell relative to a single-layer user, showing that the capacity is higher than could be achieved by scheduling a single user.

Simulation Assumptions

The example uses these assumptions.

  • The SRS configuration allows for up to 16 UEs to be scheduled.

  • The number of layers assigned to a given UE is random (either 1, 2, or 4) and is fixed for the duration of the simulation.

  • The number of SRS antenna ports is equal to the number of layers assigned.

  • For the zero forcing, regularized zero forcing, and block diagonalization precoding methods, the number of SRS antenna ports is equal to the number of physical antennas, that is, no spatial filtering of SRS ports onto a larger set of physical antennas. For joint spatial division multiplexing precoding, hybrid precoding is used so the number of SRS antenna ports is equal to the number of RF chains, which is less than the number of physical antennas.

  • The number of UE transmit antennas is equal to the number of SRS antenna ports, that is, full channel sounding is used.

  • The precoding resource block group (PRG) bundle size is the same for all UEs.

  • PDSCH is not scheduled in the downlink slots of the first frame occurring prior to the first special slot, because no channel estimate is yet available.

  • Demodulaton reference signal (DM-RS) configuration type is type 1 and DM-RS length is 2, that is, 8 orthogonal DM-RS ports can be scheduled. For scheduling more users, the example employs nonorthogonal DM-RSs by changing the scrambling identity.

  • HARQ is not supported.

  • All UEs are synchronized to within the cyclic prefix length based on the initial acquisiton and transmission timing adjustment procedures, as described in TS 38.213 Sections 8 and 4.2 [1]. A timing offset within the cyclic prefix length manifests as a phase shift in the frequency domain and is compensated by the channel estimation and equalization.

  • All UEs are received with equal power after averaging across channel variations due to fading.

Simulation Parameters

Specify the number of UEs, the number of frames to simulate, and the SNR for the downlink and the uplink, assuming that the SNR is the same for all users. For an explanation of the SNR definition that this example uses, see SNR Definition Used in Link Simulations.

numUEs = 12;        % Total number of UEs served by the base station
numFrames = 1;      % Total number of frames to simulate
SNRdBDL = 25;       % Downlink SNR in dB
SNRdBUL = 20;       % Uplink SNR in dB

Base Station Configuration

Carrier Configuration

Set the carrier parameters, specifying 51 resource blocks at 30 kHz subcarrier spacing, which corresponds to a channel bandwidth of 20 MHz.

carrier = nrCarrierConfig;
carrier.NSizeGrid = 51;
carrier.SubcarrierSpacing = 30;

TDD Configuration

The example considers a TDD configuration consisting of a number of downlink slots (D), followed by a special slot (S), followed by a number of uplink slots (U). The special slot represents a switchpoint from downlink to uplink transmission and therefore contains downlink symbols, followed by empty guard symbols, followed by uplink symbols. The number of dowlink or uplink symbols in the special slot can be zero. This example schedules SRS transmissions in the uplink part of the special slot, and schedules PDSCH transmissions in downlink slots and in the downlink part of special slots.

TDDSlotStructure.png

Represent the TDD slot pattern by an array of strings specifying the slot type.

tddPattern = ["D" "D" "D" "D" "D" "D" "D" "S" "U" "U"];

disp("Cyclic slot pattern:")
Cyclic slot pattern:
disp("Slot " + string((0:length(tddPattern)-1)') + ": " + tddPattern(:))
    "Slot 0: D"
    "Slot 1: D"
    "Slot 2: D"
    "Slot 3: D"
    "Slot 4: D"
    "Slot 5: D"
    "Slot 6: D"
    "Slot 7: S"
    "Slot 8: U"
    "Slot 9: U"

Represent the special slot configuration by a three-element vector specifying the number of downlink symbols, guard symbols, and uplink symbols in the special slot.

specialSlot = [6 4 4];

The total number of symbols in the special slot configuration must match the number of symbols in a slot given by carrier.SymbolsPerSlot.

if(sum(specialSlot)~=carrier.SymbolsPerSlot)
    error(['specialSlot must contain ' num2str(carrier.SymbolsPerSlot) ' symbols.']);
end

Antenna Array Size

Specify the antenna array size for the base station (BS). Assume a rectangular array. The antenna array size is a vector [M N P], where M is the number of rows, N is the number of columns and P is the number of polarizations in the antenna array.

bsAntSize = [2 8 2];

UE Configuration

Spatial Configuration

Specify if UE locations are randomly scattered throughout the cell sector or clustered into groups. To scatter randomly, set numGroups to 1. If clustering into groups, the number of UEs will be evenly split as much as possible amongst the groups. The number of groups must not exceed the number of UEs.

numGroups = 1;

% Assign each UE a spatial group
g = (1:numGroups).*ones(ceil(numUEs/numGroups),1);
groups = g(1:numUEs);

Number of Layers and Antenna Array Sizes

Randomly select the number of layers per UE (1, 2, or 4).

% Reset random generator for reproducibility
rng('default');

% Number of layers for each UE
numLayers = pow2(randi([0 2],[1 numUEs]))
numLayers = 1×12

     4     4     1     4     2     1     1     2     4     4     1     4

The number of layers determines the antenna array size for each UE according to this table.

Number of LayersUE Antenna Array Size1[111]2[112]4[122]Table showing relationship between antenna array size for each UE and number of layers.

% Number of rows, columns and polarizations in rectangular array for each UE
ueAntSizes = 1 + (numLayers.' > [4 2 1])
ueAntSizes = 12×3

     1     2     2
     1     2     2
     1     1     1
     1     2     2
     1     1     2
     1     1     1
     1     1     1
     1     1     2
     1     2     2
     1     2     2
      ⋮

SRS Configuration

Configure the SRS parameters for each UE. The SRSs for all UEs are configured to be transmitted in a special slot, or in an uplink slot if there is no special slot (or if it contains no uplink symbols). The example performs time-division multiplexing (TDM) of SRSs by using different OFDM symbol numbers and frequency-division multiplexing (FDM) by using different comb offsets. For each UE, the number of SRS ports is configured to be equal to the number of layers for that UE.

SRSs = hMultiUserSRS(tddPattern,specialSlot,carrier,numLayers);

For more information on SRS parameterization, see the NR SRS Configuration example.

PDSCH and DL-SCH Configuration

Configure the PDSCH and DL-SCH parameters for each UE with these parameters.

  • Rate 3/4 coding and 64-point quadrature amplitude modulation (64-QAM)

  • DM-RS configuration type 1 and DM-RS length 2, which provides 8 orthogonal DM-RS ports, see TS 38.211 Table 7.4.1.1.2-1 [5]

  • PRG bundle size of 2, see TS 38.214 Section 5.1.2.3 [6]

Configure the appropriate number of layers for each UE and set the RNTI equal to the UE number (1...numUEs).

PDSCHs = hMultiUserPDSCH(numLayers);

You can configure further PDSCH parameters for each transmission during the user selection process by using the hMultiUserSelection function.

For more information on PDSCH parameterization, see the NR PDSCH Resource Allocation and DM-RS and PT-RS Reference Signals example.

Algorithmic Parameters

MU-MIMO Precoding Method

The example supports these precoding methods.

  • 'BD': Block diagonalization, as described by Spencer, Q.H., et al. in [2]. Note that the implementation uses the blkdiagbfweights function.

  • 'ZF': Zero forcing, as described by Peel, C.B., et al. in [3].

  • 'RZF': Regularized zero forcing, as described by Peel, C.B., et al. in [3].

  • 'JSDM-JGP': Joint spatial division multiplexing with joint group processing (JGP), as described by Adhikary, A., et al. in [7].

  • 'JSDM-PGP': Joint spatial division multiplexing with per-group processing (PGP), as described by Adhikary, A., et al. in [7].

Configure the precoding method that is used to determine the beamforming weights for each PDSCH during user selection.

algParameters = struct;
algParameters.PrecodingMethod = 'RZF';

Configure the number of layers that the user selection algorithm schedules in each PRG in each slot. This value is the total number of layers scheduled across all users in any given PRG in this slot. The user selection algorithm is based on proportional fair (PF) scheduling considering each PRG separately.

algParameters.ScheduledLayers = 8;

Hybrid Precoding using Joint Spatial Division Multiplexing (JSDM)

This example provides an option to use JSDM for the MU-MIMO precoding method. JSDM enables massive MIMO by using a hybrid precoding architecture where the number of RF chains is much less than the number of physical antennas. In this example, the number of RF chains equals the number of scheduled layers when JSDM is selected. For more information on JSDM, see the Massive MIMO Hybrid Beamforming example. Note that the implementation uses the jsdmrfweights (Phased Array System Toolbox) and jsdmbbweights (Phased Array System Toolbox) functions which require the Phased Array System Toolbox.

To accommodate the needs of JSDM, the following parameters changes are recommended:

  • Increase the number of antennas. Massive MIMO generally implies antenna arrays larger than 64 elements.

  • Limit the number of groups to 2-4 (at least two groups are required). JSDM allocates a fixed number of layers to each group, which may affect PDSCH scheduling and cause some UEs to not receive data due to the PF scheduling if there aren't enough layers in the group. In this example, the number of layers assigned to each group is split evenly from the number of scheduled layers (the last group will receive the leftover layers if the layers cannot be split evenly).

  • JGP has better performance than PGP, because the PGP precoding matrix is truncated to reflect less CSI.

  • Limit the number of scheduled layers to be less than the total number of UEs (for PGP) or less than the total number of UE layers (for JGP). JSDM RF beamforming is sensitive to the rank measurements of the group spatial covariances. In this example, the measured rank of each group is limited to the number of users.

  • Adjusting the modulation order can lower the bit error rate in exchange for lower throughput. The default is set to 64-QAM.

Upon selection of JSDM, the example will enable channel filtering and disable perfect channel estimation.

Channel Estimator Configuration

The logical variable PerfectChannelEstimator controls channel estimation behavior. When you set this variable to true, the example uses perfect channel estimation for SRS and PDSCH reception. Otherwise, the example uses practical channel estimation based on the values of the received SRS and PDSCH DM-RS.

algParameters.PerfectChannelEstimator = false;

CDL Channel Models

Configure a propagation channel model for each UE. The hMultiUserChannels function uses the nrCDLChannel object to configure clustered delay line (CDL) channels. Use this function to create an initial channel object with CDL-A delay profile, 100 ns delay spread, and 5 Hz Doppler shift. The function then configures different channels for each UE by modifying the initial object to:

  • Simulate the effect of different UEs in different locations in the environment around the base station. Each UE has an azimuth and zenith angle relative to the base station; the angles of departure for each cluster are offset by these angles. When numGroups=1, the UEs are configured to have randomly selected azimuth and zenith angles; otherwise, the UEs are configured to be clustered in spatial groups such that the azimuth and zenith angles for the grouped UEs are similar.

  • Configure the UE antenna array according to the antenna array size chosen in Number of Layers and Antenna Array Sizes.

  • Set a different value of the Seed property. This ensures that the channel for each UE has independent fast fading.

delayProfile = 'CDL-A';
delaySpread = 100e-9;
maximumDopplerShift = 5;
channels = hMultiUserChannels(delayProfile,delaySpread,maximumDopplerShift,bsAntSize,ueAntSizes,groups);

To visualize the configuration of a CDL channel, see the Visualize CDL Channel Model Characteristics example. To create CDL channel model parameters by using the output of a ray tracing analysis, see the CDL Channel Model Customization with Ray Tracing example.

MU-MIMO Throughput Simulation Using Reciprocity-Based Beamforming

This diagram shows the structure of the throughput simulation.

TDDReciprocityExampleStructure.png

For slots scheduled for SRS:

  • UL transmit: Generate the SRS waveform for each UE.

  • CDL channels, AWGN: For each UE, send the waveform through the channel, combine the channel outputs at the base station, and add noise.

  • UL receive: For each UE, perform SRS-based channel and noise estimation. For more information, see the NR Uplink Channel State Information Estimation Using SRS example.

  • Update CSI: Record the channel and noise estimates for use in subsequent slots.

For slots scheduled for PDSCH:

  • User selection: Considering the most recent CSI for all UEs, determine which UEs to schedule for PDSCH and configure PDSCH parameters (allocated RBs, beamforming, DM-RS ports, scrambling identity).

  • DL transmit: For each UE, perform DL-SCH encoding of data and generate and beamform the PDSCH. Sum the beamformed PDSCHs to form the transmitted signal.

  • CDL channels, AWGN: Send the transmitted signal through the channel for each UE and add noise to create the received waveform for each UE.

  • DL receive: For each UE, demodulate the received waveform, demodulate the PDSCH and decode the DL-SCH.

  • Update data transfer: Record the transport block size (TBS) and cyclic redundancy check (CRC) for each UE, which the example uses to calculate final throughput results.

The diagnosticsOn flag controls the display of diagnostic information during the simulation. When set to true, the example displays this information:

  • The current slot number and the type of the slot (D, S, or U)

  • For slots containing SRS, a list of the UEs for which SRS is transmitted and received

  • For slots containing PDSCH, a list of the UEs for which PDSCH is scheduled, the number of allocated resource blocks (NPRB), the EVM for each layer, and the CRC result from DL-SCH decoding

[numRF,channels,algParameters] = setupJSDM(algParameters,groups,numUEs,channels,bsAntSize);

% Set up record of data transfer and CSI
dataState = setupDataTransfer(carrier,numFrames,numLayers);
csi = setupCSI(carrier,bsAntSize,ueAntSizes);

diagnosticsOn = true;

% For each slot
for nSlot = 0:(carrier.SlotsPerFrame*numFrames)-1

    % Update the slot number
    carrier.NSlot = nSlot;

    % Display slot number and type (if diagnostics are enabled)
    if (diagnosticsOn)
        disp("Slot " + string(carrier.NSlot) + ": " + tddPattern(mod(carrier.NSlot,numel(tddPattern))+1));
    end

    % Schedule UEs for data transmission
    [schedule,PDSCHs,B] = hMultiUserSelection(csi,tddPattern,specialSlot,carrier,PDSCHs,bsAntSize,algParameters);
    
    % PDSCH transmissions for all UEs scheduled for data
    [txDL,txSymbols,singleLayerTBS] = hMultiDLTransmit(carrier,PDSCHs(schedule.PDSCH),numRF,B);
    
    % SRS transmissions for all UEs scheduled for SRS
    [txUL,schedule.SRS] = hMultiULTransmit(carrier,SRSs);
    
    % Apply fading channels
    [channels,rxDL,rxUL] = hApplyMultiUserChannels(tddPattern,specialSlot,carrier,schedule,channels,txDL,txUL);
    
    % Apply AWGN
    rxDL = hApplyMultiUserAWGN(carrier,rxDL,SNRdBDL,CombineWaveforms=false);
    rxUL = hApplyMultiUserAWGN(carrier,rxUL,SNRdBUL,CombineWaveforms=true);
    
    % For all UEs scheduled for SRS, estimate CSI and record it
    [H,nVar] = hMultiULReceive(carrier,SRSs(schedule.SRS),rxUL,algParameters);
    csi = updateCSI(csi,carrier,schedule.SRS,H,nVar);
    
    % For all UEs scheduled for data, perform PDSCH reception and record the results
    [TBS,CRC,eqSymbols] = hMultiDLReceive(carrier,PDSCHs(schedule.PDSCH),rxDL,algParameters);
    dataState = updateDataTransfer(dataState,carrier,singleLayerTBS,schedule.PDSCH,TBS,CRC);

    % Display scheduled SRSs and PDSCHs, PDSCH EVM, and DL-SCH CRC (if diagnostics are enabled)
    if (diagnosticsOn)
        displayDiagnostics(schedule,PDSCHs,txSymbols,eqSymbols,CRC,groups);
    end

end
Slot 0: D
Slot 1: D
Slot 2: D
Slot 3: D
Slot 4: D
Slot 5: D
Slot 6: D
Slot 7: S
SRS transmission
Slot 8: U
Slot 9: U
Slot 10: D
Group:  1  1  1  1  1  1  1  1  1  1  1  1 
PDSCH:  1  2  3  4  5  6  7  8  9 10 11 12 
 NPRB:  7  8 43  6 43 41 24 10  8  6 30  6 
  EVM: 21  6  5  4  2  6  7 15 12  7  8 14 
       13  6     6  3        7  5  9     7 
       13  6    13              6  6     6 
       14  5     7              6  7     9 
  CRC:  1  0  0  0  0  0  0  0  0  0  0  0 
Slot 11: D
Group:  1  1  1  1  1  1  1  1  1  1  1  1 
PDSCH:  1  2  3  4  5  6  7  8  9 10 11 12 
 NPRB:  7  8 43  6 43 41 24 10  8  6 30  6 
  EVM: 21  6  5  4  2  6  7 14 11  8  8 14 
       12  6     7  3        7  5  9     7 
       13  6    14              6  6     7 
       14  5     7              6  7     9 
  CRC:  1  0  0  0  0  0  0  0  0  0  0  0 
Slot 12: D
Group:  1  1  1  1  1  1  1  1  1  1  1  1 
PDSCH:  1  2  3  4  5  6  7  8  9 10 11 12 
 NPRB:  7  8 43  6 43 41 24 10  8  6 30  6 
  EVM: 19  6  5  4  2  6  7 14 11  9  8 14 
       12  6     6  3        7  5  9     7 
       12  6    14              5  6     6 
       14  5     8              6  7     9 
  CRC:  1  0  0  0  0  0  0  0  0  0  0  0 
Slot 13: D
Group:  1  1  1  1  1  1  1  1  1  1  1  1 
PDSCH:  1  2  3  4  5  6  7  8  9 10 11 12 
 NPRB:  7  8 43  6 43 41 24 10  8  6 30  6 
  EVM: 20  6  5  5  2  6  7 14 11  8  8 15 
       12  6     7  3        8  5  9     7 
       13  6    14              5  6     7 
       14  6     7              6  7     9 
  CRC:  0  0  0  0  0  0  0  0  0  0  0  0 
Slot 14: D
Group:  1  1  1  1  1  1  1  1  1  1  1  1 
PDSCH:  1  2  3  4  5  6  7  8  9 10 11 12 
 NPRB:  7  8 43  6 43 41 24 10  8  6 30  6 
  EVM: 20  6  5  5  2  6  7 13 11  8  8 15 
       12  6     7  3        8  5  9     7 
       12  6    14              5  6     7 
       14  6     8              6  6     9 
  CRC:  1  0  0  0  0  0  0  0  0  0  0  0 
Slot 15: D
Group:  1  1  1  1  1  1  1  1  1  1  1  1 
PDSCH:  1  2  3  4  5  6  7  8  9 10 11 12 
 NPRB:  7  8 43  6 43 41 24 10  8  6 30  6 
  EVM: 19  5  5  5  2  6  7 13 11  8  8 15 
       12  6     7  3        8  5  9     7 
       12  6    14              5  6     7 
       14  5     7              6  7     9 
  CRC:  0  0  0  0  0  0  0  0  0  0  0  0 
Slot 16: D
Group:  1  1  1  1  1  1  1  1  1  1  1  1 
PDSCH:  1  2  3  4  5  6  7  8  9 10 11 12 
 NPRB:  7  8 43  6 43 41 24 10  8  6 30  6 
  EVM: 19  5  6  5  2  6  7 13 11  8  9 15 
       12  6     7  3        9  5  9     7 
       12  6    14              6  6     7 
       14  6     8              6  6     8 
  CRC:  0  0  0  0  0  0  0  0  0  0  0  0 
Slot 17: S
Group:  1  1  1  1  1  1  1  1  1  1  1  1 
PDSCH:  1  2  3  4  5  6  7  8  9 10 11 12 
 NPRB:  7  8 43  6 43 41 24 10  8  6 30  6 
  EVM: 18  6  6  5  2  7  7 13 11  8  9 15 
       13  7     7  3        9  5  9     7 
       12  6    13              5  6     7 
       14  6     7              6  7     8 
  CRC:  0  0  0  0  0  0  0  0  0  0  0  0 
SRS transmission
Slot 18: U
Slot 19: U

Throughput Results

Display a summary table of the throughput results, which shows the block error rate (BLER) and total bit throughput for each user.

results = summarizeResults(dataState);
disp(results);
    User    BLER    Throughput (bits)
    ____    ____    _________________

      1     0.5             61312    
      2       0        1.5391e+05    
      3       0         2.064e+05    
      4       0        1.1462e+05    
      5       0        4.1301e+05    
      6       0        1.9539e+05    
      7       0        1.1462e+05    
      8       0             95800    
      9       0        1.5391e+05    
     10       0        1.1462e+05    
     11       0        1.4278e+05    
     12       0        1.1462e+05    

Display the total throughput across all users.

totalThroughput = sum(results.("Throughput (bits)"));
dataRate = totalThroughput / (numFrames * 0.01) / 1e6;
disp(['Total throughput across all users: ' num2str(dataRate,'%0.3f') ' Mbps']);
Total throughput across all users: 188.098 Mbps

Display the average BLER across all users.

disp(['Average BLER across all users: ' num2str(mean(results.BLER,'omitnan'),'%0.3f')]);
Average BLER across all users: 0.042

Display the capacity relative to a single-layer user allocated to the entire carrier bandwidth. The maximum possible capacity equals the number of scheduled layers, given by algParameters.ScheduledLayers.

singleLayerThroughput = sum(dataState(1).SingleLayerTBS,'omitnan');
capacity = totalThroughput / singleLayerThroughput;
disp(['Capacity relative to a single-layer user: ' num2str(capacity,'%0.2f') 'x']);
Capacity relative to a single-layer user: 7.82x

The capacity exceeds the number of layers configured for the UEs (4 maximum, ~2.6 average), showing that MU-MIMO scheduling and precoding can successfully increase the capacity of the cell compared to making single-user transmissions.

References

1. 3GPP TS 38.213. "NR; Physical layer procedures for control." 3rd Generation Partnership Project; Technical Specification Group Radio Access Network.

2. Spencer, Q.H., et al. "Zero-Forcing Methods for Downlink Spatial Multiplexing in Multiuser MIMO Channels." IEEE Transactions on Signal Processing, Vol. 52, No. 2, February 2004, pp. 461-471.

3. Peel, C.B., et al. "A Vector-Perturbation Technique for Near-Capacity Multiantenna Multiuser Communication—Part I: Channel Inversion and Regularization." IEEE Transactions on Signal Processing, Vol. 53, No. 1, February 2005, pp. 195-202.

4. 3GPP TS 38.101-4. “NR; User Equipment (UE) radio transmission and reception; Part 4: Performance requirements.” 3rd Generation Partnership Project; Technical Specification Group Radio Access Network.

5. 3GPP TS 38.211. "NR; Physical channels and modulation." 3rd Generation Partnership Project; Technical Specification Group Radio Access Network.

6. 3GPP TS 38.214. "NR; Physical layer procedures for data." 3rd Generation Partnership Project; Technical Specification Group Radio Access Network.

7. Adhikary, A., et al., "Joint Spatial Division and Multiplexing - The Large-Scale Array Regime." IEEE Transactions on Information Theory, Vol. 59, No. 10, October 2013, pp. 6441-6463.

Local Functions

function csi = setupCSI(carrier,bsAntSize,ueAntSizes)
% Set up record of CSI obtained via SRS
    
    NCRB = carrier.NSizeGrid + carrier.NStartGrid;
    numUEs = size(ueAntSizes,1);
    csi = repmat(struct('H',[],'nVar',[],'NSlot',[]),1,numUEs);
    P = prod(bsAntSize);
    
    for ue = 1:numUEs
        
        R = prod(ueAntSizes(ue,:));
        csi(ue).H = NaN([NCRB 1 P R]);
        csi(ue).nVar = NaN([NCRB 1 R]);
        csi(ue).NSlot = NaN([NCRB 1]);
        
    end
    
end

function dataState = setupDataTransfer(carrier,numFrames,numLayers)
% Set up record of PDSCH data transfer
    
    nSlots = carrier.SlotsPerFrame * numFrames;
    TBS = NaN(1,nSlots);
    CRC = NaN(1,nSlots);
    tput = zeros(1,nSlots);
    numUEs = numel(numLayers);
    dataState = repmat(struct('TBS',TBS,'SingleLayerTBS',TBS,'CRC',CRC,'Throughput',tput),1,numUEs);
    
end

function csi = updateCSI(csi,carrier,SRS,H,nVar)
% Update record of CSI obtained via SRS
    
    for ue = SRS
        
        H_ue = H{ue==SRS};
        nVar_ue = nVar{ue==SRS};        
        idx = find(all(~isnan(nVar_ue),3));
        csi(ue).H(idx,:,:,:) = H_ue(idx,:,:,:);
        csi(ue).nVar(idx,:,:) = nVar_ue(idx,:,:);
        csi(ue).NSlot(idx) = carrier.NSlot;
        
    end
    
end

function dataState = updateDataTransfer(dataState,carrier,singleLayerTBS,PDSCH,TBS,CRC)
% Update record of PDSCH data transfer

    nSlot = carrier.NSlot;

    for ue = PDSCH

        TBS_ue = TBS{ue==PDSCH};
        CRC_ue = CRC{ue==PDSCH};
        dataState(ue).SingleLayerTBS(nSlot + 1) = singleLayerTBS;
        dataState(ue).TBS(nSlot + 1) = TBS_ue;
        dataState(ue).CRC(nSlot + 1) = CRC_ue;
        dataState(ue).Throughput(nSlot + 1) = TBS_ue .* (1 - CRC_ue);

    end

end

function results = summarizeResults(dataState)
% Summarize simulation results
    
    numUEs = numel(dataState);
    BLER = zeros(numUEs,1);
    Throughput = zeros(numUEs,1);
    
    for ue = 1:numUEs
        
        CRC = dataState(ue).CRC;
        CRC = CRC(~isnan(CRC));
        BLER(ue) = sum(CRC) / numel(CRC);
        Throughput(ue) = sum(dataState(ue).Throughput);
        
    end
    
    User = (1:numUEs).';
    results = table(User,BLER,Throughput);
    results.Properties.VariableNames{3} = 'Throughput (bits)';
    
end

function displayDiagnostics(schedule,PDSCHs,txSymbols,eqSymbols,CRC,groups)
% Display diagnostic information

    dispfn = @(x,y)disp([sprintf('%5s: ',x) sprintf('%2d ',y)]);

    if (~isempty(schedule.PDSCH))

        numUEs = numel(schedule.PDSCH);
        maxLayers = 4;
        EVM = NaN(maxLayers,numUEs);
        NPRB = zeros(1,numUEs);

        for i = 1:numUEs

            ue = schedule.PDSCH(i);
            pdsch = PDSCHs(ue).Config;
            NPRB(i) = numel(pdsch.PRBSet);
            evm = comm.EVM;
            EVM(1:pdsch.NumLayers,i) = evm(txSymbols{i},eqSymbols{i});

        end

        dispfn('Group',groups(schedule.PDSCH));
        dispfn('PDSCH',schedule.PDSCH);
        dispfn('NPRB',NPRB);

        evmlabel = '  EVM: ';
        for i = 1:maxLayers
            if (i>1)
                evmlabel(:) = ' ';
            end
            if (~all(isnan(EVM(i,:))))
                disp([evmlabel strrep(sprintf('%2d ',round(EVM(i,:))),'NaN','  ')]);
            end
        end

        dispfn('CRC',[CRC{:}]);

    end

    if (~isempty(schedule.SRS))

        disp('SRS transmission');

    end

end

function [numRF,channels,algParameters] = setupJSDM(algParameters,groups,numUEs,channels,bsAntSize)
% Modify parameters if JSDM is chosen as the precoding method

    if any(strcmp(algParameters.PrecodingMethod,{'JSDM-JGP','JSDM-PGP'}))
        algParameters.groups = groups;
        numGroups = max(groups);
        if numGroups < 2
            error('Specify more than one group for JSDM');
        end

        % The channel helper file allows for frequency-domain channel
        % estimation, but is not compatible for JSDM due to the effective
        % channel estimation. Set perfect channel estimation to false.
        algParameters.PerfectChannelEstimator = false;
        
        % Enable channel filtering for JSDM
        for u = 1:numUEs
            channels(u).channel.ChannelFiltering = true;
        end

        % One RF chain per layer
        numRF = algParameters.ScheduledLayers;
    else
        % One RF chain per antenna
        numRF = bsAntSize;
    end

end

See Also

Functions

Objects

Related Topics