I am trying to implement convolutional codes according to this MathWorks example in MatLab 2014a.

clear; close all; clc
rng default
M = 4;                 % Modulation order
k = log2(M);            % Bits per symbol
EbNoVec = (0:20)';       % Eb/No values (dB)
numSymPerFrame = 100000;   % Number of QAM symbols per frame

modul = comm.RectangularQAMModulator(M, 'BitInput', true);
berEstSoft = zeros(size(EbNoVec)); 

trellis = poly2trellis(7,[171 133]);
tbl = 32;
rate = 1/2;

decoders = comm.ViterbiDecoder(trellis,'TracebackDepth',tbl,...

for n = 1:length(EbNoVec)
    % Convert Eb/No to SNR
    snrdB = EbNoVec(n) + 10*log10(k*rate);
    % Noise variance calculation for unity average signal power.
    noiseVar = 10.^(-snrdB/10);
    % Reset the error and bit counters
    [numErrsSoft, numErrsHard, numBits] = deal(0);

    while numErrsSoft < 100 && numBits < 1e7
        % Generate binary data and convert to symbols
        dataIn = randi([0 1], numSymPerFrame*k, 1);

        % Convolutionally encode the data
        dataEnc = convenc(dataIn, trellis);

        % QAM modulate
        txSig = step(modul, dataEnc);

        % Pass through AWGN channel
        rxSig = awgn(txSig, snrdB, 'measured');

        % Demodulate the noisy signal using hard decision (bit) and
        % soft decision (approximate LLR) approaches.       
        demods = comm.RectangularQAMDemodulator(M, 'BitOutput', true, ...
        'DecisionMethod', 'Approximate log-likelihood ratio',...
        'VarianceSource', 'Property', 'Variance', noiseVar);
        rxDataSoft = step(demods, rxSig);

        % Viterbi decode the demodulated data
        dataSoft = step(decoders, rxDataSoft);

        % Calculate the number of bit errors in the frame. Adjust for the
        % decoding delay, which is equal to the traceback depth.
        numErrsInFrameSoft = biterr(dataIn(1:end-tbl), dataSoft(tbl+1:end));

        % Increment the error and bit counters
        numErrsSoft = numErrsSoft + numErrsInFrameSoft;
        numBits = numBits + numSymPerFrame*k;


    % Estimate the BER for both methods
    berEstSoft(n) = numErrsSoft/numBits;

semilogy(EbNoVec, berEstSoft,'-o','LineWidth', 1.5)
hold on
xlabel('Eb/No (dB)')
ylabel('Bit Error Rate')

And I am confused about the obtained curve:

enter image description here

Why does not the BER curve decrease exponentially after the 5dB? Have anybody faced this issue before?

  • $\begingroup$ Error floors are not uncommon for iterative ECC's: en.wikipedia.org/wiki/Error_floor $\endgroup$ – Florian Jul 17 '19 at 8:24
  • $\begingroup$ @Florian I believe this is not iterative ecc. $\endgroup$ – AlexTP Jul 17 '19 at 9:10
  • $\begingroup$ @vovenur try increasing numBits to a greater value, 1e9 for example. $\endgroup$ – AlexTP Jul 17 '19 at 9:11
  • $\begingroup$ the term 1e7 is keeping the BER curve from decreasing below $10^{-7}$. Change it to 1e8 or 1e9 and you will see a different curve. $\endgroup$ – Ahmad Bazzi Jul 18 '19 at 7:35
  • $\begingroup$ @AhmadBazzi there is a chance that the BER curve drop below $10^{-7}$ with numBits < 1e7. I think the fair explaination is what MarcusMuller has shown in his answer: numBits < 1e7 makes simulated BER values around $10^{-7}$ unreliable. $\endgroup$ – AlexTP Jul 19 '19 at 9:15
while numErrsSoft < 100 && numBits < 1e7

Nope, you can't stop after 10⁷ bits if you're after error rates < 10⁻⁶. That means you expect to see less than 10 bit errors. That's not a sufficient statistic!

So, this is where I know your curve becomes unreliable, anyway.

You might still be running into some error flow due to the implementation, but I can't look inside Matlab's implementation of neither the QAM decision nor its Viterbi, so these are "meh" at best for scientific considerations about the nature of Viterbi.


It's an old topic but could help others.

I see two possible issues:

  • A wrong scaling on the Viterbi decoder inputs:

    1. Try to force using hard decision bit input to check that BER error floor is not there anymore. Note that Hard decision downgrades BER performance by around 3 dB.
    2. Work/Understand Soft decision normalization in your chain. It can be a scale factor or representation issue.
  • Viterbi trellis initialization state: There might be some errors on the first bits going out from the decoder due to the initialization of the trellis. You could check if the errors are just at the beginning or spread randomly on the output

Still, it is recommended to reach 100 errors to have a reliable BER measure. Thus, for a 10-7, you should simulate 100*10-7 bits transmitted


I agree with Marcus Müller. In Monte Carlo simulations, due to the limited amount of trials, after a point, you come up with an error floor. To overcome this, the only way is to increase the number of trials (in other words, numbers of iterations).


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.