Правильно конвертировать из подписанного в неподписанный в VHDL - PullRequest
0 голосов
/ 03 декабря 2018

У меня есть подписанный аккумулятор, который используется в качестве индекса для BROM LUT.В любом случае, в моем коде есть проверка ошибок для обнаружения событий переполнения / недостаточного заполнения.Это абсолютно критично, так как применение - это АРУ аналогового радиочастотного интерфейса, поэтому недостаточное пропускание может привести к тому, что гудящий сигнал получит максимальное усиление, взорвав наши передние части.Таким образом, мне нужно найти способ правильно преобразовать подписанное в неподписанное.Например, вот что у меня есть:

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, биты не меняются.Таким образом, когда я устанавливаю значение gastToLut либо в значение max / min со знаком, это не переводится в соответствующее значение max / min без знака, когда я выполняю index <= unsigned(accumToLutScaled).

. Чтобы привести пример, предположим, что preSumV, mult.result и accumToLut - все 12 бит.Когда происходит событие переполнения, для StorageToLut устанавливается значение 0x7FF или 0b0111111111111, которое является действительным.Однако, когда я преобразую в unsigned, я бы хотел, чтобы это было FFF, что соответствует максимальному значению записи в LUT.Лучше всего просто добавить смещение к назначению index, или есть более чистый способ сделать это?

Ответы [ 2 ]

0 голосов
/ 04 декабря 2018

В @Tricky, добавив фиксированное смещение на основе размера моей таблицы, я исправил эту проблему:

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

0 голосов
/ 03 декабря 2018

Звучит так, будто вы ищете абсолютное значение, верно?Вы хотите знать, когда величина результата слишком велика, но вас не волнует знак.Для этого используйте встроенную функцию abs.Я полагаю, что результат abs является неподписанным значением, но вам, возможно, придется привести к unsigned.

index <= unsigned(abs(accumToLutScaled));
...