主要内容

NR PDSCH 吞吐量

此参考仿真说明如何测量 5G NR (New Radio) 链路的物理下行链路共享信道 (PDSCH) 吞吐量,如 3GPP NR 标准所定义。该示例实现了 PDSCH 和下行链路共享信道 (DL-SCH)。发射机模型包括 PDSCH 解调参考信号 (DM-RS) 和 PDSCH 相位跟踪参考信号 (PT-RS)。该示例支持簇延迟线 (CDL) 和抽头延迟线 (TDL) 传播信道。您可以执行完美同步/信道估计或实际同步/信道估计。您可以使用 Parallel Computing Toolbox™ 并行执行 SNR 循环中的 SNR 点,并使用兼容的图形处理单元 (GPU) 设备进行数据密集型计算,从而缩短总仿真时间。

简介

此示例测量 5G 链路的 PDSCH 吞吐量,如 3GPP NR 标准 [1]、[2]、[3]、[4] 所定义。

该示例对以下 5G NR 特性进行了建模:

  • DL-SCH 传输信道编码

  • 多个码字,取决于层数

  • PDSCH、PDSCH DM-RS 和 PDSCH PT-RS 生成

  • 可变子载波间隔和帧参数集 (2^n * 15 kHz)

  • 普通循环前缀或扩展循环前缀

  • TDL 和 CDL 传播信道模型

仿真的其他特性包括:

  • 使用 SVD 进行 PDSCH 子带预编码

  • CP-OFDM 调制

  • 按时隙和非按时隙的 PDSCH 与 DM-RS 映射

  • 完美同步/信道估计或实际同步/信道估计

  • 包含 16 个进程的 HARQ 操作

  • 该示例在整个载波上使用单个带宽部分

下图显示了实现的处理链。为清晰起见,省略了 DM-RS 和 PT-RS 生成。

有关此示例中实现的步骤的详细说明,请参阅对 5G NR 通信链路进行建模DL-SCH 和 PDSCH 发送和接收处理链

此示例支持宽带预编码和子带预编码。预编码矩阵使用 SVD 来确定,方法是对分配(对于宽带预编码)或子带(对于子带预编码)中所有 PDSCH PRB 的信道估计求平均值。

您可以使用 Parallel Computing Toolbox 并行执行 SNR 循环中的 SNR 点,从而缩短总仿真时间。

仿真长度和 SNR 点

以 10 毫秒帧的数量为单位,设置仿真的长度。应将 NFrames 设为较大的数值,以生成有意义的吞吐量结果。设置要仿真的 SNR 点。每层的 SNR 按每个 RE 定义,并且包含所有天线上的信号和噪声的影响。有关此示例使用的 SNR 定义的说明,请参阅SNR Definition Used in Link Simulations

simParameters = struct();       % Clear simParameters variable to contain all key simulation parameters
simParameters.NFrames = 2;      % Number of 10 ms frames
simParameters.SNRIn = [-5 0 5]; % SNR range (dB)

GPU 加速

当基于非常大的数据集运行仿真时,可以通过在 GPU 上执行计算的数据密集型部分来加速整体仿真时间。使用 UseGPU 标志可控制仿真中 GPU 的使用。该标志设置为 "off" 时,仿真在 CPU 上运行。设置为 "on" 时,仿真会使用 GPU(需要 Parallel Computing Toolbox™)。设置为 "auto" 时,如果有兼容的 GPU 设备可用,仿真将自动使用该 GPU 设备。除了将 UseGPU 设置为 "on""auto" 以在 GPU 上运行仿真之外,您还必须使用 nrCDLChannel 对象进行信道建模。

simParameters.UseGPU = "off";

信道估计器配置

逻辑变量 PerfectChannelEstimator 控制信道估计和同步行为。该变量设置为 true 时,使用完美信道估计和完美同步。否则,基于接收到的 PDSCH DM-RS 的值使用实际信道估计和实际同步。

simParameters.PerfectChannelEstimator = true;

仿真诊断

变量 DisplaySimulationInformation 控制仿真信息(例如每个子帧使用的 HARQ 进程 ID)的显示。如果出现 CRC 错误,还会显示 RV 序列的索引值。

simParameters.DisplaySimulationInformation = true;

使用 DisplayDiagnostics 标志可控制每层 EVM 的绘制。此图监控均衡后接收的信号的质量。每层 EVM 图显示:

  • 每个时隙每层的 EVM,显示了 EVM 随时间的变化。

  • 每个资源块每层的 EVM,显示了 EVM 随频率的变化。

此图会随着仿真过程而变化,并在每个时隙更新。通常情况下,低 SNR 或信道衰落会导致信号质量下降(高 EVM)。信道对每一层的影响都不同,因此,不同层的 EVM 值可能有所不同。

在某些情况下,某些层的 EVM 可能远高于其他层。这些低质量的层可能会导致 CRC 错误。此行为可能是由低 SNR 或对信道条件使用了过多的层造成的。您可以通过组合使用以下方法来避免这种情况:提高 SNR、减少层数、增加天线数量以及提高传输稳健性(降低调制方案和目标码率)。

simParameters.DisplayDiagnostics = false;

载波和 PDSCH 配置

设置仿真的关键参数。这些参数包括:

  • 带宽(以资源块为单位,每个资源块 12 个子载波)。

  • 子载波间隔:15、30、60、120 (kHz)

  • 循环前缀长度:普通或扩展

  • 小区 ID

  • 发射天线和接收天线的数量

同时还指定了包含 DL-SCH 和 PDSCH 参数的子结构体。其中的参数包括:

  • 目标码率

  • 分配的资源块 (PRBSet)

  • 调制方案:'QPSK'、'16QAM'、'64QAM'、'256QAM'

  • 层数

  • PDSCH 映射类型

  • DM-RS 配置参数

  • PT-RS 配置参数

其他仿真全局参数包括:

  • 传播信道模型时延分布(TDL 或 CDL)

% Set waveform type and PDSCH numerology (SCS and CP type)
simParameters.Carrier = nrCarrierConfig;         % Carrier resource grid configuration
simParameters.Carrier.NSizeGrid = 51;            % Bandwidth in number of resource blocks (51 RBs at 30 kHz SCS for 20 MHz BW)
simParameters.Carrier.SubcarrierSpacing = 30;    % 15, 30, 60, 120 (kHz)
simParameters.Carrier.CyclicPrefix = 'Normal';   % 'Normal' or 'Extended' (Extended CP is relevant for 60 kHz SCS only)
simParameters.Carrier.NCellID = 1;               % Cell identity

% PDSCH/DL-SCH parameters
simParameters.PDSCH = nrPDSCHConfig;      % This PDSCH definition is the basis for all PDSCH transmissions in the BLER simulation
simParameters.PDSCHExtension = struct();  % This structure is to hold additional simulation parameters for the DL-SCH and PDSCH

