メインコンテンツ

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

6G リンクレベル シミュレーション

R2024a 以降

この参照シミュレーションでは、pre-6G リンクのスループットを測定する方法を示します。これは 5G に基づいていますが、5G システムよりも広い帯域幅とサブキャリア間隔を調査できます。また、並列処理を使用し、デスクトップまたはクラウドの複数のワーカーを使ってシミュレーションを高速化します。

はじめに

この例では、pre-6G リンクの物理ダウンリンク共有チャネル (PDSCH) のスループットを測定します。この例では、5G NR の 3GPP 仕様で定義されている範囲を超えるいくつかのパラメーター範囲を使用できます。Get Started with 6G Exploration Libraryの例で説明されているように、275 個よりも多いリソース ブロックと 960 kHz よりも大きいサブキャリア間隔を使用できます。

この例では、次の機能をモデル化します。

  • ダウンリンク共有チャネル (DL-SCH) トランスポート チャネルの符号化

  • レイヤー数に応じた複数のコードワード

  • PDSCH および PDSCH の復調基準信号 (DM-RS) の生成

  • 可変サブキャリア間隔とフレーム numerology (2n×15 kHz)

  • ノーマル サイクリック プレフィックスと拡張サイクリック プレフィックス

  • クラスター遅延線 (CDL) 伝播チャネル モデル

  • 特異値分解 (SVD) を使用した PDSCH サブバンド プリコーディング

  • 完全なチャネル推定または実用的なチャネル推定

  • 最大 32 個のプロセスを使用する HARQ 操作

  • 広帯域およびサブバンドのプリコーディング

  • キャリア全体にまたがる単一の bandwidth part

  • 実行速度を高める並列処理

次の図は、実装される処理チェーンを示しています。

The diagram shows the PDSCH processing chain, including the following operations: dowlink shared channel (DL-SCH) encoding, physical downlink shared (PDSCH) channel generation, precoding, OFDM modulation, and CDL chanel. At the receiver the processing steps are: synchronization, OFDM demodulation, channel estimation and equalization, PDSCH decoding, and DL-SCH decoding.

シミュレーション パラメーターの設定

シミュレーションの長さを 10 ms のフレームの数 (NFrames) で設定します。有意なスループット結果を得るには、多数のフレームを使用します。シミュレーションを行うための SNR 点を設定します。各レイヤーの SNR はリソース エレメント (RE) ごとに定義され、すべてのアンテナにおける信号とノイズの影響が含まれます。この例で使用している SNR 定義の説明については、リンク シミュレーションで使用する SNR の定義の例を参照してください。

simParameters = struct();       % Simulation parameters structure
simParameters.NFrames = 2;      % Number of 10 ms frames
simParameters.SNRdB = -10:2:-6; % SNR range (dB)

enableParallelism 変数は、シミュレーションを単一のワーカーで実行するか、複数のワーカーを使用して並列に実行するかを制御します。並列処理を使用するには、Parallel Computing Toolbox™ のライセンスが必要です。

simParameters.enableParallelism = true;

DisplayDiagnostics フラグを有効にしたり、pdschLink 関数にブレークポイントを設定したり、コードをプロファイリングしたりする場合は、並列処理を無効にします。

チャネル推定器の構成

logical 変数 PerfectChannelEstimator は、チャネル推定の動作を制御します。true に設定すると、シミュレーションでは完全なチャネル推定が使用されます。そうでない場合、実用的なチャネル推定のために PDSCH DM-RS が使用されます。

simParameters.PerfectChannelEstimator = false;

シミュレーション診断の構成

この例では、実行時にシミュレーションの進行を監視するのに役立つ 2 つの診断フラグが提供されています。両方のフラグは、enableParallelismfalse に設定されている場合にのみ適用されます。

DisplaySimulationInformation 変数は、各サブフレームの HARQ プロセス ID などのシミュレーション情報の表示を制御します。CRC エラーの場合、冗長バージョン (RV) シーケンスのインデックスの値も表示されます。

simParameters.DisplaySimulationInformation = true;

DisplayDiagnostics フラグを使用すると、レイヤーごとに EVM をプロットできます。このプロットは、イコライズ後の受信信号の品質を監視します。レイヤーごとの EVM の Figure は以下を表示します。

  • スロット単位でのレイヤーごとの EVM。これは時間とともに変化する EVM を表示します。

  • リソース ブロック単位でのレイヤーごとの EVM。これは EVM の周波数を示します。

