I have a signed accumulator that is used as the index to a BROM LUT. Anyways, I have error checking in my code to detect overflow/underflow events. These are absolutely critical as the application is the AGC of an analog RF front end, so underflowing might cause a booming signal to get maximum gain, blowing up our front end parts. Thus, I need to find a way to properly convert from signed to unsigned. For example, here is what I have so far:
library ieee;
...
use ieee.numeric_std.all;
...
process (clk)
variable preSumV : signed(accumToLut'left downto 0) := (others => '0');
variable satCheckV : std_logic_vector(2 downto 0) := (others => '0');
begin
if rising_edge(clk) then
if reset = '1' then
preSumV := (others => '0');
satCheckV := (others => '0');
overflow <= '0';
underflow <= '0';
accumToLut <= (others => '0');
accumToLutValid <= '0';
else
accumToLutValid <= mult.resultValid;
-- accumulate
if mult.resultValid = '1' then
-- perform accum
preSumV := preSumV + mult.result(mult.result'left downto mult.result'left-accumToLut'length+1);
satCheckV := accumToLut(accumToLut'left) & mult.result(mult.result'left) & preSumV(preSumV'left);
-- check for signed OVF/saturation
-- A,B is pos, sum neg = overflow so set max pos
if satCheckV = "001" then
overflow <= '1';
accumToLut(accumToLut'left) <= '0';
accumToLut(accumToLut'left-1 downto 0) <= (others => '1');
-- A,B is neg, sum pos = underflow so set max neg
elsif satCheckV = "110" then
underflow <= '1';
accumToLut(accumToLut'left) <= '1';
accumToLut(accumToLut'left-1 downto 0) <= (others => '0');
-- -- no overflow
else
overflow <= '0';
underflow <= '0';
accumToLut <= preSumV;
--accumToLut <= preSumV(preSumV'left-1 downto 0);
end if;
end if;
end if;
end if;
end process;
accumToLutScaled <= accumToLut(accumToLut'left downto accumToLut'left-GainWordLookup'length+1);
index <= unsigned(accumToLutScaled);
GainWordLookup <= c_LinToDbLut(to_integer(accumToLutScaled));
The issue I am experiencing is the signed to unsigned conversion with the signal index. Because this is signed 2's complement, there is no change in the bits. Thus, when I set the accumToLut value to either the max/min signed value, this is not translating to the corresponding max/min unsigned value when I perform index <= unsigned(accumToLutScaled).
To provide an example, assume that preSumV, mult.result, and accumToLut are all 12 bits. When there is an overflow event, accumToLut gets set to 0x7FF or 0b0111111111111 which is valid. However, when I convert to unsigned, I would like this to be FFF, corresponding to the maximum entry in the LUT. Is it best to just add an offset to the index assignment, or is there a cleaner way of doing this?