DL-SCH и передача PDSCH и получают цепь обработки

В этом примере показано, как использовать функции 5G Toolbox™, чтобы смоделировать 5G NR физический нисходящий канал совместно использованный канал (PDSCH) ссылка, включая все шаги от транспортной генерации блока до декодирования бита в конце приемника.

Введение

Эта схема показывает нисходящий канал, совместно использованный канал (DL-SCH) и PDSCH передают и получают цепь обработки.

В этом примере показано, как смоделировать эти элементы симуляции уровня ссылки.

  • Кодирование DL-SCH

  • Гибридный ARQ (HARQ) управление

  • Кодирование PDSCH

  • Несколько - вводят, несколько - выводят (MIMO) предварительное кодирование

  • Модуляция OFDM

  • Канал распространения и шумовое сложение

  • Временная синхронизация

  • Демодуляция OFDM

  • Оценка канала и эквализация

  • Декодирование PDSCH

  • Декодирование DL-SCH

Для примера того, как использовать симуляцию уровня ссылки, чтобы измерить пропускную способность, смотрите Пропускную способность NR PDSCH.

Параметры симуляции

Задайте отношение сигнал-шум (SNR), количество пазов, чтобы симулировать, и усовершенствовать флаг оценки канала. Чтобы узнать больше об определении ОСШ, используемом в этом примере, см. Определение ОСШ, Используемое в Симуляциях Ссылки.

SNRdB = 10;                % SNR in dB
totalNoSlots = 20;         % Number of slots to simulate
perfectEstimation = false; % Perfect synchronization and channel estimation
rng("default");            % Set default random number generator for repeatability

Настройка несущей

Создайте объект настройки несущей. Этот объект управляет нумерологией, такой как, расстояние между поднесущими, полоса пропускания и длина циклического префикса (CP). Этот пример использует набор по умолчанию свойств.

carrier = nrCarrierConfig
carrier = 
  nrCarrierConfig with properties:

              NCellID: 1
    SubcarrierSpacing: 15
         CyclicPrefix: 'normal'
            NSizeGrid: 52
           NStartGrid: 0
                NSlot: 0
               NFrame: 0

   Read-only properties:
       SymbolsPerSlot: 14
     SlotsPerSubframe: 1
        SlotsPerFrame: 10

PDSCH и настройка DM-RS

Создайте объект настройки PDSCH. Задайте (16-QAM) схему модуляции и количество слоев (2). Выделите все блоки ресурса (RBS) PDSCH (полное выделение полосы). Можно также задать другие параметры выделения времени и настройки (DM-RS) опорного сигнала демодуляции в этом объекте.

pdsch = nrPDSCHConfig;
pdsch.Modulation = "16QAM";
pdsch.NumLayers = 2;
pdsch.PRBSet = 0:carrier.NSizeGrid-1;     % Full band allocation

Отобразите параметры PDSCH.

pdsch
pdsch = 
  nrPDSCHConfig with properties:

                NSizeBWP: []
               NStartBWP: []
             ReservedPRB: {[1x1 nrPDSCHReservedConfig]}
              ReservedRE: []
              Modulation: '16QAM'
               NumLayers: 2
             MappingType: 'A'
        SymbolAllocation: [0 14]
                  PRBSet: [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ... ]
    VRBToPRBInterleaving: 0
           VRBBundleSize: 2
                     NID: []
                    RNTI: 1
                    DMRS: [1x1 nrPDSCHDMRSConfig]
              EnablePTRS: 0
                    PTRS: [1x1 nrPDSCHPTRSConfig]

   Read-only properties:
            NumCodewords: 1

Установите параметры DM-RS. Чтобы улучшить оценку канала, добавьте дополнительное положение DM-RS.

pdsch.DMRS.DMRSAdditionalPosition = 1;

Установите тип настройки DM-RS и длину DM-RS, которая определяет количество ортогональных последовательностей DM-RS или портов DM-RS.

  • DMRSConfigurationType = 1 поддержки до 4 портов DM-RS, когда DMRSLength = 1.

  • DMRSConfigurationType = 1 поддержки до 8 портов DM-RS, когда DMRSLength = 2.

  • DMRSConfigurationType = 2 поддержки до 6 портов DM-RS, когда DMRSLength = 1. Это спроектировано для многопользовательского MIMO (MU-MIMO).

  • DMRSConfigurationType = 2 поддержки до 12 портов DM-RS, когда DMRSLength = 2. Это спроектировано для MU-MIMO.

