Line 7... |
Line 7... |
-- # * neorv32_cpu_bus.vhd - Instruction and data bus interface unit #
|
-- # * neorv32_cpu_bus.vhd - Instruction and data bus interface unit #
|
-- # * neorv32_cpu_cp_muldiv.vhd - MULDIV co-processor #
|
-- # * neorv32_cpu_cp_muldiv.vhd - MULDIV co-processor #
|
-- # * neorv32_cpu_ctrl.vhd - CPU control and CSR system #
|
-- # * neorv32_cpu_ctrl.vhd - CPU control and CSR system #
|
-- # * neorv32_cpu_decompressor.vhd - Compressed instructions decoder #
|
-- # * neorv32_cpu_decompressor.vhd - Compressed instructions decoder #
|
-- # * neorv32_cpu_regfile.vhd - Data register file #
|
-- # * neorv32_cpu_regfile.vhd - Data register file #
|
-- # #
|
|
-- # * neorv32_package.vhd - Main CPU/processor package file #
|
-- # * neorv32_package.vhd - Main CPU/processor package file #
|
-- # #
|
-- # #
|
-- # Check out the processor's data sheet for more information: docs/NEORV32.pdf #
|
-- # Check out the processor's data sheet for more information: docs/NEORV32.pdf #
|
-- # ********************************************************************************************* #
|
-- # ********************************************************************************************* #
|
-- # BSD 3-Clause License #
|
-- # BSD 3-Clause License #
|
Line 58... |
Line 57... |
HW_THREAD_ID : std_ulogic_vector(31 downto 0):= (others => '0'); -- hardware thread id
|
HW_THREAD_ID : std_ulogic_vector(31 downto 0):= (others => '0'); -- hardware thread id
|
CPU_BOOT_ADDR : std_ulogic_vector(31 downto 0):= (others => '0'); -- cpu boot address
|
CPU_BOOT_ADDR : std_ulogic_vector(31 downto 0):= (others => '0'); -- 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_C : boolean := false; -- implement compressed extension?
|
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
|
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
|
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
|
CPU_EXTENSION_RISCV_M : boolean := false; -- implement muld/div extension?
|
CPU_EXTENSION_RISCV_M : boolean := false; -- implement muld/div extension?
|
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension?
|
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension?
|
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
|
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
|
Line 122... |
Line 122... |
signal ctrl : std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
|
signal ctrl : std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
|
signal alu_cmp : std_ulogic_vector(1 downto 0); -- alu comparator result
|
signal alu_cmp : std_ulogic_vector(1 downto 0); -- alu comparator result
|
signal imm : std_ulogic_vector(data_width_c-1 downto 0); -- immediate
|
signal imm : std_ulogic_vector(data_width_c-1 downto 0); -- immediate
|
signal instr : std_ulogic_vector(data_width_c-1 downto 0); -- new instruction
|
signal instr : std_ulogic_vector(data_width_c-1 downto 0); -- new instruction
|
signal rs1, rs2 : std_ulogic_vector(data_width_c-1 downto 0); -- source registers
|
signal rs1, rs2 : std_ulogic_vector(data_width_c-1 downto 0); -- source registers
|
signal alu_opb : std_ulogic_vector(data_width_c-1 downto 0); -- ALU operand b
|
|
signal alu_res : std_ulogic_vector(data_width_c-1 downto 0); -- alu result
|
signal alu_res : std_ulogic_vector(data_width_c-1 downto 0); -- alu result
|
signal alu_add : std_ulogic_vector(data_width_c-1 downto 0); -- alu address result
|
signal alu_add : std_ulogic_vector(data_width_c-1 downto 0); -- alu address result
|
signal rdata : std_ulogic_vector(data_width_c-1 downto 0); -- memory read data
|
signal rdata : std_ulogic_vector(data_width_c-1 downto 0); -- memory read data
|
signal alu_wait : std_ulogic; -- alu is busy due to iterative unit
|
signal alu_wait : std_ulogic; -- alu is busy due to iterative unit
|
signal bus_i_wait : std_ulogic; -- wait for current bus instruction fetch
|
signal bus_i_wait : std_ulogic; -- wait for current bus instruction fetch
|
Line 159... |
Line 158... |
assert not (CPU_EXTENSION_RISCV_Zicsr = false) report "NEORV32 CPU CONFIG WARNING! No exception/interrupt/trap/privileged features available when CPU_EXTENSION_RISCV_Zicsr = false." severity warning;
|
assert not (CPU_EXTENSION_RISCV_Zicsr = false) report "NEORV32 CPU CONFIG WARNING! No exception/interrupt/trap/privileged features available when CPU_EXTENSION_RISCV_Zicsr = false." severity warning;
|
-- U-extension requires Zicsr extension --
|
-- U-extension requires Zicsr extension --
|
assert not ((CPU_EXTENSION_RISCV_Zicsr = false) and (CPU_EXTENSION_RISCV_U = true)) report "NEORV32 CPU CONFIG ERROR! User mode requires CPU_EXTENSION_RISCV_Zicsr extension." severity error;
|
assert not ((CPU_EXTENSION_RISCV_Zicsr = false) and (CPU_EXTENSION_RISCV_U = true)) report "NEORV32 CPU CONFIG ERROR! User mode requires CPU_EXTENSION_RISCV_Zicsr extension." severity error;
|
-- PMP requires Zicsr extension --
|
-- PMP requires Zicsr extension --
|
assert not ((CPU_EXTENSION_RISCV_Zicsr = false) and (PMP_NUM_REGIONS > 0)) report "NEORV32 CPU CONFIG ERROR! Physical memory protection (PMP) requires CPU_EXTENSION_RISCV_Zicsr extension." severity error;
|
assert not ((CPU_EXTENSION_RISCV_Zicsr = false) and (PMP_NUM_REGIONS > 0)) report "NEORV32 CPU CONFIG ERROR! Physical memory protection (PMP) requires CPU_EXTENSION_RISCV_Zicsr extension." severity error;
|
-- HPM CNT requires Zicsr extension --
|
|
assert not ((CPU_EXTENSION_RISCV_Zicsr = false) and (HPM_NUM_CNTS > 0)) report "NEORV32 CPU CONFIG ERROR! Performance monitors (HMP) require CPU_EXTENSION_RISCV_Zicsr extension." severity error;
|
|
|
|
-- Bus timeout --
|
-- Bus timeout --
|
assert not (BUS_TIMEOUT < 2) report "NEORV32 CPU CONFIG ERROR! Invalid bus access timeout value <BUS_TIMEOUT>. Has to be >= 2." severity error;
|
assert not (BUS_TIMEOUT < 2) report "NEORV32 CPU CONFIG ERROR! Invalid bus access timeout value <BUS_TIMEOUT>. Has to be >= 2." severity error;
|
|
|
-- Instruction prefetch buffer size --
|
-- Instruction prefetch buffer size --
|
assert not (is_power_of_two_f(ipb_entries_c) = false) report "NEORV32 CPU CONFIG ERROR! Number of entries in instruction prefetch buffer <ipb_entries_c> has to be a power of two." severity error;
|
assert not (is_power_of_two_f(ipb_entries_c) = false) report "NEORV32 CPU CONFIG ERROR! Number of entries in instruction prefetch buffer <ipb_entries_c> has to be a power of two." severity error;
|
-- A extension - only lr.w and sc.w supported yet --
|
-- A extension - only lr.w and sc.w supported yet --
|
assert not (CPU_EXTENSION_RISCV_A = true) report "NEORV32 CPU CONFIG WARNING! Atomic operations extension (A) only supports >lr.w< and >sc.w< instructions yet." severity warning;
|
assert not (CPU_EXTENSION_RISCV_A = true) report "NEORV32 CPU CONFIG WARNING! Atomic operations extension (A) only supports >lr.w< and >sc.w< instructions yet." severity warning;
|
|
|
|
-- Bit manipulation notifier --
|
|
assert not (CPU_EXTENSION_RISCV_B = true) report "NEORV32 CPU CONFIG WARNING! Bit manipulation extension (B) only supports 'base' instruction sub-set (Zbb) yet and is still 'unofficial' (not-ratified)." severity warning;
|
|
|
-- PMP regions check --
|
-- PMP regions check --
|
assert not (PMP_NUM_REGIONS > 64) report "NEORV32 CPU CONFIG ERROR! Number of PMP regions <PMP_NUM_REGIONS> out of valid range (0..64)." severity error;
|
assert not (PMP_NUM_REGIONS > 64) report "NEORV32 CPU CONFIG ERROR! Number of PMP regions <PMP_NUM_REGIONS> out of valid range (0..64)." severity error;
|
-- PMP granulartiy --
|
-- PMP granulartiy --
|
assert not ((is_power_of_two_f(PMP_MIN_GRANULARITY) = false) and (PMP_NUM_REGIONS > 0)) report "NEORV32 CPU CONFIG ERROR! PMP granulartiy has to be a power of two." severity error;
|
assert not ((is_power_of_two_f(PMP_MIN_GRANULARITY) = false) and (PMP_NUM_REGIONS > 0)) report "NEORV32 CPU CONFIG ERROR! PMP granulartiy has to be a power of two." severity error;
|
assert not ((PMP_MIN_GRANULARITY < 8) and (PMP_NUM_REGIONS > 0)) report "NEORV32 CPU CONFIG ERROR! PMP granulartiy has to be >= 8 bytes." severity error;
|
assert not ((PMP_MIN_GRANULARITY < 8) and (PMP_NUM_REGIONS > 0)) report "NEORV32 CPU CONFIG ERROR! PMP granulartiy has to be >= 8 bytes." severity error;
|
Line 182... |
Line 182... |
|
|
-- HPM counters check --
|
-- HPM counters check --
|
assert not (HPM_NUM_CNTS > 29) report "NEORV32 CPU CONFIG ERROR! Number of HPM counters <HPM_NUM_CNTS> out of valid range (0..29)." severity error;
|
assert not (HPM_NUM_CNTS > 29) report "NEORV32 CPU CONFIG ERROR! Number of HPM counters <HPM_NUM_CNTS> out of valid range (0..29)." severity error;
|
-- HPM counters notifier --
|
-- HPM counters notifier --
|
assert not (HPM_NUM_CNTS > 0) report "NEORV32 CPU CONFIG NOTE: Implementing " & integer'image(HPM_NUM_CNTS) & " HPM counters." severity note;
|
assert not (HPM_NUM_CNTS > 0) report "NEORV32 CPU CONFIG NOTE: Implementing " & integer'image(HPM_NUM_CNTS) & " HPM counters." severity note;
|
|
-- HPM CNT requires Zicsr extension --
|
|
assert not ((CPU_EXTENSION_RISCV_Zicsr = false) and (HPM_NUM_CNTS > 0)) report "NEORV32 CPU CONFIG ERROR! Performance monitors (HMP) require CPU_EXTENSION_RISCV_Zicsr extension." severity error;
|
|
|
|
|
-- Control Unit ---------------------------------------------------------------------------
|
-- Control Unit ---------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
neorv32_cpu_control_inst: neorv32_cpu_control
|
neorv32_cpu_control_inst: neorv32_cpu_control
|
Line 193... |
Line 195... |
-- General --
|
-- General --
|
HW_THREAD_ID => HW_THREAD_ID, -- hardware thread id
|
HW_THREAD_ID => HW_THREAD_ID, -- hardware thread id
|
CPU_BOOT_ADDR => CPU_BOOT_ADDR, -- cpu boot address
|
CPU_BOOT_ADDR => CPU_BOOT_ADDR, -- cpu boot address
|
-- RISC-V CPU Extensions --
|
-- RISC-V CPU Extensions --
|
CPU_EXTENSION_RISCV_A => CPU_EXTENSION_RISCV_A, -- implement atomic extension?
|
CPU_EXTENSION_RISCV_A => CPU_EXTENSION_RISCV_A, -- implement atomic extension?
|
|
CPU_EXTENSION_RISCV_B => CPU_EXTENSION_RISCV_B, -- implement bit manipulation extensions?
|
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension?
|
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension?
|
CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E, -- implement embedded RF extension?
|
CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E, -- implement embedded RF extension?
|
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, -- implement muld/div extension?
|
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, -- implement muld/div extension?
|
CPU_EXTENSION_RISCV_U => CPU_EXTENSION_RISCV_U, -- implement user mode extension?
|
CPU_EXTENSION_RISCV_U => CPU_EXTENSION_RISCV_U, -- implement user mode extension?
|
CPU_EXTENSION_RISCV_Zicsr => CPU_EXTENSION_RISCV_Zicsr, -- implement CSR system?
|
CPU_EXTENSION_RISCV_Zicsr => CPU_EXTENSION_RISCV_Zicsr, -- implement CSR system?
|
Line 287... |
Line 290... |
imm_i => imm, -- immediate
|
imm_i => imm, -- immediate
|
-- data output --
|
-- data output --
|
cmp_o => alu_cmp, -- comparator status
|
cmp_o => alu_cmp, -- comparator status
|
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
|
opb_o => alu_opb, -- ALU operand B
|
|
-- co-processor interface --
|
-- co-processor interface --
|
cp0_start_o => cp0_start, -- trigger co-processor 0
|
cp0_start_o => cp0_start, -- trigger co-processor 0
|
cp0_data_i => cp0_data, -- co-processor 0 result
|
cp0_data_i => cp0_data, -- co-processor 0 result
|
cp0_valid_i => cp0_valid, -- co-processor 0 result valid
|
cp0_valid_i => cp0_valid, -- co-processor 0 result valid
|
cp1_start_o => cp1_start, -- trigger co-processor 1
|
cp1_start_o => cp1_start, -- trigger co-processor 1
|
Line 336... |
Line 338... |
cp0_data <= (others => '0');
|
cp0_data <= (others => '0');
|
cp0_valid <= cp0_start; -- to make sure CPU does not get stalled if there is an accidental access
|
cp0_valid <= cp0_start; -- to make sure CPU does not get stalled if there is an accidental access
|
end generate;
|
end generate;
|
|
|
|
|
-- Co-Processor 1: Atomic Memory Access (SC - store-conditional) --------------------------
|
-- Co-Processor 1: Atomic Memory Access, SC - store-conditional ('M' extension) -----------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
atomic_op_cp: process(cp1_start, ctrl)
|
atomic_op_cp: process(cp1_start, ctrl)
|
begin
|
begin
|
-- "fake" co-processor for atomic operations
|
-- "fake" co-processor for atomic operations
|
-- used to get the result of a store-conditional operation into the data path
|
-- used to get the result of a store-conditional operation into the data path
|
Line 360... |
Line 362... |
end process atomic_op_cp;
|
end process atomic_op_cp;
|
|
|
|
|
-- Co-Processor 2: Not implemented (yet) --------------------------------------------------
|
-- Co-Processor 2: Not implemented (yet) --------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- control: ctrl cp2_start
|
neorv32_cpu_cp_bitmanip_inst_true:
|
-- inputs: rs1 rs2 alu_cmp alu_opb
|
if (CPU_EXTENSION_RISCV_B = true) generate
|
|
neorv32_cpu_cp_bitmanip_inst: neorv32_cpu_cp_bitmanip
|
|
port map (
|
|
-- global control --
|
|
clk_i => clk_i, -- global clock, rising edge
|
|
rstn_i => rstn_i, -- global reset, low-active, async
|
|
ctrl_i => ctrl, -- main control bus
|
|
start_i => cp2_start, -- trigger operation
|
|
-- data input --
|
|
cmp_i => alu_cmp, -- comparator status
|
|
rs1_i => rs1, -- rf source 1
|
|
rs2_i => rs2, -- rf source 2
|
|
-- result and status --
|
|
res_o => cp2_data, -- operation result
|
|
valid_o => cp2_valid -- data output valid
|
|
);
|
|
end generate;
|
|
|
|
neorv32_cpu_cp_bitmanip_inst_false:
|
|
if (CPU_EXTENSION_RISCV_B = false) generate
|
cp2_data <= (others => '0');
|
cp2_data <= (others => '0');
|
cp2_valid <= cp2_start; -- to make sure CPU does not get stalled if there is an accidental access
|
cp2_valid <= cp2_start; -- to make sure CPU does not get stalled if there is an accidental access
|
|
end generate;
|
|
|
|
|
-- Co-Processor 3: Not implemented (yet) --------------------------------------------------
|
-- Co-Processor 3: Not implemented (yet) --------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- control: ctrl cp3_start
|
-- control: ctrl cp3_start
|
-- inputs: rs1 rs2 alu_cmp alu_opb
|
-- inputs: rs1 rs2 alu_cmp
|
cp3_data <= (others => '0');
|
cp3_data <= (others => '0');
|
cp3_valid <= cp3_start; -- to make sure CPU does not get stalled if there is an accidental access
|
cp3_valid <= cp3_start; -- to make sure CPU does not get stalled if there is an accidental access
|
|
|
|
|
-- Bus Interface Unit ---------------------------------------------------------------------
|
-- Bus Interface Unit ---------------------------------------------------------------------
|