VHDL中的通用移位算法

VHDL中的通用移位算法,vhdl,fpga,circuit,hdl,Vhdl,Fpga,Circuit,Hdl,我正在设计通用移位算术运算符。 除了以下面介绍的方式使用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

我正在设计通用移位算术运算符。 除了以下面介绍的方式使用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;
实体isra是
港口(
clk:标准逻辑中;
rst:标准逻辑中;
di:标准逻辑向量(31到0);
sel:标准逻辑向量(31向下至0);
res:out标准逻辑向量(31向下至0):=(其他=>“0”)
);
结束isra;
过程
开始
等待clk'事件和clk='1';
如果rst='1',则
res'0');
其他的
CASE sel是
当X“00000001”=>res'0');
终例;
如果结束;
结束过程;

从硬件的角度来看,要在一个时钟中右移一个可变的位置数,每个位都是一个触发器,根据选择的32个可能值中的一个。所以从这个角度来看,这就是你如何做到的


不过,我会将sel==0设为一个case,并将其设为passthrough。从逻辑上讲,这比将所有设置为零更有意义。

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

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

使用索引

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;
过程
可变移位计数:整数范围0到31;
开始
如果rst='1',则
res'0');
ELSIF上升沿(clk)则
移位计数:=到整数(sel);
对于0到31循环中的I
如果I+shift\u计数<32,则
res(I)是否使用索引

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;
过程
可变移位计数:整数范围0到31;
开始
如果rst='1',则
res'0');
ELSIF上升沿(clk)则
移位计数:=到整数(sel);
对于0到31循环中的I
如果I+shift\u计数<32,则

res(I)您可以在不使用任何循环或case语句的情况下使用SRA函数:

res <= to_stdlogicvector(to_bitvector(di) sra to_integer(sel));
如果您不想这样做,您仍然可以将sel强制转换为未签名的。您还需要向我们提供数字位:

use ieee.numeric_bit.all;

您可以在不使用任何循环或case语句的情况下使用SRA函数:

res <= to_stdlogicvector(to_bitvector(di) sra to_integer(sel));
如果您不想这样做,您仍然可以将sel强制转换为未签名的。您还需要向我们提供数字位:

use ieee.numeric_bit.all;

解复用器?这里没有异议。你说得对,我已经改变了描述。thx用于指出这一点。解复用器?这里没有异议。你说得对,我已经改变了描述。thx代表指出这一点。thx代表答案。我同意,这是一种更为通用的方法,使其更好。问题是,在我的例子中,sel必须是32位宽的,我相信“shift_count:=to_integer(sel)”在这种情况下不起作用。正如你所说的,这个设计的棘手部分是使用聪明的解码器——32:1是不明智的。您认为坚持您的设计并使用sel(5到0)是一个好主意吗?另一件事是,是否有一个异步rst对性能有好处?Thx。这是为FPGA设计的,对吗?FPGA的逻辑元件对每个D触发器都有专用的异步复位输入,因此无论在性能还是LE使用方面都不会花费任何成本(它可能报告使用了更多的门,但这些门不能用于任何其他功能)。拥有一个更宽的
sel
总线不会造成任何伤害,因为
I+shift\u count<32
测试将自动正确处理
shift\u count
的任何值。“如果I+shift\u count<32,那么”这很聪明!谢谢你的回答。我同意,这是一种更为通用的方法,使其更好。问题是,在我的例子中,sel必须是32位宽的,我相信“shift_count:=to_integer(sel)”在这种情况下不起作用。正如你所说的,这个设计的棘手部分是使用聪明的解码器——32:1是不明智的。您认为坚持您的设计并使用sel(5到0)是一个好主意吗?另一件事是,是否有一个异步rst对性能有好处?Thx。这是为FPGA设计的,对吗?FPGA的逻辑元件对每个D触发器都有专用的异步复位输入,因此无论在性能还是LE使用方面都不会花费任何成本(它可能报告使用了更多的门,但这些门不能用于任何其他功能)。拥有一个更宽的
sel
总线不会造成任何伤害,因为
I+shift\u count<32
测试将自动正确处理
shift\u count
的任何值。“如果I+shift\u count<32,那么”这很聪明!您好,谢谢您指出。case语句中的其他语句规定res信号写入每个分支。这有助于合成工具,以防止创建闩锁。嗨,thx指出它。case语句中的其他语句规定res信号写入每个分支。这有助于合成工具防止创建闩锁。