对于 ghdl 中 foo 的 rtl 的测试台:
ghdl -r foo_tb --wave=foo_tb.ghw
./foo_tb:error: foo_tb.vhdl:15 的边界检查失败
./foo_tb:error: 模拟失败
我在 Bill 的 foo 实体和架构中添加了一个上下文子句:
library ieee;
use ieee.std_logic_1164.all;
entity foo is port (
第 15 行是对 x 的信号分配:
x <= x + 1;
这是一个模拟错误(发生在运行时)。
来自 IEEE 1076-1993:
7.2.4 添加运算符
加法运算符 + 和 - 是为任何数字类型预定义的,并具有其传统的数学含义。
这意味着“+”运算符的结果可以在 x 的子类型约束之外。请注意,声明为“+”提供重载的函数不允许指定结果子类型。(返回值可以是声明了子类型指示的对象,可以定义取值范围或数组长度)。
和 12.6.2 信号值的传播
为了在给定的仿真周期内更新信号,内核进程首先确定该信号的驱动值和有效值。然后内核进程用新确定的有效值更新包含信号当前值的变量,如下所示:
a) 如果 S 是某种非数组类型的信号,则 S 的有效值用于更新 S 的当前值。检查 S 的有效值是否属于 S 的子类型。如果此子类型检查失败,则会发生错误。最后,将 S 的有效值赋给代表信号当前值的变量。
如果添加的结果与目标 x 的子类型约束不匹配,则会产生错误。该子类型约束由 object x 声明提供,该声明为整数(范围)提供子类型指示。
对于符合 LRM 的实现,运行时错误会导致仿真终止。
如果没有用于错误报告的标准化格式,ghdl 不提供当前模拟时间。可以通过检查生成的波形找到:
波形在 20 ns 后完全更新。下一个预定活动:
library ieee;
use ieee.std_logic_1164.all;
entity foo_tb is
end entity;
architecture foo of foo_tb is
signal clk: std_logic := '0';
begin
DUT:
entity work.foo
port map (
clk => clk
);
CLOCK:
process
begin
wait for 5 ns;
clk <= not clk;
if now > 30 ns then
wait;
end if;
end process;
end architecture;
将是 25 ns 处 clk 的上升沿。
所以这告诉我们一个受约束的整数是如何产生溢出错误的。
没有子类型约束的整数怎么样:
architecture fum of foo is
signal x : integer := INTEGER'HIGH - 2;
begin
process (clk)
begin
if rising_edge(clk) then
x <= x + 1;
end if;
end process;
end architecture;
我们将 x 定义为一个不受约束的整数集,它是我们期望 x 溢出的默认值。
包标准明确声明 INTEGER "+":
-- function "+" (anonymous, anonymous: INTEGER) return INTEGER;
如果我们看到“+”具有普通的数学含义,则预期结果超出 INTEGER 的范围。
但是,从包标准中的实现依赖声明:
type integer is range -2147483648 to 2147483647;
和模拟:
我们看到 x 的值环绕。
“+”运算符结果的赋值没有违反约束:
3 种类型:
给定类型的对象的可能值集合可以受到称为约束的条件(也包括约束不施加限制的情况);如果一个值满足相应的条件,则称该值满足约束。子类型是带有约束的类型。如果一个值属于该类型并满足约束,则称该值属于给定类型的子类型;给定类型称为子类型的基本类型。类型是其自身的子类型;这样的子类型被称为不受约束的(它对应于不施加限制的条件)。类型的基类型是类型本身。
在我们的第二个架构中,没有任何约束,但在声明的 INTEGER 类型范围之外没有可能的值。相反,该值会翻转。
VHDL 的语义已构建为不需要在此处检测,这与表示二进制位(硬件)的元素的一维数组上的数学运算相匹配。