【问题标题】:write on invalid address to RAM in VHDL, Verilog, sim behaviour在 VHDL、Verilog、sim 行为中将无效地址写入 RAM
【发布时间】:2017-12-12 23:21:14
【问题描述】:

让我们有一个 BRAM 或 Verilog 或 VHDL 下的任何其他内存。 例如:

module raminfr (clk, we, a, di, do);   

input clk;   
input we;   
input  [4:0] a;   
input  [3:0] di;   
output [3:0] do;   
reg    [3:0] ram [31:0]; 

  always @(posedge clk) begin   
    if (we)   
      ram[a] <= di;   
  end   
  assign do = ram[a];   
endmodule

现在假设我们已经将有效数据写入“ram”。

如果地址“a”将具有无效值(4'bxxxx)(“we”=1 并且 clk 将具有 posedge),模拟器是否会使“ram”中的所有项目无效? 或者它让 ram 中的值保持原样?

【问题讨论】:

  • 不行,除非你写了一个明确的模型。
  • 当您询问有关仿真的问题时,由于您似乎正在考虑最终以 FPGA 为目标,因此您应该意识到无效地址或 地址时序,即使对于 read 会损坏内存内容!是的,你没看错,FPGA“ROM”的内容可能会被不正确的 reads 损坏。

标签: vhdl verilog simulation xilinx intel-fpga


【解决方案1】:

模拟器不会使任何东西失效。相反,写入将被忽略。

对于这种情况下的读取,它会返回“x”。

【讨论】:

  • IEEE Std 1800-2012 7.4.6 数组的索引和切片 如果索引表达式超出范围或索引表达式中的任何位为 x 或 z,则索引应为无效的。从具有无效索引的任何类型的解包数组中读取应返回表 7-1 中指定的值。写入具有无效索引的数组不会执行任何操作,...如果对数组的读取或写入操作发生无效索引,则实现可能会发出警告。 VHDL 呢?除了发出警告之外,它的行为取决于类型和算术包,是不同的。
【解决方案2】:

对于 Verilog

IEEE Std 1800-2009 SystemVerilog 标准包含 IEEE Std 1364-2005 Verilog 标准和 IEEE Std 1800-2005 SystemVerilog 标准。 IEEE Std 1800-2012 SystemVerilog 标准取代了 -2009 版本。

参见 IEEE Std 1800-2012 7.4.6 数组的索引和切片:

如果索引表达式超出范围或索引表达式中的任何位为xz,则索引无效。从具有无效索引的任何类型的解包数组中读取应返回表 7-1 中指定的值。 写入具有无效索引的数组不应执行任何操作,但写入队列的元素 [$+1](在 7.10.1 中描述)和创建关联的新元素除外数组(在 7.8.6 中描述)。 如果对数组进行读取或写入操作时出现无效索引,实现可能会发出警告。

对于 VHDL

等效的 VHDL 设计描述可能是:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity raminfr is
    port (
        clk:  in  std_logic;
        we:   in  std_logic;
        a:    in  std_logic_vector(4 downto 0);
        di:   in  std_logic_vector(3 downto 0);
        do:   out std_logic_vector(3 downto 0)
    );
end entity;

architecture behave of raminfr is
    type ram_type is array (0 to 15) of std_logic_vector (3 downto 0);
    signal ram:  ram_type;
begin
    process (clk)
    begin
        if rising_edge(clk) then
            if we = '1' then
                ram(to_integer(unsigned(a))) <= di;
            end if;
        end if;
end process;
    do <= ram(to_integer(unsigned(a)));
end architecture;

其中numeric_stdto_integer函数用于将a的数组值转换为整数索引。 (VHDL这里灵活一点,数组索引可以是整数类型也可以是枚举类型,统称为离散类型)。

阅读to_integer 的源代码,我们看到它会将包含“X”的输入无符号数组值转换为所有“X”,而“X”的“LEFT”值将返回一个自然整数子类型值 0 和可选择报告:

if (XARG(XARG'left) = 'X') then
      assert NO_WARNING
        report "NUMERIC_STD.TO_INTEGER: metavalue detected, returning 0"
        severity warning;
      return 0;
    end if;

通过更改本地静态的NO_WARNING 的值,可以在实现范围内禁用这些警告。使用 to_integer(或使用 Synopsys 包 std_logic_arith 和函数 conv_integer),索引将为 0。

此外,VHDL 实现还可以根据严重性警告报告停止仿真。

虽然您可以使用作为数组值提供的索引以不同方式处理分配的结果(如 2、4、8、16 或 32 个无效内存位置,具体取决于 @987654328 的“X”元素值的数量) @ 此处),您已经损害了设计模型状态的完整性,在依赖 SystemVerilog 或 VHDL 设计模型的仿真结果之前应该采取一些纠正措施。

一般来说,复杂摆弄的开销似乎不值得。这些警告属于在综合之前应审查的一类警告。

当数组值的默认初始值为元值时,这些警告可能会在数组值被重置之前发生。在大多数 FPGA 设计中,您可以通过初始化 a 和任何前辈来防止这种情况发生,因此 a 包含一个二进制表示值,或者在复位生效之前简单地忽略时间 0 的报告。

您还可以通过将 we 和任何前任初始化为“0”来防止写入地址 0。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-14
    相关资源
    最近更新 更多