simParameters.DisplayDiagnostics = false;

キャリア、PDSCH、および伝播チャネルの構成

% Set carrier parameters
simParameters.Carrier = pre6GCarrierConfig;                       % Carrier resource grid configuration
simParameters.Carrier.NSizeGrid = 330;                            % Bandwidth in number of resource blocks
simParameters.Carrier.SubcarrierSpacing = 120;                    % Subcarrier spacing

% Set PDSCH parameters
simParameters.PDSCH = pre6GPDSCHConfig;                           % PDSCH definition for all PDSCH transmissions in the BLER simulation

% Define PDSCH time-frequency resource allocation per slot to be full grid (single full grid BWP) and number of layers
simParameters.PDSCH.PRBSet = 0:simParameters.Carrier.NSizeGrid-1;                % PDSCH PRB allocation
simParameters.PDSCH.SymbolAllocation = [0,simParameters.Carrier.SymbolsPerSlot]; % Starting symbol and number of symbols of each PDSCH allocation
simParameters.PDSCH.NumLayers = 1;                                               % Number of PDSCH transmission layers

% This structure is to hold additional simulation parameters for the DL-SCH and PDSCH
simParameters.PDSCHExtension = struct();             

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

% Disable PT-RS
simParameters.PDSCH.EnablePTRS = false;

% PDSCH PRB bundling (TS 38.214 Section 5.1.2.3)
simParameters.PDSCHExtension.PRGBundleSize = [];                  % Any positive power of 2, or [] to signify "wideband"

% HARQ process parameters
simParameters.PDSCHExtension.NHARQProcesses = 16;                 % Number of parallel HARQ processes to use
simParameters.PDSCHExtension.EnableHARQ = true;                   % Enable retransmissions for each process, using RV sequence [0,2,3,1]

% LDPC decoder parameters
simParameters.PDSCHExtension.LDPCDecodingAlgorithm = 'Normalized min-sum';
simParameters.PDSCHExtension.MaximumLDPCIterationCount = 20;

% Number of antennas
simParameters.NTxAnts = 32;                                       % Number of antennas (1,2,4,8,16,32,64,128,256,512,1024) >= NumLayers
simParameters.NRxAnts = 2;

% Define the general CDL propagation channel parameters
simParameters.DelayProfile = 'CDL-A';   
simParameters.DelaySpread = 10e-9;
simParameters.MaximumDopplerShift = 70;

% Cross-check the PDSCH configuration parameters against the channel geometry 
validateParameters(simParameters);

並列実行の構成

並列実行を有効にしている場合は、並列クラスターを構成します。この例の並列実行モデルの詳細な説明については、Accelerate Link-Level Simulations with Parallel Processingの例を参照してください。

if (simParameters.enableParallelism && canUseParallelPool)
    pool = gcp; % create parallel pool, requires PCT
    numWorkers = pool.NumWorkers;
    maxNumWorkers = pool.NumWorkers;
else
    if (~canUseParallelPool && simParameters.enableParallelism)
        warning("Ignoring the value of enableParallelism ("+simParameters.enableParallelism+")"+newline+ ...
            "The simulation will run using serial execution."+newline+"You need a license of Parallel Computing Toolbox to use parallelism.")
    end
    numWorkers = 1;    % No parallelism
    maxNumWorkers = 0; % Used to convert the parfor-loop into a for-loop
end

各ワーカーに対して乱数ストリームを何度も不必要にコピーすることを避けるために、一定の乱数ストリームを作成します。サブストリームは、各ワーカーに対して互いに独立した乱数ストリームを提供します。

str1 = RandStream('Threefry','Seed',1);
constantStream = parallel.pool.Constant(str1);

ワーカーごとのスロット数を計算します。使用可能なすべてのワーカーを最大限に活用するため、例では、NFrames で指定した値よりも多くのスロットがシミュレーションされる場合があります。

numSlotsPerWorker = ceil((simParameters.NFrames*simParameters.Carrier.SlotsPerFrame)/numWorkers);
disp("Parallelism: "+simParameters.enableParallelism)
disp("Number of workers: "+numWorkers)
disp("Number of slots per worker: "+numSlotsPerWorker)
disp("Total number of frames: "+(numSlotsPerWorker*numWorkers)/simParameters.Carrier.SlotsPerFrame)

