[英]Is an inferred latch in Quartus II necessarily transparent
我有一个应该代表“分布式 RAM”的模块,其中多个寄存器可以并行写入并通过单个 MUX 读取。 一个最小的例子是:
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;
现在 Quartus II(14.1 网络版)警告说
警告 (10631):memory.vhd(21) 中的 VHDL 进程语句警告:为信号或变量“ram”推断闩锁(es),它在通过进程的一个或多个路径中保持其先前的值
如果我查看 RTL 和技术地图视图,我只会看到边缘触发触发器。 如果这里的“闩锁推理”是指“触发器推理”,那么这正是我想要的。 但是我怎么能确定“闩锁”并不意味着“透明闩锁”,即电平敏感的存储元件? 我如何在警告消息中区分这一点?
( 这个问题是相关的,但问为什么会这样,我问的是术语和“闩锁”这个词的用法。)
如果可以在以下位置分配 ram 的每一位:
elsif i_clk'event and i_clk = '1' then
...
end if;
过程的一部分,那么您的代码就很好,而 Quartus 是错误的。 此处不应推断闩锁。 仅具有低电平有效异步复位的 DFF。
但是,如果某些位从未分配过(例如ram(0)
),那么,根据 VHDL 语义,这些位仅在
i_clk
或i_reset_n
上有一个事件并且i_reset_n
低。 在恢复进程的任何其他情况下( i_clk
或i_reset_n
上的事件,其中i_reset_n
不低)它们保留其值。
有几种方法可以解释和实现这种行为(请记住,VHDL 仿真语义是由语言参考手册准确定义的,但综合语义的定义要差得多,并且在很大程度上取决于您使用的特定综合工具):
一些合成器可以决定这些位是常数“0”并且应该被简化。 这种解释在技术上是不正确的,因为如果i_reset_n
永远不会被断言,这些位将永远不会被分配并且应该保留它们的上电值,这不一定是已知的。 但是对于某些 FPGA 目标,这是有道理的。
其他一些合成器可能会认为这是典型的锁存行为,具有低电平有效启用 ( i_reset_n
) 和恒定的“0”输入或等效的东西。 它们也可能通过为所有这些位只保留一个锁存器来简化。
我在 Vivado 2014.4 中尝试了两个版本的代码:
您发布的那个(带有-- and so on
评论); Vivado 为ram
剩余 224 位推断出 32 个 DFF 和一个锁存器。
一种变体,其中-- and so on
注释被一些代码替换,这些代码可以分配ram(15 downto 3)
和ram(0)
。 Vivado 推断出 256 个 DFF,没有锁存器。
总结:检查ram
每一位实际上可以在
elsif i_clk'event and i_clk = '1' then
...
end if;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.