主要内容

NR PUSCH 吞吐量

此参考仿真说明如何测量 5G NR (New Radio) 链路的物理上行链路共享信道 (PUSCH) 吞吐量,如 3GPP NR 标准所定义。该示例实现了 PUSCH 和上行链路传输信道 (UL-SCH)。发射机模型包括 PUSCH 解调参考信号 (DM-RS)。该示例支持簇延迟线 (CDL) 和抽头延迟线 (TDL) 传播信道。您可以执行完美同步/信道估计或实际同步/信道估计。您可以使用 Parallel Computing Toolbox™ 并行执行 SNR 循环中的 SNR 点,从而缩短总仿真时间。

简介

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

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

  • UL-SCH 传输信道编码

  • PUSCH 和 PUSCH DM-RS 生成

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

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

  • TDL 和 CDL 传播信道模型

仿真的其他特性包括:

  • 基于码本和非基于码本的 PUSCH 传输方案

  • 可选的 PUSCH 变换预编码

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

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

  • 包含 16 个进程的 HARQ 操作

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

请注意,此示例不包括根据信道条件对 MIMO 预编码进行闭环自适应。示例中使用的 PUSCH MIMO 预编码如下:

  • 对于基于码本的传输,可以使用 TPMI 参数选择 PUSCH 调制内部使用的 MIMO 预编码矩阵。

  • 特定于实现的 MIMO 预编码矩阵(用于非基于码本的传输,或基于码本的传输中发射天线端口与天线之间的 MIMO 预编码)是一个单位矩阵。

您可以使用 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)

信道估计器配置

逻辑变量 PerfectChannelEstimator 控制信道估计和同步行为。该变量设置为 true 时,使用完美信道估计和完美同步。否则,基于接收到的 PUSCH 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;

载波和 PUSCH 配置

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

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

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

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

  • 小区 ID

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

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

  • 目标码率

  • 分配的资源块 (PRBSet)

  • 调制方案:'pi/2-BPSK'、'QPSK'、'16QAM'、'64QAM'、'256QAM'

  • 层数

  • 变换预编码(启用/禁用)

  • PUSCH 传输方案和 MIMO 预编码矩阵指示 (TPMI)

  • 天线端口的数量

  • PUSCH 映射类型

  • DM-RS 配置参数

  • PT-RS 配置参数

其他仿真全局参数包括:

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

请注意,如果启用了变换预编码,则应将层数设置为 1。

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

% PUSCH/UL-SCH parameters
simParameters.PUSCH = nrPUSCHConfig;      % This PUSCH definition is the basis for all PUSCH transmissions in the BLER simulation
simParameters.PUSCHExtension = struct();  % This structure is to hold additional simulation parameters for the UL-SCH and PUSCH

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

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

% Define the transform precoding enabling, layering and transmission scheme
simParameters.PUSCH.TransformPrecoding = false; % Enable or disable transform precoding
simParameters.PUSCH.NumLayers = 1;              % Number of PUSCH transmission layers
simParameters.PUSCH.TransmissionScheme = 'nonCodebook'; % Transmission scheme ('nonCodebook','codebook')
simParameters.PUSCH.NumAntennaPorts = 1;        % Number of antenna ports for codebook based precoding
simParameters.PUSCH.TPMI = 0;                   % Precoding matrix indicator for codebook based precoding

% Define codeword modulation
simParameters.PUSCH.Modulation = 'QPSK'; % 'pi/2-BPSK', 'QPSK', '16QAM', '64QAM', '256QAM'

