Main Content

DL-SCH および PDSCH の送受信処理チェーン

この例では、5G Toolbox™ 機能を使用して 5G NR 物理ダウンリンク共有チャネル (PDSCH) リンクをモデル化する方法を示します。これには、トランスポート ブロックの生成から受信機側でのビット復号化までの手順がすべて含まれます。

はじめに

以下の図は、ダウンリンク共有チャネル (DL-SCH) と PDSCH の送受信処理チェーンを示しています。

1.png

この例では、リンクレベル シミュレーションの以下の要素をモデル化する方法を示します。

  • DL-SCH 符号化

  • ハイブリッド ARQ (HARQ) 管理

  • PDSCH 符号化

  • 多入力多出力 (MIMO) プリコーディング

  • OFDM 変調

  • 伝播チャネルとノイズの付加

  • タイミング同期

  • OFDM 復調

  • チャネル推定とイコライズ

  • PDSCH 復号化

  • DL-SCH 復号化

リンクレベルのシミュレーションを使用してスループットを測定する方法の例については、NR PDSCH スループットを参照してください。

シミュレーション パラメーター

S/N 比 (SNR)、シミュレーションするスロット数、および完全なチャネル推定フラグを指定します。この例で使用されている SNR 定義の詳細については、SNR Definition Used in Link Simulationsを参照してください。

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) 長などの numerology を制御します。この例では、プロパティの既定のセットを使用します。

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) を指定します。すべてのリソース ブロック (RB) を 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 は、DMRSLength = 1 の場合、最大 4 つの DM-RS ポートをサポート。

  • DMRSConfigurationType = 1 は、DMRSLength = 2 の場合、最大 8 つの DM-RS ポートをサポート。

  • DMRSConfigurationType = 2 は、DMRSLength = 1 の場合、最大 6 つの DM-RS ポートをサポート。これは、マルチユーザー MIMO (MU-MIMO) 用に設計されています。

  • DMRSConfigurationType = 2 は、DMRSLength = 2 の場合、最大 12 個の DM-RS ポートをサポート。これは、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
            DMRSDownlinkR16: 0

   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 を使用してトランスポート チャネルをモデル化する方法の詳細については、HARQ を使用した 5G NR トランスポート チャネルのモデル化を参照してください。

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

符号化率を指定するときは、コードワードの数を考慮します。コードワードの数は、レイヤーの数に依存する PDSCH 構成オブジェクトの読み取り専用プロパティです。

  • 4 レイヤーまでは 1 つのコードワード

  • 4 レイヤーを超える場合は 2 つのコードワード

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

DL-SCH の符号化器オブジェクトおよび復号化器オブジェクトを作成します。複数のプロセスを使用するには、両方のオブジェクトで MultipleHARQProcesses プロパティを true に設定します。HARQ プロセスの数を指定する必要はありません。DL-SCH の符号化器オブジェクトおよび復号化器オブジェクトは、最大 16 個の HARQ プロセスをモデル化できます。DL-SCH の符号化器オブジェクトおよび復号化器オブジェクトで操作を実行するときに、アクティブな HARQ プロセスを特定するには、次のセクションで定義される HARQ エンティティ オブジェクトの HARQprocessID プロパティを使用します。

% 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 プロセスおよび DL-SCH の符号化器と復号化器のバッファーを管理する HARQ エンティティ オブジェクトを作成します。HARQ プロセスごとに、HARQ エンティティに以下の要素が保存されます。

  • HARQ ID 番号。

  • 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 符号化器オブジェクトの内部ソフト バッファーの 1 つに既に保存されています。

    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 DM-RS の生成

DM-RS シンボルとインデックスを生成します。

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

リソース グリッドへのマッピング

空のリソース グリッドを生成します。このグリッドはスロットを表します。

    pdschGrid = nrResourceGrid(carrier,nTxAnts);

関数 nrPDSCHIndices は、アンテナではなくレイヤーを参照するインデックスを生成します。このフォーマットは、PDSCH シンボルをレイヤーに直接マッピングする場合に役立ちます。この場合、結果のリソース グリッドはプリコーディングされません。以下の図は、レイヤーと同じ数のリソース グリッドに対して PDSCH シンボルをマッピングするプロセスを示したものです。

2.png

この例ではリソース グリッドにマッピングする前に PDSCH シンボルに MIMO プリコーディングを適用するため、MIMO プリコーディングされた PDSCH シンボルは、レイヤーではなくアンテナを参照します。レイヤー インデックスをアンテナ インデックスに変換するには、関数 nrExtractResources を使用します。以下の図は、送信アンテナと同じ数のリソース グリッドに対して MIMO プリコーディングされたシンボルをマッピングするプロセスを示したものです。

3.png

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

DM-RS シンボルを MIMO プリコーディングし、リソース グリッドにマッピングします。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" 個のサンプルは、1 スロットに相当するデータを復号化するには不十分です。スロット サンプルの一部はチャネル フィルターの遅延線にあり、まだフラッシュされていません。関連するすべてのサンプルをチャネル フィルターからフラッシュするには、入力信号をゼロでパディングします。チャネル フィルターによって発生する最大遅延は、パディングのサイズに影響します。パディングでは、すべてのマルチパス成分によって発生する遅延と、チャネル フィルターの実装遅延を考慮します。以下の図は、波形がチャネルに入る前にゼロ パディングが必要であることを示しています。

4.png

入力信号を十分な数のゼロでパディングして、生成された信号がチャネル フィルターから確実にフラッシュされて出力されるようにします。

    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 を使用してチャネル条件を推定し、ノイズの平均化と内挿を使用して、スロット内のすべての RE について推定を取得します。DM-RS はレイヤーごとに指定されるため、結果として得られる実用的なチャネル推定は、送信レイヤーと受信アンテナの間のチャネル条件を表します。実用的なチャネル推定には、MIMO プリコーディング操作の影響が含まれます。

次の図は、ダウンリンク処理チェーンにおけるチャネル推定の基準点を示しています。

5.png

完全なチャネル推定、または実用的なチャネル推定を実行します。

    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 出力には、イコライズされた各 PDSCH シンボルのチャネル状態情報 (CSI) があります。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);

CSI により、ソフト ビットまたは対数尤度比 (LLR) をスケーリングします。このスケーリングでは、チャネル条件が良好なほどより大きな重みを RE 内のシンボルに適用します。

    % 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 復号化

LLR を復号化し、エラーをチェックします。

    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

関連するトピック