Универсальный арифметический сдвиг вправо в 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;

person name    schedule 13.11.2010    source источник
comment
демультиплексор? Здесь нет демультиплекса.   -  person Ben Voigt    schedule 14.11.2010
comment
Вы правы, я изменил описание. Спасибо за указание на это.   -  person name    schedule 14.11.2010


Ответы (3)


Использовать индексацию?

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 — это описание поведения, а не мультиплексор. Компилятор может генерировать разные схемы в зависимости от того, оптимизируете ли вы размер, скорость, разрешаете ли конвейерную обработку и т. д.

Обратите внимание, что 5 мультиплексоров 2:1 могут реализовать это на гораздо меньшей площади, чем один мультиплексор 32:1. Если это не блок, который ограничивает вашу тактовую частоту, это может быть предпочтительнее.

Также обратите внимание, что ваш ввод sel слишком широк, он должен быть всего 5 бит.

person Ben Voigt    schedule 13.11.2010
comment
Спасибо за ответ. Я согласен, что это более общий подход, который делает его лучше. Проблема в том, что sel в моем случае должен иметь ширину 32 бита, и я считаю, что shift_count := to_integer(sel) в этом случае не сработает. Как вы сказали, сложная часть этого дизайна заключается в использовании умных декодеров - неразумно делать 32: 1. Считаете ли вы, что придерживаться своего дизайна и использовать sel(5 downto 0) — хорошая идея? Другое дело, хорошо ли по соображениям производительности иметь асинхронный сначала? Спасибо. - person name; 14.11.2010
comment
Это для FPGA, верно? Логические элементы FPGA имеют выделенные входы асинхронного сброса для каждого D-триггера, так что это ничего не будет стоить ни с точки зрения производительности, ни с точки зрения использования LE (он может сообщать о большем количестве используемых элементов, но эти элементы могут не использовать для каких-либо других функций). Более широкая шина sel ничему не повредит, потому что тест I + shift_count < 32 автоматически правильно обработает любое значение shift_count. - person Ben Voigt; 14.11.2010
comment
ЕСЛИ I + shift_count ‹ 32 ТО это умно! - person name; 15.11.2010

Вы можете использовать функцию SRA без каких-либо циклов или операторов case:

res <= to_stdlogicvector(to_bitvector(di) sra to_integer(sel));

Обратите внимание, что вам нужно сделать sel беззнаковым, а не std_logic_vector:

sel: in unsigned (31  downto 0);

Если вы этого не хотите, вы все равно можете преобразовать sel в unsigned. Вам также нужно нам numeric_bit:

use ieee.numeric_bit.all;
person Philippe    schedule 15.11.2010

Что ж, с аппаратной точки зрения, чтобы сдвинуть вправо за один такт переменное количество позиций, каждый бит представляет собой один триггер с одним из 32 возможных значений на основе выбора. Итак, с этой точки зрения, вот как вы это делаете.

Однако я бы сделал sel == 0 case и сделал бы его сквозным. Логически это имеет больше смысла, чем обнулять все.

person caveman    schedule 13.11.2010
comment
Привет, спасибо за указание на это. Другие операторы in case предусматривают, что сигнал res записывается в каждую ветвь. Это помогает инструменту синтеза предотвратить создание защелок. - person name; 14.11.2010