-- ################################################################################################# -- # << 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;