This is machine translation

Translated by Microsoft


802.11ac Multi-User MIMO Precoding with WINNER II Channel Model

This example shows the transmit and receive processing for a 802.11ac™ multi-user downlink transmission over a WINNER II fading channel. To run this example, you need the WLAN Toolbox™ and the WINNER II Channel Model for Communications Toolbox™. Only one WINNER II channel System object™ is needed to set up the channels from one access point to all users.





The example generates the multi-user transmit waveform, passes it through a multi-user WINNER II channel and decodes the received signal for each user to calculate the bits in error. Prior to the data transmission, the example uses a null-data packet (NDP) transmission to sound the different channel for each user and determines the precoding matrix under the assumption of perfect feedback.

Simulation Parameters and Configuration

For 802.11ac, a maximum of eight spatial streams is allowed. An 8x8 MIMO configuration for three users is used in this example, where the first user has three streams, second has one, and the third has four streams allocated to it. Different rate parameters and payload sizes for each user are specified as vector parameters for the transmission configuration.

s = rng(16);                             % Set RNG seed for repeatability

% Transmission parameters
chanBW      = 'CBW80';                   % Channel bandwidth
numUsers    = 3;                         % Number of users
numSTSVec   = [3 1 4];                   % Number of streams per user
userPos     = [0 1 2];                   % User positions
mcsVec      = [4 6 8];                   % MCS per user: 16QAM, 64QAM, 256QAM
apepVec     = [520 192 856];             % Payload per user, in bytes
chCodingVec = {'BCC', 'LDPC', 'LDPC'};   % Channel coding per user

% Precoding and equalization parameters
snr           = 47;                      % SNR in dB
eqMethod      = 'ZF';                    % Equalization method

% Create the multi-user VHT format configuration object
numTx = sum(numSTSVec);
    'NumUsers', numUsers, ...
    'NumTransmitAntennas', numTx, ...
    'GroupID', 2, ...
    'NumSpaceTimeStreams', numSTSVec,...
    'UserPositions', userPos, ...
    'MCS', mcsVec, ...
    'APEPLength', apepVec, ...
    'ChannelCoding', chCodingVec);


Sounding (NDP) Configuration


    'NumUsers', 1, ...
    'NumTransmitAntennas', numTx, ...
    'GroupID', 0, ...
    'NumSpaceTimeStreams', sum(numSTSVec),...
    'MCS', 0, ...
    'APEPLength', 0);


% Generate the null data packet, with no data
txNDPSig = wlanWaveformGenerator([], cfgVHTNDP);
NPDSigLen = size(txNDPSig, 1);

WINNER II Channel for Indoor Office (A1) Scenario

In this example, one comm.WINNER2Channel System object in the WINNER II Channel Model for Communications Toolbox™ is set up to simulate the three channels to different users. The indoor office (A1) non-line-of-sight (NLOS) scenario is configured for each user. With a fixed power delay profile, each user experiences a 16-path fading channel with the largest delay of 175 us. Each user is also assigned a low mobility as appropriate for 802.11ac.

The access point employs a uniform circular array (UCA) with a radius of 20cm. Each user employs a uniform linear array (ULA) with 5cm spacing between elements. It is also assumed that each user's number of receive antennas is equal to the number of space-time streams allocated to them.

% Set up layout parameters for WINNER II channel
AA = winner2.AntennaArray('UCA', numTx, 0.2);
for i = 1:numUsers
    AA(i+1) = winner2.AntennaArray('ULA', numSTSVec(i), 0.05);
STAIdx   = 2:(numUsers+1);
APIdx   = {1};
rndSeed = 12;
cfgLayout = winner2.layoutparset(STAIdx, APIdx, numUsers, AA, [], rndSeed);
cfgLayout.Pairing = [ones(1,numUsers);2:(numUsers+1)]; % One access point to all users
cfgLayout.ScenarioVector = ones(1,numUsers);           % A1 scenario for all links
cfgLayout.PropagConditionVector = zeros(1, numUsers);  % NLOS
for i = 1:numUsers % Randomly set velocity for each user
    v = rand(3,1) - 0.5;
    cfgLayout.Stations(i+1).Velocity = v/norm(v, 'fro');

% Set up model parameters for WINNER II channel
cfgModel = winner2.wimparset;
cfgModel.FixedPdpUsed       = 'yes';
cfgModel.FixedAnglesUsed    = 'yes';
cfgModel.IntraClusterDsUsed = 'no';
cfgModel.RandomSeed         = 111;    % Repeatability

% The maximum velocity for the 3 users is 1m/s. Set up the SampleDensity
% field to ensure that the sample rate matches the channel bandwidth.
maxMSVelocity = max(cell2mat(cellfun(@(x) norm(x, 'fro'), ...
    {cfgLayout.Stations.Velocity}, 'UniformOutput', false)));
