If I have an unsigned(MAX downto 0)
containing the value 2**MAX - 1
, do the VHDL (87|93|200X) standards define what happens when I increment it by one? (Or, similarly, when I decrement it by one from zero?)
A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type.
In the C language, overflow of unsigned integers results in wrapping, but overflow of signed integers is undefined behavior.
-fsanitize=unsigned-integer-overflow : Unsigned integer overflow, where the result of an unsigned integer computation cannot be represented in its type. Unlike signed integer overflow, this is not undefined behavior, but it is often unintentional.
In IEEE Standard VHDL Synthesis Packages: The type UNSIGNED represents an unsigned binary integer with the most significant bit on the left, while the type SIGNED represents a two's-complement binary integer with the most significant bit on the left.
Short answer:
There is no overflow handling, the overflow carry is simply lost. Thus the result is simply the integer result of your operation modulo 2^MAX.
Longer answer:
The numeric_std
package is a standard package but it is not is the Core the VHDL standards (87,93,200X).
For reference : numeric_std.vhd
The +
operator in the end calls the ADD_UNSIGNED (L, R : unsigned; C : std_logic)
function (with C = '0'
). Note that any integer/natural operand is first converted into an unsigned
.
The function's definition is:
function ADD_UNSIGNED (L, R : unsigned; C : std_logic) return unsigned is
constant L_left : integer := L'length-1;
alias XL : unsigned(L_left downto 0) is L;
alias XR : unsigned(L_left downto 0) is R;
variable RESULT : unsigned(L_left downto 0);
variable CBIT : std_logic := C;
begin
for i in 0 to L_left loop
RESULT(i) := CBIT xor XL(i) xor XR(i);
CBIT := (CBIT and XL(i)) or (CBIT and XR(i)) or (XL(i) and XR(i));
end loop;
return RESULT;
end ADD_UNSIGNED;
As you can see an "overflow" occurs if CBIT='1'
(carry bit) for i = L_left
. The result bit RESULT(i)
is calculated normally and the last carry bot value is ignored.
I've had the problem with wanting an unsigned
to overflow/underflow as in C or in Verilog and here is what I came up with (result
and delta
are unsigned
):
result <= unsigned(std_logic_vector(resize(('1' & result) - delta, result'length))); -- proper underflow
result <= unsigned(std_logic_vector(resize(('0' & result) + delta, result'length))); -- proper overflow
For overflow '0' & result
makes an unsigned
which is 1 bit larger to be able to correctly accommodate the value of the addition. The MSB is then removed by the resize
command which yields the correct overflow value. Same for underflow.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With