2

我有一个应该代表“分布式 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 Web Edition) 警告说

警告 (10631):memory.vhd(21) 处的 VHDL Process Statement 警告:推断信号或变量“ram”的锁存器,它在通过进程的一个或多个路径中保持其先前的值

如果我查看 RTL 和技术图视图,我只会看到边沿触发的触发器。如果这里的“闩锁推断”是指“触发器推断”,那么这正是我的本意。但是我怎么能确定“锁存器”并不意味着“透明锁存器”,即电平敏感存储元件?我如何在警告消息中区分这一点?

这个问题是相关的,但问为什么会这样,我问的是术语和“闩锁”这个词的使用。)

4

1 回答 1

1

如果 ram 的每一位都可以分配在:

elsif i_clk'event and i_clk = '1' then
  ...
end if;

你的过程的一部分,那么你的代码很好,而 Quartus 是错误的。此处不应推断闩锁。仅具有低电平有效异步复位的 DFF。

但是如果某些位从未被分配(例如ram(0)),那么,根据 VHDL 语义,这些位仅在

  • 有一个事件i_clki_reset_n
  • i_reset_n低。

在恢复您的流程的任何其他情况下(事件发生或i_clk不低),它们保留其价值。i_reset_ni_reset_n

有几种方法可以解释和实现这种行为(请记住,语言参考手册准确定义了 VHDL 仿真语义,但综合语义的定义要差得多,并且很大程度上取决于您使用的特定综合工具):

  • 一些合成器可以决定这些位是恒定的“0”并且应该被简化。这种解释在技术上是不正确的,因为如果i_reset_n从未断言这些位将永远不会被分配并且应该保留它们的上电值,这不一定是已知的。但是对于一些 FPGA 目标,这是有道理的。

  • 其他一些合成器可能会认为这是典型的锁存行为,低电平有效启用 ( i_reset_n) 和恒定的“0”输入或等效的东西。它们可能还会通过为所有这些位只保留一个锁存器来简化。

我在 Vivado 2014.4 中尝试了两个版本的代码:

  • 您发布的(带有-- and so on评论);Vivado 推断出 32 个 DFF 和一个用于ram.

  • 一种变体,其中-- and so on注释被一些可以分配ram(15 downto 3)和的代码替换ram(0)。Vivado 推断出 256 个 DFF 并且没有锁存器。

总结:检查每一位是否ram真的可以在

elsif i_clk'event and i_clk = '1' then
  ...
end if;
于 2015-08-25T12:17:13.720 回答