Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] inferring latch(es) for signal VHDL error

Status
Not open for further replies.

Luis Daniel Bolaños

Member level 2
Joined
Apr 4, 2014
Messages
47
Helped
2
Reputation
4
Reaction score
2
Trophy points
8
Activity points
342
Hey guys,

I am doing a Simon Says memory game with a Finite State Machine, but I keep getting these warnings about "Inferring latch(es)" in Quartus II. I need to get a clean synthesis without latches.

Please, have a look at my code.

ERROR

Warning (10631): VHDL Process Statement warning at simon_fsm.vhd(63): inferring latch(es) for signal or variable "color", which holds its previous value in one or more paths through the process
Warning (10631): VHDL Process Statement warning at simon_fsm.vhd(63): inferring latch(es) for signal or variable "nivel", which holds its previous value in one or more paths through the process
Warning (10631): VHDL Process Statement warning at simon_fsm.vhd(63): inferring latch(es) for signal or variable "global", which holds its previous value in one or more paths through the process
Warning (10631): VHDL Process Statement warning at simon_fsm.vhd(63): inferring latch(es) for signal or variable "aux", which holds its previous value in one or more paths through the process
Warning (10631): VHDL Process Statement warning at simon_fsm.vhd(63): inferring latch(es) for signal or variable "input", which holds its previous value in one or more paths through the process
Warning (10631): VHDL Process Statement warning at simon_fsm.vhd(63): inferring latch(es) for signal or variable "nx_state", which holds its previous value in one or more paths through the process

CODE

Code:
library IEEE;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity simon_fsm is

	port
	(
		reset, clk, verde_in, rojo_in, amarillo_in, azul_in, start : in std_logic;
		secuencia: in std_logic_vector(44 downto 0);
		color : out	std_logic_vector(2 downto 0)
	);
end entity;

architecture rtl of simon_fsm is

	-- Construir el tipo estado
	type estado is (s0, s1, s2, s3, s4, s5, s6);

	-- Registro para almacenar los estados de la FSM
	signal pr_state, nx_state   : estado;
	
	-- Convecion de Colores para VGA
constant azul : std_logic_vector(2 downto 0) := "001";
constant rojo : std_logic_vector(2 downto 0) := "100";
constant amarillo : std_logic_vector(2 downto 0) := "110";
constant verde : std_logic_vector(2 downto 0) := "010";
constant negro : std_logic_vector(2 downto 0) := "000";
constant blanco : std_logic_vector(2 downto 0) := "111";

signal global, nivel, aux: integer;
signal input: std_logic_vector(2 downto 0);

function sec_to_color(s: std_logic_vector(2 downto 0))
return std_logic_vector is
begin
	case s is
		when "000" => return azul;
		when "001" => return azul;
		when "010" => return verde;
		when "011" => return verde;
		when "100" => return rojo;
		when "101" => return rojo;
		when "110" => return azul;
		when others => return verde;
	end case;
end sec_to_color;

