Search code examples
vhdlvivadovivado-hls

Infinite loop in vhdl


I am trying to obtain two digit number from a std_logic_vector. I know... it is not a professional way to do that(the way I made it), but I am in the process of learning. My real problem is the 'while' loop. I can't figure it out why it is an infinite loop. Anyone who can help? In testbench the value for d is "10010"; here is the error and the code:

[Synth 8-3380]loop condition does not converge after 2000 iterations [afisare.vhd:30]

line 30 is while aux>noua loop. I am synthesizing and want to simulate after that

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity bcd is
    port( y0: out std_logic_vector(6 downto 0);
          y1: out std_logic_vector(6 downto 0);
          d: in std_logic_vector(4 downto 0);
          anode: out std_logic_vector(7 downto 0));
end bcd;


architecture afis of bcd is
begin
process(d)
variable prima: integer;
variable aux: std_logic_vector(4 downto 0);
variable din: std_logic_vector(3 downto 0);
variable noua: std_logic_vector(4 downto 0);
variable unu: std_logic;
variable zero: std_logic;
begin
prima:=0;
noua:="01001";
aux:=d;
unu:='1';
zero:='0';
while aux>noua loop
    if (aux(4)=unu and aux(3)=zero)  then
        aux(4):=zero;
    end if;
    if (aux(1)=unu and aux(0)=zero)  then
            aux(1):=zero;
     end if;
    aux:=aux xor noua;
    prima:=prima+1;
end loop;
din:=aux(3 downto 0);

case din is
    when "0000"=> y0<="0000001";
       when "0001"=>y0<="1001111";
       when "0010"=>y0<="0010010";
       when "0011"=>y0<="0000110";
       when "0100"=>y0<="1001100";
       when "0101"=>y0<="0100100";
       when "0110"=>y0<="0100000";
       when "0111"=>y0<="0001111";
       when "1000"=>y0<="0000000";
       when "1001"=>y0<="0000100";
       when others=>y0<="0110110";
end case;
case prima is 
when 0=>y1<="0000001";
when 1=>y1<="1001111";
when 2=>y1<="0010010";
when 3=>y1<="0000110";
when others=>y1<="0110110";
end case;
anode<="11111100";
end process;

end afis;

Solution

  • The synthesizer does not care about the testbench, it tries to create a piece of hardware that would be equivalent to your loop and would work for any possible input. And in order to do this it somehow tries all possibilities (32). Unfortunately it is apparently not smart enough to detect that this loop always terminates in at most 3 iterations (not sure of this "3", I may be wrong).

    Generally speaking, for synthesis, it is better to use loops with caution (static bounds of for loops, static condition of while loops). In this case it is difficult to say if you are beyond Vivado's capabilities or not. If the documentation says that non-static conditions of while loops are supported for synthesis you can open a service request, you found a bug.

    Anyway, it would be better to describe this differently. Try maybe to fix the number of iterations (after verifying by simulation or plain reasoning that 3 is enough, of course, I am just guessing):

    for i in 1 to 3 loop
      if aux>noua then
        if (aux(4)=unu and aux(3)=zero) then
          aux(4):=zero;
        end if;
        if (aux(1)=unu and aux(0)=zero) then
          aux(1):=zero;
        end if;
        aux := aux xor noua;
        prima:=prima+1;
      end if;
    end loop;