题
我正在设计通用偏移算术运算符。除了使用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成为无符号,而不是STD_LOGIC_VECTOR:
sel: in unsigned (31 downto 0);
如果您不想要它,您仍然可以将SEL置于未签名的情况下。您还需要我们numeric_bit:
use ieee.numeric_bit.all;
从硬件的角度来看,要在单个时钟中向右移动一个可变数量的位置,每个位是一个单个触发器,基于选择,具有32个可能值之一。因此,从这个角度来看,这就是您的做法。
不过,我会使SEL == 0作为情况,并使其成为传递。从逻辑上讲,这比将所有内容设置为零更有意义。
不隶属于 StackOverflow