begin

	-- Logica Secuencial
	process (clk, reset)
	begin
		if reset = '1' then
			pr_state <= s0;
		elsif (rising_edge(clk)) then
			pr_state <= nx_state;
		end if;
	end process;

	-- Logica Combinacional
	process (pr_state, start, nivel, global, aux, input, secuencia, verde_in, rojo_in, amarillo_in, azul_in)
	begin
		case pr_state is
		
			when s0 =>
				color <= blanco;
				nivel <= 1;
				global <= 0;
				aux <= 0;
				input <= "000";
				if start = '1' then					
					nx_state <= s1;
				end if;
				
			when s1 =>
				color <= sec_to_color(secuencia(44-3*global downto 42-3*global));
				if global < nivel then
					global <= global + 1;
				else
					global <= 0;
					input <= "000";
					nx_state <= s2;
				end if;
					
			when s2 =>
				if aux = 0 then
					color <= blanco;
					aux <= 1;
				else 
					color <= negro;
					aux <= 0;
					nx_state <= s3;
				end if;
					
			when s3 =>
				if verde_in = '1' then
					input <= verde;
				elsif rojo_in = '1' then
					input <= rojo;
				elsif azul_in = '1' then
					input <= azul;
				elsif amarillo_in = '1' then
					input <= amarillo;
				else
					input <= "000";
				end if;
				
				if input /= "000" then 
					nx_state <= s4;
				end if;
	
			when s4 =>
				if input = sec_to_color(secuencia(44-3*aux downto 42-3*aux)) then
					color <= input;
					if aux >= nivel then
						aux <= 0;
						nivel <= nivel + 1;
						nx_state <= s5;
					elsif aux < nivel then
						aux <= aux + 1;
						nx_state <= s3;
					elsif aux > 14 then 
						nx_state <= s6;
					end if;
				else
					nx_state <= s0;
				end if;
				
			when s5 =>
				if aux = 0 then
					color <= negro;
					aux <= 1;
				elsif aux = 1 then
					color <= blanco;
					aux <= 2;
				else 
					color <= negro;
					aux <= 0;
					nx_state <= s1;
				end if;
				
			when s6 =>
				if aux = 0 then
					color <= verde;
					aux <= 1;
					elsif aux = 1 then
					color <= azul;
					aux <= 2;
					elsif aux = 2 then
					color <= rojo;
					aux <= 3;
					elsif aux = 3 then
					color <= amarillo;
					aux <= 4;
					elsif aux = 4 then
					color <= verde;
					aux <= 5;
					elsif aux = 5 then
					color <= azul;
					aux <= 6;
					elsif aux = 6 then
					color <= rojo;
					aux <= 7;
					elsif aux = 7 then
					color <= amarillo;
					aux <= 8;
					elsif aux = 8 then
					color <= verde;
					aux <= 9;
					else
					color <= negro;
					aux <= 0;
					nx_state <= s0;
				end if;			
		end case;
	end process;
end rtl;

After the error, it also mentions "unsafe behaviour for the latch"

Thank you all :-D
 

assignment to reg without clock will lead to generate latches.
as you are assigning to all these reg in combinational block they are generating latches.
 

In an asynchronous process (your state machine) You need to ensure ALL signals are assigned in ALL cases. This is usually done by adding a default assignment before the state case statement, so that if they are not assigned in the state machine they are assigned to a default value.

Did you intend to have so many unregistered outputs?
 

In an asynchronous process (your state machine) You need to ensure ALL signals are assigned in ALL cases. This is usually done by adding a default assignment before the state case statement, so that if they are not assigned in the state machine they are assigned to a default value.

Did you intend to have so many unregistered outputs?

What do you mean by unregistered outputs? My only output is "color".

So you are saying I should start the signal on a default value before beginning the cases?
 

No. Your code does not infer a register for the color output as it is not in a clocked process. The code infers latches for all of the values as they have "memory" between interations in some cases as they are not assigned in all cases.

To avoid latches, use clocked processes, or assign in all outputs, as I stated in my previous post.
 
Ok, I got it. But my professor ask me to do the state machine that way: a non-clocked process with only combinational logic for the output, so I can't change that. Therefore, I guess I'll just take every signal and assign it to all cases. Can you help me with that please? That's a code I took from internet and fix it a bit, but I dont know that much.

Thank you
 

Ok, I got it. But my professor ask me to do the state machine that way: a non-clocked process with only combinational logic for the output, so I can't change that. Therefore, I guess I'll just take every signal and assign it to all cases. Can you help me with that please? That's a code I took from internet and fix it a bit, but I dont know that much.

Thank you

The infamous 2 process FSM that schools and books are stuck on for no good reason (synthesis tools understand 1 process FSMs).

