在VHDL中正确地从有符号转换为无符号

时间:2018-12-03 17:03:39

标签: vhdl

我有一个带符号的累加器,用作BROM LUT的索引。无论如何,我在代码中进行错误检查以检测上溢/下溢事件。这些都是绝对关键的,因为应用程序是模拟RF前端的AGC,因此下溢可能会导致隆隆信号获得最大增益,从而炸毁我们的前端部件。因此,我需要找到一种方法来正确地从有符号转换为无符号。例如,这是我到目前为止的内容:

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

我遇到的问题是信号index的有符号到无符号转换。因为这是带符号的2的补码,所以位没有变化。因此,当我将accumToLut值设置为最大/最小带符号的值时,执行index <= unsigned(accumToLutScaled)时这不会转换为相应的最大/最小带符号的值。

举个例子,假设preSumVmult.resultaccumToLut都是12位。发生溢出事件时,accumToLut将设置为有效的0x7FF0b0111111111111。但是,当我转换为无符号时,我希望它是FFF,对应于LUT中的最大条目。最好仅向index分配添加偏移量,还是有一种更简洁的方法?

2 个答案:

答案 0 :(得分:0)

听起来您正在寻找绝对价值,对吗?您想知道结果的幅度何时过大,但是您不关心符号。使用内置的abs函数来执行此操作。我相信abs的结果是一个无符号值,但是您可能不得不强制转换为无符号值。

index <= unsigned(abs(accumToLutScaled));

答案 1 :(得分:0)

在@Tricky中,根据表的大小添加了固定的偏移量,我已经解决了以下问题:

index <= unsigned(accumToLutScaled + 2**(accumToLutScaled'length - 1))