Этот пример демонстрирует, как измерить физическую пропускную эффективность нисходящего общего канала (PDSCH) в многопользовательском сценарии с несколькими входами и несколькими выходами (MU-MIMO) с LTE Toolbox™. Он моделирует режим передачи, TM9, на основе некодовой книги с блочной диагонализацией [1]. Этот пример поддерживает как схемы частотного деления дуплекса (FDD), так и схемы деления дуплекса во времени (TDD). Он также поддерживает использование Toolbox™ Parallel Computing для сокращения эффективного времени симуляции.
В сценарии MU-MIMO из-за одновременной передачи данных многим пользователям в приемнике будут присутствовать межпользовательские помехи. Межпользовательские помехи в приемник могут быть отменены с помощью методов предварительного кодирования в передатчике. Двумя методами линейного предварительного кодирования для передачи MU-MIMO являются инверсия канала и блочная диагонализация. Этот пример использует предварительное кодирование диагонализации блоков. Этот пример измеряет пропускную способность PDSCH в сценарии MU-MIMO для ряда точек отношения сигнал/шум (ОСШ). Для получения информации о том, как смоделировать, однопользовательская MIMO (SU-MIMO) в LTE смотрят на следующий пример: Пропускная способность PDSCH для основанных на нешифровальной книге Предкодирующих Схем: Порт 5 (TM7), Порт 7 или 8 или Порт 7-8 (TM8), Порт 7-14 (TM9 и TM10)
Простой блок MU-MIMO с параметрами конфигурации симуляции по умолчанию, используемыми в примере, показан на следующем рисунке.
Параметры симуляции для базовой станции и пользователей сконфигурированы в этом разделе. Пример выполняется для длины симуляции из двух систем координат для ряда точек ОСШ. Увеличение NFrames
увеличение времени симуляции и получение статистически значимых результатов производительности. Используйте переменную SNRIn
чтобы задать ОСШ, это может быть массив значений или скаляр. Согласно ограничениям в LTE [2], этот пример поддерживает максимум 4 пользователя с максимум 4 слоями для всех пользователей. Максимальное количество слоев на одного пользователя - 2. Количество передающих антенн должно быть больше или равным общему количеству приемных антенн для всех пользователей.
NFrames = 2; % Number of frames SNRIn = [8 14]; % SNR range in dB NUsers = 2; % Number of active users NTxAnts = 2; % Number of antennas at eNodeB % Specify UE-specific parameters muNumLayers = [1 1 1 1]; % Number of layers for a maximum of 4 users muNumRxAnts = [1 1 1 1]; % Number of receive antennas for a maximum of 4 users muCodeRate = [0.5 0.5 0.5 0.5]; % Code rate for a maximum of 4 users muModulation = {'16QAM';'16QAM';'16QAM';'16QAM'}; % Modulation for a maximum of 4 users
Набор параметров, необходимых для TM9, указан ниже. Этот пример не выполняет декодирование формата DCI; а DCIFormat
поле включено для полноты. Массив ячеек muPDSCH
сохраняет структуру строения передачи PDSCH для всех пользователей.
% Initialize cell arrays of PDSCH transmission configuration structures, % transport block sizes and coded transport block sizes. muPDSCH = cell(NUsers,1); trBlkSizes = cell(NUsers,1); codedTrBlkSizes = cell(NUsers,1); simulationParameters = []; % clear simulation parameters simulationParameters.NDLRB = 50; simulationParameters.PDSCH.PRBSet = (0)'; simulationParameters.PDSCH.DCIFormat = 'Format2C'; simulationParameters.PDSCH.TxScheme = 'Port7-14'; simulationParameters.PDSCH.NTxAnts = NTxAnts; simulationParameters.DuplexMode = 'FDD'; % 'FDD', 'TDD' simulationParameters.TotSubframes = 1; % PDSCH configuration structure for users based on the common and % user-specific parameters ncw = zeros(NUsers,1); for userIdx = 1:NUsers simulationParameters.PDSCH.TargetCodeRate = muCodeRate(userIdx); simulationParameters.PDSCH.Modulation = muModulation{userIdx}; simulationParameters.PDSCH.NLayers = muNumLayers(userIdx); % Initialize W to zero simulationParameters.PDSCH.W = zeros(muNumLayers(userIdx),NTxAnts); % Downlink reference measurement channel configuration enb = lteRMCDL(simulationParameters); % PDSCH transmission configuration structure for users muPDSCH{userIdx}= enb.PDSCH; % Number of codewords for users ncw(userIdx) = length(muPDSCH{userIdx}.Modulation); % Store transport block sizes for users trBlkSizes{userIdx} = muPDSCH{userIdx}.TrBlkSizes; end % Assign redundancy version sequence rvSequence = muPDSCH{1}.RVSeq;
Распечатайте сводные данные некоторых из более релевантных параметров симуляции.
hMultiUserParameterSummary(enb,muPDSCH,muNumRxAnts);
Parameter summary for TM9 MU-MIMO Transmission ------------------------------------------------------------------ Duplexing mode: FDD Transmission mode: TM9(MU-MIMO) Transmission scheme: Port7-14 Number of downlink resource blocks: 50 Number of allocated resource blocks: 1 Number of transmit antennas: 2 ------------------------------------------------------------------ Number of Transmission layers for UE-1: 1 Number of codewords for UE-1: 1 Number of receive antennas for UE-1: 1 Modulation codeword 1: 16QAM Transport block sizes codeword 1: 208 208 208 208 208 208 208 208 208 208 Code rate codeword 1: 0.5088 0.5088 0.5088 0.5088 0.5088 0.5088 0.5088 0.5088 0.5088 0.5088 ------------------------------------------------------------------ Number of Transmission layers for UE-2: 1 Number of codewords for UE-2: 1 Number of receive antennas for UE-2: 1 Modulation codeword 1: 16QAM Transport block sizes codeword 1: 208 208 208 208 208 208 208 208 208 208 Code rate codeword 1: 0.5088 0.5088 0.5088 0.5088 0.5088 0.5088 0.5088 0.5088 0.5088 0.5088
Параметры конфигурации модели канала для канала между eNodeB и пользователями хранятся в массиве ячеек muChannel
. Набор общих параметров для каждого канала первоначально задан. Параметры, определенные здесь, используются с lteFadingChannel
во время обработки субкадров.
muChannel = cell(NUsers,1); channel = struct; channel.DelayProfile ='EPA'; % Delay profile channel.MIMOCorrelation = 'Low'; % Multi-antenna correlation channel.NTerms = 16; % Oscillators used in fading model channel.ModelType = 'GMEDS'; % Rayleigh fading model type channel.InitPhase = 'Random'; % Random initial phases channel.NormalizePathGains = 'On'; % Normalize delay profile power channel.NormalizeTxAnts = 'On'; % Normalize for transmit antennas
Частота дискретизации канала зависит от размера БПФ, используемого в модуляторе OFDM. Это можно получить с помощью функции lteOFDMInfo
.
ofdmInfo = lteOFDMInfo(enb); channel.SamplingRate = ofdmInfo.SamplingRate; % Independent channel configuration parameters for each user chanSeeds = [1111 2222 3333 4444]; % Channel seed for a maximum of 4 users dopplerFreq = [5 50 25 15]; % Doppler frequency for a maximum of 4 users for userIdx = 1:NUsers muChannel{userIdx}= channel; muChannel{userIdx}.Seed = chanSeeds(userIdx); % Channel seed muChannel{userIdx}.NRxAnts = muNumRxAnts(userIdx); % Number of receive antennas muChannel{userIdx}.DopplerFreq = dopplerFreq(userIdx);% Doppler frequency end
Для определения пропускной способности в каждой точке ОСШ, субкадровая обработка PDSCH цепи включает в себя:
Вычисление матрицы предварительного кодирования - идеальная оценка канала используется, чтобы вычислить матрицу предварительного кодирования для каждого пользователя. Подробное описание этого шага приводится в следующем разделе.
Обновление текущего процесса HARQ - для каждого пользователя используются отдельные процессы HARQ.
Создание формы волны передачи - для каждого пользователя генерируются отдельные символы PDSCH. Символы PDSCH предварительно кодируются вычисленной матрицей предварительного кодирования. Предварительно кодированные символы PDSCH, соответствующие UE, объединяются и модулируются OFDM.
Моделирование канала - передайте форму волны через канал с замираниями каждому пользователю и добавьте шум (AWGN)
Выполнение синхронизации и демодуляции OFDM - отдельно для каждого пользователя. Смещите принятые символы, чтобы принять во внимание комбинацию задержки реализации и расширения задержки канала. OFDM демодулирует символы.
Декодирование PDSCH - отдельно выполняется для каждого пользователя. Идеальная оценка канала принята в приемник для операций декодирования. Получите оценку полученных кодовых слов, используя ltePDSCHDecode
для демодуляции и дескремблирования восстановленных символов PDSCH для всех пар передающей и приемной антенны.
Декодирование DL-SCH и хранение блока CRC - отдельно для каждого пользователя. Передайте вектор декодированных мягких бит в lteDLSCHDecode
, который декодирует кодовое слово и возвращает ошибку CRC блока, используемую для определения пропускной способности системы.
Матрица предварительного кодирования для каждого пользователя должна быть вычислена на основе оценок канала между eNodeB и пользователями. Матрица предварительного кодирования вычисляется с использованием метода диагонализации блоков. Для расчет матрицы предварительного кодирования в передатчике требуется информация о состоянии канала (CSI). В этом примере для простоты в базовой станции принято совершенное знание канала между eNodeB и пользователями.
Для TDD оценки канала между eNodeB и пользователями оцениваются в последнем подкадре UL перед подкадром DL. Эти оценки канала используются, чтобы вычислить матрицу предварительного кодирования, W
. Все последующие подкадры DL (включая специальные подкадры) до следующего подкадра UL предварительно кодируются матрицей W
.
Для FDD существует задержка одного подкадра между вычислением W
и подрамник, где он используется. Для примера, W
используется в подрамнике DL n
был вычислен с оценками канала, полученными в субкадре DL n-1
.
Функция hMultiUserPrecodingMatrix вычисляет W
используя следующие шаги:
Получите идеальную оценку канала для рассматриваемого субкадра для всех пользователей
Среднее значение оценок канала для всех выделенных RB
Вычислите матрицу предварительного кодирования с помощью метода диагонализации блоков согласно blkdiagbfweights
функция.
Обратите внимание, что для выделения одного ресурсного блока матрица предварительного кодирования обычно хорошо соответствует условиям канала с небольшим отклонением от оптимального предварительного кодирования. Но когда размер распределения увеличивается, матрица предварительного кодирования принимает во внимание среднее значение условий канала во всем распределении. Это среднее вызывает отклонение от оптимальной матрицы предварительного кодирования. Поэтому можно ожидать снижения эффективности при увеличениях размера выделения ресурсов.
Цикл 'for' для обработки точек ОСШ включен ниже. Чтобы включить использование параллельных вычислений для повышения скорости, используйте 'parfor' вместо 'for' в цикле. Для этого требуется Parallel Computing Toolbox. Если этот параметр не установлен, оператор по умолчанию будет иметь значение normal 'for'.
% Initialize variables used in the simulation and analysis maxThroughput = zeros(length(SNRIn),NUsers); simThroughput = zeros(length(SNRIn),NUsers); harqProcesses = cell(NUsers,1); % Initialize cell array for constellation plot rxConstellation = cell(numel(SNRIn),NUsers,2); % Copy the channel cell array and cell array of PDSCH transmission % configuration structure to optimize parallel processing (only if running % the example with Parallel Computing Toolbox) muChannelInit = muChannel; muPDSCHInit = muPDSCH; % During the simulation, some fields of enb will be updated, make a copy to % reinitialize it when simulating each SNR point enbInit = enb; % For TDD precalculate vector of subframe types: D, S and U for downlink, % special, and uplink, respectively if strcmpi(enb.DuplexMode,'TDD') subframeType = char(10,1); initialSubframeNo = enb.NSubframe; for sNo=0:9 % for all subframes in a frame enb.NSubframe = sNo; duplexInfo = lteDuplexingInfo(enb); subframeType(sNo+1) = duplexInfo.SubframeType(1); % first char: D, S or U end enb.NSubframe = initialSubframeNo; end % CFI can be a scalar, or a vector of length 10 (corresponding to a frame) % if the CFI varies per subframe. If CFI is scalar, create a local copy of % CFI as a vector (one value per subframe). if numel(enb.CFI) == 1 CFI = repmat(enb.CFI,1,10); else CFI = enb.CFI; end for snrIdx = 1:numel(SNRIn) % Comment out for parallel computing %parfor snrIdx = 1:numel(SNRIn) % Uncomment for parallel computing % Set the random number generator seed depending on the loop variable % to ensure independent random streams rng(snrIdx,'combRecursive'); % Reinitialize enb structures (they are modified during % each SNR point simulation) enb = enbInit; % Reinitialize muChannel and muPDSCH cell array muChannel = muChannelInit; muPDSCH = muPDSCHInit; % Initialize the state of all HARQ processes harqProcesses = cell(NUsers,1); for userIdx = 1:NUsers harqProcesses{userIdx} = hNewHARQProcess(enb,muPDSCH{userIdx}); end harqProcessSequence = 1; % Set up variables for the main loop lastOffset = zeros(NUsers,1); frameOffset = zeros(NUsers,1); blkCRC = []; rxSymbols = cell(NUsers,2); % DL-SCH symbols for constellation plot bitTput = cell(NUsers,1); txedTrBlkSizes = cell(NUsers,1); W = cell(NUsers,1); pdschIndices = []; pdschRho = 0; % Flag to indicate if a precoding matrix cell array W is available. isWready = false; % Flag to indicate if a subframe is to be processed. Set to true if % there is data to be processed in the subframe, i.e. non-zero transport % block size. processSubframe = false; % Main for loop: for all subframes for subframeNo = 0:(NFrames*10-1) % Update subframe number enb.NSubframe = subframeNo; % Load CFI for current subframe enb.CFI = CFI(mod(subframeNo,length(CFI))+1); % Get HARQ process ID for the subframe from HARQ process sequence harqID = harqProcessSequence(mod(subframeNo,... length(harqProcessSequence))+1); % Channel fading process time offset for the current subframe and % transport block size(s) trBlk = zeros(NUsers,2); % User can have maximum 2 transport block trBlkNext = zeros(NUsers,2); for userIdx = 1:NUsers % Initialize channel fading process time offset for each subframe muChannel{userIdx}.InitTime = subframeNo/1000; trBlk(userIdx,1:ncw(userIdx)) = trBlkSizes{userIdx}(:,mod(subframeNo, 10)+1).'; % Get transport block for next subframe trBlkNext(userIdx,1:ncw(userIdx))= trBlkSizes{userIdx}(:,mod(subframeNo+1,10)+1).'; end % Set the flag to trigger subframe processing if isWready && any(trBlk(:)) processSubframe = true; else processSubframe = false; end % Precoding matrix calculation if strcmpi(enb.DuplexMode,'TDD') % Estimate channel in UL subframe if strcmp(subframeType(mod(subframeNo,10)+1),'U') processSubframe = false; % UL subframe, no DL data % Only perform channel estimate if next subframe is DL if strcmp(subframeType(mod((subframeNo+1),10)+1),'D') W = hMultiUserPrecodingMatrix(enb,muPDSCH,muChannel); isWready = true; end end else %FDD % Calculate the precoding matrix for next subframe only if it % carries data (i.e. non-zero trBlkNext) if any(trBlkNext(:)) W = hMultiUserPrecodingMatrix(enb,muPDSCH,muChannel); isWready = true; else isWready = false; end end % Subframe processing if processSubframe % In this example, the variables pdschRho and pdschIndices will % have the same values for all users codedTrBlk = zeros(NUsers,2); for userIdx = 1:NUsers % Update current HARQ process for all users harqProcesses{userIdx}(harqID) = hHARQScheduling( ... harqProcesses{userIdx}(harqID), subframeNo, rvSequence); % Map precoding matrix of all users into PDSCH configuration % cell array muPDSCH{userIdx}.W = W{userIdx}; % PDSCH resource element power allocation in dB pdschRho = muPDSCH{userIdx}.Rho; % Generate indices for mapping of PDSCH symbols on resource % grid [pdschIndices,pdschInfo] = ltePDSCHIndices(enb,... muPDSCH{userIdx},muPDSCH{userIdx}.PRBSet); % Obtain coded transport block size codedTrBlk(userIdx,1:ncw(userIdx)) = pdschInfo.G; end % Generate grid without any PDSCH mapped [~,txGrid,enbOut] = lteRMCDLTool(enb,[]); % Get the HARQ ID sequence from 'enbOut' for HARQ processing harqProcessSequence = enbOut.PDSCH.HARQProcessSequence; % Generate complex-valued modulated symbol for PDSCH in multi-user % MIMO transmission with block-diagonalization precoding pdschSymbols = hMultiUserPDSCH(enb,muPDSCH,codedTrBlk,... harqProcesses,harqID); powerAdjPerRE = 10^(pdschRho/20); % Perform PDSCH symbols mapping on resource grid txGrid(pdschIndices) = pdschSymbols*powerAdjPerRE; % Perform OFDM modulation [waveform,ofdmInfo] = lteOFDMModulate(enb,txGrid); % Add 25 sample padding. This is to cover the range of delays % expected from channel modeling (a combination of % implementation delay and channel delay spread) txWaveform = [waveform; zeros(25,NTxAnts)]; % Calculate noise gain including compensation for downlink % power allocation SNR = 10^((SNRIn(snrIdx)-muPDSCH{userIdx}.Rho)/20); % Normalize noise power to take account of sampling rate, % which is a function of the IFFT size used in OFDM % modulation, and the number of antennas N0 = 1/(sqrt(2.0*NTxAnts*double(ofdmInfo.Nfft))*SNR); % Pass the waveform through noisy fading channels and receiver % operations for each user for userIdx = 1:NUsers % Pass data through channel model rxWaveform = lteFadingChannel(muChannel{userIdx},txWaveform); % Create additive white Gaussian noise noise = N0*complex(randn(size(rxWaveform)), ... randn(size(rxWaveform))); % Add AWGN to the received time domain waveform rxWaveform = rxWaveform + noise; % Receiver % Synchronization offset, OFDM demodulation, % perfect channel estimation, PDSCH and DL-SCH Decoding [harqProcesses{userIdx},dlschSymbols,lastOffset(userIdx)]... = hReceiverOperations(enb,muPDSCH{userIdx},rxWaveform,... muChannel{userIdx},harqProcesses{userIdx},trBlk(userIdx,... 1:ncw(userIdx)),lastOffset(userIdx),harqID,subframeNo,noise); % Store the decoded DLSCH symbols for constellation % plotting rxSymbols{userIdx,1} = [rxSymbols{userIdx,1}; dlschSymbols{1}(:)]; if ncw(userIdx)>1 rxSymbols{userIdx,2} = [rxSymbols{userIdx,2}; dlschSymbols{2}(:)]; end % Store values to calculate throughput % Only for subframes with data if(any(trBlk(userIdx,1:ncw(userIdx))) ~= 0) blkCRC = [blkCRC harqProcesses{userIdx}(harqID).blkerr]; bitTput{userIdx} = [bitTput{userIdx} ... trBlk(userIdx,1:ncw(userIdx)).*(1-harqProcesses{userIdx}(harqID).blkerr)]; txedTrBlkSizes{userIdx} = [txedTrBlkSizes{userIdx} ... trBlk(userIdx,1:ncw(userIdx))]; end end end end % Calculate the maximum and simulated throughput maxTput = zeros(NUsers,1); simTput = zeros(NUsers,1); for userIdx = 1:NUsers maxTput(userIdx) = sum(txedTrBlkSizes{userIdx}); % Max possible throughput simTput(userIdx) = sum(bitTput{userIdx},2); % Simulated throughput % Display the results dynamically in the command window fprintf('\nSNR = %.2f dB. Throughput for UE-%d %d Frame(s) = %.4f Mbps\n',... SNRIn(snrIdx),userIdx,NFrames,1e-6*simTput(userIdx)/(NFrames*10e-3)); fprintf('SNR = %.2f dB. Throughput(%%) for UE-%d %d Frame(s) = %.4f %%\n',... SNRIn(snrIdx),userIdx, NFrames,simTput(userIdx)*100/maxTput(userIdx)); end maxThroughput(snrIdx,:) = maxTput; simThroughput(snrIdx,:) = simTput; rxConstellation(snrIdx,:,:)= rxSymbols; end % Plot received symbol constellation for snrIdx = 1:numel(SNRIn) ii = 1; figure; for userIdx = 1:NUsers subplot(NUsers,max(ncw),ii); plot(rxConstellation{snrIdx,userIdx,1},'.r'); title(['User ' num2str(userIdx) ', Codeword 1, SNR '... num2str(SNRIn(snrIdx)) ' dB']); xlabel('In-Phase'); ylabel('Quadrature'); grid on; if size(rxConstellation{snrIdx,userIdx,2})~=0 ii = ii+1; subplot(NUsers,max(ncw),ii); plot(rxConstellation{snrIdx,userIdx,2},'.r'); title(['User ' num2str(userIdx) ', Codeword 2, SNR '... num2str(SNRIn(snrIdx)) ' dB']); xlabel('In-Phase'); ylabel('Quadrature'); grid on; end ii = ii+1; end end
SNR = 8.00 dB. Throughput for UE-1 2 Frame(s) = 0.0520 Mbps SNR = 8.00 dB. Throughput(%) for UE-1 2 Frame(s) = 26.3158 % SNR = 8.00 dB. Throughput for UE-2 2 Frame(s) = 0.1352 Mbps SNR = 8.00 dB. Throughput(%) for UE-2 2 Frame(s) = 68.4211 % SNR = 14.00 dB. Throughput for UE-1 2 Frame(s) = 0.1456 Mbps SNR = 14.00 dB. Throughput(%) for UE-1 2 Frame(s) = 73.6842 % SNR = 14.00 dB. Throughput for UE-2 2 Frame(s) = 0.1976 Mbps SNR = 14.00 dB. Throughput(%) for UE-2 2 Frame(s) = 100.0000 %
Результаты пропускной способности для всех пользователей отображаются в командном окне MATLAB ® после завершения симуляции для каждой точки ОСШ. Они также захватываются в выходных массивах simThroughput
и maxThroughput
.
legendString = cell(NUsers,1); figure; for userIdx = 1:NUsers plot(SNRIn, simThroughput(:,userIdx)*100./maxThroughput(:,userIdx),'*-.'); hold on; legendString{userIdx} = strcat('UE-' ,num2str(userIdx), ': ', ... num2str(muNumLayers(userIdx)), ' layer(s), ' ,num2str(NTxAnts), ... ' TxAnt(s), ', num2str(muNumRxAnts(userIdx)), ' RxAnt(s)'); end grid on; xlabel('SNR (dB)'); ylabel('Throughput (%)'); legend(legendString,'Location','SouthEast');
Для статистически допустимых результатов симуляция должно выполняться для большего количества систем координат. Рисунок ниже показывает результаты пропускной способности при симуляции 1000 систем координат.
В этом примере используются следующие вспомогательные функции:
Спенсер К., А. Суиндлхерст, М. Хаардт. Методы нулевого форсирования для пространственного мультиплексирования нисходящей линии связи в многопользовательских каналах MIMO. Транзакции IEEE по обработке сигналов, том 52, № 2, февраль 2004 года, стр. 461-471.
Lim C., T. Yoo, B. Clerckx, B. Lee, B. Shim. «Недавний тренд многопользовательского MIMO в LTE-advanced». Журнал IEEE Communications Magazine, март 2013, стр. 127-135.