cfgModel.UniformTimeSampling = 'yes';
cfgModel.SampleDensity = round(physconst('LightSpeed')/ ...

% Create the WINNER II channel System object
WINNERChan = comm.WINNER2Channel(cfgModel, cfgLayout);

% Call the info method to check some derived channel parameters
chanInfo = info(WINNERChan) %#ok<NOPTS>
chanInfo = 

  struct with fields:

               NumLinks: 3
          NumBSElements: [8 8 8]
          NumMSElements: [3 1 4]
               NumPaths: [16 16 16]
             SampleRate: [8.0000e+07 8.0000e+07 8.0000e+07]
     ChannelFilterDelay: [7 7 7]
    NumSamplesProcessed: 0

The channel filtering delay for each user is stored to account for its compensation at the receiver. In practice, symbol timing estimation would be used. At transmitter, an extra ten all-zero samples are appended to account for channel filter delay.

chanDelay   = chanInfo.ChannelFilterDelay;
numPadZeros = 10;

% Set ModelConfig.NumTimeSamples to match the length of the input signal to
% avoid warning
WINNERChan.ModelConfig.NumTimeSamples = NPDSigLen + numPadZeros;

% Sound the WINNER II channel for all users
chanOutNDP = WINNERChan([txNDPSig;zeros(numPadZeros,numTx)]);

% Add AWGN
rxNDPSig = cellfun(@awgn, chanOutNDP, ...
    num2cell(snr*ones(numUsers, 1)), 'UniformOutput', false);

Channel State Information Feedback


mat = cell(numUsers,1);
for uIdx = 1:numUsers
    % Compute the feedback matrix based on received signal per user
        cfgVHTNDP, uIdx, numSTSVec);


% Pack the per user CSI into a matrix
%   Nst-by-Nt-by-Nsts
for uIdx = 1:numUsers

% Zero-forcing or MMSE precoding solution
if strcmp(precodingType, 'ZF')
    delta = 0; % Zero-forcing
for i = 1:numST
    % Channel inversion precoding

% Set the spatial mapping based on the steering matrix
cfgVHTMU.SpatialMapping = 'Custom';

Data Transmission


% Create data sequences, one for each user
txDataBits = cell(numUsers, 1);
psduDataBits = cell(numUsers, 1);
for uIdx = 1:numUsers
    % Generate payload for each user

    % Pad payload with zeros to form a PSDU

Using the format configuration, cfgVHTMU, with the steering matrix, to generate the multi-user VHT waveform.

txSig = wlanWaveformGenerator(psduDataBits, cfgVHTMU);

The WINNER II channel object does not allow the input signal size to change once locked, so we have to call the release method before passing the waveform through it. In addition, as we restart the channel, we want it to re-process the NDP before the waveform so as to accurately mimic the channel continuity. Only the waveform portion of the channel's output is extracted for the subsequent processing of each user.


% Set ModelConfig.NumTimeSamples to match the total length of NDP plus
% waveform and padded zeros
WINNERChan.ModelConfig.NumTimeSamples = ...
    WINNERChan.ModelConfig.NumTimeSamples + length(txSig) + numPadZeros;

% Transmit through the WINNER II channel for all users, with 10 all-zero
% samples appended to account for channel filter delay
chanOut = WINNERChan([txNDPSig; zeros(numPadZeros, numTx); ...
	txSig; zeros(numPadZeros, numTx)]);

% Extract the waveform output for each user
chanOut = cellfun(@(x) x(NPDSigLen+numPadZeros+1:end,:), chanOut, 'UniformOutput', false);

% Add AWGN
rxSig = cellfun(@awgn, chanOut, ...

Data Recovery Per User



% Configure recovery object
cfgRec = wlanRecoveryConfig( ...

% Get field indices from configuration, assumed known at receiver
ind = wlanFieldIndices(cfgVHTMU);

% Single-user receivers recover payload bits
rxDataBits = cell(numUsers, 1);
scaler = zeros(numUsers, 1);
spAxes = gobjects(sum(numSTSVec), 1);
for uIdx = 1:numUsers
    rxNSig = rxSig{uIdx}(chanDelay(uIdx)+1:end, :);

    % User space-time streams
    stsU = numSTSVec(uIdx);

    % Estimate noise power in VHT fields
    lltf = rxNSig(ind.LLTF(1):ind.LLTF(2),:);
    demodLLTF = wlanLLTFDemodulate(lltf, chanBW);
    nVar = helperNoiseEstimate(demodLLTF, chanBW, sum(numSTSVec));

    % Perform channel estimation based on VHT-LTF
    demodVHTLTF = wlanVHTLTFDemodulate(rxVHTLTF, chanBW, numSTSVec);
    chanEst = wlanVHTLTFChannelEstimate(demodVHTLTF, chanBW, numSTSVec);

    % Recover information bits in VHT Data field
        chanEst, nVar, cfgVHTMU, uIdx, cfgRec);

    % Plot equalized symbols for all streams per user
    for i = 1:stsU
        axis square
        grid on;

% Scale axes for all subplots and scale figure
for i = 1:numel(spAxes)
pos = get(hfig, 'Position');



% Compare recovered bits against per-user APEPLength information bits
ber = inf(1, numUsers);
for uIdx = 1:numUsers

rng(s); % Restore RNG state
Bit Error Rate for User 1: 0
Bit Error Rate for User 2: 0
Bit Error Rate for User 3: 0.00014603


Conclusion and Further Exploration

The example shows how to use the WINNER II fading channel System object to model a multi-user VHT transmission in 802.11ac. Further exploration includes modifications to the transmission parameters, antenna arrays, channel scenarios, LOS vs. NLOS propagations, path loss modeling and shadowing modeling.

There is another version of this example in the WLAN Toolbox, which uses three independent TGac fading channels for three users: 802.11ac Multi-User MIMO Precoding (WLAN Toolbox).


This example uses the following helper functions from WLAN Toolbox™:

Selected Bibliography




  4. IST WINNER II, "WINNER II Channel Models", D1.1.2, Sep. 2007.
