neorv32/rtl/core/neorv32_cpu.vhd

390 lines
22 KiB
VHDL

-- #################################################################################################
-- # << NEORV32 - CPU Top Entity >> #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # The NEORV32 RISC-V Processor, https://github.com/stnolting/neorv32 #
-- # Copyright (c) 2024, Stephan Nolting. All rights reserved. #
-- # #
-- # Redistribution and use in source and binary forms, with or without modification, are #
-- # permitted provided that the following conditions are met: #
-- # #
-- # 1. Redistributions of source code must retain the above copyright notice, this list of #
-- # conditions and the following disclaimer. #
-- # #
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of #
-- # conditions and the following disclaimer in the documentation and/or other materials #
-- # provided with the distribution. #
-- # #
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to #
-- # endorse or promote products derived from this software without specific prior written #
-- # permission. #
-- # #
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS #
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF #
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE #
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, #
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED #
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED #
-- # OF THE POSSIBILITY OF SUCH DAMAGE. #
-- #################################################################################################
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library neorv32;
use neorv32.neorv32_package.all;
entity neorv32_cpu is
generic (
-- General --
HART_ID : std_ulogic_vector(31 downto 0); -- hardware thread ID
VENDOR_ID : std_ulogic_vector(31 downto 0); -- vendor's JEDEC ID
CPU_BOOT_ADDR : std_ulogic_vector(31 downto 0); -- cpu boot address
CPU_DEBUG_PARK_ADDR : std_ulogic_vector(31 downto 0); -- cpu debug mode parking loop entry address
CPU_DEBUG_EXC_ADDR : std_ulogic_vector(31 downto 0); -- cpu debug mode exception entry address
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A : boolean; -- implement atomic memory operations extension?
CPU_EXTENSION_RISCV_B : boolean; -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_C : boolean; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M : boolean; -- implement mul/div extension?
CPU_EXTENSION_RISCV_U : boolean; -- implement user mode extension?
CPU_EXTENSION_RISCV_Zfinx : boolean; -- implement 32-bit floating-point extension (using INT reg!)
CPU_EXTENSION_RISCV_Zicntr : boolean; -- implement base counters?
CPU_EXTENSION_RISCV_Zicond : boolean; -- implement integer conditional operations?
CPU_EXTENSION_RISCV_Zihpm : boolean; -- implement hardware performance monitors?
CPU_EXTENSION_RISCV_Zmmul : boolean; -- implement multiply-only M sub-extension?
CPU_EXTENSION_RISCV_Zxcfu : boolean; -- implement custom (instr.) functions unit?
CPU_EXTENSION_RISCV_Sdext : boolean; -- implement external debug mode extension?
CPU_EXTENSION_RISCV_Sdtrig : boolean; -- implement trigger module extension?
-- Tuning Options --
FAST_MUL_EN : boolean; -- use DSPs for M extension's multiplier
FAST_SHIFT_EN : boolean; -- use barrel shifter for shift operations
REGFILE_HW_RST : boolean; -- implement full hardware reset for register file
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS : natural range 0 to 16; -- number of regions (0..16)
PMP_MIN_GRANULARITY : natural; -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
PMP_TOR_MODE_EN : boolean; -- implement TOR mode
PMP_NAP_MODE_EN : boolean; -- implement NAPOT/NA4 modes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS : natural range 0 to 13; -- number of implemented HPM counters (0..13)
HPM_CNT_WIDTH : natural range 0 to 64 -- total size of HPM counters (0..64)
);
port (
-- global control --
clk_i : in std_ulogic; -- switchable global clock, rising edge
clk_aux_i : in std_ulogic; -- always-on clock, rising edge
rstn_i : in std_ulogic; -- global reset, low-active, async
sleep_o : out std_ulogic; -- cpu is in sleep mode when set
debug_o : out std_ulogic; -- cpu is in debug mode when set
-- interrupts --
msi_i : in std_ulogic; -- risc-v machine software interrupt
mei_i : in std_ulogic; -- risc-v machine external interrupt
mti_i : in std_ulogic; -- risc-v machine timer interrupt
firq_i : in std_ulogic_vector(15 downto 0); -- custom fast interrupts
dbi_i : in std_ulogic; -- risc-v debug halt request interrupt
-- instruction bus interface --
ibus_req_o : out bus_req_t; -- request bus
ibus_rsp_i : in bus_rsp_t; -- response bus
-- data bus interface --
dbus_req_o : out bus_req_t; -- request bus
dbus_rsp_i : in bus_rsp_t -- response bus
);
end neorv32_cpu;
architecture neorv32_cpu_rtl of neorv32_cpu is
-- auto-configuration --
constant regfile_rs3_en_c : boolean := CPU_EXTENSION_RISCV_Zxcfu or CPU_EXTENSION_RISCV_Zfinx; -- 3rd register file read port (rs3)
constant regfile_rs4_en_c : boolean := CPU_EXTENSION_RISCV_Zxcfu; -- 4th register file read port (rs4)
constant pmp_enable_c : boolean := boolean(PMP_NUM_REGIONS > 0);
-- control-unit-external CSR interface --
signal xcsr_we : std_ulogic;
signal xcsr_addr : std_ulogic_vector(11 downto 0);
signal xcsr_wdata : std_ulogic_vector(XLEN-1 downto 0);
signal xcsr_rdata_pmp : std_ulogic_vector(XLEN-1 downto 0);
signal xcsr_rdata_alu : std_ulogic_vector(XLEN-1 downto 0);
signal xcsr_rdata_res : std_ulogic_vector(XLEN-1 downto 0);
-- local signals --
signal ctrl : ctrl_bus_t; -- main control bus
signal imm : std_ulogic_vector(XLEN-1 downto 0); -- immediate
signal rs1, rs2 : std_ulogic_vector(XLEN-1 downto 0); -- source register 1,2
signal rs3, rs4 : std_ulogic_vector(XLEN-1 downto 0); -- source register 3,4
signal alu_res : std_ulogic_vector(XLEN-1 downto 0); -- alu result
signal alu_add : std_ulogic_vector(XLEN-1 downto 0); -- alu address result
signal alu_cmp : std_ulogic_vector(1 downto 0); -- comparator result
signal mem_rdata : std_ulogic_vector(XLEN-1 downto 0); -- memory read data
signal cp_done : std_ulogic; -- ALU co-processor operation done
signal lsu_wait : std_ulogic; -- wait for current data bus access
signal csr_rdata : std_ulogic_vector(XLEN-1 downto 0); -- csr read data
signal mar : std_ulogic_vector(XLEN-1 downto 0); -- memory address register
signal ma_load : std_ulogic; -- misaligned load data address
signal ma_store : std_ulogic; -- misaligned store data address
signal be_load : std_ulogic; -- bus error on load data access
signal be_store : std_ulogic; -- bus error on store data access
signal fetch_pc : std_ulogic_vector(XLEN-1 downto 0); -- pc for instruction fetch
signal curr_pc : std_ulogic_vector(XLEN-1 downto 0); -- current pc (for currently executed instruction)
signal link_pc : std_ulogic_vector(XLEN-1 downto 0); -- link pc (return address)
signal pmp_ex_fault : std_ulogic; -- PMP instruction fetch fault
signal pmp_rw_fault : std_ulogic; -- PMP read/write access fault
begin
-- Sanity Checks --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- CPU ISA configuration --
assert false report "[NEORV32] CPU ISA: rv32" &
cond_sel_string_f(CPU_EXTENSION_RISCV_E, "e", "i") &
cond_sel_string_f(CPU_EXTENSION_RISCV_M, "m", "" ) &
cond_sel_string_f(CPU_EXTENSION_RISCV_A, "a", "" ) &
cond_sel_string_f(CPU_EXTENSION_RISCV_C, "c", "" ) &
cond_sel_string_f(CPU_EXTENSION_RISCV_B, "b", "" ) &
cond_sel_string_f(CPU_EXTENSION_RISCV_U, "u", "" ) &
cond_sel_string_f(true, "_zicsr", "" ) & -- always enabled
cond_sel_string_f(CPU_EXTENSION_RISCV_Zicntr, "_zicntr", "" ) &
cond_sel_string_f(CPU_EXTENSION_RISCV_Zicond, "_zicond", "" ) &
cond_sel_string_f(true, "_zifencei", "" ) & -- always enabled
cond_sel_string_f(CPU_EXTENSION_RISCV_Zfinx, "_zfinx", "" ) &
cond_sel_string_f(CPU_EXTENSION_RISCV_Zihpm, "_zihpm", "" ) &
cond_sel_string_f(CPU_EXTENSION_RISCV_Zmmul, "_zmmul", "" ) &
cond_sel_string_f(CPU_EXTENSION_RISCV_Zxcfu, "_zxcfu", "" ) &
cond_sel_string_f(CPU_EXTENSION_RISCV_Sdext, "_sdext", "" ) &
cond_sel_string_f(CPU_EXTENSION_RISCV_Sdtrig, "_sdtrig", "" ) &
cond_sel_string_f(pmp_enable_c, "_smpmp", "" )
severity note;
-- CPU tuning options --
assert false report "[NEORV32] CPU tuning options: " &
cond_sel_string_f(FAST_MUL_EN, "fast_mul ", "") &
cond_sel_string_f(FAST_SHIFT_EN, "fast_shift ", "") &
cond_sel_string_f(REGFILE_HW_RST, "rf_hw_rst ", "")
severity note;
-- simulation notifier --
assert not (is_simulation_c = true) report "[NEORV32] Assuming this is a simulation." severity warning;
-- Control Unit ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_control_inst: entity neorv32.neorv32_cpu_control
generic map (
-- General --
HART_ID => HART_ID, -- hardware thread ID
VENDOR_ID => VENDOR_ID, -- vendor's JEDEC ID
CPU_BOOT_ADDR => CPU_BOOT_ADDR, -- cpu boot address
CPU_DEBUG_PARK_ADDR => CPU_DEBUG_PARK_ADDR, -- cpu debug mode parking loop entry address
CPU_DEBUG_EXC_ADDR => CPU_DEBUG_EXC_ADDR, -- cpu debug mode exception entry address
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A => CPU_EXTENSION_RISCV_A, -- implement atomic memory operations extension?
CPU_EXTENSION_RISCV_B => CPU_EXTENSION_RISCV_B, -- implement bit-manipulation 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_M => CPU_EXTENSION_RISCV_M, -- implement mul/div extension?
CPU_EXTENSION_RISCV_U => CPU_EXTENSION_RISCV_U, -- implement user mode extension?
CPU_EXTENSION_RISCV_Zfinx => CPU_EXTENSION_RISCV_Zfinx, -- implement 32-bit floating-point extension (using INT reg!)
CPU_EXTENSION_RISCV_Zicntr => CPU_EXTENSION_RISCV_Zicntr, -- implement base counters?
CPU_EXTENSION_RISCV_Zicond => CPU_EXTENSION_RISCV_Zicond, -- implement integer conditional operations?
CPU_EXTENSION_RISCV_Zihpm => CPU_EXTENSION_RISCV_Zihpm, -- implement hardware performance monitors?
CPU_EXTENSION_RISCV_Zmmul => CPU_EXTENSION_RISCV_Zmmul, -- implement multiply-only M sub-extension?
CPU_EXTENSION_RISCV_Zxcfu => CPU_EXTENSION_RISCV_Zxcfu, -- implement custom (instr.) functions unit?
CPU_EXTENSION_RISCV_Sdext => CPU_EXTENSION_RISCV_Sdext, -- implement external debug mode extension?
CPU_EXTENSION_RISCV_Sdtrig => CPU_EXTENSION_RISCV_Sdtrig, -- implement trigger module extension?
CPU_EXTENSION_RISCV_Smpmp => pmp_enable_c, -- implement physical memory protection?
-- Tuning Options --
FAST_MUL_EN => FAST_MUL_EN, -- use DSPs for M extension's multiplier
FAST_SHIFT_EN => FAST_SHIFT_EN, -- use barrel shifter for shift operations
REGFILE_HW_RST => REGFILE_HW_RST, -- implement full hardware reset for register file
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS => HPM_NUM_CNTS, -- number of implemented HPM counters (0..13)
HPM_CNT_WIDTH => HPM_CNT_WIDTH -- total size of HPM counters
)
port map (
-- global control --
clk_i => clk_i, -- global clock, rising edge
clk_aux_i => clk_aux_i, -- always-on clock, rising edge
rstn_i => rstn_i, -- global reset, low-active, async
ctrl_o => ctrl, -- main control bus
-- instruction fetch interface --
i_pmp_fault_i => pmp_ex_fault, -- instruction fetch pmp fault
bus_req_o => ibus_req_o, -- request
bus_rsp_i => ibus_rsp_i, -- response
-- data path interface --
alu_cp_done_i => cp_done, -- ALU iterative operation done
cmp_i => alu_cmp, -- comparator status
alu_add_i => alu_add, -- ALU address result
rs1_i => rs1, -- rf source 1
imm_o => imm, -- immediate
fetch_pc_o => fetch_pc, -- instruction fetch address
curr_pc_o => curr_pc, -- current PC (corresponding to current instruction)
link_pc_o => link_pc, -- link PC (return address)
csr_rdata_o => csr_rdata, -- CSR read data
-- external CSR interface --
xcsr_we_o => xcsr_we, -- global write enable
xcsr_addr_o => xcsr_addr, -- address
xcsr_wdata_o => xcsr_wdata, -- write data
xcsr_rdata_i => xcsr_rdata_res, -- read data
-- interrupts --
db_halt_req_i => dbi_i, -- debug mode (halt) request
msi_i => msi_i, -- machine software interrupt
mei_i => mei_i, -- machine external interrupt
mti_i => mti_i, -- machine timer interrupt
firq_i => firq_i, -- fast interrupts
-- data access interface --
lsu_wait_i => lsu_wait, -- wait for data bus
mar_i => mar, -- memory address register
ma_load_i => ma_load, -- misaligned load data address
ma_store_i => ma_store, -- misaligned store data address
be_load_i => be_load, -- bus error on load data access
be_store_i => be_store -- bus error on store data access
);
-- external CSR read-back --
xcsr_rdata_res <= xcsr_rdata_pmp or xcsr_rdata_alu;
-- CPU state --
sleep_o <= ctrl.cpu_sleep; -- set when CPU is sleeping (after WFI)
debug_o <= ctrl.cpu_debug; -- set when CPU is in debug mode
-- Register File --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_regfile_inst: entity neorv32.neorv32_cpu_regfile
generic map (
RST_EN => REGFILE_HW_RST, -- enable dedicated hardware reset ("ASIC style")
RVE_EN => CPU_EXTENSION_RISCV_E, -- implement embedded RF extension
RS3_EN => regfile_rs3_en_c, -- enable 3rd read port
RS4_EN => regfile_rs4_en_c -- enable 4th read port
)
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
-- data input --
alu_i => alu_res, -- ALU result
mem_i => mem_rdata, -- memory read data
csr_i => csr_rdata, -- CSR read data
ret_i => link_pc, -- return address
-- data output --
rs1_o => rs1, -- rs1
rs2_o => rs2, -- rs2
rs3_o => rs3, -- rs3
rs4_o => rs4 -- rs4
);
-- ALU (Arithmetic/Logic Unit) and ALU Co-Processors --------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_alu_inst: entity neorv32.neorv32_cpu_alu
generic map (
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_B => CPU_EXTENSION_RISCV_B, -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, -- implement mul/div extension?
CPU_EXTENSION_RISCV_Zicond => CPU_EXTENSION_RISCV_Zicond, -- implement integer conditional operations?
CPU_EXTENSION_RISCV_Zmmul => CPU_EXTENSION_RISCV_Zmmul, -- implement multiply-only M sub-extension?
CPU_EXTENSION_RISCV_Zfinx => CPU_EXTENSION_RISCV_Zfinx, -- implement 32-bit floating-point extension (using INT reg!)
CPU_EXTENSION_RISCV_Zxcfu => CPU_EXTENSION_RISCV_Zxcfu, -- implement custom (instr.) functions unit?
-- Tuning Options --
FAST_MUL_EN => FAST_MUL_EN, -- use DSPs for M extension's multiplier
FAST_SHIFT_EN => FAST_SHIFT_EN -- use barrel shifter for shift operations
)
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
-- CSR interface --
csr_we_i => xcsr_we, -- global write enable
csr_addr_i => xcsr_addr, -- address
csr_wdata_i => xcsr_wdata, -- write data
csr_rdata_o => xcsr_rdata_alu, -- read data
-- data input --
rs1_i => rs1, -- rf source 1
rs2_i => rs2, -- rf source 2
rs3_i => rs3, -- rf source 3
rs4_i => rs4, -- rf source 4
pc_i => curr_pc, -- current PC
imm_i => imm, -- immediate
-- data output --
cmp_o => alu_cmp, -- comparator status
res_o => alu_res, -- ALU result
add_o => alu_add, -- address computation result
-- status --
cp_done_o => cp_done -- iterative processing units done?
);
-- Load/Store Unit ------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_lsu_inst: entity neorv32.neorv32_cpu_lsu
generic map (
AMO_LRSC_ENABLE => CPU_EXTENSION_RISCV_A -- enable atomic LR/SC operations
)
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
-- cpu data access interface --
addr_i => alu_add, -- access address
wdata_i => rs2, -- write data
rdata_o => mem_rdata, -- read data
mar_o => mar, -- memory address register
wait_o => lsu_wait, -- wait for access to complete
ma_load_o => ma_load, -- misaligned load data address
ma_store_o => ma_store, -- misaligned store data address
be_load_o => be_load, -- bus error on load data access
be_store_o => be_store, -- bus error on store data access
pmp_fault_i => pmp_rw_fault, -- PMP read/write access fault
-- data bus --
bus_req_o => dbus_req_o, -- request
bus_rsp_i => dbus_rsp_i -- response
);
-- Physical Memory Protection -------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
pmp_inst_true:
if pmp_enable_c generate
neorv32_cpu_pmp_inst: entity neorv32.neorv32_cpu_pmp
generic map (
NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..16)
GRANULARITY => PMP_MIN_GRANULARITY, -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
TOR_EN => PMP_TOR_MODE_EN, -- implement TOR mode
NAP_EN => PMP_NAP_MODE_EN -- implement NAPOT/NA4 modes
)
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
-- CSR interface --
csr_we_i => xcsr_we, -- global write enable
csr_addr_i => xcsr_addr, -- address
csr_wdata_i => xcsr_wdata, -- write data
csr_rdata_o => xcsr_rdata_pmp, -- read data
-- address input --
addr_if_i => fetch_pc, -- instruction fetch address
addr_ls_i => alu_add, -- load/store address
-- faults --
fault_ex_o => pmp_ex_fault, -- instruction fetch fault
fault_rw_o => pmp_rw_fault -- read/write access fault
);
end generate;
pmp_inst_false:
if not pmp_enable_c generate
xcsr_rdata_pmp <= (others => '0');
pmp_ex_fault <= '0';
pmp_rw_fault <= '0';
end generate;
end neorv32_cpu_rtl;