Line 42... |
Line 42... |
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
|
FAST_SHIFT_EN : boolean := false; -- use barrel shifter for shift operations
|
|
TINY_SHIFT_EN : boolean := false -- use tiny (single-bit) 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 174... |
Line 175... |
if (shifter.start = '1') then -- trigger new shift
|
if (shifter.start = '1') then -- trigger new shift
|
shifter.sreg <= rs1_i; -- shift operand (can only be rs1; opa would also contain pc)
|
shifter.sreg <= rs1_i; -- shift operand (can only be rs1; opa would also contain pc)
|
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 --
|
if (or_all_f(shifter.cnt(shifter.cnt'left downto 2)) = '1') then -- shift amount >= 4
|
if (TINY_SHIFT_EN = false) and -- use coarse shifts first if TINY SHIFT option is NOT enabled
|
|
(or_all_f(shifter.cnt(shifter.cnt'left downto 2)) = '1') then -- shift amount >= 4
|
shifter.cnt <= std_ulogic_vector(unsigned(shifter.cnt) - 4);
|
shifter.cnt <= std_ulogic_vector(unsigned(shifter.cnt) - 4);
|
if (ctrl_i(ctrl_alu_shift_dir_c) = '0') then -- SLL: shift left logical
|
if (ctrl_i(ctrl_alu_shift_dir_c) = '0') then -- SLL: shift left logical
|
shifter.sreg <= shifter.sreg(shifter.sreg'left-4 downto 0) & "0000";
|
shifter.sreg <= shifter.sreg(shifter.sreg'left-4 downto 0) & "0000";
|
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(shifter.sreg'left) and ctrl_i(ctrl_alu_shift_ar_c)) &
|
(shifter.sreg(shifter.sreg'left) and ctrl_i(ctrl_alu_shift_ar_c)) &
|
(shifter.sreg(shifter.sreg'left) and ctrl_i(ctrl_alu_shift_ar_c)) &
|
(shifter.sreg(shifter.sreg'left) and ctrl_i(ctrl_alu_shift_ar_c)) &
|
(shifter.sreg(shifter.sreg'left) and ctrl_i(ctrl_alu_shift_ar_c)) &
|
(shifter.sreg(shifter.sreg'left) and ctrl_i(ctrl_alu_shift_ar_c)) & shifter.sreg(shifter.sreg'left downto 4);
|
(shifter.sreg(shifter.sreg'left) and ctrl_i(ctrl_alu_shift_ar_c)) & shifter.sreg(shifter.sreg'left downto 4);
|
end if;
|
end if;
|
-- fine shift: single shifts, 0..3 times --
|
-- fine shift: single shifts, 0..3 times; use ONLY single-bit shifts if TINY_SHIFT_EN is enabled (even smaller than the default approach) --
|
else
|
else
|
shifter.cnt <= std_ulogic_vector(unsigned(shifter.cnt) - 1);
|
shifter.cnt <= std_ulogic_vector(unsigned(shifter.cnt) - 1);
|
if (ctrl_i(ctrl_alu_shift_dir_c) = '0') then -- SLL: shift left logical
|
if (ctrl_i(ctrl_alu_shift_dir_c) = '0') then -- SLL: shift left logical
|
shifter.sreg <= shifter.sreg(shifter.sreg'left-1 downto 0) & '0';
|
shifter.sreg <= shifter.sreg(shifter.sreg'left-1 downto 0) & '0';
|
else -- SRL: shift right logical / SRA: shift right arithmetical
|
else -- SRL: shift right logical / SRA: shift right arithmetical
|