# Why is my Hard Decision Decoding of Convolutional codes not performing well?

I am encoding and decoding a randomly generated bitstream of data using a [5 7] convolutional code. For the decoding part I am using a Viterbi Decoder and trying both HDD and SDD. However, my results for HDD seem incorrect as the BER exceeds the theoretical upper bound that I have calculated. I used a bitstream of 100,000 bits. Any help as to why this is happening? I know that SDD is superior to HDD but shouldn't HDD also be below the Upper Bound? Here are the results:

Here is my function for Viterbi Decoding using HDD:

function decodedBits = viterbiDecoderAWGN_HARD(receivedBits, L, k, n, G)
% Viterbi Decoder for a (2,1) convolutional code
% L: Constraint length
% k: Number of input bits (always 1 for a rate 1/2 code)
% n: Number of output bits (always 2 for a rate 1/2 code)
% G: Generator matrix in octal form

% Generate Trellis structure
[nextState, outputTable] = generateTrellis(L, k, n, G);

numStates = 2^(L-1);
numInputs = 2^k; % Always 2 for binary

% Initialize path metrics and survivors
pathMetrics = inf(numStates, numSteps+1);
pathMetrics(1,1) = 0; % Start state assumed to be 0
survivors = zeros(numStates, numSteps);

% Convert BPSK symbols to binary digits for hard decision
hardDecisionBits = receivedBits > 0; % Convert to 0s and 1s based on the threshold

% Viterbi algorithm
for step = 1:numSteps
for currentState = 0:(numStates-1)
for inputBit = 0:(numInputs-1)
next = nextState(currentState+1, inputBit+1);
encodedSymbol = de2bi(outputTable(currentState+1, inputBit+1), n, 'left-msb');

metric = pathMetrics(currentState+1, step) + hammingDistance;
if metric < pathMetrics(next+1, step+1)
pathMetrics(next+1, step+1) = metric;
survivors(next+1, step) = currentState+1; % MATLAB indexing
end
end
end
end

% Traceback
decodedBits = zeros(1, numSteps);
[~, currentState] = min(pathMetrics(:, end)); % Finding the end state with the lowest metric
for step = numSteps:-1:1
decodedBits(step) = find([nextState(survivors(currentState, step),:)+1] == currentState, 1) - 1;
currentState = survivors(currentState, step);
end
end


I am sure that the Trellis is being generated correctly so there is no problem there. Any ideas?

• Where does the upper bound come from? And: your curves seem a bit too wiggly, have you really tried with enough sufficiently random data and sufficiently independently random noise? Commented Mar 22 at 12:28
• It's a union bound. It comes from the transfer function once I sent its derivative with respect to N equal to zero. Yes, at high SNR they do become a bit wiggly but I guess 100k bits should suffice. In terms of randomness I generate 999990 bits randomly and then append 10 zeros for termination. I ran the simulation many times and with different sized input arrays and still the BER for HDD always exceeds the bounds. Commented Mar 22 at 12:34
• I mean, 100k bits when your BER is in the order of 0.5·10⁻⁴ is of course pretty questionable, but point taken, that's not the part of the curve you're worried about. I'm not sure how you calculate the Union Bound – the usual problem with the union bound is that it's an infinite sum, and truncation turns it to be something that isn't quite a bound any more (but I doubt that should be leading what we see here). Commented Mar 22 at 12:43
• @MarcusMüller I used a million bits and got smoother curves albeit after a long time of waiting but thanks for that suggestion. However, the problem with HDD still persists! If you want I can share the calculations for the Upper Bound... Commented Mar 22 at 18:02