Main Content

NR 位相ノイズのモデリングと補償

この例では、5G OFDM システムにおける位相ノイズの影響を示し、位相トラッキング基準信号 (PT-RS) を使用して共通位相誤差 (CPE) を補償する方法を示します。この例では、CPE 補償を使用した場合と使用しない場合のエラー ベクトル振幅 (EVM) とビット エラー レート (BER) を測定します。

はじめに

5G NR では、3GPP によって位相トラッキング基準信号 (PT-RS) と呼ばれる新しい基準信号が導入されており、発振器ノイズを扱えるようになっています。発振器で発生したノイズにより、情報信号が位相変調を受け、情報信号の周波数スペクトルとタイミング特性が大きく変化することになります。この発振器に関連する現象を位相ノイズと呼びます。ローカル発振器で生成される位相ノイズは、位相ノイズのパワー スペクトル密度に応じて、ミリメートル波 (mmWave) の周波数で大幅な劣化を引き起こします。位相ノイズは、CPE とキャリア間干渉 (ICI) を発生させます。CPE は、各サブキャリアで受信シンボルを同一方向に回転させます。ICI は、サブキャリア間の直交性の喪失につながります。PT-RS が周波数領域において分散構造をもつことから、この例では主に PT-RS を使用し、システム パフォーマンスに対する CPE の影響を推定して最小化します。この例では、物理ダウンリンク共有チャネル (PDSCH) で構成される波形に位相ノイズを適用し、CPE 補償を使用した場合と使用しない場合の EVM と BER の変化を示します。次の図は、この例で実装される処理チェーンを示しています。

位相ノイズのモデル化

発振器のパワー スペクトル密度は、位相ノイズをモデル化します。この例では、多重極零点モデルを使用して、発振器のパワー スペクトル密度を概算します。simParameters 構造体の PNModel フィールドを使用して、位相ノイズ モデルを次から選択します。'A'、'B'、または 'C'。パラメーター セット 'A' と 'B' は、それぞれ 30 GHz と 60 GHz で動作する実際の発振器 (TDoc R1-163984 に記載) から取得されます。パラメーター セット 'C' は、29.55 GHz で動作する実際の発振器 (TR 38.803 の Section 6.1.10 に記載) から取得されます。

この例では、伝送帯域幅 50 MHz に対してサブキャリア間隔が 60 kHz のキャリアを使用します。

% Configure carrier
carrier = nrCarrierConfig;
carrier.SubcarrierSpacing = 60;
carrier.CyclicPrefix = 'normal';
carrier.NSizeGrid = 66;

% Set the operating frequency and choose the phase noise model
simParameters = [];
simParameters.Fc = 30e9; % Frequency in Hz
simParameters.PNModel = 'A'; % 'A' (TDoc R1-163984 Set A), 'B' (TDoc R1-163984 Set B), 'C' (TR 38.803)

% Get the sample rate
ofdmInfo = nrOFDMInfo(carrier);
sr = ofdmInfo.SampleRate;

% Phase noise level
foffsetLog = (4:0.2:log10(sr/2)); % Model offset from 1e4 Hz to sr/2 Hz
foffset = 10.^foffsetLog;         % Linear frequency offset
pn_PSD = hPhaseNoisePoleZeroModel(foffset,simParameters.Fc,simParameters.PNModel); % dBc/Hz

% Set phase noise level
pnoise = comm.PhaseNoise('FrequencyOffset',foffset,'Level',pn_PSD,'SampleRate',sr);
pnoise.RandomStream = "mt19937ar with seed";

% Visualize spectrum mask of phase noise
figure 
semilogx(foffset,pn_PSD)
xlabel('Frequency offset (Hz)')
ylabel('dBc/Hz')
title('Phase noise magnitude response')
grid on

Figure contains an axes object. The axes object with title Phase noise magnitude response contains an object of type line.

PDSCH の構成

この例では、変調スキームを '64QAM' に設定し、レイヤー数を 1 に設定して、キャリア全体を占有する PDSCH を設定します。この例では、既定で 1 つのレイヤーと符号化されていないランダム ビットから成る 1 つのコードワードを使用します。

% Set PDSCH parameters
pdsch = nrPDSCHConfig;
pdsch.PRBSet = 0:carrier.NSizeGrid-1;
pdsch.SymbolAllocation = [0 14];
pdsch.Modulation = '64QAM';
pdsch.NumLayers = 1;
pdsch.MappingType = 'A';
pdsch.NID = 1;
pdsch.RNTI = 2;