Максимальное количество слоев должно быть меньше чем или равно количеству портов DM-RS.

pdsch.DMRS.DMRSConfigurationType = 1;
pdsch.DMRS.DMRSLength = 2;
pdsch.DMRS                            % Display DM-RS properties
ans = 
  nrPDSCHDMRSConfig with properties:

      DMRSConfigurationType: 1
         DMRSReferencePoint: 'CRB0'
          DMRSTypeAPosition: 2
     DMRSAdditionalPosition: 1
                 DMRSLength: 2
            CustomSymbolSet: []
                DMRSPortSet: []
                   NIDNSCID: []
                      NSCID: 0
    NumCDMGroupsWithoutData: 2

   Read-only properties:
                  CDMGroups: [0 0]
                DeltaShifts: [0 0]
           FrequencyWeights: [2x2 double]
                TimeWeights: [2x2 double]
    DMRSSubcarrierLocations: [6x2 double]
                 CDMLengths: [2 1]

Настройка DL-SCH

Задайте скорость кода, количество процессов HARQ и значения последовательности версии сокращения (RV). Это управление последовательностью повторные передачи RV в случае ошибки. Чтобы отключить повторные передачи HARQ, можно установить rvSeq к фиксированному значению (например, 0). Для получения дополнительной информации о том, как смоделировать транспортные каналы с HARQ, см. Модель 5G Транспортные Каналы NR с HARQ.

NHARQProcesses = 16;     % Number of parallel HARQ processes
rvSeq = [0 2 3 1];

Учтите количество кодовых комбинаций при определении уровня кодирования. Количество кодовых комбинаций является свойством только для чтения объекта настройки PDSCH, который зависит от количества слоев.

  • 1 кодовая комбинация максимум для 4 слоев

  • 2 кодовых комбинации больше чем для 4 слоев

% Coding rate
if pdsch.NumCodewords == 1
    codeRate = 490/1024;
else
    codeRate = [490 490]./1024;
end

Создайте объекты энкодера и декодера DL-SCH. Чтобы использовать несколько процессов, установите MultipleHARQProcesses свойство к true для обоих объектов. Вы не должны задавать количество процессов HARQ. Объекты энкодера и декодера DL-SCH могут смоделировать до 16 процессов HARQ. Чтобы идентифицировать активный процесс HARQ при выполнении операций с объектами энкодера и декодера DL-SCH, используйте HARQprocessID свойство объекта сущности HARQ, заданного в следующем разделе.

% Create DL-SCH encoder object
encodeDLSCH = nrDLSCH;
encodeDLSCH.MultipleHARQProcesses = true;
encodeDLSCH.TargetCodeRate = codeRate;

% Create DLSCH decoder object
decodeDLSCH = nrDLSCHDecoder;
decodeDLSCH.MultipleHARQProcesses = true;
decodeDLSCH.TargetCodeRate = codeRate;
decodeDLSCH.LDPCDecodingAlgorithm = "Normalized min-sum";
decodeDLSCH.MaximumLDPCIterationCount = 6;

Управление HARQ

Создайте объект сущности HARQ справиться с процессами HARQ и буферами энкодера и декодера DL-SCH. Для каждого процесса HARQ сущность HARQ хранит эти элементы:

  • Идентификационный номер HARQ.

  • RV.

  • Номер передачи, который указывает, сколько раз был передан определенный транспортный блок.

  • Отметьте, чтобы указать, требуются ли новые данные. Новые данные требуются, когда транспортный блок получен успешно или если тайм-аут последовательности произошел (все передачи RV перестали работать).

  • Отметьте, чтобы указать, произошел ли тайм-аут последовательности (все передачи RV перестали работать).

harqEntity = HARQEntity(0:NHARQProcesses-1,rvSeq,pdsch.NumCodewords);

Настройка канала

Задайте количество передающих и приемных антенн.

nTxAnts = 8;
nRxAnts = 8;

