I am designing universal shift arithmetic operator. Is there a better way to achieve it besides using the 32bit multiplexer (decoder) in a way presented bellow?
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;
Use indexing?
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;
This version is much easier to parameterize into a generic.
Remember that VHDl is a behavioral description, it doesn't specify a mux. The compiler can generate different designs depending on whether you optimize for size, speed, allow pipelining, etc.
Note that 5 2:1 muxes can implement this in a far smaller area than a single 32:1 mux. If this isn't the block that limits your clock rate, that might be preferable.
Also note that your sel
input is far too wide, it only needs to be 5 bits.