% Set DM-RS parameters
pdsch.DMRS.DMRSConfigurationType = 1;
pdsch.DMRS.DMRSTypeAPosition = 2;
pdsch.DMRS.DMRSAdditionalPosition = 0;
pdsch.DMRS.DMRSLength = 1;
pdsch.DMRS.DMRSPortSet = [];
pdsch.DMRS.NumCDMGroupsWithoutData = 1;
pdsch.DMRS.NIDNSCID = 1;
pdsch.DMRS.NSCID = 0;

% Set PT-RS parameters
pdsch.EnablePTRS = 1;
pdsch.PTRS.TimeDensity = 1;
pdsch.PTRS.FrequencyDensity = 2;
pdsch.PTRS.REOffset = '00';
pdsch.PTRS.PTRSPortSet = [];

波形の生成

波形は 2 フレーム生成され、simParameters 構造体のフィールド NumFrames が波形のフレーム数を制御します。次の手順が含まれます。

  • PDSCH のビット容量でランダム コードワードを生成

  • ランダム コードワードの PDSCH シンボルを取得し、それらをグリッドにマッピング

  • DM-RS シンボルを生成してグリッドにマッピング

  • PT-RS シンボルを生成してグリッドにマッピング

  • すべてのフレームの完全なグリッドに対して OFDM 変調を実行

% Number of frames to generate the waveform
simParameters.NumFrames = 2;

% Get the number of slots in the waveform and number of symbols in a slot
numSlots = carrier.SlotsPerFrame*simParameters.NumFrames;
nSlotSymb = carrier.SymbolsPerSlot;

% Initialize the grid for specified number of frames
txGrid = zeros(carrier.NSizeGrid*12,nSlotSymb*numSlots,pdsch.NumLayers);

% Processing loop
txbits = [];
rng('default')
for slotIdx = 0:numSlots - 1
    % Set slot number
    carrier.NSlot = slotIdx;

    % Get PDSCH indices and structural information
    [pdschInd,pdschIndicesInfo] = nrPDSCHIndices(carrier,pdsch);

    % Generate random codeword(s)
    numCW = pdsch.NumCodewords; % Number of codewords
    data = cell(1,numCW);
    for i = 1:numCW
        data{i} = randi([0 1],pdschIndicesInfo.G(i),1);
        txbits = [txbits; data{i}]; %#ok<AGROW>
    end

    % Get modulated symbols
    pdschSym = nrPDSCH(carrier,pdsch,data);

    % Get DM-RS symbols and indices
    dmrsSym = nrPDSCHDMRS(carrier,pdsch);
    dmrsInd = nrPDSCHDMRSIndices(carrier,pdsch);

    % Get PT-RS symbols and indices
    ptrsSym = nrPDSCHPTRS(carrier,pdsch);
    ptrsInd = nrPDSCHPTRSIndices(carrier,pdsch);

    % Resource element mapping to slot grid
    slotGrid = nrResourceGrid(carrier,pdsch.NumLayers);
    slotGrid(pdschInd) = pdschSym;
    slotGrid(dmrsInd) = dmrsSym;
    slotGrid(ptrsInd) = ptrsSym;

    % Generate txGrid for all frames by mapping slotGrid at respective
    % locations
    txGrid(:,slotIdx*nSlotSymb+1:(slotIdx+1)*(nSlotSymb),:) = slotGrid;
end

% Perform OFDM modulation
carrier.NSlot = 0; % Reset the slot number to 0 for OFDM modulation
txWaveform = nrOFDMModulate(carrier,txGrid);

位相ノイズの適用

送信波形に位相ノイズを適用します。位相ノイズの影響を明確に観察するため、この例では、熱ノイズやチャネル モデルの適用を位相ノイズに付加することはしません。この例では、すべてのレイヤーに同じ位相ノイズを適用します。

rxWaveform = pnoise(txWaveform);

受信機

イコライズされた PDSCH シンボルと復号化されたビットを返す前に、受信機は次の手順を実行します。

  • タイミング同期

  • OFDM 復調

  • チャネル推定

  • イコライズ

  • CPE の推定と補正

  • PDSCH 復号化

CPE の推定と補正のステップにおいて、受信機は simParameters 構造体の logical フィールド CompensateCPE を使用します。この例では伝播チャネルを使用しないため、タイミング同期、チャネル推定、およびイコライズの手順は厳密には必要ありません。ただし、これらの手順は、チャネルを導入した場合の位相ノイズの影響を調査するのに役立ちます。

この例は、CPE 補償を使用した場合と使用しない場合の、イコライズされたコンスタレーション シンボル、EVM、およびビット エラー レートを示します。

ケース 1: CPE 補償なし

CPE 補償を無効にするには、simParameters 構造体のフィールド CompensateCPE を 0 に設定します。

