I want to do an code, which accumulates an input signal. This means the input signal is added to the previous value. This is then the output
library IEEE;
use IEEE.NUMERIC_STD.ALL;
use ieee.std_logic_1164.all
entity adder is
port(clock : in std_logic;
ADD_value : in signed(k-1 downto 0));
Result: out signed(k-1 downto 0));
end adder;
architecture behavioral of adder is
begin
variable acc_value : signed(k-1 downto 0);
process(clock)
begin
if rising_edge(clock) then
acc_value := acc_value + Add_value;
Result<=acc_value ;
end if;
end process;
end behavioral;
The problem is that both variables are signed. If an overflow occurs, the overflow goes from the k-1 position to the k-1 position, means the sign is destroyed. Per example if i have 01111 with the first "0" as sign, and i add "10" it goes to "10001", which is bitwise right, but as a signed wrong, because it is a negative value
I tried things like acc_value:= resize(acc_value + Result_var,k);
or acc_value:= to_signed(acc_value + Result_var,k);
but I had the same problem
I want as a result, to keep the data length k in case of an overflow, too. If an overflow occurs, the Result should be set to the maximum possible value in respect to the sign. This means I dont care if there is an overflow, I then only want then a maximum/minimum value
The maximum (minimum in case of negative value) as a kind of saturation. It is possible to come away from the maximum again, since negative values are allowed too.
It makes no sense to accumulate forever. There must a barrier exist, which you could check (and perhaps signal an overflow, if the barrier is exceeded). Your signal acc_value must have the width maximum_bit_width, which represents this barrier (be aware that the signal sum_temp has 1 bit more, see below). Result_var may have still the width k. Then you can code (I changed acc_value from "out" to "buffer" to be able to read it, perhaps you should introduce an intermediate signal and leave acc_value as "out" or use VHDL2008 as suggested):
acc_value : buffer signed(maximum_bit_width-1 downto 0);
…
process(clock)
variable sum_temp : signed(maximum_bit_width downto 0);
begin
if rising_edge(clock) then
sum_temp := acc_value(maximum_bit_width-1)&acc_value + Result_var;
if sum_temp(maximum_bit_width)=sum_temp(maximum_bit_width-1) then
acc_value <= sum_temp(maximum_bit_width-1 downto 0);
else
if sum_temp(maximum_bit_width)=‘0‘ then
acc_value <= (‘0‘, others => ‘1‘);
else
acc_value <= (‘1‘, others => ‘0‘);
end if;
end if;
end if;
end process;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.