我想知道VHDL中是否定义了整数溢出。我无法在2002规范中找到任何东西。
作为示例(注意,这可能无法编译,它只是一个通用示例......):
entity foo is port (
clk : std_logic
);
end entity;
architecture rtl of foo is
signal x : integer range 0 to 2 := 0;
begin
process (clk)
begin
if rising_edge(clk) then
x <= x + 1;
end if;
end process;
end architecture;
很明显,x
将从0变为1,然后变为2.是否定义了下一个增量会发生什么?是不确定的行为?
答案 0 :(得分:6)
用于ghdl中frt的rtl的测试平台:
ghdl -r foo_tb --wave = foo_tb.ghw
./foo_tb:error:foo_tb.vhdl的绑定检查失败:15
./foo_tb:error:模拟失败
我在Bill的foo实体和架构中添加了一个context子句:
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的子类型约束不匹配,则会产生错误。该子类型约束由对象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的语义已被构造为不需要在此检测,这与表示二进制位(硬件)的元素的单维数组上的数学运算相匹配。
答案 1 :(得分:3)
任何体面的模拟器都会停在那里,并显示一条错误信息,指出溢出的附加物。 (如果你记得打开检查,Xilinx Isim只是一个不错的模拟器,上次我看了)
如果你多年来做了太多的C编程,那就太怪异了!
Synthesis将执行任何节省硬件的操作(在这种情况下没有输出,完全优化X和过程!)所以最好在模拟中捕获这种错误。
答案 2 :(得分:2)
整数溢出(和下溢)是VHDL中实现定义的行为。我现在无法引用规范,但如果仔细阅读,您会发现几乎所有关于整数范围的内容都是实现定义的,超出了支持的最小范围(-2**31
到2**31
)。
32位机器上的大多数VHDL实现实际上表现得好像它们是32位2的完整整数(例如机器整数在这些平台上的行为)和64位实现通常具有64位整数,但你不能指望这一点。
对于您的特定示例,如果您使用带范围的整数子类型,如果您尝试分配超出该范围的值,则这是一个错误,并将在运行时生成断言。 (另一方面,合成器会做他们想做的任何奇怪的事情 - 通常它们会溢出,好像它是2的补码整数)。