?= and numeric_std implementation

The matching equality and inequality are predefined by the language as follows (9.2.3)

The matching equality and matching inequality operators are also defined for any one-dimensional array type whose element type is BIT or STD_ULOGIC. The operands shall be arrays of the same length.

Do these same rules relating to "operands shall be arrays of the same length" apply when overloading the operator? Currently in numeric_std, "?=" allows either array to be resized in the event they are not the same length.

Is this overloading even desirable? Note that this is not done for logic operations. I think equality checks should also preserve the sense that the arrays must be the same length and fail if they are not the same length. I also think we need a way to express this to the compiler so it can be a compile time check.

OTOH, if we just commented these functions out, then we would have the language implicit definition for them as described above from 9.2.3

Note the issue about the arrays not being equal when they are both null arrays is discussed in #24

For reference:

  -- Id: C.74
  function "?=" (L, R : UNRESOLVED_SIGNED) return STD_ULOGIC is
    constant L_LEFT          : INTEGER := L'length-1;
    constant R_LEFT          : INTEGER := R'length-1;
    alias XL                 : UNRESOLVED_SIGNED(L_LEFT downto 0) is L;
    alias XR                 : UNRESOLVED_SIGNED(R_LEFT downto 0) is R;
    constant SIZE            : NATURAL := MAXIMUM(L'length, R'length);
    variable LX              : UNRESOLVED_SIGNED(SIZE-1 downto 0);
    variable RX              : UNRESOLVED_SIGNED(SIZE-1 downto 0);
    variable result, result1 : STD_ULOGIC;  -- result
  begin  -- ?=
    if ((L'length < 1) or (R'length < 1)) then
      assert NO_WARNING
        report "NUMERIC_STD.""?="": null detected, returning X"
        severity warning;
      return 'X';
    else
      LX     := RESIZE(XL, SIZE);
      RX     := RESIZE(XR, SIZE);
      result := '1';
      for i in LX'low to LX'high loop
        result1 := LX(i) ?= RX(i);
        if result1 = 'U' then
          return 'U';
        elsif result1 = 'X' or result = 'X' then
          result := 'X';
        else
          result := result and result1;
        end if;
      end loop;
      return result;
    end if;
  end function "?=";

I suppose that this code is only a reference implementation, but I am surprised that "?=" and "and" are called, rather than using a lookup table. Furthermore, if an appropriate lookup table is used, then the handling of 'U' and 'X' could be incorporated into it.

  -- truth table for "and" function
  constant and_sticky_u_x_table : stdlogic_table := (
    --      ----------------------------------------------------
    --      |  U    X    0    1    Z    W    L    H    -         |   |  
    --      ----------------------------------------------------
             ('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U'),  -- | U |
             ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X'),  -- | X |
             ('U', 'X', '0', '0', '0', '0', '0', '0', '0'),  -- | 0 |
             ('U', 'X', '0', '1', 'X', 'X', '0', '1', 'X'),  -- | 1 |
             ('U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X'),  -- | Z |
             ('U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X'),  -- | W |
             ('U', 'X', '0', '0', '0', '0', '0', '0', '0'),  -- | L |
             ('U', 'X', '0', '1', 'X', 'X', '0', '1', 'X'),  -- | H |
             ('U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X')   -- | - |
             );

This could be used to improve the speed of the handling of the table. It seems like the body of the loop could be simply:

  result := and_sticky_u_x_table(result, LX(i) ?= RX(i)) ;

I suppose if we took a deep dive into the packages this may need to be done more extensively, so maybe this is a mute point unless someone is interested in the work.

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