在 VHDL、Verilog、sim 行为中将无效地址写入 RAM
write on invalid address to RAM in VHDL, Verilog, sim behaviour
让我们在 Verilog 或 VHDL 下拥有 BRAM 或任何其他存储器。
例如:
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 中的值保持原样?
模拟器不会使任何东西失效。相反,写入将被忽略。
对于这种情况下的读取,它会 return 'x' 不过。
对于 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 索引和数组切片:
If an index expression is out of bounds or if any bit in the index expression is x or z, then the index shall be invalid. Reading from an unpacked array of any kind with an invalid index shall return the value specified in Table 7-1. Writing to an array with an invalid index shall perform no operation, with the exceptions of writing to element [$+1] of a queue (described in 7.10.1) and creating a new element of an associative array (described in 7.8.6). Implementations may issue a warning if an invalid index occurs for a read or write operation on an array.
对于 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',并且该值的 'LEFT 值为 'X' 将 return 自然整数子类型值 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 个无效内存位置,具体取决于 'X' 元素的数量a
的值),您已经破坏了设计模型状态的完整性,在依赖 SystemVerilog 或 VHDL 设计模型的仿真结果之前应该采取一些纠正措施。
总的来说,复杂摆弄的开销似乎不值得。这些警告属于 class 个警告,应在综合前进行审查。
当数组值的默认初始值为元值时,这些警告可能会在重置数组值之前发生。在大多数 FPGA 设计中,您可以通过初始化 a
和任何前辈来防止这种情况发生,因此 a
包含一个二进制表示值,或者在重置生效之前简单地忽略时间 0 的报告。
您还可以通过将 we
和任何前任初始化为“0”来防止写入地址 0。
让我们在 Verilog 或 VHDL 下拥有 BRAM 或任何其他存储器。 例如:
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 中的值保持原样?
模拟器不会使任何东西失效。相反,写入将被忽略。
对于这种情况下的读取,它会 return 'x' 不过。
对于 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 索引和数组切片:
If an index expression is out of bounds or if any bit in the index expression is x or z, then the index shall be invalid. Reading from an unpacked array of any kind with an invalid index shall return the value specified in Table 7-1. Writing to an array with an invalid index shall perform no operation, with the exceptions of writing to element [$+1] of a queue (described in 7.10.1) and creating a new element of an associative array (described in 7.8.6). Implementations may issue a warning if an invalid index occurs for a read or write operation on an array.
对于 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',并且该值的 'LEFT 值为 'X' 将 return 自然整数子类型值 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 个无效内存位置,具体取决于 'X' 元素的数量a
的值),您已经破坏了设计模型状态的完整性,在依赖 SystemVerilog 或 VHDL 设计模型的仿真结果之前应该采取一些纠正措施。
总的来说,复杂摆弄的开销似乎不值得。这些警告属于 class 个警告,应在综合前进行审查。
当数组值的默认初始值为元值时,这些警告可能会在重置数组值之前发生。在大多数 FPGA 设计中,您可以通过初始化 a
和任何前辈来防止这种情况发生,因此 a
包含一个二进制表示值,或者在重置生效之前简单地忽略时间 0 的报告。
您还可以通过将 we
和任何前任初始化为“0”来防止写入地址 0。