对于 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 数组的索引和切片:
如果索引表达式超出范围或索引表达式中的任何位为x或z,则索引无效。从具有无效索引的任何类型的解包数组中读取应返回表 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_std包to_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。