simParameters.CompensateCPE = 0;
[eqSymbols,rxbits] = practicalReceiver(carrier,pdsch,simParameters,rxWaveform);
refSymbols = getConstellationPoints(pdsch);
% Display the constellation diagram
figure
plot(eqSymbols,'.')
hold on
plot(refSymbols,'+')
title('Equalized Symbols Constellation Without CPE Compensation')
grid on
xlabel('In-Phase')
ylabel('Quadrature')

Figure contains an axes object. The axes object with title Equalized Symbols Constellation Without CPE Compensation contains 2 objects of type line.

% Display RMS EVM
evm = comm.EVM('ReferenceSignalSource','Estimated from reference constellation','ReferenceConstellation',refSymbols);
fprintf('RMS EVM (in percent) for equalized symbols without CPE compensation: %f%% \n',evm(eqSymbols))
RMS EVM (in percent) for equalized symbols without CPE compensation: 7.431048% 
% Display bit error rate
errorRate = nnz(rxbits-txbits)/numel(txbits);
fprintf('Bit error rate without CPE compensation: %f \n',errorRate)
Bit error rate without CPE compensation: 0.005525 

ケース 2: CPE 補償あり

CPE 補償を有効にするには、simParameters 構造体のフィールド CompensateCPE を 0 に設定します。PT-RS を使用して、スロット内のすべての OFDM シンボル位置で CPE を推定します。PT-RS OFDM シンボルの範囲内の OFDM シンボル位置で CPE を補正します。

simParameters.CompensateCPE = 1;
[eqSymbolsCPE,rxbitsCPE] = practicalReceiver(carrier,pdsch,simParameters,rxWaveform);
% Display the constellation diagram
figure
plot(eqSymbolsCPE,'.')
hold on
plot(refSymbols,'+')
title('Equalized Symbols Constellation With CPE Compensation')
grid on
xlabel('In-Phase')
ylabel('Quadrature')

Figure contains an axes object. The axes object with title Equalized Symbols Constellation With CPE Compensation contains 2 objects of type line.

% Display RMS EVM
fprintf('RMS EVM (in percent) for equalized symbols with CPE compensation: %f%% \n',evm(eqSymbolsCPE))
RMS EVM (in percent) for equalized symbols with CPE compensation: 4.557690% 
% Display bit error rate
errorRateCPE = nnz(rxbitsCPE-txbits)/numel(txbits);
fprintf('Bit error rate with CPE compensation: %f \n',errorRateCPE)
Bit error rate with CPE compensation: 0.000052 

その他の調査

  • 位相ノイズの影響を可視化するには、搬送波周波数、サブキャリア間隔、リソース ブロック数、変調スキーム、およびフレーム数を変更します。

  • コンスタレーションに対する位相ノイズの影響を確認するには、位相ノイズ モデルを変更します。

  • 異なる構成での CPE 補償の影響を解析するには、PT-RS の時間密度と周波数密度を変更します。

  • 熱ノイズとチャネル モデルを含めて、位相ノイズの影響を可視化します。

まとめ

この例では、位相ノイズの影響を示し、PT-RS を使用して CPE を推定および補正する方法を示します。この例では、CPE 補償によって EVM が減少し、ビット エラー レートが改善されることも示します。表示されたコンスタレーション プロットは、mmWave 周波数で ICI が非常に大きく、CPE 補償に加えて ICI 補償を実行する必要があることを示しています。

ローカル関数

