问题
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?)
回答1:
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.
回答2:
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.
回答3:
For a value of MAX equal to 7 adding 1 to 2**7 - 1 (127) will result in the value 2**7 (128).
The maximum unsigned value is determined by the length of an unsigned array type:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity foo is
end entity;
architecture faa of foo is
constant MAX: natural := 7;
signal somename: unsigned (MAX downto 0) := (others => '1');
begin
UNLABELED:
process
begin
report "somename'length = " & integer'image(somename'length);
report "somename maximum value = " &integer'image(to_integer(somename));
wait;
end process;
end architecture;
The aggregate (others => '1')
represents a '1' in each element of somename
which is an unsigned array type and represents the maximum binary value possible.
This gives:
foo.vhdl:15:9:@0ms:(report note): somename'length = 8
foo.vhdl:16:9:@0ms:(report note): somename maximum value = 255
The length is 8 and the numerical value range representable by the unsigned array type is from 0 to 2**8 - 1 (255), the maximum possible value is greater than 2**7 (128) and there is no overflow.
This was noticed in a newer question VHDL modulo 2^32 addition. In the context of your accepted answer it assumes you meant length instead of the leftmost value.
The decrement from zero case does result in a value of 2**8 - 1 (255) (MAX = 7). An underflow or an overflow depending on your math religion.
Hat tip to Jonathan Drolet for pointing this out in the linked newer question.
来源:https://stackoverflow.com/questions/11769754/is-overflow-defined-for-vhdl-numeric-std-signed-unsigned