% PUSCH DM-RS configuration
simParameters.PUSCH.DMRS.DMRSTypeAPosition = 2;       % Mapping type A only. First DM-RS symbol position (2,3)
simParameters.PUSCH.DMRS.DMRSLength = 1;              % Number of front-loaded DM-RS symbols (1(single symbol),2(double symbol))
simParameters.PUSCH.DMRS.DMRSAdditionalPosition = 1;  % Additional DM-RS symbol positions (max range 0...3)
simParameters.PUSCH.DMRS.DMRSConfigurationType = 1;   % DM-RS configuration type (1,2)
simParameters.PUSCH.DMRS.NumCDMGroupsWithoutData = 2; % Number of CDM groups without data
simParameters.PUSCH.DMRS.NIDNSCID = 0;                % Scrambling identity (0...65535)
simParameters.PUSCH.DMRS.NSCID = 0;                   % Scrambling initialization (0,1)
simParameters.PUSCH.DMRS.NRSID = 0;                   % Scrambling ID for low-PAPR sequences (0...1007)
simParameters.PUSCH.DMRS.GroupHopping = 0;            % Group hopping (0,1)
simParameters.PUSCH.DMRS.SequenceHopping = 0;         % Sequence hopping (0,1)
simParameters.PUSCH.DMRS.DMRSPortSet = [];            % Use this to specify explicit DM-RS port numbers (TS 38.212 Section 7.3.1.1). Empty corresponds to the first NumLayers valid ports

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

% Additional simulation and UL-SCH related parameters
%
% Target code rate
simParameters.PUSCHExtension.TargetCodeRate = 193 / 1024; % Code rate used to calculate transport block size
%
% HARQ process and rate matching/TBS parameters
simParameters.PUSCHExtension.XOverhead = 6*simParameters.PUSCH.EnablePTRS; % Set PUSCH rate matching overhead for TBS (Xoh) to 6 when PT-RS is enabled, otherwise 0
simParameters.PUSCHExtension.NHARQProcesses = 16; % Number of parallel HARQ processes to use
simParameters.PUSCHExtension.EnableHARQ = true;   % Enable retransmissions for each process, using RV sequence [0,2,3,1]
simParameters.PUSCHExtension.EnableCBGTransmission = false; % Enable CBG-based transmission, otherwise TB-based transmission
simParameters.PUSCHExtension.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.PUSCHExtension.LDPCDecodingAlgorithm = 'Normalized min-sum';
simParameters.PUSCHExtension.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 = 1; % Number of transmit antennas
simParameters.NRxAnts = 2; % Number of receive antennas

% 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 = 'TDL-A'; % 'TDL-A', ..., 'TDL-E', 'CDL-A', ..., 'CDL-E', 'None'
simParameters.DelaySpread = 30e-9;
simParameters.MaximumDopplerShift = 10;

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

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

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

传播信道模型构造

创建用于仿真的信道模型对象。CDL 和 TDL 信道模型均受支持 [5]。

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

获取最大信道延迟。

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

处理循环

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

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

  • 生成资源网格。使用 nrULSCH System object™ 执行信道编码。该对象对输入传输块进行操作,并保留传输块的内部副本,以备需要重传时使用。使用 nrPUSCH 函数调制 PUSCH 上的编码比特。然后对生成的信号应用特定于实现的 MIMO 预编码。请注意,如果 TxScheme='codebook',则 nrPUSCH 已经在内部应用了基于码本的 MIMO 预编码,而特定于实现的 MIMO 预编码是 MIMO 预编码的一个附加阶段。

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

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

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

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

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

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

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

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

% Set up redundancy version (RV) sequence for all HARQ processes
if simParameters.PUSCHExtension.EnableHARQ
    % From PUSCH demodulation requirements in RAN WG4 meeting #88bis (R4-1814062)
    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 retransmission
if simParameters.PUSCHExtension.EnableCBGTransmission
    maxNumCBG = simParameters.PUSCHExtension.MaxNumCBG;
else
    maxNumCBG = 1;
end

% Create UL-SCH encoder System object to perform transport channel encoding
encodeULSCH = nrULSCH;
encodeULSCH.MultipleHARQProcesses = true;
encodeULSCH.CBGTransmission = true;
encodeULSCH.TargetCodeRate = simParameters.PUSCHExtension.TargetCodeRate;

% Create UL-SCH decoder System object to perform transport channel decoding
% Use layered belief propagation for LDPC decoding, with half the number of
% iterations as compared to the default for belief propagation decoding
decodeULSCH = nrULSCHDecoder;
decodeULSCH.MultipleHARQProcesses = true;
decodeULSCH.CBGTransmission = true;
decodeULSCH.TargetCodeRate = simParameters.PUSCHExtension.TargetCodeRate;
decodeULSCH.LDPCDecodingAlgorithm = simParameters.PUSCHExtension.LDPCDecodingAlgorithm;
decodeULSCH.MaximumLDPCIterationCount = simParameters.PUSCHExtension.MaximumLDPCIterationCount;

