Main Content

Hard- vs. Soft-Decision Demodulation Examples

Log-Likelihood Ratio (LLR) Demodulation

This example shows the BER performance improvement for QPSK modulation when using log-likelihood ratio (LLR) instead of hard-decision demodulation in a convolutionally coded communication link. With LLR demodulation, one can use the Viterbi decoder either in the unquantized decoding mode or the soft-decision decoding mode. Unquantized decoding, where the decoder inputs are real values, though better in terms of BER, is not practically viable. In the more practical soft-decision decoding, you quantize the demodulator output before sending it to the decoder. It is generally observed that soft-decision decoding does not incur a significant cost in BER while significantly reducing the decoder complexity. This example validates the BER performance through simulation.

For a Simulink™ version of this example, see LLR vs. Hard Decision Demodulation in Simulink.


Initialize simulation parameters.

M = 4;               % Modulation order
bitsPerIter = 1.2e4; % Number of bits to simulate
EbNo = 3;            % Information bit Eb/No in dB

Initialize coding properties for a rate 1/2, constraint length 7 code.

codeRate = 1/2;          % Code rate of convolutional encoder
constLen = 7;            % Constraint length of encoder
codeGenPoly = [171 133]; % Code generator polynomial of encoder
tblen = 32;              % Traceback depth of Viterbi decoder
trellis = poly2trellis(constLen,codeGenPoly);

Create a comm.ConvolutionalEncoder System object™ by using trellis as an input.

enc = comm.ConvolutionalEncoder(trellis);


The signal going into the AWGN channel is the modulated encoded signal. To achieve the required noise level, adjust the Eb/No for coded bits and multi-bit symbols. Calculate the SNR value based on the Eb/No value you want to simulate.

SNR = convertSNR(EbNo,"ebno","BitsPerSymbol",log2(M),"CodingRate",codeRate);

Viterbi Decoding

Create comm.ViterbiDecoder objects to act as the hard-decision, unquantized, and soft-decision decoders. For all three decoders, set the traceback depth to tblen.

