LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; use std.textio.all; -- Imports the standard textio package. use work.utils_pkg.all; -- Imports the standard textio package. ENTITY shifter IS Generic ( data_width : natural := 32; aggregate_size : natural := 8; do_pipelined : boolean := true ); Port ( rst : in STD_LOGIC; clk : in STD_LOGIC; sa : in integer; din_vld : in STD_LOGIC; din : in unsigned(data_width-1 downto 0); dout_vld : out STD_LOGIC; dout : out unsigned(data_width-1 downto 0) ); END shifter; ARCHITECTURE behavior OF shifter IS constant num_rounds : natural := NextExpBaseTwo(data_width/aggregate_size); subtype sa_rnd_t is signed(num_rounds-1 downto 0); subtype word_t is unsigned(data_width-1 downto 0); type word_array_t is array (0 to num_rounds) of word_t; signal rot_data : word_array_t; signal sa_rnd : sa_rnd_t; type sa_rnd_array_t is array (0 to num_rounds) of sa_rnd_t; signal sa_rnd_pipe : sa_rnd_array_t; signal dout_vld_pipe : unsigned(0 to num_rounds); -------------------------------------------------------------------------- function rol_stage(x : unsigned; en : std_logic; stage_num : natural; size : natural) return unsigned is variable result : unsigned(x'range); constant sa : natural := (2**stage_num) * size; begin if en = '1' then result := x(x'left-sa downto 0) & x(x'left downto x'length-sa); else result := x; end if; return result; end rol_stage; -------------------------------------------------------------------------- begin -------------------------------------------------------------------------- gen_non_pipelined: if do_pipelined = false generate begin rot_data(0) <= din; gen_rotate_right: for stage in 0 to num_rounds-1 generate begin rot_data(stage+1) <= rol_stage(rot_data(stage), sa_rnd(stage), stage, aggregate_size); end generate; sa_rnd <= to_signed(sa, num_rounds); dout <= rot_data(num_rounds); dout_vld <= din_vld; end generate; -------------------------------------------------------------------------- gen_pipelined: if do_pipelined = true generate begin rot_data(0) <= din; sa_rnd_pipe(0) <= to_signed(sa, num_rounds); dout_vld_pipe(0) <= din_vld; gen_rotate_right: for stage in 0 to num_rounds-1 generate begin process(clk) begin if rising_edge(clk) then if rst = '1' then dout_vld_pipe(stage+1) <= '0'; else dout_vld_pipe(stage+1) <= dout_vld_pipe(stage); if dout_vld_pipe(stage) = '1' then sa_rnd_pipe(stage+1) <= sa_rnd_pipe(stage); rot_data(stage+1) <= rol_stage(rot_data(stage), sa_rnd_pipe(stage)(stage), stage, aggregate_size); end if; end if; end if; end process; end generate; dout <= rot_data(num_rounds); dout_vld <= dout_vld_pipe(num_rounds); end generate; -------------------------------------------------------------------------- end behavior;