Reputation: 21
I'm trying learning to code in VHDL and the below code gives me no errors when compiling but gives me a latching warning. I need to get rid of this latch as I believe it is causing me problems in my next piece of code which will use this (8x8 multiplier).
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
ENTITY control IS
PORT (
clk, reset_a, start : IN STD_LOGIC;
count : IN UNSIGNED (1 DOWNTO 0);
input_sel, shift_sel : OUT UNSIGNED(1 DOWNTO 0);
state_out : OUT UNSIGNED(2 DOWNTO 0);
done, clk_ena, sclr_n : OUT STD_LOGIC
);
END ENTITY control;
ARCHITECTURE logic OF control IS
type logic_state is (idle, lsb, mid, msb, calc_done, err);
signal current_state: logic_state;
signal next_state: logic_state;
BEGIN
PROCESS (clk, reset_a)
BEGIN
if reset_a = '1' then
current_state <= idle;
elsif rising_edge (clk) then
current_state <= next_state;
end if;
END PROCESS;
PROCESS (current_state, start, count)
BEGIN
CASE current_state IS
when idle =>
if start = '1' then
next_state <= lsb;
else
next_state <= idle;
end if;
when lsb =>
if start = '0' and count = "00" then
next_state <= mid;
else
next_state <= err;
end if;
when mid =>
if start = '0' then
if (count = "01") then
next_state <= mid;
elsif (count = "10") then
next_state <= msb;
else
next_state <= err;
end if;
end if;
when msb =>
if start = '0' then
if (count = "11") then
next_state <= calc_done;
else
next_state <= err;
end if;
end if;
when calc_done =>
if start = '0' then
next_state <= idle;
else
next_state <= err;
end if;
when err =>
if start = '1' then
next_state <= lsb;
else
next_state <= err;
end if;
END CASE;
END PROCESS;
mealy: PROCESS (current_state, start, count)
BEGIN
input_sel <= "00";
shift_sel <= "00";
done <= '0';
clk_ena <= '0';
sclr_n <= '1';
CASE current_state IS
when idle =>
if start = '1' then
sclr_n <= '0';
clk_ena <= '1';
END IF;
when lsb =>
if start = '0' and count = "00" then
sclr_n <= '1';
end if;
when mid =>
if start = '0' then
if (count = "01") then
input_sel <= "01";
shift_sel <= "01";
elsif (count = "10") then
input_sel <= "10";
shift_sel <= "01";
end if;
end if;
when msb =>
if start = '0' then
if (count = "11") then
input_sel <= "11";
shift_sel <= "10";
end if;
end if;
when calc_done =>
if start = '0' then
input_sel <= "00";
shift_sel <= "00";
done <= '1';
clk_ena <= '0';
end if;
when err =>
if start = '1' then
input_sel <= "00";
shift_sel <= "00";
done <= '0';
clk_ena <= '1';
sclr_n <= '0';
end if;
END CASE;
END PROCESS mealy;
moore: PROCESS(current_state)
BEGIN
state_out <= "000";
CASE current_state IS
WHEN idle =>
WHEN lsb =>
state_out <= "001";
WHEN mid =>
state_out <= "010";
WHEN msb =>
state_out <= "011";
WHEN calc_done =>
state_out <= "100";
WHEN err =>
state_out <= "101";
END CASE;
END PROCESS moore;
END ARCHITECTURE logic;
I get the following warning:
Warning (10631): VHDL Process Statement warning at mult_control.vhd(65): inferring latch(es) for signal
or variable "next_state", which holds its previous value in one or more paths through the process
That points to this node (line 33):
PROCESS (current_state, start, count)
And that warning leads to other warnings (for every type .idle, .mid, .msb, etc.):
Warning (13012): Latch next_state.idle_218 has unsafe behavior
Warning (13013): Ports D and ENA on the latch are fed by the same signal start
Thank you!
Upvotes: 1
Views: 1715
Reputation:
line 33 is in the second process (with no label).
Why are there inferred latches?
See IEEE Std 1076.6-2004 (withdrawn) RTL Synthesis
6.2.1.1 Level-sensitive storage from process with sensitivity list
A level-sensitive storage element shall be modeled for a signal (or variable) when all the following apply:
a) The signal (or variable) has an explicit assignment.
b) The signal (or variable) does not have an execution path with as a condition.
c) There are executions of the process that do not execute an explicit assignment (via an assignment statement) to the signal (or variable).By default, the effect of an identity assignment of the signal (or variable) shall be as though the assignment was not present. If the combinational attribute decorates the signal (or variable), combinational logic with feedback shall be synthesized.
To avoid unintentional latches as condition c) has to be invalid.
An example in the question code that can cause latches:
when msb =>
if start = '0' then
if (count = "11") then
next_state <= calc_done;
else
next_state <= err;
end if;
end if;
This is missing an else for the outer if statement and meets rule c) quoted above. That can be cured:
when msb =>
if start = '0' then
if (count = "11") then
next_state <= calc_done;
else
next_state <= err;
end if;
else -- now all binary values of start in state msb assign next_state
next_state <= msb;
end if;
You can assign a value to a target before an if statement that otherwise meets c):
when msb =>
next_state <= msb; -- not always assigned in the if statement
if start = '0' then
if (count = "11") then
next_state <= calc_done;
else
next_state <= err;
end if;
end if;
In a sequence of statements the 'default' assignment occurs unless overwritten by a subsequent assignment in the if statement.
The question's code has other occurrences of c) issues (including in other processes) that can be similarly treated.
Upvotes: 1