Line 52... |
Line 52... |
use neorv32.neorv32_package.all;
|
use neorv32.neorv32_package.all;
|
|
|
entity neorv32_cpu is
|
entity neorv32_cpu is
|
generic (
|
generic (
|
-- General --
|
-- General --
|
HW_THREAD_ID : std_ulogic_vector(31 downto 0):= (others => '0'); -- hardware thread id
|
HW_THREAD_ID : natural := 0; -- hardware thread id (32-bit)
|
CPU_BOOT_ADDR : std_ulogic_vector(31 downto 0):= (others => '0'); -- cpu boot address
|
CPU_BOOT_ADDR : std_ulogic_vector(31 downto 0):= x"00000000"; -- cpu boot address
|
BUS_TIMEOUT : natural := 63; -- cycles after an UNACKNOWLEDGED bus access triggers a bus fault exception
|
BUS_TIMEOUT : natural := 63; -- cycles after an UNACKNOWLEDGED bus access triggers a bus fault exception
|
-- RISC-V CPU Extensions --
|
-- RISC-V CPU Extensions --
|
CPU_EXTENSION_RISCV_A : boolean := false; -- implement atomic extension?
|
CPU_EXTENSION_RISCV_A : boolean := false; -- implement atomic extension?
|
CPU_EXTENSION_RISCV_B : boolean := false; -- implement bit manipulation extensions?
|
CPU_EXTENSION_RISCV_B : boolean := false; -- implement bit manipulation extensions?
|
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
|
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
|
Line 142... |
Line 142... |
signal be_store : std_ulogic; -- bus error on store data access
|
signal be_store : std_ulogic; -- bus error on store data access
|
signal fetch_pc : std_ulogic_vector(data_width_c-1 downto 0); -- pc for instruction fetch
|
signal fetch_pc : std_ulogic_vector(data_width_c-1 downto 0); -- pc for instruction fetch
|
signal curr_pc : std_ulogic_vector(data_width_c-1 downto 0); -- current pc (for current executed instruction)
|
signal curr_pc : std_ulogic_vector(data_width_c-1 downto 0); -- current pc (for current executed instruction)
|
|
|
-- co-processor interface --
|
-- co-processor interface --
|
signal cp0_data, cp1_data, cp2_data, cp3_data : std_ulogic_vector(data_width_c-1 downto 0);
|
signal cp_start : std_ulogic_vector(7 downto 0); -- trigger co-processor i
|
signal cp0_valid, cp1_valid, cp2_valid, cp3_valid : std_ulogic;
|
signal cp_valid : std_ulogic_vector(7 downto 0); -- co-processor i done
|
signal cp0_start, cp1_start, cp2_start, cp3_start : std_ulogic;
|
signal cp_result : cp_data_if_t; -- co-processor result
|
|
|
-- pmp interface --
|
-- pmp interface --
|
signal pmp_addr : pmp_addr_if_t;
|
signal pmp_addr : pmp_addr_if_t;
|
signal pmp_ctrl : pmp_ctrl_if_t;
|
signal pmp_ctrl : pmp_ctrl_if_t;
|
|
|
Line 271... |
Line 271... |
clk_i => clk_i, -- global clock, rising edge
|
clk_i => clk_i, -- global clock, rising edge
|
ctrl_i => ctrl, -- main control bus
|
ctrl_i => ctrl, -- main control bus
|
-- data input --
|
-- data input --
|
mem_i => rdata, -- memory read data
|
mem_i => rdata, -- memory read data
|
alu_i => alu_res, -- ALU result
|
alu_i => alu_res, -- ALU result
|
csr_i => csr_rdata, -- CSR read data
|
|
-- data output --
|
-- data output --
|
rs1_o => rs1, -- operand 1
|
rs1_o => rs1, -- operand 1
|
rs2_o => rs2, -- operand 2
|
rs2_o => rs2, -- operand 2
|
cmp_o => comparator -- comparator status
|
cmp_o => comparator -- comparator status
|
);
|
);
|
Line 300... |
Line 299... |
imm_i => imm, -- immediate
|
imm_i => imm, -- immediate
|
-- data output --
|
-- data output --
|
res_o => alu_res, -- ALU result
|
res_o => alu_res, -- ALU result
|
add_o => alu_add, -- address computation result
|
add_o => alu_add, -- address computation result
|
-- co-processor interface --
|
-- co-processor interface --
|
cp0_start_o => cp0_start, -- trigger co-processor 0
|
cp_start_o => cp_start, -- trigger co-processor i
|
cp0_data_i => cp0_data, -- co-processor 0 result
|
cp_valid_i => cp_valid, -- co-processor i done
|
cp0_valid_i => cp0_valid, -- co-processor 0 result valid
|
cp_result_i => cp_result, -- co-processor result
|
cp1_start_o => cp1_start, -- trigger co-processor 1
|
|
cp1_data_i => cp1_data, -- co-processor 1 result
|
|
cp1_valid_i => cp1_valid, -- co-processor 1 result valid
|
|
cp2_start_o => cp2_start, -- trigger co-processor 2
|
|
cp2_data_i => cp2_data, -- co-processor 2 result
|
|
cp2_valid_i => cp2_valid, -- co-processor 2 result valid
|
|
cp3_start_o => cp3_start, -- trigger co-processor 3
|
|
cp3_data_i => cp3_data, -- co-processor 3 result
|
|
cp3_valid_i => cp3_valid, -- co-processor 3 result valid
|
|
-- status --
|
-- status --
|
wait_o => alu_wait -- busy due to iterative processing units
|
wait_o => alu_wait -- busy due to iterative processing units
|
);
|
);
|
|
|
|
|
Line 330... |
Line 320... |
port map (
|
port map (
|
-- global control --
|
-- global control --
|
clk_i => clk_i, -- global clock, rising edge
|
clk_i => clk_i, -- global clock, rising edge
|
rstn_i => rstn_i, -- global reset, low-active, async
|
rstn_i => rstn_i, -- global reset, low-active, async
|
ctrl_i => ctrl, -- main control bus
|
ctrl_i => ctrl, -- main control bus
|
start_i => cp0_start, -- trigger operation
|
start_i => cp_start(0), -- trigger operation
|
-- data input --
|
-- data input --
|
rs1_i => rs1, -- rf source 1
|
rs1_i => rs1, -- rf source 1
|
rs2_i => rs2, -- rf source 2
|
rs2_i => rs2, -- rf source 2
|
-- result and status --
|
-- result and status --
|
res_o => cp0_data, -- operation result
|
res_o => cp_result(0), -- operation result
|
valid_o => cp0_valid -- data output valid
|
valid_o => cp_valid(0) -- data output valid
|
);
|
);
|
end generate;
|
end generate;
|
|
|
neorv32_cpu_cp_muldiv_inst_false:
|
neorv32_cpu_cp_muldiv_inst_false:
|
if (CPU_EXTENSION_RISCV_M = false) generate
|
if (CPU_EXTENSION_RISCV_M = false) generate
|
cp0_data <= (others => '0');
|
cp_result(0) <= (others => '0');
|
cp0_valid <= cp0_start; -- to make sure CPU does not get stalled if there is an accidental access
|
cp_valid(0) <= cp_start(0); -- to make sure CPU does not get stalled if there is an accidental access
|
end generate;
|
end generate;
|
|
|
|
|
-- Co-Processor 1: Atomic Memory Access ('A' Extension) -----------------------------------
|
-- Co-Processor 1: Atomic Memory Access ('A' Extension) -----------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- "pseudo" co-processor for atomic operations
|
-- "pseudo" co-processor for atomic operations
|
-- used to get the result of a store-conditional operation into the data path
|
-- required to get the result of a store-conditional operation into the data path
|
atomic_op_cp: process(clk_i)
|
atomic_op_cp: process(clk_i)
|
begin
|
begin
|
if rising_edge(clk_i) then
|
if rising_edge(clk_i) then
|
if (cp1_start = '1') then
|
if (cp_start(1) = '1') then
|
atomic_sc_res <= not ctrl(ctrl_bus_lock_c);
|
atomic_sc_res <= not ctrl(ctrl_bus_lock_c);
|
else
|
else
|
atomic_sc_res <= '0';
|
atomic_sc_res <= '0';
|
end if;
|
end if;
|
end if;
|
end if;
|
end process atomic_op_cp;
|
end process atomic_op_cp;
|
|
|
-- CP result --
|
-- CP result --
|
cp1_data(data_width_c-1 downto 1) <= (others => '0');
|
cp_result(1)(data_width_c-1 downto 1) <= (others => '0');
|
cp1_data(0) <= atomic_sc_res when (CPU_EXTENSION_RISCV_A = true) else '0';
|
cp_result(1)(0) <= atomic_sc_res when (CPU_EXTENSION_RISCV_A = true) else '0';
|
cp1_valid <= cp1_start; -- always assigned even if A is disabled to make sure CPU does not get stalled if there is an accidental access
|
cp_valid(1) <= cp_start(1); -- always assigned even if A extension is disabled to make sure CPU does not get stalled if there is an accidental access
|
|
|
|
|
-- Co-Processor 2: Bit Manipulation ('B' Extension) ---------------------------------------
|
-- Co-Processor 2: Bit Manipulation ('B' Extension) ---------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
neorv32_cpu_cp_bitmanip_inst_true:
|
neorv32_cpu_cp_bitmanip_inst_true:
|
Line 378... |
Line 368... |
port map (
|
port map (
|
-- global control --
|
-- global control --
|
clk_i => clk_i, -- global clock, rising edge
|
clk_i => clk_i, -- global clock, rising edge
|
rstn_i => rstn_i, -- global reset, low-active, async
|
rstn_i => rstn_i, -- global reset, low-active, async
|
ctrl_i => ctrl, -- main control bus
|
ctrl_i => ctrl, -- main control bus
|
start_i => cp2_start, -- trigger operation
|
start_i => cp_start(2), -- trigger operation
|
-- data input --
|
-- data input --
|
cmp_i => comparator, -- comparator status
|
cmp_i => comparator, -- comparator status
|
rs1_i => rs1, -- rf source 1
|
rs1_i => rs1, -- rf source 1
|
rs2_i => rs2, -- rf source 2
|
rs2_i => rs2, -- rf source 2
|
-- result and status --
|
-- result and status --
|
res_o => cp2_data, -- operation result
|
res_o => cp_result(2), -- operation result
|
valid_o => cp2_valid -- data output valid
|
valid_o => cp_valid(2) -- data output valid
|
);
|
);
|
end generate;
|
end generate;
|
|
|
neorv32_cpu_cp_bitmanip_inst_false:
|
neorv32_cpu_cp_bitmanip_inst_false:
|
if (CPU_EXTENSION_RISCV_B = false) generate
|
if (CPU_EXTENSION_RISCV_B = false) generate
|
cp2_data <= (others => '0');
|
cp_result(2) <= (others => '0');
|
cp2_valid <= cp2_start; -- to make sure CPU does not get stalled if there is an accidental access
|
cp_valid(2) <= cp_start(2); -- to make sure CPU does not get stalled if there is an accidental access
|
end generate;
|
end generate;
|
|
|
|
|
-- Co-Processor 3: Not implemented --------------------------------------------------------
|
-- Co-Processor 3: CSR (Read) Access ('Zicsr' Extension) ----------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
cp3_data <= (others => '0');
|
-- "pseudo" co-processor for CSR *read* access operations
|
cp3_valid <= cp3_start; -- to make sure CPU does not get stalled if there is an accidental access
|
-- required to get the CSR read data into the data path
|
|
cp_result(3) <= csr_rdata when (CPU_EXTENSION_RISCV_Zicsr = true) else (others => '0');
|
|
cp_valid(3) <= cp_start(3); -- always assigned even if Zicsr extension is disabled to make sure CPU does not get stalled if there is an accidental access
|
|
|
|
|
|
-- Co-Processor 4..7: Not Implemented Yet -------------------------------------------------
|
|
-- -------------------------------------------------------------------------------------------
|
|
cp_result(4) <= (others => '0');
|
|
cp_valid(4) <= '0';
|
|
--
|
|
cp_result(5) <= (others => '0');
|
|
cp_valid(5) <= '0';
|
|
--
|
|
cp_result(6) <= (others => '0');
|
|
cp_valid(6) <= '0';
|
|
--
|
|
cp_result(7) <= (others => '0');
|
|
cp_valid(7) <= '0';
|
|
|
|
|
-- Bus Interface Unit ---------------------------------------------------------------------
|
-- Bus Interface Unit ---------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
neorv32_cpu_bus_inst: neorv32_cpu_bus
|
neorv32_cpu_bus_inst: neorv32_cpu_bus
|