Numeric_Std vs Std_Logic_Unsigned

One of VHDL’s annoyances is the excessive typing.  It’s one of the things VHDL got wrong.  As a result, two competing solutions were developed.  Sadly, neither is perfect.

VHDL distinguishes between unsigned, signed, and std_logic_vector for addition.  The addition operation is the same for unsigned/signed, and is typically expected to be the same for std_logic_vector.

Synopsys created a std_logic_arith package to perform math functions, and included std_logic_signed and std_logic_unsigned to allow the user to give a default of signed/unsigned to the std_logic_vectors.

Not to be outdone, an IEEE standard library, numeric_std, was created.  The library uses the same names for the types.  This means that numeric_std and std_logic_arith will result in conflicts when used in the same source file.  Numeric_std, like std_logic_arith, doesn’t declare what addition means for std_logic_vectors.  However, it is the preferred package and doesn’t include a numeric_std_unsigned/signed (until vhdl-2008).

I should point out that sometimes, addition can be used just for the logic structure.  I showed the example of “-x and x”, which finds the first set lsb.  This might not be a good example though, as it is fairly esoteric.  In this case, the addition is from the negation of x, which is (not x)+1.

I discovered an interesting thing recently.  While numeric_std doesn’t define operations on std_logic_vectors, std_logic_unsigned doesn’t define operations on unsigneds.  In fact, the two packages don’t actually conflict*.  Likewise, std_logic_signed and numeric_std don’t conflict either.  However, numeric std does conflict with std_logic_arith, and std_logic_unsigned conflicts with std_logic_signed.  What this all means is that numeric_std and std_logic_unsigned can be used together.

As a side note, std_logic_signed/std_logic_unsigned technically conflict with the use of std_logic_vectors, as “=” and “/=” are redefined.  Some tools may give errors that no function is defined for “=” due to a quirk in the VHDL LRM.

There are some limits with importing std_logic_unsigned though.  The “-x and x” operation I described above still won’t work.  std_logic_unsigned doesn’t define the “-” used for negation.  If std_logic_signed and numeric_std are used together, this will work.  However, it will result in “x > y” working in the signed sense.  This is not what would be expected by most users.

Thus far, the compromise I’ve found is:

  • use ieee.numeric_std.all —  Too many people will complain if you don’t.
  • use ieee.std_logic_signed.”+” — this will let you do basic operations
  • use ieee.std_logic_signed.”-” — this lets you do subtraction
  • use ieee.std_logic_unsigned.conv_integer; — converts std_logic_vector to integer
  • use ieee.std_logic_arith.conv_std_logic_vector; — convert integer to std_logic_vector.

This is a compromise.  It uses standard packages only.  It doesn’t cause conflicts between the packages.  It allows math operations on std_logic_vectors.  It doesn’t allow any ambiguous operations like greater/lesser or multiplication to be used on std_logic_vectors.  It does look strange though, because of the strong opinions that only numeric_std should be used.

This entry was posted in Fundamentals, VHDL. Bookmark the permalink.

Comments are closed.