% Check that the number of layers is valid for the number of antennas
if pdsch.NumLayers > min(nTxAnts,nRxAnts)
    error("The number of layers ("+string(pdsch.NumLayers)+") must be smaller than min(nTxAnts,nRxAnts) ("+string(min(nTxAnts,nRxAnts))+")")
end

Создайте объект канала.

channel = nrTDLChannel;
channel.DelayProfile = "TDL-C";
channel.NumTransmitAntennas = nTxAnts;
channel.NumReceiveAntennas = nRxAnts;

Установите частоту дискретизации канала на тот из сигнала OFDM. Чтобы получить частоту дискретизации сигнала OFDM, используйте nrOFDMInfo функция.

ofdmInfo = nrOFDMInfo(carrier);
channel.SampleRate = ofdmInfo.SampleRate;

Передача и прием

Настройте цикл, чтобы симулировать передачу и прием пазов. Создайте comm.ConstellationDiagram отобразить созвездие компенсируемого сигнала.

constPlot = comm.ConstellationDiagram;                                          % Constellation diagram object
constPlot.ReferenceConstellation = getConstellationRefPoints(pdsch.Modulation); % Reference constellation values
constPlot.EnableMeasurements = 1;                                               % Enable EVM measurements

% Initial timing offset
offset = 0;

estChannelGrid = getInitialChannelEstimate(channel,carrier);
newPrecodingWeight = getPrecodingMatrix(pdsch.PRBSet,pdsch.NumLayers,estChannelGrid);

for nSlot = 0:totalNoSlots-1
    % New slot
    carrier.NSlot = nSlot;

Вычислите транспортный размер блока

Транспортный размер блока является количеством битов, чтобы отправить к этапам кодирования канала. Это значение зависит от способности PDSCH. Чтобы вычислить транспортный размер блока, используйте nrTBS функция.

    % Generate PDSCH indices info, which is needed to calculate the transport
    % block size
    [pdschIndices,pdschInfo] = nrPDSCHIndices(carrier,pdsch);

    % Calculate transport block sizes
    Xoh_PDSCH = 0;
    trBlkSizes = nrTBS(pdsch.Modulation,pdsch.NumLayers,numel(pdsch.PRBSet),pdschInfo.NREPerPRB,codeRate,Xoh_PDSCH);

HARQ, обрабатывающий (организацию буферизации данных)

Этот раздел объясняет организацию буферизации данных в энкодере и декодере.

  • Буферы энкодера DL-SCH: Сгенерируйте новый транспортный блок, если новые данные требуются для активного процесса HARQ. Сохраните транспортный блок в соответствующем буфере. Если новые данные не требуются, энкодер DL-SCH использует свои буферизированные биты для повторной передачи.

  • Буферы декодера DL-SCH: мягкие буферы в приемнике хранят ранее полученные версии той же кодовой комбинации. Эти буферы очищены автоматически на успешный прием (никакая ошибка CRC). Однако, если концы последовательности RV без успешного декодирования, сбросьте буферы вручную при помощи resetSoftBuffer объектная функция.

    % Get new transport blocks and flush decoder soft buffer, as required
    for cwIdx = 1:pdsch.NumCodewords
        if harqEntity.NewData(cwIdx)
            % Create and store a new transport block for transmission
            trBlk = randi([0 1],trBlkSizes(cwIdx),1);
            setTransportBlock(encodeDLSCH,trBlk,cwIdx-1,harqEntity.HARQProcessID);

            % If the previous RV sequence ends without successful
            % decoding, flush the soft buffer
            if harqEntity.SequenceTimeout(cwIdx)
                resetSoftBuffer(decodeDLSCH,cwIdx-1,harqEntity.HARQProcessID);
            end
        end
    end

Кодирование DL-SCH

Закодируйте транспортные блоки. Транспортный блок уже хранится в одном из внутренних мягких буферов объекта энкодера DL-SCH.

    codedTrBlock = encodeDLSCH(pdsch.Modulation,pdsch.NumLayers,pdschInfo.G,harqEntity.RedundancyVersion,harqEntity.HARQProcessID);

Модуляция PDSCH и предварительное кодирование MIMO

Сгенерируйте символы PDSCH от закодированных транспортных блоков.

    pdschSymbols = nrPDSCH(carrier,pdsch,codedTrBlock);

