代码之家  ›  专栏  ›  技术社区  ›  nichollsg

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

  •  1
  • nichollsg  · 技术社区  · 6 年前

    我有一个带符号的累加器,它用作BROM LUT的索引。无论如何,我在代码中检查错误以检测溢出/下溢事件。这些是绝对关键的,因为应用程序是模拟射频前端的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 index <= unsigned(accumToLutScaled) .

    为了提供一个例子,假设 preSumV , mult.result ,及 accumToLut 0x7FF 0b0111111111111 FFF ,对应于LUT中的最大条目。是否最好只将偏移量添加到 指数

    2 回复  |  直到 6 年前
        1
  •  0
  •   Russell    6 年前

    abs 函数来执行此操作。我相信abs的结果是一个无符号值,但您可能必须强制转换为无符号。

    index <= unsigned(abs(accumToLutScaled));
    
        2
  •  0
  •   nichollsg    6 年前

    从@Tricky开始,根据我的表的大小添加一个固定的偏移量,我已经解决了这个问题:

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