I have a module that should represent a "distributed RAM", where multiple registers can be written in parallel and read through a single MUX. A minimal example would be:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity memory is
port
(
i_clk : in std_logic;
i_reset_n : in std_logic;
i_write_en : in std_logic;
i_some_condition : in std_logic;
i_other_condition : in std_logic;
i_data : in std_logic_vector(15 downto 0);
i_addr : in std_logic_vector(3 downto 0);
o_data : out std_logic_vector(15 downto 0)
);
end memory;
architecture synthesis of memory is
type RAM_T is array (15 downto 0) of std_logic_vector(15 downto 0);
signal ram : RAM_T;
begin
p: process(i_clk, i_reset_n)
begin
if i_reset_n = '0' then
ram <= (others => (others => '0'));
elsif i_clk'event and i_clk = '1' then
if i_write_en = '1' then
if i_some_condition = '1' then
ram(1) <= i_data;
end if;
if i_other_condition = '1' then
ram(2) <= i_data;
end if;
-- and so on
end if;
end if;
end process p;
o_data <= ram(to_integer(unsigned(i_addr)));
end;
Now Quartus II (14.1 Web Edition) warns that
Warning (10631): VHDL Process Statement warning at memory.vhd(21): inferring latch(es) for signal or variable "ram", which holds its previous value in one or more paths through the process
If I look at the RTL and technology map view, I see only edge triggered flip-flops. If "latch inference" here means "flip flop inference", then that is exactly what I intended. But how can I be sure that "latch" does not mean "transparent latch", i.e. a level sensitiv storage element? How could I distinguish this in the warning messages?
(This question is related, but asks why this is happening, I'm asking about the terminology and use of the word "latch".)
If each bit of ram can be assigned in the:
part of your process, then your code is fine and it is Quartus that is wrong. No latches should be inferred here. Only DFFs with active low asynchronous reset.
But if some bits are never assigned (e.g.
ram(0)
), then, according the VHDL semantics, these bits are only assigned (and they are always assigned '0') wheni_clk
ori_reset_n
andi_reset_n
is low.In any other circumstance that resumes your process (event on
i_clk
ori_reset_n
wherei_reset_n
is not low) they retain their value.There are several ways to interpret and implement this behaviour (remember that VHDL simulation semantics is accurately defined by the Language Reference Manual but that the synthesis semantics is far less well defined and strongly depends on the particular synthesis tool you are using):
Some synthesizers could decide that these bits are constant '0' and shall be simplified out. This interpretation is not technically right because if
i_reset_n
is never asserted the bits will never be assigned and should retain their power-up value, which is not necessarily known. But with some FPGA targets it makes sense.Some other synthesizers could decide that this is a typical latch behaviour with active low enable (
i_reset_n
) and a constant '0' input or something equivalent. They will probably also simplify by keeping only one single latch for all these bits.I tried two versions of your code with Vivado 2014.4:
The one you posted (with the
-- and so on
comment); Vivado infers 32 DFFs and one single latch for the 224 remaining bits ofram
.A variant where the
-- and so on
comment is replaced by some code that can assign any ofram(15 downto 3)
andram(0)
. Vivado infers 256 DFFs and no latches.Summary: check that each bit of
ram
can actually be assigned in the