"range constraint violation" 尝试在 VHDL 中模拟电路时出错

"range constraint violation" error when trying to simulate a circuit in VHDL

我是 VHDL 的新手,我正在尝试如下模拟一个块:

  1. 它有四个 std_logic_vector 输入,名称为 abcd。 输入 ab 是有符号数,输入 cd 是 无符号数。
  2. 它有四个输出名为 uvwx。输出 uv 是有符号数,输出 wx 是无符号数。
  3. 输出定义如下:

    u = a + b

    v = a / 2

    w = c * d

    x = c * 2

  4. 内部信号为整数。

我能够编译模块和测试平台。我遇到的问题是当我尝试模拟电路时显示以下错误消息:

ncsim: *E,TRRANGEC: range constraint violation.
          File: ./operator2.vhd, line = 38, pos = 36
         Scope: :inst_operator:$PROCESS_007
          Time: 0 FS + 0

因此,模拟器没有启动。我不明白这一行怎么会错:

x <= std_logic_vector(to_unsigned(sx, 17));

我尝试将此行更改为其他执行相同操作的行,但在同一行中出现错误。如果我删除此行,则会在第 37 行报告错误。您能给我提示以找出我的错误吗?以下是模块的代码:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity operator2 is
    port(
        a: in std_logic_vector(15 downto 0);
        b: in std_logic_vector(15 downto 0);
        c: in std_logic_vector(15 downto 0);
        d: in std_logic_vector(15 downto 0);
        u: out std_logic_vector(16 downto 0);
        v: out std_logic_vector(14 downto 0);
        w: out std_logic_vector(31 downto 0);
        x: out std_logic_vector(16 downto 0)
    );

end entity operator2;

architecture a2 of operator2 is

    signal su: integer;
    signal sv: integer;
    signal sw: integer;
    signal sx: integer;

begin

    --signals affectation
    su <= to_integer(signed(a)) + to_integer(signed(b));
    sv <= to_integer(signed(a)) / 2;
    sw <= to_integer(unsigned(c)) * to_integer(unsigned(d));
    sx <= to_integer(unsigned(c)) * 2;

    --outputs affectation
    u <= std_logic_vector(to_signed(su, 17));
    v <= std_logic_vector(to_signed(sv, 15));
    w <= std_logic_vector(to_unsigned(sw, 32));
    x <= std_logic_vector(to_unsigned(sx, 17)); --This is the line reporting the error during the simulation**

end architecture a2;

第 37 行是错误:VHDL 中自然数的最大范围是 31 位(因为自然数是整数范围的非负子集)所以 to_unsigned 32 位范围是 .. . 有问题(非正式地,David 可能很快就会与 LRM 参考资料一起使用)。为什么你的模拟器报错行,我答不上来。 GHDL 按预期报告 "error: bound check failure at operator2.vhd:37"。

请注意,真正的问题是这一行:

 sw <= to_integer(unsigned(c)) * to_integer(unsigned(d));

它试图将两个 16 位无符号数的乘积填充到具有 31 位正数范围的整数中,这...并不总是有效。

我建议将 "sw" 设为 32 位无符号整数,而不是整数,这样可以正确处理整个范围。

为了清楚起见,我会考虑对其他内部信号做同样的事情。没有必要在数值范围的基础上这样做,但如果你将它们保持为 "integer",最好改进它们的声明以使设计意图明确:

signal sx: integer;                   -- obscures the design
signal sx: natural range 0 to 131071; -- documents the intent

如果您这样做了,您可能会更快地发现问题。

正如评论中指出的那样,使用 natural 而不是 integer 给出了有效的默认值 (natural'left = 0) 而不是无法转换为 unsigned (integer'left = -2**31)

或者,为其输入(C 和 D)提供保证 - 如果您可以将其中至少一个限制为 15 位 - 那也可以。

我会更进一步,声明所有正确类型的端口,signedunsigned 视情况而定,并消除大多数不必要的类型转换,这些转换对可读性没有任何作用。这也将完全消除内部信号,从而大大减少冗长的设计。

当您使用整数值时,您应该初始化它们的值。在您的信号(su、sv、sw 和 sx)中,您必须这样做,因为它们是整数值(从 -2^31 到 2^31)。 请尝试:

signal su: integer :=0;
signal sv: integer :=0;
signal sw: integer :=0;
signal sx: integer :=0;

如果不初始化它们,它们将取最高值(2^31),这样可能会在模拟过程中出现问题。