% Define PDSCH time-frequency resource allocation per slot to be full grid (single full grid BWP)
simParameters.PDSCH.PRBSet = 0:simParameters.Carrier.NSizeGrid-1;                 % PDSCH PRB allocation
simParameters.PDSCH.SymbolAllocation = [0,simParameters.Carrier.SymbolsPerSlot];  % Starting symbol and number of symbols of each PDSCH allocation
simParameters.PDSCH.MappingType = 'A';     % PDSCH mapping type ('A'(slot-wise),'B'(non slot-wise))

% Scrambling identifiers
simParameters.PDSCH.NID = simParameters.Carrier.NCellID;
simParameters.PDSCH.RNTI = 1;

% PDSCH resource block mapping (TS 38.211 Section 7.3.1.6)
simParameters.PDSCH.VRBToPRBInterleaving = 0; % Disable interleaved resource mapping
simParameters.PDSCH.VRBBundleSize = 4;

% Define the number of transmission layers to be used
simParameters.PDSCH.NumLayers = 2;            % Number of PDSCH transmission layers

% Define codeword modulation and target coding rate
% The number of codewords is directly dependent on the number of layers so ensure that
% layers are set first before getting the codeword number
if simParameters.PDSCH.NumCodewords > 1                             % Multicodeword transmission (when number of layers being > 4)
    simParameters.PDSCH.Modulation = {'16QAM','16QAM'};             % 'QPSK', '16QAM', '64QAM', '256QAM'
    simParameters.PDSCHExtension.TargetCodeRate = [490 490]/1024;   % Code rate used to calculate transport block sizes
else
    simParameters.PDSCH.Modulation = '16QAM';                       % 'QPSK', '16QAM', '64QAM', '256QAM'
    simParameters.PDSCHExtension.TargetCodeRate = 490/1024;         % Code rate used to calculate transport block sizes
end

% DM-RS and antenna port configuration (TS 38.211 Section 7.4.1.1)
simParameters.PDSCH.DMRS.DMRSTypeAPosition = 2;      % Mapping type A only. First DM-RS symbol position (2,3)
simParameters.PDSCH.DMRS.DMRSLength = 1;             % Number of front-loaded DM-RS symbols (1(single symbol),2(double symbol))
simParameters.PDSCH.DMRS.DMRSAdditionalPosition = 2; % Additional DM-RS symbol positions (max range 0...3)
simParameters.PDSCH.DMRS.DMRSConfigurationType = 2;  % DM-RS configuration type (1,2)
simParameters.PDSCH.DMRS.NumCDMGroupsWithoutData = 1;% Number of CDM groups without data
simParameters.PDSCH.DMRS.NIDNSCID = 1;               % Scrambling identity (0...65535)
simParameters.PDSCH.DMRS.NSCID = 0;                  % Scrambling initialization (0,1)
simParameters.PDSCH.DMRS.DMRSPortSet = [];           % Use this to specify explicit DM-RS port numbers (TS 38.212 Section 7.3.1.2). Empty corresponds to the first NumLayers valid ports

% PT-RS configuration (TS 38.211 Section 7.4.1.2)
simParameters.PDSCH.EnablePTRS = 0;                  % Enable or disable PT-RS (1 or 0)
simParameters.PDSCH.PTRS.TimeDensity = 1;            % PT-RS time density (L_PT-RS) (1, 2, 4)
simParameters.PDSCH.PTRS.FrequencyDensity = 2;       % PT-RS frequency density (K_PT-RS) (2 or 4)
simParameters.PDSCH.PTRS.REOffset = '00';            % PT-RS resource element offset ('00', '01', '10', '11')
simParameters.PDSCH.PTRS.PTRSPortSet = [];           % PT-RS antenna port, subset of DM-RS port set. Empty corresponds to lower DM-RS port number

% Reserved PRB patterns, if required (for CORESETs, forward compatibility etc)
simParameters.PDSCH.ReservedPRB{1}.SymbolSet = [];   % Reserved PDSCH symbols
simParameters.PDSCH.ReservedPRB{1}.PRBSet = [];      % Reserved PDSCH PRBs
simParameters.PDSCH.ReservedPRB{1}.Period = [];      % Periodicity of reserved resources

% Additional simulation and DL-SCH related parameters
%
% PDSCH PRB bundling (TS 38.214 Section 5.1.2.3)
simParameters.PDSCHExtension.PRGBundleSize = [];     % 2, 4, or [] to signify "wideband"
%
% HARQ process and rate matching/TBS parameters
simParameters.PDSCHExtension.XOverhead = 6*simParameters.PDSCH.EnablePTRS; % Set PDSCH rate matching overhead for TBS (Xoh) to 6 when PT-RS is enabled, otherwise 0
simParameters.PDSCHExtension.NHARQProcesses = 16;    % Number of parallel HARQ processes to use
simParameters.PDSCHExtension.EnableHARQ = true;      % Enable retransmissions for each process, using RV sequence [0,2,3,1]
simParameters.PDSCHExtension.EnableCBGTransmission = false; % Enable CBG-based transmission, otherwise TB-based transmission
simParameters.PDSCHExtension.MaxNumCBG = 4;          % Maximum number of CBGs per transport block for each HARQ process in CBG-based transmission

% LDPC decoder parameters
% Available algorithms: 'Belief propagation', 'Layered belief propagation', 'Normalized min-sum', 'Offset min-sum'
simParameters.PDSCHExtension.LDPCDecodingAlgorithm = 'Normalized min-sum';
simParameters.PDSCHExtension.MaximumLDPCIterationCount = 6;

% Define the overall transmission antenna geometry at end-points
% If using a CDL propagation channel then the integer number of antenna elements is
% turned into an antenna panel configured when the channel model object is created
simParameters.NTxAnts = 8;                        % Number of PDSCH transmission antennas (1,2,4,8,16,32,64,128,256,512,1024) >= NumLayers
if simParameters.PDSCH.NumCodewords > 1           % Multi-codeword transmission
    simParameters.NRxAnts = 8;                    % Number of UE receive antennas (even number >= NumLayers)
else
    simParameters.NRxAnts = 2;                    % Number of UE receive antennas (1 or even number >= NumLayers)
end

% Define data type ('single' or 'double') for resource grids and waveforms
simParameters.DataType = 'single';

% Define the general CDL or TDL propagation channel parameters.
% If you later want to debug unexpected simulation results, set DelayProfile to
% 'None' to disable channel impairments due to mobility, fading, multipath,
% delay, and antenna effects.
simParameters.DelayProfile = 'CDL-C'; % 'CDL-A', ..., 'CDL-E', 'TDL-A', ..., 'TDL-E', 'None'
simParameters.DelaySpread = 300e-9;
simParameters.MaximumDopplerShift = 5;

