How to implement convolutional encoder in VHDL

Why we need an encoder

In the communication link, noise, multipath effects, and other channel impairments can induce errors in the communication link. In this post, we already addressed the topic introducing the Reed-Solomon encoder.

Here we want to explore another encoder widely used in communication links: Convolutional Encoder.

After a brief introduction to the Convolutional encoder, we will focus on what interests us most: the VHDL implementation of a Convolutional Encoder.

Figure 1 – Example of a communication channel

Convolutional Encoder Architecture

When we talk about encoders, we can classify the channel coding in two main categories:

BLOCK CODING:

TRELLIS CODING:

  • Convolutional coding
  • TCM (Trellis Code Modulation)
  • Turbo codes (SCCC or PCCC)
  • Turbo TCM

In this post, we are going to analyze the architecture of the Convolutional Encoder used in DVB-S standard and its implementation in VHDL.

The convolutional encoder is based on a rate 1/2 mother convolutional code with constraint length K = 7 corresponding to 64 trellis states.

The input serial stream is encoded into two branches, X and Y, with the following polynomials:

  • X output (171 octal)
  • Y output (133 octal)

The octal notation 171 (binary 001 111 001) and 133 (binary 001 011 011) define which delay-line taps are XOR-ed for each output branch. The leftmost bit corresponds to the input bit, and the remaining six bits map to the six delay stages r_delay(5) through r_delay(0). A ‘1’ in the polynomial means that tap contributes to the XOR sum.

Figure 2 reports the encoder architecture.

Figure 2 – DVB-S Convolutional Encoder Architecture

Interactive Simulator

Try the interactive convolutional encoder below. Click “Clock” to step through the input sequence and watch the data flow through the shift register.

Convolutional Encoder DVB-S — rate 1/2, K=7
- i_data 0 r_delay(5) 0 r_delay(4) 0 r_delay(3) 0 r_delay(2) 0 r_delay(1) 0 r_delay(0) shift direction Branch X (171 octal) taps: r5, r4, r3, r0 ⊕ ⊕ ⊕ ⊕ 0 o_data_out_x Branch Y (133 octal) taps: r4, r2, r1, r0 ⊕ ⊕ ⊕ ⊕ 0 o_data_out_y
Clock: 0 | i_data: - | r_delay: 000000 | X: 0 | Y: 0
Clock i_data r_delay(5..0) X Y

VHDL implementation of Convolutional Encoder

Figure 2 shows the classical architecture of a convolutional encoder.

The VHDL implementation is straightforward. Just implement the delay line and the two branches with XOR as shown below.

library ieee;
use ieee.std_logic_1164.all;


entity conv_encoder is
port (
  i_clk                                   : in  std_logic;
  i_rstb                                  : in  std_logic;
  i_sync_reset                            : in  std_logic;
  i_data_enable                           : in  std_logic;
  i_data                                  : in  std_logic;
  o_data_valid                            : out std_logic;
  o_data_out_x                            : out std_logic;
  o_data_out_y                            : out std_logic);
end conv_encoder;

architecture rtl of conv_encoder is

constant C_XPOLY              : std_logic_vector(5 downto 0) := ("111001");  -- 1 71 oct, first '1' is not computed since is the input
constant C_YPOLY              : std_logic_vector(5 downto 0) := ("011011");  -- 1 33 oct, first '1' is not computed since is the input

signal r_delay                : std_logic_vector(5 downto 0);

begin

p_encoder : process(i_clk,i_rstb)
variable v_x            : std_logic;
variable v_y            : std_logic;
begin
  if(i_rstb='0') then
    o_data_valid     <= '0';
    o_data_out_x     <= '0';
    o_data_out_y     <= '0';
    r_delay          <= (others=>'0');
  elsif(rising_edge(i_clk)) then
    o_data_valid     <= i_data_enable;
    if(i_sync_reset='1') then
      r_delay      <= (others=>'0');
    elsif(i_data_enable='1') then
      r_delay          <= i_data&r_delay(r_delay'length-1 downto 1);
    end if;
    v_x   := i_data;
    v_y   := i_data;
    for i in r_delay'length-1 downto 0 loop
      if(C_XPOLY(i)='1') then
        v_x   := v_x xor r_delay(i);
      end if;
      if(C_YPOLY(i)='1') then
        v_y   := v_y xor r_delay(i);
      end if;
    end loop;
    o_data_out_x     <= v_x;
    o_data_out_y     <= v_y;
  end if;
end process p_encoder;

end rtl;

VHDL Simulation of Convolutional Encoder

In order to verify the VHDL implementation of the convolutional encoder, the best thing is to simulate the VHDL code and compare the encoder output with a reference pattern.

What is the best way to generate a reference I/O pattern?

Matlab or Octave allow us to generate a reference pattern for the convolutional encoder.

Below is an example of the Matlab/Octave commands used to generate the reference matching vector:

clear all;
clc;

NumBit = 1000;

trellis = poly2trellis(7,[171 133]);

dataIn = randi([0 1],NumBit,1);

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


fid = fopen("ConvEnc.txt",'wt');
for i = 1 : NumBit
  fprintf(fid,'%4d%4d%4d \n',dataIn(i), dataEnc(2*i-1), dataEnc(2*i));
end;

fclose(fid)

Figure 3 – ModelSim simulation of Convolutional Encoder VHDL code

In Figure 3, the yellow “error_flag” signal is used to simplify the matching between the output of the Convolutional Encoder VHDL module and the reference Matlab test vector.

The input and output data of the convolutional encoder are read from the reference file and run-time verified during the VHDL simulation.

Layout of Convolutional Encoder

Figure 4 reports the RTL view of the VHDL code presented above.

The figure highlights the XOR function for the X and Y branches. The RTL view confirms that the delay line is implemented as a chain of six flip-flops, with the X and Y branches computed by two separate XOR trees that combine the selected taps according to the generator polynomials.

Figure 4 – RTL view of Convolutional Encoder VHDL code


How to implement convolutional encoder in VHDL

Get the complete VHDL code from this article.


Conclusion

In this post, we have presented the general architecture of a convolutional encoder. A VHDL example has been tailored to this architecture.

The Matlab/Octave script provided can be used to generate reference vectors for VHDL matching.


References

[1] https://www.intel.com/content/www/us/en/products/programmable.html

[2] https://www.mathworks.com/

[3] https://www.scilab.org

[4] https://www.gnu.org/software/octave/

[5] https://en.wikipedia.org/wiki/Convolutional_code

[6] “Channel coding: Convolutional codes” Vahid Meghdadi, University of Limoges

[7] Digital Video Broadcasting (DVB); Framing structure, channel coding and modulation for 11/12 GHz satellite services EN 300 421 V1.1.2