Line 40... |
Line 40... |
|
|
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 (
|
|
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
|
|
CPU_EXTENSION_RISCV_M : boolean := false -- implement mul/div extension?
|
|
);
|
|
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
|
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
|
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); -- delayed PC
|
pc2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- delayed 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
|
Line 73... |
Line 68... |
end neorv32_cpu_alu;
|
end neorv32_cpu_alu;
|
|
|
architecture neorv32_cpu_cpu_rtl of neorv32_cpu_alu is
|
architecture neorv32_cpu_cpu_rtl of neorv32_cpu_alu is
|
|
|
-- operands --
|
-- operands --
|
signal opa, opb, opc, pc_inc : std_ulogic_vector(data_width_c-1 downto 0);
|
signal opa, opb, opc : std_ulogic_vector(data_width_c-1 downto 0);
|
|
|
-- results --
|
-- results --
|
signal add_res : std_ulogic_vector(data_width_c-1 downto 0);
|
signal add_res : std_ulogic_vector(data_width_c-1 downto 0);
|
signal alu_res : std_ulogic_vector(data_width_c-1 downto 0);
|
signal alu_res : std_ulogic_vector(data_width_c-1 downto 0);
|
|
|
Line 107... |
Line 102... |
|
|
begin
|
begin
|
|
|
-- Operand Mux ----------------------------------------------------------------------------
|
-- Operand Mux ----------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
input_op_mux: process(ctrl_i, csr_i, pc2_i, pc_i, rs1_i, rs2_i, imm_i, pc_inc)
|
input_op_mux: process(ctrl_i, csr_i, pc2_i, rs1_i, rs2_i, imm_i)
|
begin
|
begin
|
-- opa (first ALU input operand) --
|
-- opa (first ALU input operand) --
|
case ctrl_i(ctrl_alu_opa_mux_msb_c downto ctrl_alu_opa_mux_lsb_c) is
|
if (ctrl_i(ctrl_alu_opa_mux_msb_c) = '0') then
|
when "00" => opa <= rs1_i;
|
if (ctrl_i(ctrl_alu_opa_mux_lsb_c) = '0') then
|
when "01" => opa <= pc2_i;
|
opa <= rs1_i;
|
when "10" => opa <= csr_i;
|
else
|
when others => opa <= pc_i;
|
opa <= pc2_i;
|
end case;
|
end if;
|
|
else
|
|
opa <= csr_i;
|
|
end if;
|
-- opb (second ALU input operand) --
|
-- opb (second ALU input operand) --
|
case ctrl_i(ctrl_alu_opb_mux_msb_c downto ctrl_alu_opb_mux_lsb_c) is
|
if (ctrl_i(ctrl_alu_opb_mux_msb_c) = '0') then
|
when "00" => opb <= rs2_i;
|
if (ctrl_i(ctrl_alu_opb_mux_lsb_c) = '0') then
|
when "01" => opb <= imm_i;
|
opb <= rs2_i;
|
when "10" => opb <= rs1_i;
|
else
|
when others => opb <= pc_inc;
|
opb <= imm_i;
|
end case;
|
end if;
|
|
else
|
|
opb <= rs1_i;
|
|
end if;
|
-- opc (second operand for comparison (and SUB)) --
|
-- opc (second operand for comparison (and SUB)) --
|
if (ctrl_i(ctrl_alu_opc_mux_c) = '0') then
|
if (ctrl_i(ctrl_alu_opc_mux_c) = '0') then
|
opc <= imm_i;
|
opc <= imm_i;
|
else
|
else
|
opc <= rs2_i;
|
opc <= rs2_i;
|
end if;
|
end if;
|
end process input_op_mux;
|
end process input_op_mux;
|
|
|
-- PC increment --
|
|
pc_inc <= x"00000002" when (CPU_EXTENSION_RISCV_C = true) else x"00000004";
|
|
|
|
|
|
-- Comparator Unit ------------------------------------------------------------------------
|
-- Comparator Unit ------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- less than (x < y) --
|
-- less than (x < y) --
|
cmp_opx <= (rs1_i(rs1_i'left) and (not ctrl_i(ctrl_alu_unsigned_c))) & rs1_i;
|
cmp_opx <= (rs1_i(rs1_i'left) and (not ctrl_i(ctrl_alu_unsigned_c))) & rs1_i;
|
Line 200... |
Line 198... |
cp_cmd_ff <= '0';
|
cp_cmd_ff <= '0';
|
cp_busy <= '0';
|
cp_busy <= '0';
|
cp_rb_ff0 <= '0';
|
cp_rb_ff0 <= '0';
|
cp_rb_ff1 <= '0';
|
cp_rb_ff1 <= '0';
|
elsif rising_edge(clk_i) then
|
elsif rising_edge(clk_i) then
|
if (CPU_EXTENSION_RISCV_M = true) then
|
if (ctrl_i(ctrl_sys_m_ext_en_c) = '1') then
|
cp_cmd_ff <= ctrl_i(ctrl_cp_use_c);
|
cp_cmd_ff <= ctrl_i(ctrl_cp_use_c);
|
cp_rb_ff0 <= '0';
|
cp_rb_ff0 <= '0';
|
cp_rb_ff1 <= cp_rb_ff0;
|
cp_rb_ff1 <= cp_rb_ff0;
|
if (cp_start = '1') then
|
if (cp_start = '1') then
|
cp_busy <= '1';
|
cp_busy <= '1';
|