If you took the code from the internet, maybe you should go through the code and understand what it is doing so you will no longer have to say " but I dont know that much." Doing so will actual help you learn how to read other peoples code and understand it (which is something that you'll be doing a lot of when you have a job).
 

The infamous 2 process FSM that schools and books are stuck on for no good reason (synthesis tools understand 1 process FSMs).

Because back in the black and white days, tools could only understand 2 process state machines. This was when lecturers devised their lesson plans and learned their VHDL. Many dont use their skill any more, and stick with the old notes/textbooks.
 

Because back in the black and white days, tools could only understand 2 process state machines. This was when lecturers devised their lesson plans and learned their VHDL. Many dont use their skill any more, and stick with the old notes/textbooks.

Tricky, I know this...I'm one of those old ****s that's almost as old as dirt. ;-) I actually remember using tools that required 2 process state machines, I also remember writing FPGA FSMs using schematics.
 

Ok, I got it. But my professor ask me to do the state machine that way: a non-clocked process with only combinational logic for the output, so I can't change that. Therefore, I guess I'll just take every signal and assign it to all cases. Can you help me with that please? That's a code I took from internet and fix it a bit, but I dont know that much.

Thank you

The easiest way is to assign the signals a value before the case statement. eg:

Code:
color <= (others => '0');
input <= "000";

case pr_state is
  when s1 =>
    --no assignments here, so color = 0 and input = 0

  when s2 =>
    input <= "011"; --overrides default assignment
    color <= blue;

This way everything assigned a default will always have a value and a latch will not be infered. Dont be tempted to do something silly like:

color <= color;

as that IS a latch.
 
The easiest way is to assign the signals a value before the case statement. eg:

Code:
color <= (others => '0');
input <= "000";

case pr_state is
  when s1 =>
    --no assignments here, so color = 0 and input = 0

  when s2 =>
    input <= "011"; --overrides default assignment
    color <= blue;

This way everything assigned a default will always have a value and a latch will not be infered. Dont be tempted to do something silly like:

color <= color;

as that IS a latch.

Thank you!! It worked!! :grin:
 

Hi again, sorry for bothering you, but I got another problem related to the latches.

I did as you said, defined default values for my variables before the cases and it reduced from 400 logic elements to 9. However, it seems like because variables nivel and temp have default values, the actual values do not increase during the process.

Here is the code

Code:
-- Se describe el juego Simon Says usando FSM
library IEEE;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity simon_fsm is

	port
	(
		reset, clk, start : in std_logic;
		input : in std_logic_vector (2 downto 0);
		secuencia: in std_logic_vector(44 downto 0);
		color : out	std_logic_vector(2 downto 0)
	);
end entity;

architecture rtl of simon_fsm is

	-- Construir el tipo estado
	type estado is (s0, s1, s2, s3);

	-- Registro para almacenar los estados de la FSM
	signal pr_state, nx_state   : estado;
	
	-- Convecion de Colores para VGA
constant azul : std_logic_vector(2 downto 0) := "001";
constant rojo : std_logic_vector(2 downto 0) := "100";
constant amarillo : std_logic_vector(2 downto 0) := "110";
constant verde : std_logic_vector(2 downto 0) := "010";
constant negro : std_logic_vector(2 downto 0) := "000";
constant blanco : std_logic_vector(2 downto 0) := "111";

begin

	-- Logica Secuencial
	process (clk, reset)
	begin
		if reset = '1' then
			pr_state <= s0;
		elsif (rising_edge(clk)) then
			pr_state <= nx_state;
		end if;
	end process;

	-- Logica Combinacional
	process (pr_state, start, input, secuencia)
	variable global, nivel : integer;	
	variable temp : std_logic_vector (2 downto 0);
	begin
		color <= negro;
				nivel := 0;
				global := 0;
				temp := "000";
				nx_state <= s1;
				
		case pr_state is
			when s0 =>	
				
				if start = '1' then	
				  color <= negro;
				  nivel := 0;
				  global := 0;				
					nx_state <= s1;
				else 
					nx_state <= s0;
				end if;
				
			when s1 =>
					color <= secuencia(44-3*global downto 42-3*global);
					if global < nivel then
					  	global := global + 1;
						nx_state <= s1;
					  else
						global := 0;
					  nx_state <= s2;
					end if;
										
			when s2 =>
				
				if input /= "000" then 
				  temp := input;
				  global := 0;
					nx_state <= s3;
				else
					nx_state <= s2;
				end if;
	
			when s3 =>
			
				if temp /= secuencia(44-3*global downto 42-3*global) then
				  color <= blanco;
					nx_state <= s0;
				else
				  color <= temp;
					if global >= nivel then
						global := 0;
						nivel := nivel + 1;
						nx_state <= s1;
					elsif global < nivel then
						global := global + 1;
						nx_state <= s3;
					elsif global > 14 then 
						nx_state <= s0;
						global := 0;
					end if;
				end if;
			end case;
	end process;
