Main Content

Equalize OFDM Data Using Channel Estimates

This example shows how to use the OFDM Equalizer block to equalize data subcarriers using channel estimates. In this example, the model uses the first frame to estimate the channel, stores the estimates, and equalizes the remaining frames using the stored channel estimates. The HDL Algorithm subsystem in this example supports HDL code generation.

Set Input Data Parameters

Set up workspace variables for the model to use. You can modify these values according to your requirements.

rng('default');
numFrames = 6;                                      % Number of frames
numOFDMSymPerFrame = 140;                           % Number of OFDM symbols per frame
maxLenChEstiPerSym = 14400;                         % Maximum length of channel estimates per symbol
numSubCarPerSym = 72;                               % Number of subcarriers per OFDM symbol
hEstLen = numSubCarPerSym * numOFDMSymPerFrame;     % Channel estimate length
totNumOFDMSymbols = numFrames * numOFDMSymPerFrame; % Total number of OFDM symbols

Generate Sinusoidal Input Data Subcarriers

Use the hEstLen and numOFDMSym variables to generate complex sinusoidal input data subcarriers with their real and imaginary parts generated separately. Plot the input as a real part and an imaginary part using separate plots.

dataInGrid = zeros(numSubCarPerSym,totNumOFDMSymbols);
for subCarCount = 0:numSubCarPerSym-1
    for numOFDMSymCount = 0:totNumOFDMSymbols-1
        realXgain = 1 + .2*sin(2*pi*subCarCount/numSubCarPerSym);
        realYgain = 1 + .5*sin(2*pi*numOFDMSymCount/numOFDMSymPerFrame);
        imagXgain = 1 + .3*sin(2*pi*subCarCount/numSubCarPerSym);
        imagYgain = 1 + .4*sin(2*pi*numOFDMSymCount/numOFDMSymPerFrame);
        dataInGrid(subCarCount+1,numOFDMSymCount+1) = realXgain*realYgain + 1i*(imagXgain*imagYgain);
    end
end
validIn = true(1,length(dataInGrid(:)));

% Normalize data subcarriers to make signal power unity
dataInGrid = dataInGrid./sqrt(mean(abs(dataInGrid).^2,'all'));

figure(1);
surf(real(dataInGrid))
xlabel('OFDM Symbols')
ylabel('Subcarriers')
zlabel('Magnitude')
title('Input Data Grid (Real Part)')

figure(2);
surf(imag(dataInGrid))
xlabel('OFDM Symbols')
ylabel('Subcarriers')
zlabel('Magnitude')
title('Input Data Grid (Imaginary Part)')

Generate Channel Estimates using MATLAB® Function

Generate the reference data subcarriers using the variables numOFDMSymToBeAvg, interpolFac, and numScPerSym. Use the channelEstReferenceForEqualizer function to generate the channel estimates hEstIn.

numOFDMSymToBeAvg = 1;                                            % Number of OFDM symbols to be averaged
interpolFac = 1;                                                  % Interpolation factor
dataInForChannelEsti = dataInGrid(:,1:numOFDMSymPerFrame);
validInForChanEsti = validIn(1:numSubCarPerSym*numOFDMSymPerFrame);

numScPerSymIn = numSubCarPerSym*true(1,length(dataInForChannelEsti(:)));

refDataIn = randsrc(size(dataInForChannelEsti(:),1),size(dataInForChannelEsti(:),2),[1 1]);
refValidIn = boolean(zeros(1,numOFDMSymPerFrame*numSubCarPerSym));
startRefValidIndex = randi(interpolFac,1,1);
for numOFDMSymCount = 1:numOFDMSymPerFrame
    refValidIn(startRefValidIndex+(numOFDMSymCount-1)*numSubCarPerSym:interpolFac:numSubCarPerSym*numOFDMSymCount) = true;
end

dataOut1 = channelEstReferenceForEqualizer( ...
    numOFDMSymToBeAvg,interpolFac,numSubCarPerSym,numOFDMSymPerFrame, ...
    dataInForChannelEsti(:),validInForChanEsti,refDataIn,refValidIn,numScPerSymIn);
matlabOut = dataOut1(:);
hEstIn = zeros(numel(matlabOut)*numSubCarPerSym*numOFDMSymToBeAvg,1);
for ii= 1:numel(matlabOut)
    loadArray = [matlabOut(ii).dataOut; repmat(matlabOut(ii).dataOut,[numOFDMSymToBeAvg-1 1]); zeros((length(hEstIn)-numSubCarPerSym*numOFDMSymToBeAvg),1)];
    shiftArray = circshift(loadArray,(ii-1)*numSubCarPerSym*numOFDMSymToBeAvg);
    hEstIn =  hEstIn + shiftArray;