decHard = comm.ViterbiDecoder(trellis,'InputFormat','Hard', ...

decUnquant = comm.ViterbiDecoder(trellis,'InputFormat','Unquantized', ...

decSoft = comm.ViterbiDecoder(trellis,'InputFormat','Soft', ...

Calculating the Error Rate

Create comm.ErrorRate objects to compare the decoded bits to the original transmitted bits. The Viterbi decoder creates a delay in the decoded bit stream output equal to the traceback length. To account for this delay, set the ReceiveDelay property of the comm.ErrorRate objects to tblen.

errHard = comm.ErrorRate('ReceiveDelay',tblen);
errUnquant = comm.ErrorRate('ReceiveDelay',tblen);
errSoft = comm.ErrorRate('ReceiveDelay',tblen);

System Simulation

Generate bitsPerIter message bits. Then convolutionally encode and modulate the data.

txData = randi([0 1],bitsPerIter,1); 
encData = enc(txData);
modData = pskmod(encData,M,pi/4,InputType="bit");

Pass the modulated signal through an AWGN channel.

[rxSig,nVar] = awgn(modData,SNR);

Before using a comm.ViterbiDecoder object in the soft-decision mode, the output of the demodulator needs to be quantized. This example uses a comm.ViterbiDecoder object with a SoftInputWordLength of 3. This value is a good compromise between short word lengths and a small BER penalty. Define partition points for 3-bit quantization.

demodLLR.Variance = nVar;
partitionPoints = (-1.5:0.5:1.5)/nVar;

Demodulate the received signal and output hard-decision bits.

hardData = pskdemod(rxSig,M,pi/4,OutputType="bit");

Demodulate the received signal and output LLR values.

LLRData = pskdemod(rxSig,M,pi/4,OutputType="llr",NoiseVariance=nVar);

Hard-decision decoding

Pass the demodulated data through the Viterbi decoder. Compute the error statistics.

rxDataHard = decHard(hardData);
berHard = errHard(txData,rxDataHard);

Unquantized decoding

Pass the demodulated data through the Viterbi decoder. Compute the error statistics.

rxDataUnquant = decUnquant(LLRData);
berUnquant = errUnquant(txData,rxDataUnquant);

Soft-decision decoding

Pass the demodulated data to the quantiz function. This data must be multiplied by -1 before being passed to the quantizer, because, in soft-decision mode, the Viterbi decoder assumes that positive numbers correspond to 1s and negative numbers to 0s. Pass the quantizer output to the Viterbi decoder. Compute the error statistics.

quantizedValue = quantiz(-LLRData,partitionPoints);
rxDataSoft = decSoft(double(quantizedValue));
berSoft = errSoft(txData,rxDataSoft);

Running Simulation Example

Simulate the previously described communications system over a range of Eb/No values by executing the simulation file simLLRvsHD. It plots BER results as they are generated. BER results for hard-decision demodulation and LLR demodulation with unquantized and soft-decision decoding are plotted in red, blue, and black, respectively. A comparison of simulation results with theoretical results is also shown. Observe that the BER is only slightly degraded by using soft-decision decoding instead of unquantized decoding. The gap between the BER curves for soft-decision decoding and the theoretical bound can be narrowed by increasing the number of quantizer levels.

This example may take some time to compute BER results. If you have the Parallel Computing Toolbox™ (PCT) installed, you can set usePCT to true to run the simulation in parallel. In this case, the file LLRvsHDwithPCT is run.

To obtain results over a larger range of Eb/No values, modify the appropriate supporting files. Note that you can obtain more statistically reliable results by collecting more errors.

usePCT = false;
if usePCT && license('checkout','Distrib_Computing_Toolbox') ...
        && ~isempty(ver('parallel'))


The following functions are used in this example:

LLR vs. Hard Decision Demodulation in Simulink

This model shows the improvement in BER performance when using log-likelihood ratio (LLR) instead of hard decision demodulation in a convolutionally coded communication link.

For a MATLAB® version of this example, see Log-Likelihood Ratio (LLR) Demodulation.

System Setup

This example model simulates a convolutionally coded communication system having one transmitter, an AWGN channel and three receivers. The convolutional encoder has a code rate of 1/2. The system employs a 16-QAM modulation. The modulated signal passes through an additive white Gaussian noise channel. The top receiver performs hard decision demodulation in conjunction with a Viterbi decoder that is set up to perform hard decision decoding. The second receiver has the demodulator configured to compute log-likelihood ratios (LLRs) that are then quantized using a 3-bit quantizer. It is well known that the quantization levels are dependent on noise variance for optimum performance [2]. The exact boundaries of the quantizer are empirically determined here. A Viterbi decoder that is set up for soft decision decoding processes these quantized values. The LLR values computed by the demodulator are multiplied by -1 to map them to the right quantizer index for use with Viterbi Decoder. To compute the LLR, the demodulator must be given the variance of noise as seen at its input. The third receiver includes a demodulator that computes LLRs which are processed by a Viterbi decoder that is set up in unquantized mode. The BER performance of each receiver is computed and displayed.

modelName = 'commLLRvsHD';

System Simulation and Visualization

Simulate this system over a range of information bit Eb/No values. Adjust these Eb/No values for coded bits and multi-bit symbols to get noise variance values required for the AWGN block and Rectangular QAM Baseband Demodulator block. Collect BER results for each Eb/No value and visualize the results.

EbNo     = 2:0.5:8; % information rate Eb/No in dB
codeRate = 1/2;     % code rate of convolutional encoder
nBits    = 4;       % number of bits in a 16-QAM symbol
Pavg     = 10;      % average signal power of a 16-QAM modulated signal
snr      = EbNo - 10*log10(1/codeRate) + 10*log10(nBits); % SNR in dB
noiseVarVector = Pavg ./ (10.^(snr./10)); % noise variance

% Initialize variables for storing the BER results
ber_HD  = zeros(1,length(EbNo));
ber_SD  = zeros(1,length(EbNo));
ber_LLR = zeros(1, length(EbNo));

% Loop over all noiseVarVector values
for idx=1:length(noiseVarVector)
    noiseVar = noiseVarVector(idx); %#ok<NASGU>
    % Collect BER results
    ber_HD(idx)  = BER_HD(1);
    ber_SD(idx)  = BER_SD(1);
    ber_LLR(idx) = BER_LLR(1);

% Perform curve fitting and plot the results
fitBER_HD  = real(berfit(EbNo,ber_HD));
fitBER_SD  = real(berfit(EbNo,ber_SD));
fitBER_LLR = real(berfit(EbNo,ber_LLR));
semilogy(EbNo,ber_HD,'r*', ...
    EbNo,ber_SD,'g*', ...
    EbNo,ber_LLR,'b*', ...
    EbNo,fitBER_HD,'r', ...
    EbNo,fitBER_SD,'g', ...
legend('Hard Decision Decoding', ...
    'Soft Decision Decoding','Unquantized Decoding');
xlabel('Eb/No (dB)');
title('LLR vs. Hard Decision Demodulation with Viterbi Decoding');
grid on;

To experiment with this system further, try different modulation types. This system uses a binary mapped modulation scheme for faster error collection but it is well known that Gray mapped signal constellation provides better BER performance. Experiment with various constellation ordering options in the modulator and demodulator blocks. Configure the demodulator block to compute approximate LLR to see the difference in the BER performance compared to hard decision demodulation and LLR. Try out a different range of Eb/No values. Finally, investigate different quantizer boundaries for your modulation scheme and Eb/No values.

Using Dataflow in Simulink

You can configure this example to use data-driven execution by setting the Domain parameter to dataflow for Dataflow Subsystem. With dataflow, blocks inside the domain, execute based on the availability of data as rather than the sample timing in Simulink®. Simulink automatically partitions the system into concurrent threads. This autopartitioning accelerates simulation and increases data throughput. To learn more about dataflow and how to run this example using multiple threads, see Multicore Simulation of Comparing Demodulation Types.

% Cleanup
clear modelName EbNo codeRate nBits Pavg snr noiseVarVector ...
    ber_HD ber_SD ber_LLR idx noiseVar fitBER_HD fitBER_SD fitBER_LLR;

Selected Bibliography

[1] J. L. Massey, "Coding and Modulation in Digital Communications", Proc. Int. Zurich Seminar on Digital Communications, 1974

[2] J. A. Heller, I. M. Jacobs, "Viterbi Decoding for Satellite and Space Communication", IEEE® Trans. Comm. Tech. vol COM-19, October 1971

Related Topics