I am starting with VHDL and have some troubles.
I tried to implement the double dabble algorithm to convert an input binarystring to bcd code.
For this I have implemented it like in the wiki or in other references. However, I have the problem that
bcdVec(3 downto 0) <= std_ulogic_vector(unsigned(bcdVec(3 downto 0)) + unsigned(three));
does not have any effect (three = std_ulogic_vector(3 downto 0) := "0011"). I have tested it with a report statement before and after the calculation but it gives the same result.
at 210 ns(1): Note: 7 (/bcd_conversion_tb/uut/).
at 210 ns(1): Note: 7 (/bcd_conversion_tb/uut/).
Maybe someone has a nice hint for me, thanks!
If it helps here is the whole code of the process:
BCDProc: process(Reset, CLK_50M) is
begin
if(Reset = ResetLevel) then
working <= '0';
i <= 0;
ready <= '1';
busy <= '0';
bcdVec <= (others => '0');
binVec <= binaryvec;
hundrets_BCD <= (others => '0');
tens_BCD <= (others => '0');
ones_BCD <= (others => '0');
elsif (CLK_50M'event AND CLK_50M = '1') then
if(start = '1') then
working <= '1';
ready <= '0';
end if;
if(i = 7) then
-- split vector to matching BCD values
ones_BCD <= std_ulogic_vector(bcdVec(3 downto 0));
tens_BCD <= std_ulogic_vector(bcdVec(7 downto 4));
hundrets_BCD <= std_ulogic_vector(bcdVec(11 downto 8));
i <= 0;
tmp <= 0;
ready <= '1';
busy <= '0';
working <= '0';
end if;
if (i < 8 AND working = '1') then
busy <= '1';
--check if bcd value is >4, if so then add 3
if(i < 8 AND bcdVec (3 downto 0) > "0100") then
report tmp'image(to_integer(unsigned(bcdVec(3 downto 0))));
bcdVec(3 downto 0) <= std_ulogic_vector(unsigned(bcdVec(3 downto 0)) + unsigned(three));
report tmp'image(to_integer(unsigned(bcdVec(3 downto 0))));
end if;
if(i < 8 AND bcdVec (7 downto 4) > "0100") then
tmp <= to_integer(unsigned(bcdVec(7 downto 4)));
tmp <= tmp + 3;
bcdVec(7 downto 4) <= std_ulogic_vector(to_unsigned(tmp, 4));
end if;
if(i < 8 AND bcdVec (11 downto 8) > "0100") then
tmp <= to_integer(unsigned(bcdVec(11 downto 8)));
tmp <= tmp + 3;
bcdVec(11 downto 8) <= std_ulogic_vector(to_unsigned(tmp, 4));
end if;
--perform the shiftoperations
bcdVec(11 downto 0) <= bcdVec (10 downto 0) & binVec(7);
binVec(7 downto 0) <= binVec(6 downto 0) & '0';
--increment countervariable
i <= i+1;
end if;
end if;
end process BCDProc;
Signal assignments never update until a process suspends. This process only suspends at its sensitivity list. Hence your following snapshot of tmp will not add 3 to bcdVec, but instead will add 3 to the value tmp was on the last execution of the process - ie: the previous rising edge of CLK_50M.
if(i < 8 AND bcdVec (11 downto 8) > "0100") then
tmp <= to_integer(unsigned(bcdVec(11 downto 8)));
tmp <= tmp + 3;
bcdVec(11 downto 8) <= std_ulogic_vector(to_unsigned(tmp, 4));
end if;
You do similar things throughout your entire process. For example, you schedule working to go to '1' if start is '1', then later you override that value if "i = 7",
if(start = '1') then
working <= '1';
ready <= '0';
end if;
if(i = 7) then
. . .
working <= '0';
end if;
and then later you try to test to see what is (excerpt below), however, the process has not suspended, so the the value of working has not been updated yet and it will still have the value it had on the previous execution.
if (i < 8 AND working = '1') then