【问题标题】:Universal shift arithmetic right in VHDLVHDL中的通用移位算术
【发布时间】:2010-11-13 20:16:14
【问题描述】:

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

【问题讨论】:

  • 解复用器?这里没有解复用器。
  • 你是对的,我已经改变了描述。谢谢指出这一点。

标签: vhdl fpga circuit hdl


【解决方案1】:

您可以在没有任何循环或案例语句的情况下使用 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;

【讨论】:

    【解决方案2】:

    使用索引?

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

    【讨论】:

    • 谢谢你的答案。我同意这是一种更通用的方法,可以使它更好。问题是我的 sel 必须是 32 位宽,我相信“shift_count := to_integer(sel)”在这种情况下不起作用。正如你所说,这个设计的棘手部分是使用聪明的解码器 - 做 32:1 是不明智的。你认为坚持你的设计并使用 sel(5 downto 0) 是个好主意吗?另一件事是,如果出于性能原因使用异步 rst 是否有益?谢谢。
    • 这是用于 FPGA 的,对吧? FPGA 的逻辑元件对每个 D 触发器都有专用的异步复位输入,因此它不会在性能或 LE 使用方面付出任何代价(它可能会报告使用了更多 ,但这些门可以'不用于任何其他功能)。拥有更宽的sel 总线应该不会造成任何伤害,因为I + shift_count &lt; 32 测试会自动正确处理shift_count 的任何值。
    • "IF I + shift_count
    【解决方案3】:

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

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

    【讨论】:

    • 嗨,谢谢指出。其他 in case 语句规定 res 信号写入每个分支。这有助于综合工具防止创建闩锁。
    猜你喜欢
    • 1970-01-01
    • 2020-07-02
    • 1970-01-01
    • 1970-01-01
    • 2011-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多