Search code examples
vhdldecoderviterbi

Viterbi Decoder VHDL project


I'm making a Viterbi Decoder on VHDL and almost everything seems to be working as planned, all of the arrays are filled correctly.

The only problem is that the final step of outputing decoded bits isn't working, variable temp_dec seems to never change its value (right now temp_dec and smallest_metric are signals because I was trying to figure out the values that they are assigned, but they are supposed to be variables).

This is the result of simulation as a screenshot:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;

entity vit_dec is
    port(
        clk : in std_logic;
        enable : in std_logic;
        rst : in std_logic;
        enc_bits : in std_logic_vector(2 downto 0);
        dec_bits : out std_logic
        );
end entity;

architecture rtl of vit_dec is
    type rib is array (1 to 32) of std_logic_vector(2 downto 0);
    type metric is array (1 to 16) of std_logic_vector(6 downto 0);
    type traceback is array (1 to 6) of std_logic_vector(1 to 16);
    
    signal smallest_metric : integer range 0 to 16 := 1;
    signal temp_dec : std_logic_vector(3 downto 0) := "0000";
    
    signal dec_flag : std_logic := '0';
    signal tb_flag : std_logic := '0';
    signal dec_window : std_logic_vector(1 to 6) := (others => '0');
    signal rib_metrics : rib := (others => "000");
    signal path_metric : metric := ("0000000", "0111111", "0111111", "0111111",
                                    "0111111", "0111111", "0111111", "0111111",
                                    "0111111", "0111111", "0111111", "0111111",
                                    "0111111", "0111111", "0111111", "0111111");
                                        
    signal traceback_bits : traceback := (others => "0000000000000000");
    
    begin 
        
    process(clk)
        constant rib_values : rib := ("000", "111", "010", "101", "011", "100", "001" ,"110",
                                      "101", "010", "111", "000", "110", "001", "100", "011",
                                      "111", "000", "101", "010", "100", "011", "110", "001",
                                      "010", "101", "000", "111", "001", "110", "011", "100");
                                      
        variable temp_xor : std_logic_vector(2 downto 0);
        variable ham_dist : std_logic_vector(2 downto 0);
    begin
        
            if rising_edge(clk) and enable = '1' then
                
                for i in 1 to 32 loop
                
                    temp_xor := enc_bits xor rib_values(i);
                    
                    case temp_xor is
                        when "000" => ham_dist := "000";
                        when "001"|"010"|"100" => ham_dist := "001";
                        when "011"|"101"|"110" => ham_dist := "010";
                        when "111" => ham_dist := "011";
                        when others => ham_dist := "111";
                    end case;
                        
                    rib_metrics(i) <= ham_dist;
                    
                end loop;
        
            end if;
        
    end process;
    
    process(clk)
        variable a : unsigned(6 downto 0);
        variable b : unsigned(6 downto 0);
        variable temp_metric : metric := (others => "0000000");
        variable temp_tb : std_logic_vector(1 to 16) := "0000000000000000";
        variable tb_cntr : integer range 0 to 7 := 0;
    begin
    
            if rising_edge(clk) and enable = '1' then
            
                tb_cntr := tb_cntr + 1;
            
                for i in 1 to 8 loop
                
                    a := unsigned(path_metric(2*i-1)) + ("0000" & unsigned(rib_metrics(2*i-1)));
                    b := unsigned(path_metric(2*i)) + ("0000" & unsigned(rib_metrics(2*i)));
                    
                    if a < b then 
                        temp_metric(i) := std_logic_vector(a);
                        temp_tb(i) := '0';
                    elsif a > b then
                        temp_metric(i) := std_logic_vector(b);
                        temp_tb(i) := '1';
                    else
                        temp_metric(i) := std_logic_vector(a);
                        temp_tb(i) := '0';
                    end if;
                    
                end loop;
                
                for i in 1 to 8 loop
                
                    a := unsigned(path_metric(2*i-1)) + unsigned(rib_metrics((2*i-1)+16));
                    b := unsigned(path_metric(2*i)) + unsigned(rib_metrics(2*i+16));
                    
                    if a < b then 
                        temp_metric(i+8) := std_logic_vector(a);
                        temp_tb(i+8) := '0';
                    elsif a > b then
                        temp_metric(i+8) := std_logic_vector(b);
                        temp_tb(i+8) := '1';
                    else
                        temp_metric(i+8) := std_logic_vector(a);
                        temp_tb(i+8) := '0';
                    end if;
                    
                end loop;
                
                traceback_bits(tb_cntr) <= temp_tb;
                
                if tb_cntr = 6 then
                    
                    tb_cntr := 0;
                    tb_flag <= '1'; 
                
                else
                
                    tb_flag <= '0';
                    
                end if;
                
                if tb_flag = '1' then
                
                    dec_flag <= '1';
                    
                else

                    dec_flag <= '0';
                
                end if;
                
                    path_metric <= temp_metric;
                
            end if;
            
    end process;
    
    
    process(clk)
        --variable smallest_metric : integer range 0 to 16 := 1;
        variable temp_dec_window : std_logic_vector(6 downto 1) := "000000";
        variable c : integer range 0 to 450 := 450;
        --variable temp_dec : std_logic_vector(3 downto 0) := "0000";
        variable tb_temp : std_logic_vector(1 to 16) := "0000000000000000";
    begin
    
        if rising_edge(clk) and enable = '1' and tb_flag = '1' then
            
            for i in 1 to 16 loop
            
                if c > to_integer(unsigned(path_metric(i))) then
                
                    smallest_metric <= i;
                    c := to_integer(unsigned(path_metric(i)));
                    
                end if;
                
            end loop;
            
            for i in 6 to 1 loop
            
                temp_dec <= std_logic_vector(to_unsigned(smallest_metric, temp_dec'length));
                temp_dec_window(i) := temp_dec(0);
                tb_temp := traceback_bits(i);
                
                if smallest_metric < 9 then
                    
                    case tb_temp(smallest_metric) is
                        when '0' => smallest_metric <= smallest_metric * 2 - 1;
                        when '1' => smallest_metric <= smallest_metric * 2;
                        when others => report("error");
                    end case;
                    
                else
                    
                    case tb_temp(smallest_metric) is
                        when '0' => smallest_metric <= (smallest_metric - 8) * 2 - 1;
                        when '1' => smallest_metric <= (smallest_metric - 8) * 2;
                        when others => report("error");
                    end case;
                    
                end if;
                    
            end loop;
                    
                dec_window <= temp_dec_window;
    
        end if;
            
    end process;
    
    process(clk)
        variable pntr : integer range 0 to 7 := 0;
    begin
        
        if rising_edge(clk) and enable = '1' and (dec_flag = '1' or pntr > 0) then
        
            pntr := pntr + 1;
            dec_bits <= dec_window(pntr);
            
            if pntr = 6 then
                
                pntr := 0;
                
            end if;
            
        end if; 
            
    end process;    
        
end architecture;

In temp_dec variable I expect smallest_metric value that is converted to std_logic_vector.


Solution

  • for i in 6 to 1 loop
    

    This is a null range, hence the for loop iterates a grand total of 0 times. Given this is the only place temp_dec is assigned a value, it is therefore never assigned a value.

    a range with to is intended to increment over the range with the low number on the left. downto is required if you want to do a descending range.