function [eqSymbols,rxbits] = practicalReceiver(carrier,pdsch,params,rxWaveform)
% Returns equalized modulated symbols after performing the timing
% estimation, OFDM demodulation, channel estimation, MMSE equalization,
% CPE estimation and correction, and PDSCH decoding.

    % Get the current slot number, number of slots, number of symbols
    % per slot, and total number of symbols
    nSlot = carrier.NSlot;
    numSlots = carrier.SlotsPerFrame*params.NumFrames;
    nSlotSymb = carrier.SymbolsPerSlot;
    numTotalSymbols = numSlots*nSlotSymb;

    % Get reference grid with DM-RS symbols
    dmrsSymCell = cell(1,numSlots);
    dmrsIndCell = cell(1,numSlots);
    refGrid = zeros(carrier.NSizeGrid*12,numTotalSymbols,pdsch.NumLayers);
    for NSlot = 0:numSlots-1
        carrier.NSlot = NSlot;
        slotGrid = nrResourceGrid(carrier,pdsch.NumLayers);
        dmrsSymCell{NSlot+1} = nrPDSCHDMRS(carrier,pdsch);
        dmrsIndCell{NSlot+1} = nrPDSCHDMRSIndices(carrier,pdsch);
        slotGrid(dmrsIndCell{NSlot+1}) = dmrsSymCell{NSlot+1};
        refGrid(:,NSlot*nSlotSymb+1:(NSlot+1)*(nSlotSymb),:) = slotGrid;
    end

    % Perform timing estimation and correction
    carrier.NSlot = nSlot;
    offset = nrTimingEstimate(carrier,rxWaveform,refGrid);
    waveformSync = 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 slots being demodulated
    rxGrid = nrOFDMDemodulate(carrier,waveformSync);
    [K,L,R] = size(rxGrid);
    if (L < numTotalSymbols)
        rxGrid = cat(2,rxGrid,zeros(K,numTotalSymbols-L,R));
    end

    % Declare storage variables
    eqSymbols = [];  % equalized symbols for constellation plot
    rxbits = [];

    for NSlot = 0:numSlots-1
        % Extract grid for current slot
        currentGrid = rxGrid(:,NSlot*nSlotSymb+(1:nSlotSymb),:);

        % Get the PDSCH resources
        carrier.NSlot = NSlot;
        dmrsSymbols = dmrsSymCell{NSlot+1};
        dmrsIndices = dmrsIndCell{NSlot+1};
        ptrsSymbols = nrPDSCHPTRS(carrier,pdsch);
        ptrsIndices = nrPDSCHPTRSIndices(carrier,pdsch);
        [pdschIndices,pdschIndicesInfo] = nrPDSCHIndices(carrier,pdsch);

        % Channel estimation
        [estChannelGrid,noiseEst] = nrChannelEstimate(currentGrid,dmrsIndices,dmrsSymbols,"CDMLengths",pdsch.DMRS.CDMLengths);

        % Get PDSCH resource elements from the received grid
        [pdschRx,pdschHest] = nrExtractResources(pdschIndices,currentGrid,estChannelGrid);

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

        % Common phase error (CPE) estimation and correction
        if params.CompensateCPE
            % Initialize temporary grid to store equalized symbols
            tempGrid = nrResourceGrid(carrier,pdsch.NumLayers);

            % Extract PT-RS symbols from received grid and estimated
            % channel grid
            [ptrsRx,ptrsHest,~,~,~,ptrsLayerIndices] = nrExtractResources(ptrsIndices,currentGrid,estChannelGrid,tempGrid);

            % Equalize PT-RS symbols and map them to tempGrid
            ptrsEq = nrEqualizeMMSE(ptrsRx,ptrsHest,noiseEst);
            tempGrid(ptrsLayerIndices) = ptrsEq;

            % Estimate the residual channel at the PT-RS locations in
            % tempGrid
            cpe = nrChannelEstimate(tempGrid,ptrsIndices,ptrsSymbols);

            % Sum estimates across subcarriers, receive antennas, and
            % layers. Then, get the CPE by taking the angle of the
            % resultant sum
            cpe = angle(sum(cpe,[1 3 4]));

            % Map the equalized PDSCH symbols to tempGrid
            tempGrid(pdschIndices) = pdschEq;

            % Correct CPE in each OFDM symbol within the range of reference
            % PT-RS OFDM symbols
            if numel(pdschIndicesInfo.PTRSSymbolSet) > 0
                symLoc = pdschIndicesInfo.PTRSSymbolSet(1)+1:pdschIndicesInfo.PTRSSymbolSet(end)+1;
                tempGrid(:,symLoc,:) = tempGrid(:,symLoc,:).*exp(-1i*cpe(symLoc));
            end

            % Extract PDSCH symbols
            pdschEq = tempGrid(pdschIndices);
        end

        % Store the equalized symbols and output them for all the slots
        eqSymbols = [eqSymbols; pdschEq]; %#ok<AGROW>

        % Decode the PDSCH symbols and get the hard bits
        eqbits = nrPDSCHDecode(carrier,pdsch,pdschEq);
        for i = 1:numel(eqbits)
            rxbits = [rxbits; double(eqbits{i}<0)]; %#ok<AGROW>
        end

    end

end

function sym = getConstellationPoints(pdsch)
%getConstellationPoints Constellation points
%   SYM = getConstellationPoints(PDSCH) returns the constellation points
%   SYM based on modulation schemes provided in PDSCH configuration object.

    sym = [];
    modulation = string(pdsch.Modulation);  % Convert modulation scheme to string type
    ncw = pdsch.NumCodewords;               % Number of codewords
    if ncw == 2 && (numel(modulation) == 1)
        modulation(end+1) = modulation(1);
    end
    % Get the constellation points
    for cwIndex = 1:ncw
        qm = strcmpi(modulation(cwIndex),{'QPSK','16QAM','64QAM','256QAM'})*[2 4 6 8]';
        sym = [sym; nrSymbolModulate(int2bit((0:2^qm-1)',qm),modulation(cwIndex))]; %#ok<AGROW>
    end

end

関連するトピック