Получите веса перед кодированием. Этот пример принимает знание канала для предварительного кодирования. (Для примера того, как использовать оценку канала в приемнике, чтобы вычислить веса, используемые для передачи в следующем пазе, смотрите Пропускную способность NR PDSCH.)

    precodingWeights = newPrecodingWeight;

Предварительно закодируйте символы PDSCH.

    pdschSymbolsPrecoded = pdschSymbols*precodingWeights;

Генерация PDSCH RS DM

Сгенерируйте символы DM-RS и индексы.

    dmrsSymbols = nrPDSCHDMRS(carrier,pdsch);
    dmrsIndices = nrPDSCHDMRSIndices(carrier,pdsch);

Отображение с сеткой ресурса

Сгенерируйте пустую сетку ресурса. Эта сетка представляет паз.

    pdschGrid = nrResourceGrid(carrier,nTxAnts);

nrPDSCHIndices функция генерирует индексы, которые относятся к слоям и не антеннам. Этот формат полезен при отображении символов PDSCH непосредственно со слоями. В этом случае получившиеся сетки ресурса не предварительно закодированы. Этот рисунок показывает процесс отображения символов PDSCH к стольким же сеток ресурса сколько слои.

Поскольку этот пример применяет предварительное кодирование MIMO к символам PDSCH прежде, чем сопоставить их с сетками ресурса, ПРЕДВАРИТЕЛЬНО ЗАКОДИРОВАННЫЕ MIMO символы PDSCH относятся к антеннам и не слоям. Чтобы преобразовать индексы слоя в индексы антенны, используйте nrExtractResources функция. Этот рисунок показывает процесс отображения символов MIMO-precoded к стольким же сеток ресурса сколько передающие антенны.

    [~,pdschAntIndices] = nrExtractResources(pdschIndices,pdschGrid);
    pdschGrid(pdschAntIndices) = pdschSymbolsPrecoded;

MIMO-precode и карта символы DM-RS к сетке ресурса. Подобно индексам PDSCH индексы DM-RS относятся к слоям. Чтобы преобразовать эти индексы слоя в индексы антенны, используйте nrExtractResources функционируйте снова.

    % PDSCH DM-RS precoding and mapping
    for p = 1:size(dmrsSymbols,2)
        [~,dmrsAntIndices] = nrExtractResources(dmrsIndices(:,p),pdschGrid);
        pdschGrid(dmrsAntIndices) = pdschGrid(dmrsAntIndices) + dmrsSymbols(:,p)*precodingWeights(p,:);
    end

Модуляция OFDM

OFDM-модулируйте сетку ресурса.

    [txWaveform,waveformInfo] = nrOFDMModulate(carrier,pdschGrid);

Канал распространения

Канал распространения генерирует N выборки выхода для входа с выборками N. Однако блок N, выборки выхода включают канал, фильтрует переходный процесс (K выборки). Поскольку этап синхронизации удаляет этот начальный переходный процесс, если паз в канале, выход имеет выборки N, выборки N-K, остается после синхронизации. Выборок N-K недостаточно, чтобы декодировать ценность паза данных. Часть выборок паза находится в линии задержки фильтра канала и еще не сбрасывается. Чтобы сбросить все соответствующие выборки из фильтра канала, заполните входной сигнал нулями. Максимальная задержка, которую вводит фильтр канала, влияет на размер дополнения. Дополнение составляет задержку, введенную всеми многопутевыми компонентами и задержкой реализации фильтра канала. Этот рисунок показывает потребность в нуле, дополняющем, прежде чем форма волны введет канал.

Заполните входной сигнал достаточным количеством нулей, чтобы гарантировать, что сгенерированный сигнал сбрасывается из фильтра канала.

    chInfo = info(channel);
    maxChDelay = ceil(max(chInfo.PathDelays*channel.SampleRate)) + chInfo.ChannelFilterDelay;
    txWaveform = [txWaveform; zeros(maxChDelay,size(txWaveform,2))];

Отправьте сигнал через канал и добавьте шум.

    [rxWaveform,pathGains,sampleTimes] = channel(txWaveform);
    noise = generateAWGN(SNRdB,nRxAnts,waveformInfo.Nfft,size(rxWaveform));
    rxWaveform = rxWaveform + noise;