% Cross-check the PDSCH layering against the channel geometry
validateNumLayers(simParameters);

仿真依赖于有关基带波形的各种信息,例如采样率。

waveformInfo = nrOFDMInfo(simParameters.Carrier); % Get information about the baseband waveform after OFDM modulation step

传播信道模型构造

创建用于仿真的信道模型对象。CDL 和 TDL 信道模型均受支持 [5]。但是,要在 GPU 上运行仿真,必须使用 CDL 信道模型。

[channel,simParameters] = createChannel(simParameters,waveformInfo);

获取信道多径分量对应的最大延迟采样数。该值根据具有最大延迟的信道路径和信道滤波器的实现延迟计算得出。稍后需要该值来刷新信道滤波器,以获得接收信号。

chInfo = info(channel);
maxChDelay = chInfo.MaximumChannelDelay;

基于 simParameters.DataType 和 simParameters.UseGPU 创建资源网格的原型

if simParameters.UseGPU == "on" || (simParameters.UseGPU == "auto" && canUseGPU)
    device = gpuDevice().Name;
    fprintf('\nUsing GPU device %s for computation\n',device);
    simParameters.Prototype = zeros(0,0,simParameters.DataType,"gpuArray");
    if class(channel) == "nrTDLChannel"
        error("The nrTDLChannel object does not support GPU arrays. Use an nrCDLChannel object instead.")
    end
else
    simParameters.Prototype =  zeros(0,0,simParameters.DataType);
end

处理循环

要确定每个 SNR 点的吞吐量,请按以下步骤分析每个传输实例的 PDSCH 数据:

  • 更新当前 HARQ 进程。检查给定 HARQ 进程的传输状态,以确定是否需要重传。如果不需要,则生成新数据。

  • 生成资源网格。通过调用 nrDLSCH System object 执行信道编码。该对象对输入传输块进行操作,并保留传输块的内部副本,以备需要重传时使用。使用 nrPDSCH 函数调制 PDSCH 上的编码比特。然后对生成的信号应用预编码。

  • 生成波形。对生成的网格进行 OFDM 调制。

  • 对含噪信道进行建模。通过 CDL 或 TDL 衰落信道传输波形。添加 AWGN。有关此示例使用的 SNR 定义的说明,请参阅SNR Definition Used in Link Simulations

  • 执行同步和 OFDM 解调。对于完美同步,重新构造信道冲激响应以同步接收的波形。对于实际同步,对接收的波形与 PDSCH DM-RS 进行相关性分析。然后对同步后的信号进行 OFDM 解调。

  • 执行信道估计。对于完美信道估计,重新构造信道冲激响应并执行 OFDM 解调。对于实际信道估计,使用 PDSCH DM-RS。

  • 执行均衡和 CPE 补偿。对估计的信道进行 MMSE 均衡处理。使用 PT-RS 符号估计公共相位误差 (CPE),然后在参考 PT-RS OFDM 符号的范围内校正每个 OFDM 符号中的误差。

  • 计算预编码矩阵。通过使用奇异值分解 (SVD) 为下一次传输生成预编码矩阵 W。

  • 对 PDSCH 进行解码。要获取接收的码字的估计,请使用 nrPDSCHDecode 函数,结合噪声估计,对所有发射和接收天线对组恢复的 PDSCH 符号进行解调和解扰。

  • 解码下行链路共享信道 (DL-SCH) 并根据块 CRC 错误更新 HARQ 进程。将解码后的软比特向量传递给 nrDLSCHDecoder System object。该对象解码码字并返回用于确定系统吞吐量的块 CRC 错误。

% Array to store the maximum throughput for all SNR points
numSNRPoints = numel(simParameters.SNRIn);
maxThroughput = zeros(numSNRPoints,1);
% Array to store the simulation throughput for all SNR points
simThroughput = zeros(numSNRPoints,1);
% Array to store measured SNR for all SNR points
rxAntennaSNR = zeros(numSNRPoints,1);

% Set up redundancy version (RV) sequence for all HARQ processes
if simParameters.PDSCHExtension.EnableHARQ
    % In the final report of RAN WG1 meeting #91 (R1-1719301), it was
    % observed in R1-1717405 that if performance is the priority, [0 2 3 1]
    % should be used. If self-decodability is the priority, it should be
    % taken into account that the upper limit of the code rate at which
    % each RV is self-decodable is in the following order: 0>3>2>1
    rvSeq = [0 2 3 1];
else
    % HARQ disabled - single transmission with RV=0, no retransmissions
    rvSeq = 0;
end

% Set up maximum number of CBGs in retransmissions
if simParameters.PDSCHExtension.EnableCBGTransmission
    maxNumCBG = simParameters.PDSCHExtension.MaxNumCBG;
else
    maxNumCBG = 1;
end

% Create DL-SCH encoder system object to perform transport channel encoding
encodeDLSCH = nrDLSCH;
encodeDLSCH.MultipleHARQProcesses = true;
encodeDLSCH.CBGTransmission = true;
encodeDLSCH.TargetCodeRate = simParameters.PDSCHExtension.TargetCodeRate;

% Create DL-SCH decoder system object to perform transport channel decoding
decodeDLSCH = nrDLSCHDecoder;
decodeDLSCH.MultipleHARQProcesses = true;
decodeDLSCH.CBGTransmission = true;
decodeDLSCH.TargetCodeRate = simParameters.PDSCHExtension.TargetCodeRate;
decodeDLSCH.LDPCDecodingAlgorithm = simParameters.PDSCHExtension.LDPCDecodingAlgorithm;
decodeDLSCH.MaximumLDPCIterationCount = simParameters.PDSCHExtension.MaximumLDPCIterationCount;

