Hard vs soft decision decoding — bits, metrics, and coding gain

Coding path:
Hamming codes → Hard vs soft decisions → ML decoding



In one sentence: Hard decoding quantizes each channel output to a bit before the decoder; soft decoding feeds real-valued reliabilities — usually worth about 2 dB in AWGN.

What are hard and soft decision decoding

Hard decision decoding and soft decision decoding are two different methods used for decoding error-correcting codes.

With hard decision decoding, the demodulator compares the received sample with a threshold and hands the decoder a bit. Everything between the sample and the threshold is thrown away.

Soft decision decoding keeps the sample, or a reliability number derived from it, and folds that number into the decoding metric. The gain over hard decisions is about 2 dB for common binary codes on AWGN, and it is most useful in the SNR region where the code is actually correcting errors, not at high SNR where both decoders are already clean.

While soft decision decoding can achieve better error correction, it is more complex and computationally expensive than hard decision decoding.

More details

Let’s expatiate on the concepts of hard decision and soft decision decoding. Consider a simple even parity encoder given below.

Input bit 1Input bit 2Even parity bitCodeword
000000
011011
101101
110110
Even-parity codewords for two information bits.

The set of all possible codewords generated by the encoder are 000,011,101 and 110.

Suppose the message bits are 01.

Hard decision decoding

Case 1 : Assume that our communication model consists of a parity encoder, communication channel (attenuates the data randomly) and a hard decision decoder

The message bits “01” are applied to the parity encoder and we get “011” as the output codeword.

Hard decision decoding a simple illustration
Figure 1: Hard decision decoding – a simple illustration

The output codeword “011” is transmitted through the channel. A 0 is sent as 0 V and a 1 is sent as 1 V. The channel attenuates the signal that is being transmitted and the receiver sees a distorted waveform ( “Red color waveform”). The hard decision decoder makes a decision based on the threshold voltage. In our case the threshold voltage is chosen as 0.5 Volt ( midway between “0” and “1” Volt ) . At each sampling instant in the receiver (as shown in the figure above) the hard decision detector determines the state of the bit to be “0” if the voltage level falls below the threshold and “1” if the voltage level is above the threshold. Therefore, the output of the hard decision block is “001”. Perhaps this “001” output is not a valid codeword ( compare this with the all possible codewords given in the table above) , which implies that the message bits cannot be recovered properly. The decoder compares the output of the hard decision block with the all possible codewords and computes the minimum Hamming distance for each case (as illustrated in the table below).

CodewordHard decisionHamming distance
0000011
0110011
1010011
1100013
Three codewords tie at distance 1 from the hard-decision word 001.

The decoder has to pick a valid codeword at the smallest Hamming distance. The minimum distance here is 1, and three codewords share it: 000, 011 and 101. The word that was actually sent is 011, not 001. 001 is only the hard-decision string. A decoder that breaks the tie by choosing one of the three at random recovers the transmitted word one time in three. The even-parity code has no single nearest neighbour in this case, so the hard decisions have not selected a unique codeword.

Soft Decision Decoding

The difference between hard and soft decision decoder is as follows

  • In Hard decision decoding, the received codeword is compared with the all possible codewords and the codeword which gives the minimum Hamming distance is selected
  • In Soft decision decoding, the received codeword is compared with the all possible codewords and the codeword which gives the minimum Euclidean distance is selected. The soft decoder therefore uses the analog samples. On an AWGN channel the maximum-likelihood choice is the codeword closest to the received vector in Euclidean distance, which is equivalent to picking the largest correlation, or to feeding log-likelihood ratios into the decoder

For the same encoder and channel combination lets see the effect of replacing the hard decision block with a soft decision block.

Soft-decision decoding - a simple illustration
Figure 2: Soft-decision decoding – a simple illustration

Voltage levels of the received signal at each sampling instant are shown in the figure. The soft decision block calculates the Euclidean distance between the received signal and the all possible codewords.

CodewordSymbol voltagesSquared Euclidean distance
0000 V, 0 V, 0 V0.69
0110 V, 1 V, 1 V0.49
1011 V, 0 V, 1 V0.89
1101 V, 1 V, 0 V1.49
Squared Euclidean distance from the received samples 0.2 V, 0.4 V and 0.7 V. The nearest codeword is 011.

