-- -- Signed or unsigned variable right-shift. -- -- Joris van Rantwijk 2024 -- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity shift_engine is generic ( -- Input word length. input_data_bits: integer range 4 to 64; -- Output word length. output_data_bits: integer range 4 to 64; -- Number of bit positions to pre-shift left before shifting right. pre_shift_left: integer range 0 to 16; -- True to apply sign extension when shifting. -- False to apply zero extension. signed_data: boolean ); port ( -- Main clock, active on rising edge. clk: in std_logic; -- Data input operand. -- A new input word is accepted on every clock cycle. in_data: in std_logic_vector(input_data_bits - 1 downto 0); -- Shift input operand. -- It indicates the number of bit positions to shift right, expressed -- as an unsigned integer in range 0 to 15. -- A new input word is accepted on every clock cycle. in_shift: in std_logic_vector(3 downto 0); -- Shifted output data. -- The output corresponds to the input delayed by 1 clock cycle. out_data: out std_logic_vector(output_data_bits - 1 downto 0) ); end entity; architecture arch of shift_engine is -- Output register. signal r_data: std_logic_vector(output_data_bits - 1 downto 0); begin -- Drive output. out_data <= r_data; -- -- Synchronous process. -- process (clk) is begin if rising_edge(clk) then if signed_data then r_data <= std_logic_vector( shift_right( shift_left( resize(signed(in_data), output_data_bits), pre_shift_left), to_integer(unsigned(in_shift)))); else r_data <= std_logic_vector( shift_right( shift_left( resize(unsigned(in_data), output_data_bits), pre_shift_left), to_integer(unsigned(in_shift)))); end if; end if; end process; end architecture;