for snrIdx = 1:numSNRPoints      % comment out for parallel computing
% parfor snrIdx = 1:numSNRPoints % uncomment for parallel computing
% To reduce the total simulation time, you can execute this loop in
% parallel by using the Parallel Computing Toolbox. Comment out the 'for'
% statement and uncomment the 'parfor' statement. If the Parallel Computing
% Toolbox is not installed, 'parfor' defaults to normal 'for' statement.
% Because parfor-loop iterations are executed in parallel in a
% nondeterministic order, the simulation information displayed for each SNR
% point can be intertwined. To switch off simulation information display,
% set the 'displaySimulationInformation' variable above to false

    % Reset the random number generator so that each SNR point will
    % experience the same noise realization
    rng('default');

    % Take full copies of the simulation-level parameter structures so that they are not
    % PCT broadcast variables when using parfor
    simLocal = simParameters;
    waveinfoLocal = waveformInfo;

    % Take copies of channel-level parameters to simplify subsequent parameter referencing
    carrier = simLocal.Carrier;
    pdsch = simLocal.PDSCH;
    pdschextra = simLocal.PDSCHExtension;
    decodeDLSCHLocal = decodeDLSCH;  % Copy of the decoder handle to help PCT classification of variable
    decodeDLSCHLocal.reset();        % Reset decoder at the start of each SNR point

    % Prepare simulation for new SNR point
    SNRdB = simLocal.SNRIn(snrIdx);
    fprintf('\nSimulating transmission scheme 1 (%dx%d) and SCS=%dkHz with %s channel at %gdB SNR for %d 10ms frame(s)\n', ...
        simLocal.NTxAnts,simLocal.NRxAnts,carrier.SubcarrierSpacing, ...
        simLocal.DelayProfile,SNRdB,simLocal.NFrames);

    % Specify the fixed order in which we cycle through the HARQ process IDs
    harqSequence = 0:pdschextra.NHARQProcesses-1;

    % Initialize the state of all HARQ processes
    harqEntity = HARQEntity(harqSequence,rvSeq,pdsch.NumCodewords,maxNumCBG);

    % Reset the channel so that each SNR point will experience the same
    % channel realization
    reset(channel);

    % Total number of slots in the simulation period
    NSlots = simLocal.NFrames * carrier.SlotsPerFrame;

    % Obtain a precoding matrix (wtx) to be used in the transmission of the
    % first transport block
    estChannelGridAnts = getInitialChannelEstimate(carrier,channel,simLocal.DataType,maxChDelay);
    newWtx = hSVDPrecoders(carrier,pdsch,estChannelGridAnts,pdschextra.PRGBundleSize);

    % Timing offset, updated in every slot for perfect synchronization and
    % when the correlation is strong for practical synchronization
    offset = 0;

    % Noise power, normalized by the IFFT size used in OFDM modulation, as
    % the OFDM modulator applies this normalization to the transmitted
    % waveform. Also normalize by the number of receive antennas, as the
    % channel model applies this normalization to the received waveform by
    % default
    SNR = 10^(SNRdB/10);
    N0 = 1/sqrt(simLocal.NRxAnts*waveinfoLocal.Nfft*SNR);
    nVar = N0^2*waveinfoLocal.Nfft;

    % Initialize variables to store power measurements
    rxSigPower = zeros(NSlots,1);

    % Loop over the entire waveform length
    for nslot = 0:NSlots-1

        % Update the carrier slot numbers for new slot
        carrier.NSlot = nslot;

        % Calculate the transport block sizes for the transmission in the slot
        [pdschIndices,pdschIndicesInfo] = nrPDSCHIndices(carrier,pdsch);
        trBlkSizes = nrTBS(pdsch.Modulation,pdsch.NumLayers,numel(pdsch.PRBSet),pdschIndicesInfo.NREPerPRB,pdschextra.TargetCodeRate,pdschextra.XOverhead);

        % HARQ processing
        for cwIdx = 1:pdsch.NumCodewords
            % If new data for current process and codeword then create a new DL-SCH transport block
            if harqEntity.NewData(cwIdx)
                trBlk = randi([0 1],trBlkSizes(cwIdx),1,'like',simLocal.Prototype);
                setTransportBlock(encodeDLSCH,double(trBlk),cwIdx-1,harqEntity.HARQProcessID);
                % If new data because of previous RV sequence time out then flush decoder soft buffer explicitly
                if harqEntity.SequenceTimeout(cwIdx)
                    resetSoftBuffer(decodeDLSCHLocal,cwIdx-1,harqEntity.HARQProcessID);
                end
            end
        end

        % Encode the DL-SCH transport blocks
        codedTrBlocks = encodeDLSCH(pdsch.Modulation,pdsch.NumLayers, ...
            pdschIndicesInfo.G,harqEntity.RedundancyVersion, ...
            harqEntity.HARQProcessID,harqEntity.CBGTI);

        % Get precoding matrix (wtx) calculated in previous slot
        wtx = newWtx;

        % Create a resource grid like the prototype array for a slot
        pdschGrid = zeros(carrier.NSizeGrid*12,carrier.SymbolsPerSlot,simLocal.NTxAnts,"like",simLocal.Prototype);

        % PDSCH modulation and precoding
        pdschSymbols = nrPDSCH(carrier,pdsch,codedTrBlocks);
        [pdschAntSymbols,pdschAntIndices] = nrPDSCHPrecode(carrier,pdschSymbols,pdschIndices,wtx);

        % PDSCH mapping in grid associated with PDSCH transmission period
        pdschGrid(pdschAntIndices) = pdschAntSymbols;

        % PDSCH DM-RS precoding and mapping
        dmrsSymbols = nrPDSCHDMRS(carrier,pdsch);
        dmrsIndices = nrPDSCHDMRSIndices(carrier,pdsch);
        [dmrsAntSymbols,dmrsAntIndices] = nrPDSCHPrecode(carrier,dmrsSymbols,dmrsIndices,wtx);
        pdschGrid(dmrsAntIndices) = dmrsAntSymbols;

        % PDSCH PT-RS precoding and mapping
        ptrsSymbols = nrPDSCHPTRS(carrier,pdsch);
        ptrsIndices = nrPDSCHPTRSIndices(carrier,pdsch);
        [ptrsAntSymbols,ptrsAntIndices] = nrPDSCHPrecode(carrier,ptrsSymbols,ptrsIndices,wtx);
        pdschGrid(ptrsAntIndices) = ptrsAntSymbols;

        % OFDM modulation
        txWaveform = nrOFDMModulate(carrier,pdschGrid);

        % Pass data through channel model. Append zeros at the end of the
        % transmitted waveform to flush channel content. These zeros take
        % into account any delay introduced in the channel. This is a mix
        % of multipath delay and implementation delay. This value may
        % change depending on the sampling rate, delay profile, and delay
        % spread. The channel model also returns the OFDM channel response
        % and timing offset for the specified carrier
        txWaveform = [txWaveform; zeros(maxChDelay,size(txWaveform,2))]; %#ok<AGROW>
        [rxWaveform,ofdmResponse,timingOffset] = channel(txWaveform,carrier);

        % Measure the received signal power at each Rx antenna. Average the
        % power across Rx antennas and normalize by the number of allocated
        % resource elements (REs). NRE counts the occupied REs in the
        % transmitted OFDM resource grid. This measurement assumes that all
        % physical channels and signals in the resource grid have the same
        % average power per RE.
        rxPowerAnt = rms(rxWaveform).^2;
        NRE = nnz(any(pdschGrid,3));
        rxSigPower(nslot+1) = mean(rxPowerAnt)/NRE;

        % Add AWGN to the received time domain waveform
        noise = N0*randn(size(rxWaveform),"like",rxWaveform);
        rxWaveform = rxWaveform + noise;

        if (simLocal.PerfectChannelEstimator)
            % For perfect synchronization, use the timing offset obtained
            % from the channel
            offset = timingOffset;
        else
            % Practical synchronization. Correlate the received waveform
            % with the PDSCH DM-RS to give timing offset estimate 't' and
            % correlation magnitude 'mag'. The function
            % hSkipWeakTimingOffset is used to update the receiver timing
            % offset. If the correlation peak in 'mag' is weak, the current
            % timing estimate 't' is ignored and the previous estimate
            % 'offset' is used
            [t,mag] = nrTimingEstimate(carrier,rxWaveform,dmrsIndices,dmrsSymbols);
            offset = hSkipWeakTimingOffset(offset,t,mag);
            % Display a warning if the estimated timing offset exceeds the
            % maximum channel delay
            if offset > maxChDelay
                warning(['Estimated timing offset (%d) is greater than the maximum channel delay (%d).' ...
                    ' This will result in a decoding failure. This may be caused by low SNR,' ...
                    ' or not enough DM-RS symbols to synchronize successfully.'],offset,maxChDelay);
            end
        end
        rxWaveform = rxWaveform(1+offset:end,:);

        % Perform OFDM demodulation on the received data to recreate the
        % resource grid, including padding in the event that practical
        % synchronization results in an incomplete slot being demodulated
        rxGrid = nrOFDMDemodulate(carrier,rxWaveform);
        [K,L,R] = size(rxGrid);
        if (L < carrier.SymbolsPerSlot)
            rxGrid = cat(2,rxGrid,zeros(K,carrier.SymbolsPerSlot-L,R));
        end

        if (simLocal.PerfectChannelEstimator)
            % For perfect channel estimate, use the OFDM channel response
            % obtained from the channel
            estChannelGridAnts = ofdmResponse;

            % Use the precalculated noise variance as the perfect noise
            % estimate
            noiseEst = nVar;

            % Apply precoding to channel estimate and get PDSCH resource
            % elements from the received grid and channel estimate
            estChannelGridPorts = precodeChannelEstimate(carrier,estChannelGridAnts,permute(wtx,[2 1 3]));
            [pdschRx,pdschHest] = nrExtractResources(pdschIndices,rxGrid,estChannelGridPorts);
        else
            % Practical channel estimation between the received grid and
            % each transmission layer, using the PDSCH DM-RS for each
            % layer. This channel estimate includes the effect of
            % transmitter precoding
            [estChannelGridPorts,noiseEst] = nrChannelEstimate(carrier,rxGrid,dmrsIndices,dmrsSymbols,'PRGBundleSize',pdschextra.PRGBundleSize,'CDMLengths',pdsch.DMRS.CDMLengths);

            % Average noise estimate across PRGs and layers
            noiseEst = mean(noiseEst,'all');

            % Get PDSCH resource elements from the received grid and
            % channel estimate
            [pdschRx,pdschHest] = nrExtractResources(pdschIndices,rxGrid,estChannelGridPorts);

            % Remove precoding from estChannelGridPorts to get channel
            % estimate w.r.t. antennas
            estChannelGridAnts = precodeChannelEstimate(carrier,estChannelGridPorts,conj(wtx));
        end

        % Equalization
        [pdschEq,csi] = nrEqualizeMMSE(pdschRx,pdschHest,noiseEst);

        % Common phase error (CPE) compensation
        if ~isempty(ptrsIndices)
            pdschEq = hCompensateCPE(carrier,pdsch,pdschEq,rxGrid,estChannelGridPorts,noiseEst);
        end

        % Decode PDSCH physical channel
        [dlschLLRs,rxSymbols] = nrPDSCHDecode(carrier,pdsch,pdschEq,noiseEst);

        % Display EVM per layer, per slot and per RB
        if (simLocal.DisplayDiagnostics)
            plotLayerEVM(NSlots,nslot,pdsch,size(pdschGrid),pdschIndices,pdschSymbols,pdschEq);
        end

        % Scale LLRs by CSI
        csi = nrLayerDemap(csi); % CSI layer demapping
        for cwIdx = 1:pdsch.NumCodewords
            Qm = length(dlschLLRs{cwIdx})/length(rxSymbols{cwIdx}); % bits per symbol
            csi{cwIdx} = repmat(csi{cwIdx}.',Qm,1);                 % expand by each bit per symbol
            dlschLLRs{cwIdx} = dlschLLRs{cwIdx} .* csi{cwIdx}(:);   % scale by CSI
        end

        % Decode the DL-SCH transport channel
        decodeDLSCHLocal.TransportBlockLength = trBlkSizes;
        [decbits,blkerr,cbgerr] = decodeDLSCHLocal(dlschLLRs, ...
            pdsch.Modulation,pdsch.NumLayers,harqEntity.RedundancyVersion, ...
            harqEntity.HARQProcessID,harqEntity.CBGTI);

        % Store values to calculate throughput
        simThroughput(snrIdx) = simThroughput(snrIdx) + sum(~blkerr .* trBlkSizes);
        maxThroughput(snrIdx) = maxThroughput(snrIdx) + sum(trBlkSizes);

        % Update current process with CRC error and advance to next process
        procstatus = updateAndAdvance(harqEntity,blkerr,trBlkSizes,pdschIndicesInfo.G,cbgerr);
        if (simLocal.DisplaySimulationInformation)
            fprintf('\n(%3.2f%%) NSlot=%d, %s',100*(nslot+1)/NSlots,nslot,procstatus);
        end

        % Get precoding matrix for next slot
        newWtx = hSVDPrecoders(carrier,pdsch,estChannelGridAnts,pdschextra.PRGBundleSize);

    end

    % Calculate the noise power per RE and Rx antenna. This is constant
    % across all slots.
    noisePower = N0^2/(waveinfoLocal.Nfft*carrier.SymbolsPerSlot);

    % Since the received power varies over time due to channel effects,
    % compute the average power across all slots to determine the average
    % SNR per receive antenna and RE.
    rxAntennaSNR(snrIdx) = pow2db(mean(rxSigPower)./noisePower);

    % Display the results dynamically in the command window
    if (simLocal.DisplaySimulationInformation)
        fprintf('\n');
    end
    fprintf('\nThroughput(Mbps) for %d frame(s) = %.4f\n',simLocal.NFrames,1e-6*simThroughput(snrIdx)/(simLocal.NFrames*10e-3));
    fprintf('Throughput(%%) for %d frame(s) = %.4f\n',simLocal.NFrames,simThroughput(snrIdx)*100/maxThroughput(snrIdx));

end
Simulating transmission scheme 1 (8x2) and SCS=30kHz with CDL-C channel at -5dB SNR for 2 10ms frame(s)

(2.50%) NSlot=0, HARQ Proc 0: CW0: Initial transmission failed  (TBS=30216,RV=0,CR=0.474736).
(5.00%) NSlot=1, HARQ Proc 1: CW0: Initial transmission failed  (TBS=30216,RV=0,CR=0.474736).
(7.50%) NSlot=2, HARQ Proc 2: CW0: Initial transmission failed  (TBS=30216,RV=0,CR=0.474736).
(10.00%) NSlot=3, HARQ Proc 3: CW0: Initial transmission failed  (TBS=30216,RV=0,CR=0.474736).
(12.50%) NSlot=4, HARQ Proc 4: CW0: Initial transmission failed  (TBS=30216,RV=0,CR=0.474736).
(15.00%) NSlot=5, HARQ Proc 5: CW0: Initial transmission failed  (TBS=30216,RV=0,CR=0.474736).
(17.50%) NSlot=6, HARQ Proc 6: CW0: Initial transmission failed  (TBS=30216,RV=0,CR=0.474736).
(20.00%) NSlot=7, HARQ Proc 7: CW0: Initial transmission failed  (TBS=30216,RV=0,CR=0.474736).
(22.50%) NSlot=8, HARQ Proc 8: CW0: Initial transmission failed  (TBS=30216,RV=0,CR=0.474736).
(25.00%) NSlot=9, HARQ Proc 9: CW0: Initial transmission failed  (TBS=30216,RV=0,CR=0.474736).
(27.50%) NSlot=10, HARQ Proc 10: CW0: Initial transmission failed  (TBS=30216,RV=0,CR=0.474736).
(30.00%) NSlot=11, HARQ Proc 11: CW0: Initial transmission failed  (TBS=30216,RV=0,CR=0.474736).
(32.50%) NSlot=12, HARQ Proc 12: CW0: Initial transmission failed  (TBS=30216,RV=0,CR=0.474736).
(35.00%) NSlot=13, HARQ Proc 13: CW0: Initial transmission failed  (TBS=30216,RV=0,CR=0.474736).
(37.50%) NSlot=14, HARQ Proc 14: CW0: Initial transmission failed  (TBS=30216,RV=0,CR=0.474736).
(40.00%) NSlot=15, HARQ Proc 15: CW0: Initial transmission failed  (TBS=30216,RV=0,CR=0.474736).
(42.50%) NSlot=16, HARQ Proc 0: CW0: Retransmission #1 passed  (TBS=30216,RV=2,CR=0.474736).
(45.00%) NSlot=17, HARQ Proc 1: CW0: Retransmission #1 passed  (TBS=30216,RV=2,CR=0.474736).
(47.50%) NSlot=18, HARQ Proc 2: CW0: Retransmission #1 passed  (TBS=30216,RV=2,CR=0.474736).
(50.00%) NSlot=19, HARQ Proc 3: CW0: Retransmission #1 passed  (TBS=30216,RV=2,CR=0.474736).
(52.50%) NSlot=20, HARQ Proc 4: CW0: Retransmission #1 passed  (TBS=30216,RV=2,CR=0.474736).
(55.00%) NSlot=21, HARQ Proc 5: CW0: Retransmission #1 passed  (TBS=30216,RV=2,CR=0.474736).
(57.50%) NSlot=22, HARQ Proc 6: CW0: Retransmission #1 passed  (TBS=30216,RV=2,CR=0.474736).
(60.00%) NSlot=23, HARQ Proc 7: CW0: Retransmission #1 passed  (TBS=30216,RV=2,CR=0.474736).
(62.50%) NSlot=24, HARQ Proc 8: CW0: Retransmission #1 passed  (TBS=30216,RV=2,CR=0.474736).
(65.00%) NSlot=25, HARQ Proc 9: CW0: Retransmission #1 passed  (TBS=30216,RV=2,CR=0.474736).
(67.50%) NSlot=26, HARQ Proc 10: CW0: Retransmission #1 passed  (TBS=30216,RV=2,CR=0.474736).
(70.00%) NSlot=27, HARQ Proc 11: CW0: Retransmission #1 passed  (TBS=30216,RV=2,CR=0.474736).
(72.50%) NSlot=28, HARQ Proc 12: CW0: Retransmission #1 passed  (TBS=30216,RV=2,CR=0.474736).
(75.00%) NSlot=29, HARQ Proc 13: CW0: Retransmission #1 passed  (TBS=30216,RV=2,CR=0.474736).
(77.50%) NSlot=30, HARQ Proc 14: CW0: Retransmission #1 passed  (TBS=30216,RV=2,CR=0.474736).
(80.00%) NSlot=31, HARQ Proc 15: CW0: Retransmission #1 passed  (TBS=30216,RV=2,CR=0.474736).
(82.50%) NSlot=32, HARQ Proc 0: CW0: Initial transmission failed  (TBS=30216,RV=0,CR=0.474736).
(85.00%) NSlot=33, HARQ Proc 1: CW0: Initial transmission failed  (TBS=30216,RV=0,CR=0.474736).
(87.50%) NSlot=34, HARQ Proc 2: CW0: Initial transmission failed  (TBS=30216,RV=0,CR=0.474736).
(90.00%) NSlot=35, HARQ Proc 3: CW0: Initial transmission failed  (TBS=30216,RV=0,CR=0.474736).
(92.50%) NSlot=36, HARQ Proc 4: CW0: Initial transmission failed  (TBS=30216,RV=0,CR=0.474736).
(95.00%) NSlot=37, HARQ Proc 5: CW0: Initial transmission failed  (TBS=30216,RV=0,CR=0.474736).
(97.50%) NSlot=38, HARQ Proc 6: CW0: Initial transmission failed  (TBS=30216,RV=0,CR=0.474736).
(100.00%) NSlot=39, HARQ Proc 7: CW0: Initial transmission failed  (TBS=30216,RV=0,CR=0.474736).

Throughput(Mbps) for 2 frame(s) = 24.1728
Throughput(%) for 2 frame(s) = 40.0000

Simulating transmission scheme 1 (8x2) and SCS=30kHz with CDL-C channel at 0dB SNR for 2 10ms frame(s)

(2.50%) NSlot=0, HARQ Proc 0: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(5.00%) NSlot=1, HARQ Proc 1: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(7.50%) NSlot=2, HARQ Proc 2: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(10.00%) NSlot=3, HARQ Proc 3: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(12.50%) NSlot=4, HARQ Proc 4: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(15.00%) NSlot=5, HARQ Proc 5: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(17.50%) NSlot=6, HARQ Proc 6: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(20.00%) NSlot=7, HARQ Proc 7: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(22.50%) NSlot=8, HARQ Proc 8: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(25.00%) NSlot=9, HARQ Proc 9: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(27.50%) NSlot=10, HARQ Proc 10: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(30.00%) NSlot=11, HARQ Proc 11: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(32.50%) NSlot=12, HARQ Proc 12: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(35.00%) NSlot=13, HARQ Proc 13: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(37.50%) NSlot=14, HARQ Proc 14: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(40.00%) NSlot=15, HARQ Proc 15: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(42.50%) NSlot=16, HARQ Proc 0: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(45.00%) NSlot=17, HARQ Proc 1: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(47.50%) NSlot=18, HARQ Proc 2: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(50.00%) NSlot=19, HARQ Proc 3: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(52.50%) NSlot=20, HARQ Proc 4: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(55.00%) NSlot=21, HARQ Proc 5: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(57.50%) NSlot=22, HARQ Proc 6: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(60.00%) NSlot=23, HARQ Proc 7: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(62.50%) NSlot=24, HARQ Proc 8: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(65.00%) NSlot=25, HARQ Proc 9: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(67.50%) NSlot=26, HARQ Proc 10: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(70.00%) NSlot=27, HARQ Proc 11: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(72.50%) NSlot=28, HARQ Proc 12: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(75.00%) NSlot=29, HARQ Proc 13: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(77.50%) NSlot=30, HARQ Proc 14: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(80.00%) NSlot=31, HARQ Proc 15: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(82.50%) NSlot=32, HARQ Proc 0: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(85.00%) NSlot=33, HARQ Proc 1: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(87.50%) NSlot=34, HARQ Proc 2: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(90.00%) NSlot=35, HARQ Proc 3: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(92.50%) NSlot=36, HARQ Proc 4: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(95.00%) NSlot=37, HARQ Proc 5: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(97.50%) NSlot=38, HARQ Proc 6: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(100.00%) NSlot=39, HARQ Proc 7: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).