Log-likelihood ratios

A modern decoder rarely sees the raw voltage. The demodulator passes a log-likelihood ratio. With a 0 sent as 0 V, a 1 sent as 1 V, and Gaussian noise of variance$latex \sigma^2$, equal priors give

\[L(y) = \ln\frac{P(b=0\mid y)}{P(b=1\mid y)} = \frac{1-2y}{2\sigma^2}\]

The sign is the hard decision (positive favours 0) and the magnitude is the confidence. For the usual antipodal mapping, 0 as$latex -1$ and 1 as$latex +1$, the same idea reduces to$latex L(y) = 2y/\sigma^2$. Soft-decision Viterbi uses these values as branch metrics and can still emit a hard bit at the end. The soft-output Viterbi algorithm (SOVA) goes one step further and attaches a reliability to that bit, which is what a later decoder in a concatenated scheme wants. SOVA is not itself the definition of soft-decision decoding.

The distances in the two tables are small enough to recompute directly.

import numpy as np

codewords = np.array([
    [0, 0, 0],
    [0, 1, 1],
    [1, 0, 1],
    [1, 1, 0],
], dtype=float)
hard = np.array([0, 0, 1])
soft = np.array([0.2, 0.4, 0.7])

hamming = np.sum(codewords != hard, axis=1).astype(int)
euclidean = np.sum((codewords - soft) ** 2, axis=1)
print("Hamming  ", hamming.tolist())
print("Euclidean", np.round(euclidean, 2).tolist())
print("Hard-decision tie", codewords[hamming == hamming.min()].astype(int).tolist())
print("Soft-decision pick", codewords[np.argmin(euclidean)].astype(int).tolist())

sigma2 = 0.25
llr = (1.0 - 2.0 * soft) / (2.0 * sigma2)
print("LLR (positive favours 0)", np.round(llr, 3).tolist())

The minimum Euclidean distance is 0.49 corresponding to “0 1 1” codeword (which is what we transmitted). The decoder selects this codeword as the output. Even though the parity encoder cannot correct errors, the soft decision scheme helped in recovering the data in this case. This fact delineates the improvement that will be seen when this soft decision scheme is used in combination with forward error correcting (FEC) schemes like convolutional codes , LDPC etc

From this illustration we can understand that the soft decision decoders use all of the information ( voltage levels in this case) in the process of decision making whereas the hard decision decoders do not fully utilize the information available in the received signal (evident from calculating Hamming distance just by comparing the signal level with the threshold whereby neglecting the actual voltage levels).

Note: This is just to illustrate the concept of Soft decision and Hard decision decoding. Prudent souls will be quick enough to find that the parity code example will fail for other voltage levels (e.g. : 0.2V , 0.4 V and 0.6V) . This is because the parity encoders are not capable of correcting errors but are capable of detecting single bit errors.

On a trellis code the same Euclidean (or correlation) metric is what a soft-decision Viterbi decoder puts on each branch. SOVA, published by Hagenauer and Hoeher in 1989, is the version of that algorithm that also returns a reliability for each decided bit.

For further reading

[1] J. Hagenauer and P. Hoeher, “A Viterbi algorithm with soft-decision outputs and its applications,” IEEE GLOBECOM, pp. 1680–1686, 1989.
[2] S. Lin and D. J. Costello, Error Control Coding, 2nd ed., Pearson, 2004, Chapter 10.

FAQ

What is a soft decision value in a decoder? Instead of passing a hard 0/1 bit, the demodulator passes a real-valued reliability, commonly a log-likelihood ratio (LLR). The sign is the bit guess; the magnitude says how confident the channel observation was.

Why does soft-decision decoding usually gain about 2 dB? Hard decisions throw away amplitude information, so the decoder treats every bit flip as equally likely. Soft metrics let the decoder down-weight unreliable bits and perform closer to true maximum-likelihood sequence detection on the code trellis or graph.

When is hard decision still acceptable? At very high SNR, for extremely simple parity checks, or when implementation cost forbids LLRs. Otherwise, modern links (LTE/NR turbo/LDPC, Wi-Fi LDPC, etc.) expect soft inputs.

