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
.
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.