PDSCH リンクレベル シミュレーション

このセクションでは、Nworkers 個の PDSCH リンクを並列にシミュレーションします。ここで、Nworkers は使用可能なワーカーの数です。各ワーカーはすべての SNR 点をシミュレーションします。parfor ループでは、構文 parfor (pforIdx = 1:numWorkers,maxNumWorkers) が使用されます。コードをデバッグするには、maxNumWorkers0 に設定して、シミュレーションを並列実行から逐次的実行に切り替えます。maxNumWorkers の値に関係なく、parfor ループの本体にブレークポイントを設定することはできません。ただし、maxNumWorkers = 0 の場合は、parfor ループの本体から呼び出される関数内にブレークポイントを設定できます。

% Results storage
result = struct(NumSlots=0,NumBits=0,NumCorrectBits=0);
results = repmat(result,numWorkers,numel(simParameters.SNRdB));

% Parallel processing, worker parfor-loop
parfor (pforIdx = 1:numWorkers,maxNumWorkers)     
    % Set random streams to ensure repeatability
    % Use substreams in the generator so each worker uses mutually independent streams
    stream = constantStream.Value;      % Extract the stream from the Constant
    stream.Substream = pforIdx;         % Set substream value = parfor index
    RandStream.setGlobalStream(stream); % Set global stream per worker

    % Per worker processing
    results(pforIdx,:) = pdschLink(simParameters,numSlotsPerWorker,pforIdx);
end

結果

測定したスループットを表示します。これは、使用可能なリソースを所与とするリンクの最大スループットがデータ伝送に占める割合として計算されます。

[throughput,throughputMbps,summaryTable] = processResults(simParameters,results);
disp(summaryTable)
figure;
plot(simParameters.SNRdB,throughput,'o-.')
xlabel('SNR (dB)'); ylabel('Throughput (%)'); grid on;
title(sprintf('%s (%dx%d) / NRB=%d / SCS=%dkHz', ...
              simParameters.DelayProfile,simParameters.NTxAnts,simParameters.NRxAnts, ...
              simParameters.Carrier.NSizeGrid,simParameters.Carrier.SubcarrierSpacing));

ローカル関数

