【问题标题】:"range constraint violation" error when trying to simulate a circuit in VHDL尝试在 VHDL 中模拟电路时出现“违反范围约束”错误
【发布时间】:2017-01-28 20:19:41
【问题描述】:

我是 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;

【问题讨论】:

  • 要么将 swsx 初始化为 natural'left 和 natural'right 内的值,要么将它们定义为 natural 类型:signal sw: natural; signal sx: natural;。问题是swsx 的默认值超出了to_unsigned 转换的自然范围。请注意,w(31) 将始终为“0”。
  • @user1155120 : 你确定 w(31) 总是'0',给定(比如说)c = d = x"ffff"(两个有效的 16 位无符号值)?跨度>
  • sw 作为整数只能为无符号数提供 31 位(自然范围)。负数表示我们在此处看到的边界检查失败。 (所有这一切都假设一个整数的最小保证范围 –2147483647 到 +2147483647,这在常见的模拟器中是通用的。一个正数只能是 31 位)。

标签: integer vhdl unsigned signed bitvector


【解决方案1】:

当您使用整数值时,您应该初始化它们的值。在您的信号(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),这样可能会在模拟过程中导致问题。

【讨论】:

    【解决方案2】:

    第 37 行是错误:VHDL 中 natural 的最大范围是 31 位(因为 natural 是整数范围的非负子集)所以 to_unsigned 具有 32 位范围是......有问题的(非正式地, David 可能很快就会与 LRM 参考一起)。为什么您的模拟器在错误的行上报告它,我无法回答。 GHDL 按预期报告“错误:operator2.vhd:37 的绑定检查失败”。

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

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

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

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

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

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

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

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

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

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

    【讨论】:

    • 他的模拟器报告了正确的行,而不是两者中的第一个。 (第 37 行也有一个边界错误,这是 sw 和 sx 的默认值的结果,如果您必须参考:IEEE Std 1076-2008 6.4.2.3 “在没有显式默认表达式的情况下,隐式默认为标量子类型的信号或复合信号的每个标量子元素假定值,每个标量子元素本身都是标量子类型的信号。标量子类型 T 的信号的隐含默认值定义为给定的值由 T'LEFT。”超出 to_unsigned 的范围。
    • 并理解为什么使用默认值 14.7.5.2 初始化。在初始化期间更新信号值将导致进程执行直到暂停(并且所有并发语句都被详细说明为进程的组合(如这里)或进程和块语句的组合)。 INTEGER'LEFT 超出了 NATURAL 类型的范围(在 to_unsigned 参数中使用)。
    猜你喜欢
    • 2021-12-11
    • 1970-01-01
    • 1970-01-01
    • 2012-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-29
    • 1970-01-01
    相关资源
    最近更新 更多