19 thoughts on “Hard vs soft decision decoding — bits, metrics, and coding gain”

  1. Hello, Mathuranathan.

    Can I use this term 10^(-Eb_N0_dB(ii)/20)*n, (n = 1/sqrt(2)*[randn(1,N)] for specify AWGN if I use soft decoding algorithm and have 8 levels of quantizer (2.8 V:-0.4 V:-2.8 V)?

    Thanks.

    Reply
      • While I getting BER curve, I noticed that BER=0 for Eb/N0 = 0 dB. I think I get this wrong result because amplitude of noise very small for transmitted signals 0 ->2.8 V and 1 -> -2.8. What can I do to get right result?

        Reply
        • This is just a hint of what you can try. But not the complete solution, since you know your code best.

          1) check for a simple Hard decision decoding.
          2) Simulate for a very high SNR condition (~40 dB) where noise is virtually non-existent. Check the decoded data and source data in the transmitter. They should match exactly. If they are not matching, you have to debug your decoding algorithm or other parts of the code.
          3) If results in step 2 are matching, revert to soft decision decoding and keep the SNR very high. Again, the decoded data and source data should match. If not, debug for the problem in the soft decision decoding algorithm.
          4) Everything goes well and still you are getting erroneous results: Tweak the noise term.

          Reply
          • When I use 10^(-Eb_N0_dB(ii)/20)*n, (n = 1/sqrt(2)*[randn(1,N)]) for specify AWGN, I suppose that energy of bit Eb = 1, don’t i? But I associate 0 (or 1) with 2.8 V (or -2.8 V), maybe error can be in this?

          • I am not sure about whats going on in your code.
            Just as an example, For BPSK, the mapping 0->-1V and 1-> +1V or vice versa, will give proper results when using the above equation.

            If you are using 2.8 voltage range, the noise term has to be scaled properly.

            I have come up with a new method for doing this. This will be documented in detail in third edition of the ebook (work in progress).

            The best way is to measure the energy content of the signal and generate the required noise. This will work for any voltage ranges.

            1) E_meas = 1/N * sum( abs(s)^2 ) ; % measured energy
            2) N_required = E_meas / (Es/N0)_given; %(Es/N0)_given is the given energy per symbol to noise ration (not Eb/N0 given)
            3) sigma = sqrt(N_required/2);
            4) noise = sigma*randn(1,N); %mu=0 and use sigma term above to calculate noise.
            5) y = s+ n ; %add the signal and generated noise

            This method eliminates the need for confusion scaling terms that are difficult to understand.

  2. hello
    I am looking for Matlab code for convolutional coded BPSK over AWGN, with soft decision vetrbi decoding.
    I bought your book but i couldn’t find this code in it.
    could you please help me with it.
    Regards

    Reply
    • The simulation code for the mentioned special topic is not available in the ebook. However, you can combine the code give in “Chapter 6.2 BER vs. Eb/N0 for BPSK modulation over AWGN” with the code given for convolutional coding and trellis decoding given at mathworks documentation -http://www.mathworks.com/help/comm/ug/error-detection-and-correction.html#fp7405

      Thanks for your interest !!!

      Reply
    • you can try this code:
      function [ brr ] = brr(n,k)%nis number of transmeted message and k is the constraint %length of convolutional code
      % Traceback Length
      tblen = 5*k;
      snr=0:5;
      for ii=1:length(snr)
      msg = round(rand(1,n));
      code = convenc(msg,trel);
      code=-2*code+1;
      SNRdBs = snr(ii)+ 10*log(0.5)/log(10);
      N0=10^(-SNRdBs/10);
      ucode=code+sqrt(N0/2)*(randn(1,length(code)));
      ucode=real(ucode);
      dcdsoft = vitdec(ucode,trel,tblen,’cont’,’unquant’);
      diff=msg(1,1:end-tblen)-dcdsoft(1,tblen+1:end);
      %diff=msg-dcdsoft;
      s(ii)=sum(abs(diff))/length(msg)
      end
      semilogy(snr,s,’r’)
      end

      Reply
  3. i’m looking for Matlab code for convolutional coded BPSK over exponential correlated rayleigh channel, with soft decision vetirbi decoding.
    could you please help me.
    best regards

    Reply

Leave a Comment