Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is overflow defined for VHDL numeric_std signed/unsigned

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?)

like image 521
detly Avatar asked Aug 02 '12 01:08

detly


People also ask

Can unsigned numbers have overflow?

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.

Is signed integer overflow defined?

In the C language, overflow of unsigned integers results in wrapping, but overflow of signed integers is undefined behavior.

Is unsigned overflow 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.

What is signed and unsigned in VHDL?

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.


2 Answers

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.

like image 117
wap26 Avatar answered Sep 24 '22 09:09

wap26


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.

like image 34
yado Avatar answered Sep 25 '22 09:09

yado