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.