Line 42... |
Line 42... |
library neorv32;
|
library neorv32;
|
use neorv32.neorv32_package.all;
|
use neorv32.neorv32_package.all;
|
|
|
entity neorv32_cpu_alu is
|
entity neorv32_cpu_alu is
|
generic (
|
generic (
|
CPU_EXTENSION_RISCV_M : boolean := true -- implement muld/div extension?
|
CPU_EXTENSION_RISCV_M : boolean := true; -- implement muld/div extension?
|
|
FAST_SHIFT_EN : boolean := false -- use barrel shifter for shift operations
|
);
|
);
|
port (
|
port (
|
-- global control --
|
-- global control --
|
clk_i : in std_ulogic; -- global clock, rising edge
|
clk_i : in std_ulogic; -- global clock, rising edge
|
rstn_i : in std_ulogic; -- global reset, low-active, async
|
rstn_i : in std_ulogic; -- global reset, low-active, async
|
Line 93... |
Line 94... |
start : std_ulogic;
|
start : std_ulogic;
|
run : std_ulogic;
|
run : std_ulogic;
|
halt : std_ulogic;
|
halt : std_ulogic;
|
cnt : std_ulogic_vector(4 downto 0);
|
cnt : std_ulogic_vector(4 downto 0);
|
sreg : std_ulogic_vector(data_width_c-1 downto 0);
|
sreg : std_ulogic_vector(data_width_c-1 downto 0);
|
|
-- for barrel shifter only --
|
|
bs_a_in : std_ulogic_vector(4 downto 0);
|
|
bs_d_in : std_ulogic_vector(data_width_c-1 downto 0);
|
end record;
|
end record;
|
signal shifter : shifter_t;
|
signal shifter : shifter_t;
|
|
|
-- co-processor arbiter and interface --
|
-- co-processor arbiter and interface --
|
type cp_ctrl_t is record
|
type cp_ctrl_t is record
|
Line 156... |
Line 160... |
addsub_res <= res_v(31 downto 0);
|
addsub_res <= res_v(31 downto 0);
|
addsub_res <= res_v(31 downto 0);
|
addsub_res <= res_v(31 downto 0);
|
end process binary_arithmetic_core;
|
end process binary_arithmetic_core;
|
|
|
|
|
-- Iterative Shifter Unit -----------------------------------------------------------------
|
-- Shifter Unit ---------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
shifter_unit: process(rstn_i, clk_i)
|
shifter_unit: process(rstn_i, clk_i)
|
|
variable bs_input_v : std_ulogic_vector(data_width_c-1 downto 0);
|
|
variable bs_level_4_v : std_ulogic_vector(data_width_c-1 downto 0);
|
|
variable bs_level_3_v : std_ulogic_vector(data_width_c-1 downto 0);
|
|
variable bs_level_2_v : std_ulogic_vector(data_width_c-1 downto 0);
|
|
variable bs_level_1_v : std_ulogic_vector(data_width_c-1 downto 0);
|
|
variable bs_level_0_v : std_ulogic_vector(data_width_c-1 downto 0);
|
begin
|
begin
|
if (rstn_i = '0') then
|
if (rstn_i = '0') then
|
shifter.sreg <= (others => '0');
|
shifter.sreg <= (others => '0');
|
shifter.cnt <= (others => '0');
|
shifter.cnt <= (others => '0');
|
shifter.cmd_ff <= '0';
|
shifter.cmd_ff <= '0';
|
|
if (FAST_SHIFT_EN = true) then
|
|
shifter.bs_d_in <= (others => '0');
|
|
shifter.bs_a_in <= (others => '0');
|
|
end if;
|
elsif rising_edge(clk_i) then
|
elsif rising_edge(clk_i) then
|
shifter.cmd_ff <= shifter.cmd;
|
shifter.cmd_ff <= shifter.cmd;
|
|
|
|
-- --------------------------------------------------------------------------------
|
|
-- Iterative shifter (small but slow) (default)
|
|
-- --------------------------------------------------------------------------------
|
|
if (FAST_SHIFT_EN = false) then
|
|
|
if (shifter.start = '1') then -- trigger new shift
|
if (shifter.start = '1') then -- trigger new shift
|
shifter.sreg <= opa; -- shift operand
|
shifter.sreg <= opa; -- shift operand
|
shifter.cnt <= opb(index_size_f(data_width_c)-1 downto 0); -- shift amount
|
shifter.cnt <= opb(index_size_f(data_width_c)-1 downto 0); -- shift amount
|
elsif (shifter.run = '1') then -- running shift
|
elsif (shifter.run = '1') then -- running shift
|
-- coarse shift: multiples of 4 --
|
-- coarse shift: multiples of 4 --
|
Line 191... |
Line 211... |
else -- SRL: shift right logical / SRA: shift right arithmetical
|
else -- SRL: shift right logical / SRA: shift right arithmetical
|
shifter.sreg <= (shifter.sreg(shifter.sreg'left) and ctrl_i(ctrl_alu_shift_ar_c)) & shifter.sreg(shifter.sreg'left downto 1);
|
shifter.sreg <= (shifter.sreg(shifter.sreg'left) and ctrl_i(ctrl_alu_shift_ar_c)) & shifter.sreg(shifter.sreg'left downto 1);
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
|
-- --------------------------------------------------------------------------------
|
|
-- Barrel shifter (huge but fast)
|
|
-- --------------------------------------------------------------------------------
|
|
else
|
|
|
|
-- operands and cycle control --
|
|
if (shifter.start = '1') then -- trigger new shift
|
|
shifter.bs_d_in <= opa; -- shift data
|
|
shifter.bs_a_in <= opb(index_size_f(data_width_c)-1 downto 0); -- shift amount
|
|
shifter.cnt <= (others => '0');
|
|
end if;
|
|
|
|
-- convert left shifts to right shifts --
|
|
if (ctrl_i(ctrl_alu_shift_dir_c) = '0') then -- is left shift?
|
|
bs_input_v := bit_rev_f(shifter.bs_d_in); -- reverse bit order of input operand
|
|
else
|
|
bs_input_v := shifter.bs_d_in;
|
|
end if;
|
|
-- shift >> 16 --
|
|
if (shifter.bs_a_in(4) = '1') then
|
|
bs_level_4_v(31 downto 16) := (others => (bs_input_v(bs_input_v'left) and ctrl_i(ctrl_alu_shift_ar_c)));
|
|
bs_level_4_v(15 downto 00) := (bs_input_v(31 downto 16));
|
|
else
|
|
bs_level_4_v := bs_input_v;
|
|
end if;
|
|
-- shift >> 8 --
|
|
if (shifter.bs_a_in(3) = '1') then
|
|
bs_level_3_v(31 downto 24) := (others => (bs_input_v(bs_input_v'left) and ctrl_i(ctrl_alu_shift_ar_c)));
|
|
bs_level_3_v(23 downto 00) := (bs_level_4_v(31 downto 8));
|
|
else
|
|
bs_level_3_v := bs_level_4_v;
|
|
end if;
|
|
-- shift >> 4 --
|
|
if (shifter.bs_a_in(2) = '1') then
|
|
bs_level_2_v(31 downto 28) := (others => (bs_input_v(bs_input_v'left) and ctrl_i(ctrl_alu_shift_ar_c)));
|
|
bs_level_2_v(27 downto 00) := (bs_level_3_v(31 downto 4));
|
|
else
|
|
bs_level_2_v := bs_level_3_v;
|
|
end if;
|
|
-- shift >> 2 --
|
|
if (shifter.bs_a_in(1) = '1') then
|
|
bs_level_1_v(31 downto 30) := (others => (bs_input_v(bs_input_v'left) and ctrl_i(ctrl_alu_shift_ar_c)));
|
|
bs_level_1_v(29 downto 00) := (bs_level_2_v(31 downto 2));
|
|
else
|
|
bs_level_1_v := bs_level_2_v;
|
|
end if;
|
|
-- shift >> 1 --
|
|
if (shifter.bs_a_in(0) = '1') then
|
|
bs_level_0_v(31 downto 31) := (others => (bs_input_v(bs_input_v'left) and ctrl_i(ctrl_alu_shift_ar_c)));
|
|
bs_level_0_v(30 downto 00) := (bs_level_1_v(31 downto 1));
|
|
else
|
|
bs_level_0_v := bs_level_1_v;
|
|
end if;
|
|
-- re-convert original left shifts --
|
|
if (ctrl_i(ctrl_alu_shift_dir_c) = '0') then
|
|
shifter.sreg <= bit_rev_f(bs_level_0_v);
|
|
else
|
|
shifter.sreg <= bs_level_0_v;
|
|
end if;
|
|
end if;
|
end if;
|
end if;
|
end process shifter_unit;
|
end process shifter_unit;
|
|
|
-- is shift operation? --
|
-- is shift operation? --
|
shifter.cmd <= '1' when (ctrl_i(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) = alu_cmd_shift_c) else '0';
|
shifter.cmd <= '1' when (ctrl_i(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) = alu_cmd_shift_c) else '0';
|