是否在VHDL中定义了整数溢出?

时间:2012-11-19 01:34:32

标签: vhdl

我想知道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.是否定义了下一个增量会发生什么?是不确定的行为?

3 个答案:

答案 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不会提供当前的模拟时间。可以通过检查产生的波形来找到:

foo_tb.png

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;

和模拟:

foo_tb_wrap_around.png

我们看到x环绕的值。

“+”运算符结果的赋值没有违反约束:

3种类型:

  

给定类型的对象的可能值的集合可以经受被称为约束的条件(也包括不施加约束的约束的情况);如果满足相应条件,则称该值满足约束。子类型是与约束一起的类型。如果一个值属于该类型并满足约束,则该值属于给定类型的子类型;给定的类型称为子类型的基本类型。类型是其自身的子类型;据说这种子类型不受约束(它对应于不施加限制的条件)。类型的基类型是类型本身。

在我们的第二个架构中,没有约束,但类型为INTEGER的声明范围之外没有可能的值。而值则反过来。

VHDL的语义已被构造为不需要在此检测,这与表示二进制位(硬件)的元素的单维数组上的数学运算相匹配。

答案 1 :(得分:3)

任何体面的模拟器都会停在那里,并显示一条错误信息,指出溢出的附加物。 (如果你记得打开检查,Xilinx Isim只是一个不错的模拟器,上次我看了)

如果你多年来做了太多的C编程,那就太怪异了!

Synthesis将执行任何节省硬件的操作(在这种情况下没有输出,完全优化X和过程!)所以最好在模拟中捕获这种错误。

答案 2 :(得分:2)

整数溢出(和下溢)是VHDL中实现定义的行为。我现在无法引用规范,但如果仔细阅读,您会发现几乎所有关于整数范围的内容都是实现定义的,超出了支持的最小范围(-2**312**31)。

32位机器上的大多数VHDL实现实际上表现得好像它们是32位2的完整整数(例如机器整数在这些平台上的行为)和64位实现通常具有64位整数,但你不能指望这一点。

对于您的特定示例,如果您使用带范围的整数子类型,如果您尝试分配超出该范围的值,则这是一个错误,并将在运行时生成断言。 (另一方面,合成器会做他们想做的任何奇怪的事情 - 通常它们会溢出,好像它是2的补码整数)。