Универсальная смена арифметики вправо в VHDL
Вопрос
Я проектирую универсальную смену арифметического оператора. Есть ли лучший способ добиться этого, кроме того, используя 32-битный мультиплексор (декодер) на пути, представленный ниже?
ENTITY isra IS
PORT (
clk: in std_logic;
rst: in std_logic;
di: in std_logic_vector (31 downto 0);
sel: in std_logic_vector (31 downto 0);
res: out std_logic_vector (31 downto 0) := (others => '0')
);
END isra;
PROCESS
BEGIN
WAIT UNTIL clk'EVENT AND clk = '1';
IF rst = '1' THEN
res <= (others => '0');
ELSE
CASE sel IS
when X"00000001" => res <= to_stdlogicvector(to_bitvector(a) sra 1);
when X"00000002" => res <= to_stdlogicvector(to_bitvector(a) sra 2);
...
when X"0000001F" => res <= to_stdlogicvector(to_bitvector(a) sra 31);
when others => res <= (others => '0');
END CASE;
END IF;
END PROCESS;
Решение
Используйте индексацию?
PROCESS
VARIABLE shift_count : INTEGER RANGE 0 TO 31;
BEGIN
IF rst = '1' THEN
res <= (others => '0');
ELSIF RISING_EDGE(clk) THEN
shift_count := to_integer(sel);
FOR I IN 0 TO 31 LOOP
IF I + shift_count < 32 THEN
res(I) <= din(I + shift_count);
ELSE
res(I) <= din(31); -- for logical shift right, use '0' instead
END IF;
END LOOP;
END IF;
END PROCESS;
Эта версия намного проще для параметризации в общий.
Помните, что VHDL является поведенческим описанием, он не указывает MUX. Компилятор может генерировать различные конструкции в зависимости от того, оптимизируете ли вы для размера, скорости, разрешают кондиционирование и т. Д.
Обратите внимание, что 5 2: 1 MUXES могут реализовывать это в гораздо меньшей площади, чем один 32: 1 MUX. Если это не блок, который ограничивает вашу такту, это может быть предпочтительным.
Также обратите внимание, что ваш sel
Вход слишком широкий, он должен быть только 5 бит.
Другие советы
Вы можете использовать функцию SRA без каких-либо петель или отчетов о случаях:
res <= to_stdlogicvector(to_bitvector(di) sra to_integer(sel));
Обратите внимание, что вам нужно сделать Sel unsigned, а не std_logic_vector:
sel: in unsigned (31 downto 0);
Если вы не хотите этого, вы все еще можете отказаться от SEL в беззнаков. Вам также нужно нам numeric_bit:
use ieee.numeric_bit.all;
Ну а с аппаратной точки зрения, чтобы перейти прямо в одних часах переменное количество позиций, каждый бит представляет собой один флип-флоп с одним из 32 возможных значений на основе выбора. Итак, с этой точки зрения, вот как вы это делаете.
Я бы сделал Sel == 0 случай и сделать его пасстородом, хотя. Логично, что имеет больше смысла, чем настроить все к нулям.