Throughput(Mbps) for 2 frame(s) = 60.4320
Throughput(%) for 2 frame(s) = 100.0000

Simulating transmission scheme 1 (8x2) and SCS=30kHz with CDL-C channel at 5dB SNR for 2 10ms frame(s)

(2.50%) NSlot=0, HARQ Proc 0: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(5.00%) NSlot=1, HARQ Proc 1: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(7.50%) NSlot=2, HARQ Proc 2: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(10.00%) NSlot=3, HARQ Proc 3: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(12.50%) NSlot=4, HARQ Proc 4: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(15.00%) NSlot=5, HARQ Proc 5: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(17.50%) NSlot=6, HARQ Proc 6: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(20.00%) NSlot=7, HARQ Proc 7: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(22.50%) NSlot=8, HARQ Proc 8: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(25.00%) NSlot=9, HARQ Proc 9: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(27.50%) NSlot=10, HARQ Proc 10: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(30.00%) NSlot=11, HARQ Proc 11: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(32.50%) NSlot=12, HARQ Proc 12: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(35.00%) NSlot=13, HARQ Proc 13: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(37.50%) NSlot=14, HARQ Proc 14: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(40.00%) NSlot=15, HARQ Proc 15: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(42.50%) NSlot=16, HARQ Proc 0: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(45.00%) NSlot=17, HARQ Proc 1: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(47.50%) NSlot=18, HARQ Proc 2: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(50.00%) NSlot=19, HARQ Proc 3: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(52.50%) NSlot=20, HARQ Proc 4: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(55.00%) NSlot=21, HARQ Proc 5: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(57.50%) NSlot=22, HARQ Proc 6: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(60.00%) NSlot=23, HARQ Proc 7: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(62.50%) NSlot=24, HARQ Proc 8: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(65.00%) NSlot=25, HARQ Proc 9: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(67.50%) NSlot=26, HARQ Proc 10: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(70.00%) NSlot=27, HARQ Proc 11: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(72.50%) NSlot=28, HARQ Proc 12: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(75.00%) NSlot=29, HARQ Proc 13: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(77.50%) NSlot=30, HARQ Proc 14: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(80.00%) NSlot=31, HARQ Proc 15: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(82.50%) NSlot=32, HARQ Proc 0: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(85.00%) NSlot=33, HARQ Proc 1: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(87.50%) NSlot=34, HARQ Proc 2: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(90.00%) NSlot=35, HARQ Proc 3: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(92.50%) NSlot=36, HARQ Proc 4: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(95.00%) NSlot=37, HARQ Proc 5: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(97.50%) NSlot=38, HARQ Proc 6: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).
(100.00%) NSlot=39, HARQ Proc 7: CW0: Initial transmission passed  (TBS=30216,RV=0,CR=0.474736).