end

% Repeat hEstIn for dataIn generation
hEstInForDataIn = repmat(hEstIn,numFrames,1);

% Normalize channel estimates to make signal power unity
hEstIn = hEstIn./sqrt(mean(abs(hEstIn).^2,'all'));
hEstIn = [hEstIn; hEstIn(end)*ones((hEstLen*((totNumOFDMSymbols/numOFDMSymPerFrame)-1)),1)];

% Generate noise samples
n = (1/sqrt(2))*(randn(length(dataInGrid(:)),1)+1i*randn(length(dataInGrid(:)),1)); % white gaussian noise, variance=1, mean=0;

SNR = 40;
% Calculate noise variance
nVar = (10^(-SNR/10));
noiseVarIn = (10^(-SNR/10))*ones(1,length(dataInGrid(:)));

modelname = 'genhdlOFDMEqualizerModel';
open_system(modelname);

EqMdUsed = get_param('genhdlOFDMEqualizerModel/HDL Algorithm/OFDM Equalizer','EqualizationMethod');
if strcmp(EqMdUsed,'ZF')
    % ZF equalization
    dataIn = hEstInForDataIn.*dataInGrid(:);
else
    % MMSE equalization
    dataIn = hEstInForDataIn.*dataInGrid(:) + (n.*(sqrt(nVar)))./(sqrt(var(n)));
end
% Generate signal with channel estimate length per symbol
hEstLenIn = hEstLen*true(1,length(dataInGrid(:)));
loadhEst = logical([1 zeros(1,length(dataInGrid(:))-1)]);
resetSig = false(1,length(dataInGrid(:)));

Run Simulink® Model

Running the model imports the input signal variables from the MATLAB workspace to the OFDM Equalizer block in the model.

out = sim(modelname);

Export Stream of Equalized Data from Simulink to MATLAB Workspace

Export the output of the OFDM Equalizer block to the MATLAB workspace. Plot the real part and imaginary part of the exported block output.

simOut = out.dataOut.Data(out.validOut.Data);
N = length(simOut)-mod(length(simOut),numSubCarPerSym);
temp = simOut(1:N);
EqualizerSimOut = reshape(temp,numSubCarPerSym,length(temp)/numSubCarPerSym);

figure(3);
surf(real(EqualizerSimOut))
xlabel('OFDM Symbols')
ylabel('Subcarriers')
zlabel('Magnitude')
title('OFDM Equalizer Output (Real Part)')

figure(4);
surf(imag(EqualizerSimOut))
xlabel('OFDM Symbols')
ylabel('Subcarriers')
zlabel('Magnitude')
title('OFDM Equalizer Output (Imaginary Part)')

Perform Equalization Using MATLAB

Equalize the channel with equalization equations by using MATLAB.

if strcmp(EqMdUsed, 'ZF')
    % ZF equalization
    matOut = dataIn./hEstInForDataIn;
else
    % MMSE equalization
    matOut = (1./(conj(hEstInForDataIn).*hEstInForDataIn+nVar)).*(conj(hEstInForDataIn)).*dataIn;
end

Compare Simulink Block Output with MATLAB Output

Compare the OFDM Equalizer block output with the MATLAB output. Plot the output comparison as a real part and an imaginary part using separate plots.

figure('units','normalized','outerposition',[0 0 1 1])
subplot(2,1,1)
plot(real(matOut(:)));
hold on;
plot(real(simOut(:)));
grid on
legend('MATLAB reference output','Simulink block output')
xlabel('Sample Index')
ylabel('Magnitude')
title('Comparison of Simulink Block and MATLAB Function (Real Part)')

subplot(2,1,2)
plot(imag(matOut(:)));
hold on;
plot(imag(simOut(:)));
grid on
legend('MATLAB reference output','Simulink block output')
xlabel('Sample Index')
ylabel('Magnitude')
title('Comparison of Simulink Block and MATLAB Function (Imaginary Part)')

sqnrRealdB = 10*log10(double(var(real(simOut(:)))/abs(var(real(simOut(:)))-var(real(matOut(:))))));
sqnrImagdB = 10*log10(double(var(imag(simOut(:)))/abs(var(imag(simOut(:)))-var(imag(matOut(:))))));

fprintf('\n OFDM Equalizer \n SQNR of real part: %.2f dB',sqnrRealdB);
fprintf('\n SQNR of imaginary part: %.2f dB\n',sqnrImagdB);
 OFDM Equalizer 
 SQNR of real part: 36.56 dB
 SQNR of imaginary part: 42.16 dB

See Also

Blocks

Functions