1

我正在设计通用移位算术运算符。除了以下面介绍的方式使用 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;
4

3 回答 3

4

您可以使用不带任何循环或 case 语句的 SRA 函数:

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

请注意,您需要将 sel 设为无符号,而不是 std_logic_vector:

sel: in unsigned (31  downto 0);

如果您不想这样,您仍然可以将 sel 转换为无符号。您还需要我们 numeric_bit:

use ieee.numeric_bit.all;
于 2010-11-15T15:57:07.163 回答
1

从硬件的角度来看,要在单个时钟中右移可变数量的位置,每个位都是一个触发器,具有基于选择的 32 个可能值之一。所以从这个角度来看,这就是你的做法。

不过,我会将 sel == 0 设为一个案例并将其设为直通。从逻辑上讲,这比将所有内容都设置为零更有意义。

于 2010-11-13T20:36:01.423 回答
1

使用索引?

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 位。

于 2010-11-13T21:16:51.340 回答