Throughput(Mbps) for 2 frame(s) = 60.4320
Throughput(%) for 2 frame(s) = 100.0000

结果

显示测得的吞吐量。这是根据可用于数据传输的资源,计算得出的链路最大可能吞吐量的百分比。

figure;
plot(simParameters.SNRIn,simThroughput*100./maxThroughput,'o-.')
xlabel('SNR (dB)'); ylabel('Throughput (%)'); grid on;
title(sprintf('%s (%dx%d) / NRB=%d / SCS=%dkHz', ...
              simParameters.DelayProfile,simParameters.NTxAnts,simParameters.NRxAnts, ...
              simParameters.Carrier.NSizeGrid,simParameters.Carrier.SubcarrierSpacing));

% Bundle key parameters and results into a combined structure for recording
simResults = struct();
simResults.simParameters = simParameters;
simResults.simThroughput = simThroughput;
simResults.maxThroughput = maxThroughput;
simResults.rxAntennaSNR = rxAntennaSNR;

summaryTable = processResults(simResults);

显示包含测得的吞吐量和 SNR 的表。SNRIn 列中列出了仿真中指定的目标平均 SNR。Rx Antenna SNR 列中列出了在信道输出端测得的每个接收天线和 RE 的平均 SNR。测得的 SNR 包括信道和 MIMO 预编码引起的效应。有关此示例使用的 SNR 定义的说明,请参阅SNR Definition Used in Link Simulations