for snrIdx = 1:numel(simParameters.SNRIn)    % comment out for parallel computing
% parfor snrIdx = 1:numel(simParameters.SNRIn) % 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;
    pusch = simLocal.PUSCH;
    puschextra = simLocal.PUSCHExtension;
    decodeULSCHLocal = decodeULSCH;  % Copy of the decoder handle to help PCT classification of variable
    decodeULSCHLocal.reset();        % Reset decoder at the start of each SNR point

    % Create PUSCH object configured for the non-codebook transmission
    % scheme, used for receiver operations that are performed with respect
    % to the PUSCH layers
    puschNonCodebook = pusch;
    puschNonCodebook.TransmissionScheme = 'nonCodebook';

    % 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:puschextra.NHARQProcesses-1;

    % Initialize the state of all HARQ processes
    harqEntity = HARQEntity(harqSequence,rvSeq,pusch.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;

    % 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*double(waveinfoLocal.Nfft)*SNR);
    nVar = N0^2*double(waveinfoLocal.Nfft);

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

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

        % Calculate the PUSCH indices and PT-RS indices. If
        % TransformPrecoding = 1, the PT-RS indices represent the
        % projection of PT-RS locations prior to transform precoding onto
        % the carrier resource grid
        [puschIndices,puschIndicesInfo,ptrsIndices] = nrPUSCHIndices(carrier,pusch);

        % Calculate the transport block size for the transmission in the slot
        MRB = numel(puschIndicesInfo.PRBSet);
        trBlkSize = nrTBS(pusch.Modulation,pusch.NumLayers,MRB,puschIndicesInfo.NREPerPRB,puschextra.TargetCodeRate,puschextra.XOverhead);

        % HARQ processing
        % If new data for current process then create a new UL-SCH transport block
        if harqEntity.NewData
            trBlk = randi([0 1],trBlkSize,1);
            setTransportBlock(encodeULSCH,trBlk,harqEntity.HARQProcessID);
            % If new data because of previous RV sequence time out then flush decoder soft buffer explicitly
            if harqEntity.SequenceTimeout
                resetSoftBuffer(decodeULSCHLocal,harqEntity.HARQProcessID);
            end
        end

        % Encode the UL-SCH transport block
        codedTrBlock = encodeULSCH(pusch.Modulation,pusch.NumLayers, ...
            puschIndicesInfo.G,harqEntity.RedundancyVersion, ...
            harqEntity.HARQProcessID,harqEntity.CBGTI);

        % Create resource grid for a slot
        puschGrid = nrResourceGrid(carrier,simLocal.NTxAnts);

        % PUSCH modulation. If TxScheme = 'codebook', perform
        % codebook-based MIMO precoding at the same time. If
        % TransformPrecoding = 1, the PUSCH symbols and PT-RS symbols are
        % multiplexed before transform precoding
        [puschSymbols,ptrsSymbols] = nrPUSCH(carrier,pusch,codedTrBlock);

        % Implementation-specific PUSCH MIMO precoding and mapping. This
        % MIMO precoding step is in addition to any codebook based
        % MIMO precoding done during PUSCH modulation above
        if (strcmpi(pusch.TransmissionScheme,'codebook'))
            % Codebook based MIMO precoding, F precodes between PUSCH
            % transmit antenna ports and transmit antennas
            F = eye(pusch.NumAntennaPorts,simLocal.NTxAnts);
        else
            % Non-codebook based MIMO precoding, F precodes between PUSCH
            % layers and transmit antennas
            F = eye(pusch.NumLayers,simLocal.NTxAnts);
        end
        [~,puschAntIndices] = nrExtractResources(puschIndices,puschGrid);
        puschGrid(puschAntIndices) = puschSymbols * F;

        % Implementation-specific PUSCH DM-RS MIMO precoding and mapping
        % using the nrPDSCHPrecode function which supports PUSCH MIMO
        % precoding as well. The first DM-RS creation includes codebook
        % based MIMO precoding if applicable
        dmrsSymbols = nrPUSCHDMRS(carrier,pusch);
        dmrsIndices = nrPUSCHDMRSIndices(carrier,pusch);
        [dmrsAntSymbols,dmrsAntIndices] = nrPDSCHPrecode(carrier,dmrsSymbols,dmrsIndices,F);
        puschGrid(dmrsAntIndices) = dmrsAntSymbols;

        % Implementation-specific PUSCH PT-RS MIMO precoding and mapping
        % using the nrPDSCHPrecode function which supports PUSCH MIMO
        % precoding as well. If TransformPrecoding = 1, puschSymbols
        % already include PT-RS symbols
        if ~pusch.TransformPrecoding
            [ptrsAntSymbols,ptrsAntIndices] = nrPDSCHPrecode(carrier,ptrsSymbols,ptrsIndices,F);
            puschGrid(ptrsAntIndices) = ptrsAntSymbols;
        end

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

        % 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);

        % 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 PUSCH 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
            estChannelGrid = ofdmResponse;

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

            % Apply MIMO deprecoding to estChannelGrid to give an estimate
            % per transmission layer
            K = size(estChannelGrid,1);
            estChannelGrid = reshape(estChannelGrid,K*carrier.SymbolsPerSlot*simLocal.NRxAnts,simLocal.NTxAnts);
            estChannelGrid = estChannelGrid * F.';
            if (strcmpi(pusch.TransmissionScheme,'codebook'))
                W = nrPUSCHCodebook(pusch.NumLayers,pusch.NumAntennaPorts,pusch.TPMI,pusch.TransformPrecoding);
                estChannelGrid = estChannelGrid * W.';
            end
            estChannelGrid = reshape(estChannelGrid,K,carrier.SymbolsPerSlot,simLocal.NRxAnts,[]);
        else
            % Practical channel estimation between the received grid and
            % each transmission layer, using the PUSCH DM-RS for each layer
            % which are created by specifying the non-codebook transmission
            % scheme
            dmrsLayerSymbols = nrPUSCHDMRS(carrier,puschNonCodebook);
            dmrsLayerIndices = nrPUSCHDMRSIndices(carrier,puschNonCodebook);
            [estChannelGrid,noiseEst] = nrChannelEstimate(carrier,rxGrid,dmrsLayerIndices,dmrsLayerSymbols,'CDMLengths',pusch.DMRS.CDMLengths);
        end

        % Get PUSCH resource elements from the received grid
        [puschRx,puschHest] = nrExtractResources(puschIndices,rxGrid,estChannelGrid);

        % Equalization
        [puschEq,csi] = nrEqualizeMMSE(puschRx,puschHest,noiseEst);

        % CPE compensation
        if pusch.EnablePTRS
            puschEq = hCompensateCPE(carrier,puschNonCodebook,puschEq,rxGrid,estChannelGrid,noiseEst);
        end

        % Decode PUSCH physical channel
        [ulschLLRs,rxSymbols] = nrPUSCHDecode(carrier,puschNonCodebook,puschEq,noiseEst);

        % Display EVM per layer, per slot and per RB. Reference symbols for
        % each layer are created by specifying the non-codebook
        % transmission scheme
        if (simLocal.DisplayDiagnostics)
            refSymbols = nrPUSCH(carrier,puschNonCodebook,codedTrBlock);
            plotLayerEVM(NSlots,nslot,puschNonCodebook,size(puschGrid),puschIndices,refSymbols,puschEq);
        end

        % Apply channel state information (CSI) produced by the equalizer,
        % including the effect of transform precoding if enabled
        if (pusch.TransformPrecoding)
            MSC = MRB * 12;
            csi = nrTransformDeprecode(csi,MRB) / sqrt(MSC);
            csi = repmat(csi((1:MSC:end).'),1,MSC).';
            if pusch.EnablePTRS
                % PUSCH and PT-RS symbols are multiplexed when PT-RS is
                % enabled. Extract the CSI corresponding to PUSCH symbols
                ptrsLayerIndices = nrPUSCHPTRSIndices(carrier,pusch);
                csi(ptrsLayerIndices) = [];
            end
            csi = reshape(csi,size(rxSymbols));
        end
        csi = nrLayerDemap(csi);
        Qm = length(ulschLLRs) / length(rxSymbols);
        csi = reshape(repmat(csi{1}.',Qm,1),[],1);
        ulschLLRs = ulschLLRs .* csi;

        % Decode the UL-SCH transport channel
        decodeULSCHLocal.TransportBlockLength = trBlkSize;
        [decbits,blkerr,cbgerr] = decodeULSCHLocal(ulschLLRs, ...
            pusch.Modulation,pusch.NumLayers,harqEntity.RedundancyVersion, ...
            harqEntity.HARQProcessID,harqEntity.CBGTI);

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

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

    end

    % 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 (1x2) and SCS=15kHz with TDL-A channel at -5dB SNR for 2 10ms frame(s)

(5.00%) NSlot=0, HARQ Proc 0: CW0: Initial transmission failed  (TBS=2856,RV=0,CR=0.190705).
(10.00%) NSlot=1, HARQ Proc 1: CW0: Initial transmission failed  (TBS=2856,RV=0,CR=0.190705).
(15.00%) NSlot=2, HARQ Proc 2: CW0: Initial transmission failed  (TBS=2856,RV=0,CR=0.190705).
(20.00%) NSlot=3, HARQ Proc 3: CW0: Initial transmission failed  (TBS=2856,RV=0,CR=0.190705).
(25.00%) NSlot=4, HARQ Proc 4: CW0: Initial transmission failed  (TBS=2856,RV=0,CR=0.190705).
(30.00%) NSlot=5, HARQ Proc 5: CW0: Initial transmission failed  (TBS=2856,RV=0,CR=0.190705).
(35.00%) NSlot=6, HARQ Proc 6: CW0: Initial transmission failed  (TBS=2856,RV=0,CR=0.190705).
(40.00%) NSlot=7, HARQ Proc 7: CW0: Initial transmission failed  (TBS=2856,RV=0,CR=0.190705).
(45.00%) NSlot=8, HARQ Proc 8: CW0: Initial transmission failed  (TBS=2856,RV=0,CR=0.190705).
(50.00%) NSlot=9, HARQ Proc 9: CW0: Initial transmission failed  (TBS=2856,RV=0,CR=0.190705).
(55.00%) NSlot=10, HARQ Proc 10: CW0: Initial transmission failed  (TBS=2856,RV=0,CR=0.190705).
(60.00%) NSlot=11, HARQ Proc 11: CW0: Initial transmission failed  (TBS=2856,RV=0,CR=0.190705).
(65.00%) NSlot=12, HARQ Proc 12: CW0: Initial transmission failed  (TBS=2856,RV=0,CR=0.190705).
(70.00%) NSlot=13, HARQ Proc 13: CW0: Initial transmission failed  (TBS=2856,RV=0,CR=0.190705).
(75.00%) NSlot=14, HARQ Proc 14: CW0: Initial transmission failed  (TBS=2856,RV=0,CR=0.190705).
(80.00%) NSlot=15, HARQ Proc 15: CW0: Initial transmission failed  (TBS=2856,RV=0,CR=0.190705).
(85.00%) NSlot=16, HARQ Proc 0: CW0: Retransmission #1 passed  (TBS=2856,RV=2,CR=0.190705).
(90.00%) NSlot=17, HARQ Proc 1: CW0: Retransmission #1 passed  (TBS=2856,RV=2,CR=0.190705).
(95.00%) NSlot=18, HARQ Proc 2: CW0: Retransmission #1 passed  (TBS=2856,RV=2,CR=0.190705).
(100.00%) NSlot=19, HARQ Proc 3: CW0: Retransmission #1 passed  (TBS=2856,RV=2,CR=0.190705).

Throughput(Mbps) for 2 frame(s) = 0.5712
Throughput(%) for 2 frame(s) = 20.0000

Simulating transmission scheme 1 (1x2) and SCS=15kHz with TDL-A channel at 0dB SNR for 2 10ms frame(s)

(5.00%) NSlot=0, HARQ Proc 0: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(10.00%) NSlot=1, HARQ Proc 1: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(15.00%) NSlot=2, HARQ Proc 2: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(20.00%) NSlot=3, HARQ Proc 3: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(25.00%) NSlot=4, HARQ Proc 4: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(30.00%) NSlot=5, HARQ Proc 5: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(35.00%) NSlot=6, HARQ Proc 6: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(40.00%) NSlot=7, HARQ Proc 7: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(45.00%) NSlot=8, HARQ Proc 8: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(50.00%) NSlot=9, HARQ Proc 9: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(55.00%) NSlot=10, HARQ Proc 10: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(60.00%) NSlot=11, HARQ Proc 11: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(65.00%) NSlot=12, HARQ Proc 12: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(70.00%) NSlot=13, HARQ Proc 13: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(75.00%) NSlot=14, HARQ Proc 14: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(80.00%) NSlot=15, HARQ Proc 15: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(85.00%) NSlot=16, HARQ Proc 0: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(90.00%) NSlot=17, HARQ Proc 1: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(95.00%) NSlot=18, HARQ Proc 2: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(100.00%) NSlot=19, HARQ Proc 3: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).

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

Simulating transmission scheme 1 (1x2) and SCS=15kHz with TDL-A channel at 5dB SNR for 2 10ms frame(s)

(5.00%) NSlot=0, HARQ Proc 0: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(10.00%) NSlot=1, HARQ Proc 1: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(15.00%) NSlot=2, HARQ Proc 2: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(20.00%) NSlot=3, HARQ Proc 3: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(25.00%) NSlot=4, HARQ Proc 4: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(30.00%) NSlot=5, HARQ Proc 5: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(35.00%) NSlot=6, HARQ Proc 6: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(40.00%) NSlot=7, HARQ Proc 7: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(45.00%) NSlot=8, HARQ Proc 8: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(50.00%) NSlot=9, HARQ Proc 9: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(55.00%) NSlot=10, HARQ Proc 10: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(60.00%) NSlot=11, HARQ Proc 11: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(65.00%) NSlot=12, HARQ Proc 12: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(70.00%) NSlot=13, HARQ Proc 13: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(75.00%) NSlot=14, HARQ Proc 14: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(80.00%) NSlot=15, HARQ Proc 15: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(85.00%) NSlot=16, HARQ Proc 0: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(90.00%) NSlot=17, HARQ Proc 1: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(95.00%) NSlot=18, HARQ Proc 2: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).
(100.00%) NSlot=19, HARQ Proc 3: CW0: Initial transmission passed  (TBS=2856,RV=0,CR=0.190705).

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

结果

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

figure;
plot(simParameters.SNRIn,simThroughput*100./maxThroughput,'o-.')
xlabel('SNR (dB)'); ylabel('Throughput (%)'); grid on;
if (simParameters.PUSCH.TransformPrecoding)
    ofdmType = 'DFT-s-OFDM';
else
    ofdmType = 'CP-OFDM';
end
title(sprintf('%s / NRB=%d / SCS=%dkHz / %s %d/1024 / %dx%d', ...
    ofdmType,simParameters.Carrier.NSizeGrid,simParameters.Carrier.SubcarrierSpacing, ...
    simParameters.PUSCH.Modulation, ...
    round(simParameters.PUSCHExtension.TargetCodeRate*1024),simParameters.NTxAnts,simParameters.NRxAnts));

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

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

精选参考文献

  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 validateNumLayers(simParameters)
% Validate the number of layers, relative to the antenna geometry

    numlayers = simParameters.PUSCH.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 plotLayerEVM(NSlots,nslot,pusch,siz,puschIndices,puschSymbols,puschEq)
% Plot EVM information

    persistent slotEVM;
    persistent rbEVM
    persistent evmPerSlot;

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

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

    drawnow;

end

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

    % Constructed the CDL or TDL channel model object
    if contains(simParameters.DelayProfile,'CDL','IgnoreCase',true)

        channel = nrCDLChannel; % CDL channel object

        % Swap transmit and receive sides as the default CDL channel is
        % configured for downlink transmissions.
        swapTransmitAndReceive(channel);

        % Turn the number of antennas into antenna panel array layouts. If
        % NRxAnts 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 NTxAnts is not 1 or
        % even, its value is rounded up to the nearest even number.
        channel = hArrayGeometry(channel,simParameters.NTxAnts,simParameters.NRxAnts,'uplink');
        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';

        % Swap transmit and receive sides as the default TDL channel is
        % configured for downlink transmissions
        swapTransmitAndReceive(channel);

        % 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 estimate 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

另请参阅

对象

函数

主题