function [throughput,throughputMbps,summaryTable] = processResults(simParameters,results)
% Process multi-worker and multi-SNR results

    numSNRPts = size(results,2);
    
    totalSimulatedSlots = sum(reshape([results(:).NumSlots].',[],numSNRPts),1);
    totalSimulatedBits = sum(reshape([results(:).NumBits].',[],numSNRPts),1);
    totalCorrectBits = sum(reshape([results(:).NumCorrectBits].',[],numSNRPts),1);
    totalSimulatedFrames = totalSimulatedSlots/simParameters.Carrier.SlotsPerFrame;
    
    % Throughput results calculation
    throughput = 100*(totalCorrectBits./totalSimulatedBits);
    throughputMbps = 1e-6*totalCorrectBits/(simParameters.NFrames*10e-3);
    summaryTable = table(simParameters.SNRdB.',totalSimulatedBits.',totalSimulatedSlots.', ...
        totalSimulatedFrames.',throughput.',throughputMbps.');
    summaryTable.Properties.VariableNames = ["SNR" "Simulated bits" "Number of Tr Blocks" ...
        "Number of frames" "Throughput (%)" "Throughput (Mbps)"];

end

function resultsPerWorker = pdschLink(simParameters,totalNumSlots,workerId)
% PDSCH link simulation
    
    % Take copies of channel-level parameters to simplify subsequent parameter referencing 
    carrier = simParameters.Carrier;
    pdsch = simParameters.PDSCH;
    pdschextra = simParameters.PDSCHExtension;

    % Results storage
    result = struct(NumSlots=0,NumBits=0,NumCorrectBits=0);
    resultsPerWorker = repmat(result,1,numel(simParameters.SNRdB));

    % Create DL-SCH encoder/decoder
    [encodeDLSCH,decodeDLSCH] = dlschEncoderDecoder(pdschextra);

    % OFDM waveform information
    ofdmInfo = hpre6GOFDMInfo(carrier);
        
    % Create CDL channel
    channel = nrCDLChannel;
    channel = hArrayGeometry(channel,simParameters.NTxAnts,simParameters.NRxAnts);
    nTxAnts = prod(channel.TransmitAntennaArray.Size);
    nRxAnts = prod(channel.ReceiveAntennaArray.Size);
    channel.DelayProfile = simParameters.DelayProfile;
    channel.DelaySpread = simParameters.DelaySpread;
    channel.MaximumDopplerShift = simParameters.MaximumDopplerShift;
    channel.SampleRate = ofdmInfo.SampleRate;
    % New seed for each worker, but the same for each SNR point so they all
    % experience the same channel realization.
    channel.Seed = randi([0 2^32-1]);

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

    % Set up redundancy version (RV) sequence for all HARQ processes
    if simParameters.PDSCHExtension.EnableHARQ        
        rvSeq = [0 2 3 1];
    else
        % HARQ disabled - single transmission with RV=0, no retransmissions
        rvSeq = 0;
    end

    % for all SNR points
    for snrIdx = 1:length(simParameters.SNRdB)

        % Noise power calculation
        SNR = 10^(simParameters.SNRdB(snrIdx)/10); % Calculate linear noise gain
        N0 = 1/sqrt(double(ofdmInfo.Nfft)*SNR*nRxAnts);
        % Get noise power per resource element (RE) from noise power in the
        % time domain (N0^2)
        nPowerPerRE = N0^2*ofdmInfo.Nfft;

        % Reset the channel and DL-SCH decoder at the start of each SNR simulation
        reset(channel);
        reset(decodeDLSCH);        

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

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

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

        %  Progress when parallel processing is enabled
        if (simParameters.enableParallelism && workerId==1)
            fprintf('Simulating SNR=%.2f dB, progress: \n0%% \n',simParameters.SNRdB(snrIdx))
        end

        % Process all the slots per worker
        for nSlot = 0:totalNumSlots-1

            % New slot number
            carrier.NSlot = nSlot;

            % Calculate the transport block sizes for the transmission in the slot
            [pdschIndices,pdschIndicesInfo] = hpre6GPDSCHIndices(carrier,pdsch);
            trBlkSizes = hpre6GTBS(pdsch,pdschextra.TargetCodeRate);

            % Generate new data and DL-SCH encode
            codedTrBlocks = getDLSCHCodeword(encodeDLSCH,trBlkSizes,pdschIndicesInfo.Qm,pdsch.NumLayers,pdschIndicesInfo.G,harqEntity);
        
            % PDSCH modulation of codeword(s), MIMO precoding and OFDM
            [txWaveform,pdschSymbols]= hPDSCHTransmit(carrier,pdsch,codedTrBlocks,wtx);

            % Pass data through channel model
            txWaveform = [txWaveform; zeros(maxChDelay,size(txWaveform,2))];
            [rxWaveform,pathGains,sampleTimes] = channel(txWaveform);

            % Add noise
            noise = N0*randn(size(rxWaveform),"like",rxWaveform);
            rxWaveform = rxWaveform + noise;

            % Synchronization, OFDM demodulation, channel estimation,
            % equalization, and PDSCH demodulation            
            pathFilters = getPathFilters(channel);
            
            perfEstConfig = perfectEstimatorConfig(pathGains,sampleTimes,pathFilters,nPowerPerRE,simParameters.PerfectChannelEstimator);
            [dlschLLRs,wtx,pdschEq] = hPDSCHReceive(carrier,pdsch,pdschextra,rxWaveform,wtx,perfEstConfig);

            % Display EVM per layer, per slot and per RB
            if (simParameters.DisplayDiagnostics)
                gridSize = [carrier.NSizeGrid*12 carrier.SymbolsPerSlot nTxAnts];
                plotLayerEVM(totalNumSlots,nSlot,pdsch,gridSize,pdschIndices,pdschSymbols,pdschEq,simParameters.SNRdB(snrIdx));
            end

            % Decode the DL-SCH transport channel

            % If new data because of previous RV sequence time out then flush decoder soft buffer explicitly
            for cwIdx = 1:pdsch.NumCodewords
                if harqEntity.NewData(cwIdx) && harqEntity.SequenceTimeout(cwIdx)
                    resetSoftBuffer(decodeDLSCH,cwIdx-1,harqEntity.HARQProcessID);
                end
            end
            decodeDLSCH.TransportBlockLength = trBlkSizes;
            [~,blkerr] = decodeDLSCH(dlschLLRs,pdschIndicesInfo.Qm,pdsch.NumLayers,harqEntity.RedundancyVersion,harqEntity.HARQProcessID);

            % Update current process with CRC error and advance to next process
            procstatus = updateAndAdvance(harqEntity,blkerr,trBlkSizes,pdschIndicesInfo.G);
            if (simParameters.DisplaySimulationInformation && ~simParameters.enableParallelism)
                fprintf('(%3.2f%%), SNR=%.2f dB, NSlot=%d, %s\n',100*(nSlot+1)/totalNumSlots,simParameters.SNRdB(snrIdx),nSlot,procstatus);
            elseif (simParameters.enableParallelism && workerId==1 && ~mod((nSlot+1),ceil((10*totalNumSlots)/100))) % Progress when parallel processing is enabled
                % Update progress with approximately 10% steps
                fprintf('%3.2f%% \n',100*(nSlot+1)/totalNumSlots)
            end

            % SNR point simulation results            
            resultsPerWorker(snrIdx).NumSlots = resultsPerWorker(snrIdx).NumSlots+1;
            resultsPerWorker(snrIdx).NumBits = resultsPerWorker(snrIdx).NumBits+sum(trBlkSizes);
            resultsPerWorker(snrIdx).NumCorrectBits = resultsPerWorker(snrIdx).NumCorrectBits+sum(~blkerr .* trBlkSizes);

        end % for nSlot = 0:totalNumSlots

    end % for all SNR points
end

function [encodeDLSCH,decodeDLSCH] = dlschEncoderDecoder(PDSCHExtension)
% Create and parameterize the DL-SCH encoder and decoder objects
    
    % Create DL-SCH encoder object
    encodeDLSCH = hpre6GDLSCH;
    encodeDLSCH.MultipleHARQProcesses = true;
    encodeDLSCH.TargetCodeRate = PDSCHExtension.TargetCodeRate;
    
    % Create DL-SCH decoder object
    decodeDLSCH = hpre6GDLSCHDecoder;
    decodeDLSCH.MultipleHARQProcesses = true;
    decodeDLSCH.TargetCodeRate = PDSCHExtension.TargetCodeRate;
    decodeDLSCH.LDPCDecodingAlgorithm = PDSCHExtension.LDPCDecodingAlgorithm;
    decodeDLSCH.MaximumLDPCIterationCount = PDSCHExtension.MaximumLDPCIterationCount;
end

function codedTrBlocks = getDLSCHCodeword(encodeDLSCH,trBlkSizes,Qm,NumLayers,G,harqEntity)
% Get DL-SCH codeword

    % HARQ processing
    for cwIdx = 1:length(G)
        % If new data for current process and codeword then create a new DL-SCH transport block
        if harqEntity.NewData(cwIdx) 
            trBlk = randi([0 1],trBlkSizes(cwIdx),1);
            setTransportBlock(encodeDLSCH,trBlk,cwIdx-1,harqEntity.HARQProcessID);
        end
    end

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

end

function perfEstInfo = perfectEstimatorConfig(pathGains,sampleTimes,pathFilters,noiseEst,perfChEst)
% Perfect channel estimator configuration

    perfEstInfo.PathGains = pathGains;
    perfEstInfo.PathFilters = pathFilters;
    perfEstInfo.SampleTimes = sampleTimes;
    perfEstInfo.NoiseEstimate = noiseEst;
    perfEstInfo.PerfectChannelEstimator = perfChEst;

end

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

    ofdmInfo = hpre6GOFDMInfo(carrier);
    
    chInfo = info(propchannel);
    maxChDelay = chInfo.MaximumChannelDelay;
    
    % Temporary waveform (only needed for the sizes)
    tmpWaveform = zeros((ofdmInfo.SampleRate/1000/carrier.SlotsPerSubframe)+maxChDelay,nTxAnts,"single");
    
    % Filter through channel    
    [~,pathGains,sampleTimes] = propchannel(tmpWaveform);
    
    % Perfect timing synch    
    pathFilters = getPathFilters(propchannel);
    offset = nrPerfectTimingEstimate(pathGains,pathFilters);
    
    % Perfect channel estimate
    estChannelGrid = hpre6GPerfectChannelEstimate(carrier,pathGains,pathFilters,offset,sampleTimes);
    
end

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

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

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

function validateParameters(simParameters)

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

end

参考

|

トピック