Временная синхронизация

Можно выполнить совершенную или практическую синхронизацию.

  • Идеальная синхронизация принимает знание канала (nrPerfectTimingEstimate). Канал возвращает информацию об усилениях пути, и путь фильтрует импульсную характеристику. Можно использовать эту информацию, чтобы определить смещение, которое сопоставлено с самым сильным многопутевым компонентом через все снимки состояния канала и через все передающие и приемные антенны.

  • Практическая синхронизация выполняет взаимную корреляцию полученного сигнала с символами PDSCH DM-RS во временном интервале (nrTimingEstimate). В некоторых неблагоприятных случаях эта взаимная корреляция может быть слабой из-за исчезновения или шума, приводящего к ошибочному смещению синхронизации. Функциональный hSkipWeakTimingOffset проверяет величину взаимной корреляции mag. Если взаимная корреляция слаба, функция игнорирует текущую оценку синхронизации и вместо этого использует предыдущую оценку (offset).

Выполните совершенную или практическую оценку синхронизации и синхронизацию.

    if perfectEstimation
        % Get path filters for perfect timing estimation
        pathFilters = getPathFilters(channel); 
        [offset,mag] = nrPerfectTimingEstimate(pathGains,pathFilters);
    else
        [t,mag] = nrTimingEstimate(carrier,rxWaveform,dmrsIndices,dmrsSymbols);
        offset = hSkipWeakTimingOffset(offset,t,mag);
    end
    rxWaveform = rxWaveform(1+offset:end,:);

Демодуляция OFDM

OFDM-демодулируйте синхронизируемый сигнал.

    rxGrid = nrOFDMDemodulate(carrier,rxWaveform);

Оценка канала

Оценка канала обеспечивает представление эффектов канала на элемент ресурса (RE). Эквалайзер использует эту информацию, чтобы компенсировать искажение, введенное каналом.

Можно выполнить совершенную или практическую оценку канала.

  • Совершенная оценка канала принимает знание канала (nrPerfectChannelEstimate). Совершенная оценка канала представляет условия канала между передающими и приемными антеннами. Поскольку эквалайзер требует знания канала между слоями передачи и получить антеннами, необходимо применить предварительное кодирование к совершенной оценке канала.

  • Практическая оценка канала использует PDSCH DM-RS, чтобы оценить условия канала и использует усреднение шума и интерполяцию, чтобы получить оценку для всего REs в пазе. Поскольку DM-RSs задан на слой, получившаяся практическая оценка канала представляет условия канала между слоями передачи и получить антеннами. Практическая оценка канала включает эффект операции MIMO перед кодированием.

Этот рисунок показывает контрольные точки оценок канала в цепи обработки нисходящего канала.