end rtl;

I know that because when I remove the defaut assignations

Code:
nivel := 0;
global := 0;
temp := "000";

it works, but again I get a lot of latches. The condition

Code:
if temp /= secuencia(44-3*global downto 42-3*global) then

always ocurrs I think because temp is always "000" so it never goes from s3 to s1, and the same happens to global < nivel condition

What can I do?
 

This is where a testbench is required to test your functionality.

Also, is there any reason you havent registered your color output?
 

However, it seems like because variables nivel and temp have default values, the actual values do not increase during the process.

This happens because you are using these variables, also variable global as asynchronous memory elements. Statements like global := global + 1; don't synthesize to correct working logic under this circumstances. It makes no difference in this case if you are using variables or signals, if the variables/signals are used as memory elements, keeping information across state machine cycles, they must not be assigned in a combinational process.

The two process FSM template requires to assign them in the clocked process, using auxilary signals that take the output of the combinational process. If you are required to use this design style, firstly try to minimize the number of additional memory elements (that actually represent FSM "substates"). Secondly code the necessary ones (like timers or counters) in a proper form.

In a single process FSM, you can write the assignments as they happen, without writing auxilary constructs. Nevertheless you should always consider if you are doing something reasonable.
 
The two process FSM template requires to assign them in the clocked process, using auxilary signals that take the output of the combinational process. If you are required to use this design style, firstly try to minimize the number of additional memory elements (that actually represent FSM "substates"). Secondly code the necessary ones (like timers or counters) in a proper form.

I can not add anything to the clocked process, I have to keep this style. What do you mean by FSM substates? and how do I code a timer? You mean to change the logic?

This is where a testbench is required to test your functionality.

Also, is there any reason you havent registered your color output?

What do you mean by register the color output?

Here is the testbench I use

Code:
library IEEE;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity testbench is
end entity;

architecture prueba of testbench is
  component simon_fsm is

	port
	(
		reset, clk, start : in std_logic;
		input : in std_logic_vector (2 downto 0);
		secuencia: in std_logic_vector(44 downto 0);
		color : out	std_logic_vector(2 downto 0)
	);
end component;

-- Declaracion de Senales

signal clk: std_logic := '0';
signal reset: std_logic := '0';
signal input: std_logic_vector (2 downto 0) := "000";
signal start: std_logic := '1';
signal secuencia : std_logic_vector (44 downto 0) := "110010110001100010100010001100110010001110100";
signal color: std_logic_vector (2 downto 0) := "000";
begin
  sim: simon_fsm port map (reset, clk, start, input, secuencia, color);
    start <= '0' after 20 ns;
    clk <= not clk after 10 ns;
    input <= "110" after 40 ns, "000" after 80 ns;
end architecture;

You can see at 50 ns that it goes from S3 to S0 even when input /= "000"
 

I can not add anything to the clocked process, I have to keep this style.
The style requires that all registers (not only pr_state, also global, temp and nivel) are assigned in a clocked process.
 

The style requires that all registers (not only pr_state, also global, temp and nivel) are assigned in a clocked process.
Ok, I will convice my teacher 8-O
So, what do I have to do? Use signals instead of variables and modify them between processes? What do you recommend me?
 

Each registered value can be implemented as a pair of a combinational and a registered signal similar to nx_state and pr_state.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top