Line 58... |
Line 58... |
rstn_i : in std_ulogic; -- global reset, low-active, async
|
rstn_i : in std_ulogic; -- global reset, low-active, async
|
ctrl_i : in std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
|
ctrl_i : in std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
|
-- data input --
|
-- data input --
|
rs1_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 1
|
rs1_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 1
|
rs2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 2
|
rs2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 2
|
pc2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- delayed PC
|
pc_i : in std_ulogic_vector(data_width_c-1 downto 0); -- current PC
|
|
pc2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- next PC
|
imm_i : in std_ulogic_vector(data_width_c-1 downto 0); -- immediate
|
imm_i : in std_ulogic_vector(data_width_c-1 downto 0); -- immediate
|
csr_i : in std_ulogic_vector(data_width_c-1 downto 0); -- CSR read data
|
csr_i : in std_ulogic_vector(data_width_c-1 downto 0); -- CSR read data
|
-- data output --
|
-- data output --
|
cmp_o : out std_ulogic_vector(1 downto 0); -- comparator status
|
cmp_o : out std_ulogic_vector(1 downto 0); -- comparator status
|
res_o : out std_ulogic_vector(data_width_c-1 downto 0); -- ALU result
|
res_o : out std_ulogic_vector(data_width_c-1 downto 0); -- ALU result
|
Line 83... |
Line 84... |
-- operands --
|
-- operands --
|
signal opa, opb : std_ulogic_vector(data_width_c-1 downto 0);
|
signal opa, opb : std_ulogic_vector(data_width_c-1 downto 0);
|
|
|
-- results --
|
-- results --
|
signal addsub_res : std_ulogic_vector(data_width_c downto 0);
|
signal addsub_res : std_ulogic_vector(data_width_c downto 0);
|
--
|
signal alu_res : std_ulogic_vector(data_width_c-1 downto 0);
|
signal cp_res : std_ulogic_vector(data_width_c-1 downto 0);
|
signal cp_res : std_ulogic_vector(data_width_c-1 downto 0);
|
signal arith_res : std_ulogic_vector(data_width_c-1 downto 0);
|
|
signal logic_res : std_ulogic_vector(data_width_c-1 downto 0);
|
|
|
|
-- co-processor arbiter and interface --
|
-- co-processor arbiter and interface --
|
type cp_ctrl_t is record
|
type cp_ctrl_t is record
|
cmd : std_ulogic;
|
cmd : std_ulogic;
|
cmd_ff : std_ulogic;
|
cmd_ff : std_ulogic;
|
Line 117... |
Line 116... |
cmp_o <= cmp;
|
cmp_o <= cmp;
|
|
|
|
|
-- ALU Input Operand Mux ------------------------------------------------------------------
|
-- ALU Input Operand Mux ------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
opa <= pc2_i when (ctrl_i(ctrl_alu_opa_mux_c) = '1') else rs1_i; -- operand a (first ALU input operand), only required for arithmetic ops
|
opa <= pc_i when (ctrl_i(ctrl_alu_opa_mux_c) = '1') else rs1_i; -- operand a (first ALU input operand), only required for arithmetic ops
|
opb <= imm_i when (ctrl_i(ctrl_alu_opb_mux_c) = '1') else rs2_i; -- operand b (second ALU input operand)
|
opb <= imm_i when (ctrl_i(ctrl_alu_opb_mux_c) = '1') else rs2_i; -- operand b (second ALU input operand)
|
|
|
|
|
-- Binary Adder/Subtracter ----------------------------------------------------------------
|
-- Binary Adder/Subtracter ----------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
Line 134... |
Line 133... |
begin
|
begin
|
-- operand sign-extension --
|
-- operand sign-extension --
|
op_a_v := (opa(opa'left) and (not ctrl_i(ctrl_alu_unsigned_c))) & opa;
|
op_a_v := (opa(opa'left) and (not ctrl_i(ctrl_alu_unsigned_c))) & opa;
|
op_b_v := (opb(opb'left) and (not ctrl_i(ctrl_alu_unsigned_c))) & opb;
|
op_b_v := (opb(opb'left) and (not ctrl_i(ctrl_alu_unsigned_c))) & opb;
|
-- add/sub(slt) select --
|
-- add/sub(slt) select --
|
if (ctrl_i(ctrl_alu_addsub_c) = '1') then -- subtraction
|
if (ctrl_i(ctrl_alu_op0_c) = '1') then -- subtraction
|
op_y_v := not op_b_v;
|
op_y_v := not op_b_v;
|
cin_v(0) := '1';
|
cin_v(0) := '1';
|
else -- addition
|
else -- addition
|
op_y_v := op_b_v;
|
op_y_v := op_b_v;
|
cin_v(0) := '0';
|
cin_v(0) := '0';
|
end if;
|
end if;
|
-- adder core (result + carry/borrow) --
|
-- adder core --
|
addsub_res <= std_ulogic_vector(unsigned(op_a_v) + unsigned(op_y_v) + unsigned(cin_v(0 downto 0)));
|
addsub_res <= std_ulogic_vector(unsigned(op_a_v) + unsigned(op_y_v) + unsigned(cin_v(0 downto 0)));
|
end process binary_arithmetic_core;
|
end process binary_arithmetic_core;
|
|
|
-- direct output of address result --
|
-- direct output of adder result --
|
add_o <= addsub_res(data_width_c-1 downto 0);
|
add_o <= addsub_res(data_width_c-1 downto 0);
|
|
|
-- ALU arithmetic logic core --
|
|
arithmetic_core: process(ctrl_i, addsub_res)
|
-- ALU Operation Select -------------------------------------------------------------------
|
|
-- -------------------------------------------------------------------------------------------
|
|
alu_core: process(ctrl_i, addsub_res, rs1_i, opb)
|
begin
|
begin
|
if (ctrl_i(ctrl_alu_arith_c) = alu_arith_cmd_addsub_c) then -- ADD/SUB
|
case ctrl_i(ctrl_alu_op2_c downto ctrl_alu_op0_c) is
|
arith_res <= addsub_res(data_width_c-1 downto 0);
|
when alu_op_add_c => alu_res <= addsub_res(data_width_c-1 downto 0); -- (default)
|
else -- SLT
|
when alu_op_sub_c => alu_res <= addsub_res(data_width_c-1 downto 0);
|
arith_res <= (others => '0');
|
-- when alu_op_mova_c => alu_res <= rs1_i; -- FIXME
|
arith_res(0) <= addsub_res(addsub_res'left); -- => carry/borrow
|
when alu_op_slt_c => alu_res <= (others => '0'); alu_res(0) <= addsub_res(addsub_res'left); -- => carry/borrow
|
end if;
|
when alu_op_movb_c => alu_res <= opb;
|
end process arithmetic_core;
|
when alu_op_xor_c => alu_res <= rs1_i xor opb; -- only rs1 required for logic ops (opa would also contain pc)
|
|
when alu_op_or_c => alu_res <= rs1_i or opb;
|
|
when alu_op_and_c => alu_res <= rs1_i and opb;
|
|
when others => alu_res <= addsub_res(data_width_c-1 downto 0);
|
|
end case;
|
|
end process alu_core;
|
|
|
|
-- ALU Function Select --------------------------------------------------------------------
|
|
-- -------------------------------------------------------------------------------------------
|
|
alu_function_mux: process(ctrl_i, alu_res, pc2_i, csr_i, cp_res)
|
|
begin
|
|
case ctrl_i(ctrl_alu_func1_c downto ctrl_alu_func0_c) is
|
|
when alu_func_core_c => res_o <= alu_res; -- (default)
|
|
when alu_func_nxpc_c => res_o <= pc2_i;
|
|
when alu_func_csrr_c => res_o <= csr_i;
|
|
when alu_func_copro_c => res_o <= cp_res;
|
|
when others => res_o <= alu_res; -- undefined
|
|
end case;
|
|
end process alu_function_mux;
|
|
|
|
|
|
-- **************************************************************************************************************************
|
|
-- Co-Processors
|
|
-- **************************************************************************************************************************
|
|
|
-- Co-Processor Arbiter -------------------------------------------------------------------
|
-- Co-Processor Arbiter -------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- Interface:
|
-- Interface:
|
-- Co-processor "valid" signal has to be asserted (for one cycle) one cycle before asserting output data
|
-- Co-processor "valid" signal has to be asserted (for one cycle) one cycle before asserting output data
|
Line 191... |
Line 214... |
end if;
|
end if;
|
end if;
|
end if;
|
end process cp_arbiter;
|
end process cp_arbiter;
|
|
|
-- is co-processor operation? --
|
-- is co-processor operation? --
|
cp_ctrl.cmd <= '1' when (ctrl_i(ctrl_alu_func1_c downto ctrl_alu_func0_c) = alu_func_cmd_copro_c) else '0';
|
cp_ctrl.cmd <= '1' when (ctrl_i(ctrl_alu_func1_c downto ctrl_alu_func0_c) = alu_func_copro_c) else '0';
|
cp_ctrl.start <= '1' when (cp_ctrl.cmd = '1') and (cp_ctrl.cmd_ff = '0') else '0';
|
cp_ctrl.start <= '1' when (cp_ctrl.cmd = '1') and (cp_ctrl.cmd_ff = '0') else '0';
|
|
|
-- co-processor select / star trigger --
|
-- co-processor select / star trigger --
|
cp_start(0) <= '1' when (cp_ctrl.start = '1') and (ctrl_i(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) = "00") else '0';
|
cp_start(0) <= '1' when (cp_ctrl.start = '1') and (ctrl_i(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) = "00") else '0';
|
cp_start(1) <= '1' when (cp_ctrl.start = '1') and (ctrl_i(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) = "01") else '0';
|
cp_start(1) <= '1' when (cp_ctrl.start = '1') and (ctrl_i(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) = "01") else '0';
|
Line 207... |
Line 230... |
|
|
-- co-processor result - only the *actually selected* co-processor may output data != 0 --
|
-- co-processor result - only the *actually selected* co-processor may output data != 0 --
|
cp_res <= cp_result(0) or cp_result(1) or cp_result(2) or cp_result(3);
|
cp_res <= cp_result(0) or cp_result(1) or cp_result(2) or cp_result(3);
|
|
|
|
|
-- ALU Logic Core -------------------------------------------------------------------------
|
|
-- -------------------------------------------------------------------------------------------
|
|
alu_logic_core: process(ctrl_i, rs1_i, opb)
|
|
begin
|
|
case ctrl_i(ctrl_alu_logic1_c downto ctrl_alu_logic0_c) is
|
|
when alu_logic_cmd_movb_c => logic_res <= opb; -- (default)
|
|
when alu_logic_cmd_xor_c => logic_res <= rs1_i xor opb; -- only rs1 required for logic ops (opa would also contain pc)
|
|
when alu_logic_cmd_or_c => logic_res <= rs1_i or opb;
|
|
when alu_logic_cmd_and_c => logic_res <= rs1_i and opb;
|
|
when others => logic_res <= opb; -- undefined
|
|
end case;
|
|
end process alu_logic_core;
|
|
|
|
|
|
-- ALU Function Select --------------------------------------------------------------------
|
|
-- -------------------------------------------------------------------------------------------
|
|
alu_function_mux: process(ctrl_i, arith_res, logic_res, csr_i, cp_res)
|
|
begin
|
|
case ctrl_i(ctrl_alu_func1_c downto ctrl_alu_func0_c) is
|
|
when alu_func_cmd_arith_c => res_o <= arith_res; -- (default)
|
|
when alu_func_cmd_logic_c => res_o <= logic_res;
|
|
when alu_func_cmd_csrr_c => res_o <= csr_i;
|
|
when alu_func_cmd_copro_c => res_o <= cp_res;
|
|
when others => res_o <= arith_res; -- undefined
|
|
end case;
|
|
end process alu_function_mux;
|
|
|
|
|
|
-- **************************************************************************************************************************
|
|
-- Co-Processors
|
|
-- **************************************************************************************************************************
|
|
|
|
-- Co-Processor 0: Shifter (CPU Core ISA) --------------------------------------------------
|
-- Co-Processor 0: Shifter (CPU Core ISA) --------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
neorv32_cpu_cp_shifter_inst: neorv32_cpu_cp_shifter
|
neorv32_cpu_cp_shifter_inst: neorv32_cpu_cp_shifter
|
generic map (
|
generic map (
|
FAST_SHIFT_EN => FAST_SHIFT_EN -- use barrel shifter for shift operations
|
FAST_SHIFT_EN => FAST_SHIFT_EN -- use barrel shifter for shift operations
|