disp(summaryTable);
    SNRIn    Throughput (%)    Throughput (Mbps)    BLER (%)    Rx Antenna SNR
    _____    ______________    _________________    ________    ______________

     -5            40                24.17             60             5.2     
      0           100                60.43              0            10.2     
      5           100                60.43              0            15.2     

下图显示了对 10000 个子帧进行仿真(NFrames = 1000SNRIn = -18:2:16)获得的吞吐量结果。

精选参考文献

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

  2. 3GPP TS 38.212."NR; Multiplexing and channel coding."3rd Generation Partnership Project; Technical Specification Group Radio Access Network.

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

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

  5. 3GPP TR 38.901."Study on channel model for frequencies from 0.5 to 100 GHz."3rd Generation Partnership Project; Technical Specification Group Radio Access Network.

局部函数

function summaryTable = processResults(results)
% Create a simulation results table

    NFrames = results.simParameters.NFrames;
    SNRIn = results.simParameters.SNRIn;

    totalBits = results.maxThroughput;
    correctBits = results.simThroughput;

    throughputMbps = round(1e-6*correctBits/(NFrames*10e-3),2);
    throughput = round(100*(correctBits./totalBits),2);

    bler = 100 - throughput;
    SNRout = round(results.rxAntennaSNR,1);
    summaryTable = table(SNRIn.',throughput,throughputMbps,bler,SNRout);

    summaryTable.Properties.VariableNames = ["SNRIn" "Throughput (%)" "Throughput (Mbps)" "BLER (%)" "Rx Antenna SNR"];

end

function validateNumLayers(simParameters)
% Validate the number of layers, relative to the antenna geometry

    numlayers = simParameters.PDSCH.NumLayers;
    ntxants = simParameters.NTxAnts;
    nrxants = simParameters.NRxAnts;
    antennaDescription = sprintf('min(NTxAnts,NRxAnts) = min(%d,%d) = %d',ntxants,nrxants,min(ntxants,nrxants));
    if numlayers > min(ntxants,nrxants)
        error('The number of layers (%d) must satisfy NumLayers <= %s', ...
            numlayers,antennaDescription);
    end

    % Display a warning if the maximum possible rank of the channel equals
    % the number of layers
    if (numlayers > 2) && (numlayers == min(ntxants,nrxants))
        warning(['The maximum possible rank of the channel, given by %s, is equal to NumLayers (%d).' ...
            ' This may result in a decoding failure under some channel conditions.' ...
            ' Try decreasing the number of layers or increasing the channel rank' ...
            ' (use more transmit or receive antennas).'],antennaDescription,numlayers); %#ok<SPWRN>
    end

end

function estChannelGrid = getInitialChannelEstimate(carrier,propchannel,dataType,maxChDelay)
% Obtain channel estimate before first transmission. This can be used to
% obtain a precoding matrix for the first slot.

    ofdmInfo = nrOFDMInfo(carrier);

    % Clone of the channel
    chClone = propchannel.clone();
    chClone.release();

    % No filtering needed to get perfect channel estimate
    chClone.ChannelFiltering = false;
    chClone.OutputDataType = dataType;
    if ~strcmp(chClone.DelayProfile,"None")
        chClone.NumTimeSamples = (ofdmInfo.SampleRate/1000/carrier.SlotsPerSubframe)+maxChDelay;
    end

    % Get the perfect channel estimate
    estChannelGrid = chClone(carrier);

end

function estChannelGrid = precodeChannelEstimate(carrier,estChannelGrid,W)
% Apply precoding matrix W to the last dimension of the channel estimate

    [K,L,R,P] = size(estChannelGrid);
    estChannelGrid = reshape(estChannelGrid,[K*L R P]);
    estChannelGrid = nrPDSCHPrecode(carrier,estChannelGrid,reshape(1:numel(estChannelGrid),[K*L R P]),W);
    estChannelGrid = reshape(estChannelGrid,K,L,R,[]);

end

function plotLayerEVM(NSlots,nslot,pdsch,siz,pdschIndices,pdschSymbols,pdschEq)
% Plot EVM information

    persistent slotEVM;
    persistent rbEVM
    persistent evmPerSlot;

    if (nslot==0)
        slotEVM = comm.EVM;
        rbEVM = comm.EVM;
        evmPerSlot = NaN(NSlots,pdsch.NumLayers);
        figure;
    end
    evmPerSlot(nslot+1,:) = slotEVM(pdschSymbols,pdschEq);
    subplot(2,1,1);
    plot(0:(NSlots-1),evmPerSlot,'o-');
    xlabel('Slot number');
    ylabel('EVM (%)');
    legend("layer " + (1:pdsch.NumLayers),'Location','EastOutside');
    title('EVM per layer per slot');

    subplot(2,1,2);
    [k,~,p] = ind2sub(siz,pdschIndices);
    rbsubs = floor((k-1) / 12);
    NRB = siz(1) / 12;
    evmPerRB = NaN(NRB,pdsch.NumLayers);
    for nu = 1:pdsch.NumLayers
        for rb = unique(rbsubs).'
            this = (rbsubs==rb & p==nu);
            evmPerRB(rb+1,nu) = rbEVM(pdschSymbols(this),pdschEq(this));
        end
    end
    plot(0:(NRB-1),evmPerRB,'x-');
    xlabel('Resource block');
    ylabel('EVM (%)');
    legend("layer " + (1:pdsch.NumLayers),'Location','EastOutside');
    title(['EVM per layer per resource block, slot #' num2str(nslot)]);

    drawnow;

end

function [channel,simParameters] = createChannel(simParameters,waveformInfo)

    % Construct the CDL or TDL channel model object
    if contains(simParameters.DelayProfile,'CDL','IgnoreCase',true) || ...
            strcmpi(simParameters.DelayProfile,'None')

        channel = nrCDLChannel; % CDL channel object

        % Turn the number of antennas into antenna panel array layouts. If
        % NTxAnts is not one of (1,2,4,8,16,32,64,128,256,512,1024), its value
        % is rounded up to the nearest value in the set. If NRxAnts is not 1 or
        % even, its value is rounded up to the nearest even number.
        channel = hArrayGeometry(channel,simParameters.NTxAnts,simParameters.NRxAnts);
        simParameters.NTxAnts = prod(channel.TransmitAntennaArray.Size);
        simParameters.NRxAnts = prod(channel.ReceiveAntennaArray.Size);

    else

        channel = nrTDLChannel; % TDL channel object

        % Configure the channel to automatically select a sample rate for
        % generating channel coefficients
        channel.PathGainSampleRate = 'auto';

        % Set the channel geometry
        channel.NumTransmitAntennas = simParameters.NTxAnts;
        channel.NumReceiveAntennas = simParameters.NRxAnts;

    end

    % Assign simulation channel parameters and waveform sample rate to the
    % object, and specify OFDM channel response as the channel response output
    % so that perfect channel estimation is calculated while filtering the
    % signal
    channel.DelayProfile = simParameters.DelayProfile;
    if ~strcmp(channel.DelayProfile,"None")
        channel.DelaySpread = simParameters.DelaySpread;
        channel.MaximumDopplerShift = simParameters.MaximumDopplerShift;
        channel.SampleRate = waveformInfo.SampleRate;
    end
    channel.ChannelResponseOutput = 'ofdm-response';

end

另请参阅

对象

函数

主题