为什么`to_unsigned(0,4)> = -1`在运行时评估为“FALSE”?

时间:2017-01-16 14:24:01

标签: vhdl

使用以下测试代码:

library ieee;
use ieee.numeric_std.all;
architecture sim of tb is
begin
  process is
  begin
    for c in -1 to 1 loop
      assert to_unsigned(0, 4) >= c report "Fails: 0 >= " & integer'image(c) severity NOTE;
    end loop;
    wait;
  end process;
end architecture;

使用ModelSim 10.5a显示此输出:

Loading work.tb(sim)
** Note: Fails: 0 >= -1
   Time: 0 ns  Iteration: 0  Instance: /tb
** Note: Fails: 0 >= 1
   Time: 0 ns  Iteration: 0  Instance: /tb

如此有效地to_unsigned(0, 4) >= -1评估为FALSE,并且在我使用for循环时不会在运行时报告此情况。这是为什么?

请注意,如果我在不使用to_unsigned(0, 4) >= -1循环的情况下编写for来获取运行时的-1值,那么ModelSim编译器将报告“值-1(类型为std。 STANDARD.NATURAL)超出范围0到2147483647。“。

1 个答案:

答案 0 :(得分:2)

TL / DR:无论您获得Modelsim的技术支持,请询问此问题,并通过回复更新问题。

使用(通常非常严格和准确)ghdl模拟器进行快速重写和交叉检查:

library ieee;
use ieee.numeric_std.all;

entity tb is
end tb;

architecture sim of tb is
begin
  process is
  begin
    for c in -1 to 1 loop
      assert to_unsigned(0, 4) 
       >= 
       c 
       report "Fails: 0 >= " & integer'image(c) severity NOTE;
    end loop;
    wait;
  end process;
end architecture;
  

ghdl -r tb
  ./tb:error:bb.vhd的绑定检查失败:14
  ./tb:error:模拟失败

在评估c时精确显示绑定检查错误,该错误不在无符号或自然的合法范围内。

所以问题是,ghdl或Modelsim选择了不合适的>=运算符吗?

numeric_std的源只显示两个>=运算符定义,其中第一个参数是unsigned。 (对于VHDL-2008标准,此文件为“2008版权所有”。)

  -- Id: C.19
  function ">=" (L, R : UNRESOLVED_UNSIGNED) return BOOLEAN;
  -- Result subtype: BOOLEAN
  -- Result: Computes "L >= R" where L and R are UNRESOLVED_UNSIGNED vectors possibly
  --         of different lengths.

  -- Id: C.23
  function ">=" (L : UNRESOLVED_UNSIGNED; R : NATURAL) return BOOLEAN;
  -- Result subtype: BOOLEAN
  -- Result: Computes "L >= R" where L is an UNRESOLVED_UNSIGNED vector and
  --         R is a nonnegative INTEGER.

两者都不允许签名数量(签名或整数)作为第二个参数。

因此,您可能希望查看安装中numeric_std的源代码,以查看它是否是一个不同的版本,>=运算符允许混合的Unsigned和Integer数据类型。我怀疑它是否存在:这种误解会危险地发生。

如果没有这样的操作员,那么Modelsim在这里是允许的;是否有编制选项来打开更严格的合规性?

如果你认为这是不必要的迂腐,请考虑一下:

c := -1;
if to_unsigned(0, 4) >= c then
    emergency_stop;
end if;