Выполните совершенную или практическую оценку канала.

    if perfectEstimation
        % Perform perfect channel estimation between transmit and receive
        % antennas.
        estChGridAnts = nrPerfectChannelEstimate(carrier,pathGains,pathFilters,offset,sampleTimes);

        % Get perfect noise estimate (from noise realization)
        noiseGrid = nrOFDMDemodulate(carrier,noise(1+offset:end ,:));
        noiseEst = var(noiseGrid(:));

        % Get precoding matrix for next slot
        newPrecodingWeight = getPrecodingMatrix(pdsch.PRBSet,pdsch.NumLayers,estChGridAnts);

        % Apply precoding to estChGridAnts. The resulting estimate is for
        % the channel estimate between layers and receive antennas.
        estChGridLayers = precodeChannelEstimate(estChGridAnts,precodingWeights.');
    else
        % Perform practical channel estimation between layers and receive
        % antennas.
        [estChGridLayers,noiseEst] = nrChannelEstimate(carrier,rxGrid,dmrsIndices,dmrsSymbols,'CDMLengths',pdsch.DMRS.CDMLengths);

        % Remove precoding from estChannelGrid before precoding
        % matrix calculation
        estChGridAnts = precodeChannelEstimate(estChGridLayers,conj(precodingWeights));

        % Get precoding matrix for next slot
        newPrecodingWeight = getPrecodingMatrix(pdsch.PRBSet,pdsch.NumLayers,estChGridAnts);
    end

Постройте оценку канала между первым слоем, и первые получают антенну.

    mesh(abs(estChGridLayers(:,:,1,1)));

Figure contains an axes object. The axes object with title Channel Estimate contains an object of type surface.

    title('Channel Estimate');
    xlabel('OFDM Symbol');
    ylabel("Subcarrier");
    zlabel("Magnitude");

На данном этапе можно использовать оценку канала, чтобы получить матрицу перед кодированием для передачи в следующем пазе. Поскольку этот пример принимает знание канала в передатчике, вы не должны вычислять матрицу перед кодированием в конце приемника. Для примера того, как вычислить матрицу перед кодированием для передачи данных на основе оценки канала в приемнике, смотрите Пропускную способность NR PDSCH.

Эквализация

Эквалайзер использует оценку канала, чтобы компенсировать искажение, введенное каналом.

Извлеките символы PDSCH из полученной сетки и сопоставленных оценок канала. csi выведите имеет информацию о состоянии канала (CSI) для каждого из компенсируемых символов PDSCH. CSI является мерой условий канала для каждого символа PDSCH. Используйте CSI, чтобы взвесить декодируемые мягкие биты после того, как декодирование PDSCH, эффективно увеличивая важность символов, испытывающих лучше, образует канал условия.

    [pdschRx,pdschHest] = nrExtractResources(pdschIndices,rxGrid,estChGridLayers);
    [pdschEq,csi] = nrEqualizeMMSE(pdschRx,pdschHest,noiseEst);

Постройте созвездие компенсируемых символов. График включает схемы созвездия для всех слоев.

    constPlot.ChannelNames = "Layer "+(pdsch.NumLayers:-1:1);
    constPlot.ShowLegend = true;
    % Constellation for the first layer has a higher SNR than that for the
    % last layer. Flip the layers so that the constellations do not mask
    % each other.
    constPlot(fliplr(pdschEq));

Декодирование PDSCH

Декодируйте компенсируемые символы PDSCH и получите мягкие битные кодовые комбинации.

    [dlschLLRs,rxSymbols] = nrPDSCHDecode(carrier,pdsch,pdschEq,noiseEst);

Масштабируйте мягкие биты или отношения логарифмической правдоподобности (LLRs) CSI. Это масштабирование применяет больший вес к символам в REs с лучшими условиями канала.

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

Декодирование DL-SCH

Декодируйте LLRs и проверьте ошибки.

    decodeDLSCH.TransportBlockLength = trBlkSizes;
    [decbits,blkerr] = decodeDLSCH(dlschLLRs,pdsch.Modulation,pdsch.NumLayers, ...
        harqEntity.RedundancyVersion,harqEntity.HARQProcessID);

Обновление процесса HARQ

Обновите текущий процесс HARQ с получившимся состоянием блочной ошибки, и затем перейдите к следующему процессу. Этот шаг обновляет информацию, связанную с активным процессом HARQ в сущности HARQ.

    statusReport = updateAndAdvance(harqEntity,blkerr,trBlkSizes,pdschInfo.G);    

Обобщите HARQ и информацию о декодировании для существующего паза.

    disp("Slot "+(nSlot)+". "+statusReport);
Slot 0. HARQ Proc 0: CW0: Initial transmission passed (RV=0,CR=0.482212).
Slot 1. HARQ Proc 1: CW0: Initial transmission passed (RV=0,CR=0.482212).
Slot 2. HARQ Proc 2: CW0: Initial transmission passed (RV=0,CR=0.482212).
Slot 3. HARQ Proc 3: CW0: Initial transmission passed (RV=0,CR=0.482212).
Slot 4. HARQ Proc 4: CW0: Initial transmission passed (RV=0,CR=0.482212).
Slot 5. HARQ Proc 5: CW0: Initial transmission passed (RV=0,CR=0.482212).
Slot 6. HARQ Proc 6: CW0: Initial transmission passed (RV=0,CR=0.482212).
Slot 7. HARQ Proc 7: CW0: Initial transmission passed (RV=0,CR=0.482212).
Slot 8. HARQ Proc 8: CW0: Initial transmission passed (RV=0,CR=0.482212).
Slot 9. HARQ Proc 9: CW0: Initial transmission passed (RV=0,CR=0.482212).
Slot 10. HARQ Proc 10: CW0: Initial transmission passed (RV=0,CR=0.482212).
Slot 11. HARQ Proc 11: CW0: Initial transmission passed (RV=0,CR=0.482212).
Slot 12. HARQ Proc 12: CW0: Initial transmission passed (RV=0,CR=0.482212).
Slot 13. HARQ Proc 13: CW0: Initial transmission passed (RV=0,CR=0.482212).
Slot 14. HARQ Proc 14: CW0: Initial transmission passed (RV=0,CR=0.482212).
Slot 15. HARQ Proc 15: CW0: Initial transmission passed (RV=0,CR=0.482212).
Slot 16. HARQ Proc 0: CW0: Initial transmission passed (RV=0,CR=0.482212).
Slot 17. HARQ Proc 1: CW0: Initial transmission passed (RV=0,CR=0.482212).
Slot 18. HARQ Proc 2: CW0: Initial transmission passed (RV=0,CR=0.482212).
Slot 19. HARQ Proc 3: CW0: Initial transmission passed (RV=0,CR=0.482212).
end % for nSlot = 0:totalNoSlots

Локальные функции

function noise = generateAWGN(SNRdB,nRxAnts,Nfft,sizeRxWaveform)
% Generate AWGN for a given value of SNR in dB (SNRDB), which is the
% receiver SNR per RE and antenna, assuming the channel does
% not affect the power of the signal. NRXANTS is the number of receive
% antennas. NFFT is the FFT size used in OFDM demodulation. SIZERXWAVEFORM
% is the size of the receive waveform used to calculate the size of the
% noise matrix.

    % Normalize noise power 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. The SNR is defined per RE for each receive antenna (TS
    % 38.101-4).
    SNR = 10^(SNRdB/10); % Calculate linear noise gain
    N0 = 1/sqrt(2.0*nRxAnts*double(Nfft)*SNR);
    noise = N0*complex(randn(sizeRxWaveform),randn(sizeRxWaveform));
end
    
function wtx = getPrecodingMatrix(PRBSet,NLayers,hestGrid)
% Calculate precoding matrix given an allocation and a channel estimate
    
    % Allocated subcarrier indices
    allocSc = (1:12)' + 12*PRBSet(:).';
    allocSc = allocSc(:);
    
    % Average channel estimate
    [~,~,R,P] = size(hestGrid);
    estAllocGrid = hestGrid(allocSc,:,:,:);
    Hest = permute(mean(reshape(estAllocGrid,[],R,P)),[2 3 1]);
    
    % SVD decomposition
    [~,~,V] = svd(Hest);
    
    wtx = V(:,1:NLayers).';
    wtx = wtx/sqrt(NLayers); % Normalize by NLayers
end

function estChannelGrid = getInitialChannelEstimate(channel,carrier)
% Obtain an initial channel estimate for calculating the precoding matrix.
% This function assumes a perfect channel estimate

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

    % No filtering needed to get channel path gains
    chClone.ChannelFiltering = false;    
    
    % Get channel path gains
    [pathGains,sampleTimes] = chClone();
    
    % Perfect timing synchronization
    pathFilters = getPathFilters(chClone);
    offset = nrPerfectTimingEstimate(pathGains,pathFilters);
    
    % Perfect channel estimate
    estChannelGrid = nrPerfectChannelEstimate(carrier,pathGains,pathFilters,offset,sampleTimes);
end

function refPoints = getConstellationRefPoints(mod)
% Calculate the reference constellation points for a given modulation
% scheme.
    switch mod
        case "QPSK"
            nPts = 4;
        case "16QAM"
            nPts = 16;
        case "64QAM"
            nPts = 64;
        case "256QAM"
            nPts = 256;            
    end
    binaryValues = int2bit(0:nPts-1,log2(nPts));
    refPoints = nrSymbolModulate(binaryValues(:),mod);
end

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

    % Linearize 4-D matrix and reshape after multiplication
    K = size(estChannelGrid,1);
    L = size(estChannelGrid,2);
    R = size(estChannelGrid,3);
    estChannelGrid = reshape(estChannelGrid,K*L*R,[]);
    estChannelGrid = estChannelGrid*W;
    estChannelGrid = reshape(estChannelGrid,K,L,R,[]);

end

Похожие темы