Bug in Numeric_std in "=" and "/="

In /= operator, there is a check for a 0 length string that always returns TRUE if one argument is a 0 length string. However, if both arguments are 0 length string, then this should return FALSE. While this may not negatively impact RTL code, it does impact testbench code.

  -- Id: C.31
  function "/=" (L, R : UNRESOLVED_UNSIGNED) return BOOLEAN is
    constant L_LEFT : INTEGER := L'length-1;
    constant R_LEFT : INTEGER := R'length-1;
    alias XL        : UNRESOLVED_UNSIGNED(L_LEFT downto 0) is L;
    alias XR        : UNRESOLVED_UNSIGNED(R_LEFT downto 0) is R;
    constant SIZE   : NATURAL := MAXIMUM(L'length, R'length);
    variable L01    : UNRESOLVED_UNSIGNED(L_LEFT downto 0);
    variable R01    : UNRESOLVED_UNSIGNED(R_LEFT downto 0);
  begin
    if ((L'length < 1) or (R'length < 1)) then
      assert NO_WARNING
        report "NUMERIC_STD.""/="": null argument detected, returning TRUE"
        severity warning;
      return true;
    end if;
    L01 := TO_01(XL, 'X');
    R01 := TO_01(XR, 'X');
    if ((L01(L01'left) = 'X') or (R01(R01'left) = 'X')) then
      assert NO_WARNING
        report "NUMERIC_STD.""/="": metavalue detected, returning TRUE"
        severity warning;
      return true;
    end if;
    return not(UNSIGNED_EQUAL(RESIZE(L01, SIZE), RESIZE(R01, SIZE)));
  end function "/=";

The check I am using is: signal ParamID : std_logic_vector(TID'range) := IfElse(INIT_ID /= "", INIT_ID, (TID'range => '0')) ;

Of course, this can be rewritten to: signal ParamID : std_logic_vector(TID'range) := IfElse(INIT_ID'length > 0, INIT_ID, (TID'range => '0')) ;

However, the same check on a string works just fine, so one would expect the pattern to work for std_logic_vector/unsigned. Note it is calling the numeric_std one since I included numeric_std_unsigned package.

Oddly though it is getting past the compiler and running. I wonder why about that. Have to write more tests.

LRM References:

1076-2019 P153 Starting at first paragraph:

The equality and inequality operators (= and /=) are defined for all types other than file types, protected types and types that contain a file type or protected type. The equality operator returns the value TRUE if the two operands are equal and returns the value FALSE otherwise. The inequality operator returns the value FALSE if the two operands are equal and returns the value TRUE otherwise.

Two scalar values of the same type are equal if and only if the values are the same. Two composite values of the same type are equal if and only if for each element of the left operand there is a matching element of the right operand and vice versa, and the values of matching elements are equal, as given by the predefined equality operator for the element type. In particular, two null arrays of the same type are always equal.

Clearly the implementation of "=" and "/=" in numeric_std are incorrect.

Edited by JimLewis
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information