OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /neorv32/trunk/rtl/core
    from Rev 14 to Rev 15
    Reverse comparison

Rev 14 → Rev 15

/neorv32_cpu.vhd
58,8 → 58,13
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M : boolean := false; -- implement muld/div extension?
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension?
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean := true; -- implement instruction stream sync.?
-- Physical Memory Protection (PMP) --
PMP_USE : boolean := false; -- implement PMP?
PMP_NUM_REGIONS : natural := 4; -- number of regions (max 16)
PMP_GRANULARITY : natural := 15; -- region granularity (1=8B, 2=16B, 3=32B, ...) default is 64k
-- Bus Interface --
BUS_TIMEOUT : natural := 15 -- cycles after which a valid bus access will timeout
);
130,8 → 135,46
signal cp0_data, cp1_data : std_ulogic_vector(data_width_c-1 downto 0);
signal cp0_valid, cp1_valid : std_ulogic;
 
-- pmp interface --
signal pmp_addr : pmp_addr_if_t;
signal pmp_maddr : pmp_addr_if_t;
signal pmp_ctrl : pmp_ctrl_if_t;
signal priv_mode : std_ulogic_vector(1 downto 0); -- current CPU privilege level
 
begin
 
-- Sanity Checks --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
sanity_check: process(clk_i)
begin
if rising_edge(clk_i) then
-- CSR system --
if (CPU_EXTENSION_RISCV_Zicsr = false) then
assert false report "NEORV32 CONFIG WARNING! No exception/interrupt/machine features available when CPU_EXTENSION_RISCV_Zicsr = false." severity warning;
end if;
-- U-extension requires Zicsr extension --
if (CPU_EXTENSION_RISCV_Zicsr = false) and (CPU_EXTENSION_RISCV_U = true) then
assert false report "NEORV32 CONFIG ERROR! User mode requires CPU_EXTENSION_RISCV_Zicsr = true." severity error;
end if;
-- PMP requires Zicsr extension --
if (CPU_EXTENSION_RISCV_Zicsr = false) and (PMP_USE = true) then
assert false report "NEORV32 CONFIG ERROR! Physical memory protection (PMP) requires CPU_EXTENSION_RISCV_Zicsr = true." severity error;
end if;
-- performance counters requires Zicsr extension --
if (CPU_EXTENSION_RISCV_Zicsr = false) and (CSR_COUNTERS_USE = true) then
assert false report "NEORV32 CONFIG ERROR! Performance counter CSRs require CPU_EXTENSION_RISCV_Zicsr = true." severity error;
end if;
-- PMP regions --
if (PMP_NUM_REGIONS > pmp_max_r_c) and (PMP_USE = true) then
assert false report "NEORV32 CONFIG ERROR! Number of PMP regions out of valid range." severity error;
end if;
-- PMP granulartiy --
if ((PMP_GRANULARITY <= 1) or (PMP_GRANULARITY > 31)) and (PMP_USE = true) then
assert false report "NEORV32 CONFIG ERROR! Invalid PMP grnaulartiy (1 < G < 32)." severity error;
end if;
end if;
end process sanity_check;
 
-- Control Unit ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_control_inst: neorv32_cpu_control
141,11 → 184,16
HW_THREAD_ID => HW_THREAD_ID, -- hardware thread id
CPU_BOOT_ADDR => CPU_BOOT_ADDR, -- cpu boot address
-- RISC-V CPU Extensions --
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 muld/div extension?
CPU_EXTENSION_RISCV_Zicsr => CPU_EXTENSION_RISCV_Zicsr, -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei => CPU_EXTENSION_RISCV_Zifencei -- implement instruction stream sync.?
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 muld/div 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_Zifencei => CPU_EXTENSION_RISCV_Zifencei, -- implement instruction stream sync.?
-- Physical memory protection (PMP) --
PMP_USE => PMP_USE, -- implement physical memory protection?
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (1..4)
PMP_GRANULARITY => PMP_GRANULARITY -- granularity (0=none, 1=8B, 2=16B, 3=32B, ...)
)
port map (
-- global control --
176,6 → 224,11
firq_i => firq_i,
-- system time input from MTIME --
time_i => time_i, -- current system time
-- physical memory protection --
pmp_addr_o => pmp_addr, -- addresses
pmp_maddr_i => pmp_maddr, -- masked addresses
pmp_ctrl_o => pmp_ctrl, -- configs
priv_mode_o => priv_mode, -- current CPU privilege level
-- bus access exceptions --
mar_i => mar, -- memory address register
ma_instr_i => ma_instr, -- misaligned instruction address
276,7 → 329,11
neorv32_cpu_bus_inst: neorv32_cpu_bus
generic map (
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension?
BUS_TIMEOUT => BUS_TIMEOUT -- cycles after which a valid bus access will timeout
BUS_TIMEOUT => BUS_TIMEOUT, -- cycles after which a valid bus access will timeout
-- Physical memory protection (PMP) --
PMP_USE => PMP_USE, -- implement physical memory protection?
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (1..4)
PMP_GRANULARITY => PMP_GRANULARITY -- granularity (0=none, 1=8B, 2=16B, 3=32B, ...)
)
port map (
-- global control --
301,6 → 358,11
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
-- physical memory protection --
pmp_addr_i => pmp_addr, -- addresses
pmp_maddr_o => pmp_maddr, -- masked addresses
pmp_ctrl_i => pmp_ctrl, -- configs
priv_mode_i => priv_mode, -- current CPU privilege level
-- instruction bus --
i_bus_addr_o => i_bus_addr_o, -- bus access address
i_bus_rdata_i => i_bus_rdata_i, -- bus read data
/neorv32_cpu_bus.vhd
44,7 → 44,11
entity neorv32_cpu_bus is
generic (
CPU_EXTENSION_RISCV_C : boolean := true; -- implement compressed extension?
BUS_TIMEOUT : natural := 15 -- cycles after which a valid bus access will timeout
BUS_TIMEOUT : natural := 15; -- cycles after which a valid bus access will timeout
-- Physical memory protection (PMP) --
PMP_USE : boolean := false; -- implement physical memory protection?
PMP_NUM_REGIONS : natural := 4; -- number of regions (1..4)
PMP_GRANULARITY : natural := 16 -- granularity (0=none, 1=8B, 2=16B, 3=32B, ...)
);
port (
-- global control --
69,6 → 73,11
ma_store_o : out std_ulogic; -- misaligned store data address
be_load_o : out std_ulogic; -- bus error on load data access
be_store_o : out std_ulogic; -- bus error on store data access
-- physical memory protection --
pmp_addr_i : in pmp_addr_if_t; -- addresses
pmp_maddr_o : out pmp_addr_if_t; -- masked addresses
pmp_ctrl_i : in pmp_ctrl_if_t; -- configs
priv_mode_i : in std_ulogic_vector(1 downto 0); -- current CPU privilege level
-- instruction bus --
i_bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
i_bus_rdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
96,6 → 105,20
 
architecture neorv32_cpu_bus_rtl of neorv32_cpu_bus is
 
-- PMP modes --
constant pmp_off_mode_c : std_ulogic_vector(1 downto 0) := "00"; -- null region (disabled)
constant pmp_tor_mode_c : std_ulogic_vector(1 downto 0) := "01"; -- top of range
constant pmp_na4_mode_c : std_ulogic_vector(1 downto 0) := "10"; -- naturally aligned four-byte region
constant pmp_napot_mode_c : std_ulogic_vector(1 downto 0) := "11"; -- naturally aligned power-of-two region (>= 8 bytes)
 
-- PMP configuration register bits --
constant pmp_cfg_r_c : natural := 0; -- read permit
constant pmp_cfg_w_c : natural := 1; -- write permit
constant pmp_cfg_x_c : natural := 2; -- execute permit
constant pmp_cfg_al_c : natural := 3; -- mode bit low
constant pmp_cfg_ah_c : natural := 4; -- mode bit high
constant pmp_cfg_l_c : natural := 7; -- locked entry
 
-- data interface registers --
signal mar, mdo, mdi : std_ulogic_vector(data_width_c-1 downto 0);
 
117,6 → 140,24
end record;
signal i_arbiter, d_arbiter : bus_arbiter_t;
 
-- physical memory protection --
type pmp_addr34_t is array (0 to PMP_NUM_REGIONS-1) of std_ulogic_vector(data_width_c+1 downto 0);
type pmp_addr_t is array (0 to PMP_NUM_REGIONS-1) of std_ulogic_vector(data_width_c-1 downto 0);
type pmp_t is record
addr_mask : pmp_addr34_t; -- 34-bit
i_match : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region match for instruction interface
d_match : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region match for data interface
if_fault : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region access fault for fetch operation
ld_fault : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region access fault for load operation
st_fault : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region access fault for store operation
end record;
signal pmp : pmp_t;
 
-- pmp faults anybody? --
signal if_pmp_fault : std_ulogic; -- pmp instruction access fault
signal ld_pmp_fault : std_ulogic; -- pmp load access fault
signal st_pmp_fault : std_ulogic; -- pmp store access fault
 
begin
 
-- Data Interface: Access Address ---------------------------------------------------------
303,7 → 344,7
i_bus_wdata_o <= (others => '0');
i_bus_ben_o <= (others => '0');
i_bus_we_o <= '0';
i_bus_re_o <= ctrl_i(ctrl_bus_if_c) and (not i_misaligned); -- no actual read when misaligned
i_bus_re_o <= ctrl_i(ctrl_bus_if_c) and (not i_misaligned) and (not if_pmp_fault); -- no actual read when misaligned or PMP fault
i_bus_fence_o <= ctrl_i(ctrl_bus_fencei_c);
instr_o <= i_bus_rdata_i;
 
357,14 → 398,101
ma_store_o <= d_arbiter.wr_req and d_arbiter.err_align;
be_store_o <= d_arbiter.wr_req and d_arbiter.err_bus;
 
-- data bus --
-- data bus (read/write)--
d_bus_addr_o <= mar;
d_bus_wdata_o <= d_bus_wdata;
d_bus_ben_o <= d_bus_ben;
d_bus_we_o <= ctrl_i(ctrl_bus_wr_c) and (not d_misaligned); -- no actual write when misaligned
d_bus_re_o <= ctrl_i(ctrl_bus_rd_c) and (not d_misaligned); -- no actual read when misaligned
d_bus_we_o <= ctrl_i(ctrl_bus_wr_c) and (not d_misaligned) and (not st_pmp_fault); -- no actual write when misaligned or PMP fault
d_bus_re_o <= ctrl_i(ctrl_bus_rd_c) and (not d_misaligned) and (not ld_pmp_fault); -- no actual read when misaligned or PMP fault
d_bus_fence_o <= ctrl_i(ctrl_bus_fence_c);
d_bus_rdata <= d_bus_rdata_i;
 
 
-- Physical Memory Protection (PMP) -------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- compute address masks --
pmp_masks: process(pmp_addr_i, pmp, pmp_ctrl_i)
begin
for r in 0 to PMP_NUM_REGIONS-1 loop -- iterate over all regions
pmp.addr_mask(r) <= (others => '0'); -- default
for i in PMP_GRANULARITY+2 to 33 loop
if (i = PMP_GRANULARITY+2) then
if (pmp_ctrl_i(r)(pmp_cfg_ah_c downto pmp_cfg_al_c) = pmp_napot_mode_c) then
pmp.addr_mask(r)(i) <= '0';
else -- OFF or unsupported mode
pmp.addr_mask(r)(i) <= '1'; -- required for SW to check min granularity when entry is disabled
end if;
else
if (pmp_ctrl_i(r)(pmp_cfg_ah_c downto pmp_cfg_al_c) = pmp_napot_mode_c) then
-- current bit = not AND(all previous bits)
pmp.addr_mask(r)(i) <= not and_all_f(pmp_addr_i(r)(i-1 downto PMP_GRANULARITY+2));
else -- OFF or unsupported mode
pmp.addr_mask(r)(i) <= '1'; -- required for SW to check min granularity when entry is disabled
end if;
end if;
end loop; -- i
end loop; -- r
end process pmp_masks;
 
 
-- masked pmpaddr output for CSR read-back --
pmp_masked_output: process(pmp_addr_i, pmp)
begin
pmp_maddr_o <= (others => (others => '0'));
for r in 0 to PMP_NUM_REGIONS-1 loop -- iterate over all regions
pmp_maddr_o(r) <= pmp_addr_i(r) and pmp.addr_mask(r);
end loop; -- r
end process pmp_masked_output;
 
 
-- check for access address match --
pmp_addr_check: process (pmp, fetch_pc_i, mar, pmp_addr_i)
variable i_cmp_v : std_ulogic_vector(31 downto 0);
variable d_cmp_v : std_ulogic_vector(31 downto 0);
variable b_cmp_v : std_ulogic_vector(31 downto 0);
begin
for r in 0 to PMP_NUM_REGIONS-1 loop -- iterate over all regions
b_cmp_v := pmp_addr_i(r)(33 downto 2) and pmp.addr_mask(r)(33 downto 2);
-- instruction interface --
i_cmp_v := fetch_pc_i and pmp.addr_mask(r)(33 downto 2);
if (i_cmp_v(31 downto PMP_GRANULARITY+2) = b_cmp_v(31 downto PMP_GRANULARITY+2)) then
pmp.i_match(r) <= '1';
else
pmp.i_match(r) <= '0';
end if;
-- data interface --
d_cmp_v := mar and pmp.addr_mask(r)(33 downto 2);
if (d_cmp_v(31 downto PMP_GRANULARITY+2) = b_cmp_v(31 downto PMP_GRANULARITY+2)) then
pmp.d_match(r) <= '1';
else
pmp.d_match(r) <= '0';
end if;
end loop; -- r
end process pmp_addr_check;
 
 
-- check access type and regions's permissions --
pmp_check_permission: process(pmp, pmp_ctrl_i, priv_mode_i)
begin
for r in 0 to PMP_NUM_REGIONS-1 loop -- iterate over all regions
if ((priv_mode_i = u_priv_mode_c) or (pmp_ctrl_i(r)(pmp_cfg_l_c) = '1')) and -- user privilege level or locked pmp entry - enforce permissions also for machine mode
(pmp_ctrl_i(r)(pmp_cfg_ah_c downto pmp_cfg_al_c) /= pmp_off_mode_c) then -- active entry
pmp.if_fault(r) <= pmp.i_match(r) and (not pmp_ctrl_i(r)(pmp_cfg_x_c)); -- fetch access match no execute permission
pmp.ld_fault(r) <= pmp.d_match(r) and (not pmp_ctrl_i(r)(pmp_cfg_r_c)); -- load access match no read permission
pmp.st_fault(r) <= pmp.d_match(r) and (not pmp_ctrl_i(r)(pmp_cfg_w_c)); -- store access match no write permission
else
pmp.if_fault(r) <= '0';
pmp.ld_fault(r) <= '0';
pmp.st_fault(r) <= '0';
end if;
end loop; -- r
end process pmp_check_permission;
 
 
-- final PMP access fault signals --
if_pmp_fault <= or_all_f(pmp.if_fault) when (PMP_USE = true) else '0';
ld_pmp_fault <= or_all_f(pmp.ld_fault) when (PMP_USE = true) else '0';
st_pmp_fault <= or_all_f(pmp.st_fault) when (PMP_USE = true) else '0';
 
 
end neorv32_cpu_bus_rtl;
/neorv32_cpu_control.vhd
53,8 → 53,13
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M : boolean := false; -- implement muld/div extension?
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension?
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean := true -- implement instruction stream sync.?
CPU_EXTENSION_RISCV_Zifencei : boolean := true; -- implement instruction stream sync.?
-- Physical memory protection (PMP) --
PMP_USE : boolean := false; -- implement physical memory protection?
PMP_NUM_REGIONS : natural := 4; -- number of regions (1..4)
PMP_GRANULARITY : natural := 0 -- granularity (0=none, 1=8B, 2=16B, 3=32B, ...)
);
port (
-- global control --
85,6 → 90,11
firq_i : in std_ulogic_vector(3 downto 0);
-- system time input from MTIME --
time_i : in std_ulogic_vector(63 downto 0); -- current system time
-- physical memory protection --
pmp_addr_o : out pmp_addr_if_t; -- addresses
pmp_maddr_i : in pmp_addr_if_t; -- masked addresses
pmp_ctrl_o : out pmp_ctrl_if_t; -- configs
priv_mode_o : out std_ulogic_vector(1 downto 0); -- current CPU privilege level
-- bus access exceptions --
mar_i : in std_ulogic_vector(data_width_c-1 downto 0); -- memory address register
ma_instr_i : in std_ulogic; -- misaligned instruction address
192,6 → 202,8
signal bus_fast_ir : std_ulogic;
 
-- RISC-V control and status registers (CSRs) --
type pmp_ctrl_t is array (0 to PMP_NUM_REGIONS-1) of std_ulogic_vector(7 downto 0);
type pmp_addr_t is array (0 to PMP_NUM_REGIONS-1) of std_ulogic_vector(data_width_c-1 downto 0);
type csr_t is record
we : std_ulogic; -- write enable
we_nxt : std_ulogic;
203,6 → 215,8
mie_meie : std_ulogic; -- mie.MEIE: machine external interrupt enable (R/W)
mie_mtie : std_ulogic; -- mie.MEIE: machine timer interrupt enable (R/W
mie_firqe : std_ulogic_vector(3 downto 0); -- mie.firq*e: fast interrupt enabled (R/W)
mpp : std_ulogic_vector(1 downto 0); -- machine previous privilege mode
privilege : std_ulogic_vector(1 downto 0); -- hart's current previous privilege mode
mepc : std_ulogic_vector(data_width_c-1 downto 0); -- mepc: machine exception pc (R/W)
mcause : std_ulogic_vector(data_width_c-1 downto 0); -- mcause: machine trap cause (R/-)
mtvec : std_ulogic_vector(data_width_c-1 downto 0); -- mtvec: machine trap-handler base address (R/W), bit 1:0 == 00
212,6 → 226,8
minstret : std_ulogic_vector(32 downto 0); -- minstret (R/W), plus carry bit
mcycleh : std_ulogic_vector(19 downto 0); -- mcycleh (R/W) - REDUCED BIT-WIDTH!
minstreth : std_ulogic_vector(19 downto 0); -- minstreth (R/W) - REDUCED BIT-WIDTH!
pmpcfg : pmp_ctrl_t; -- physical memory protection - configuration registers
pmpaddr : pmp_addr_t; -- physical memory protection - address registers
end record;
signal csr : csr_t;
 
224,6 → 240,9
signal illegal_register : std_ulogic; -- only for E-extension
signal illegal_compressed : std_ulogic; -- only fir C-extension
 
-- access (privilege) check --
signal csr_acc_valid : std_ulogic; -- valid CSR access (implemented and valid access rights)
 
begin
 
-- ****************************************************************************************************************************
544,7 → 563,7
 
-- Execute Engine FSM Comb ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
execute_engine_fsm_comb: process(execute_engine, fetch_engine, ipb, trap_ctrl, csr, ctrl,
execute_engine_fsm_comb: process(execute_engine, fetch_engine, ipb, trap_ctrl, csr, ctrl, csr_acc_valid,
alu_add_i, alu_wait_i, bus_d_wait_i, ma_load_i, be_load_i, ma_store_i, be_store_i)
variable alu_immediate_v : std_ulogic;
variable alu_operation_v : std_ulogic_vector(2 downto 0);
744,7 → 763,7
 
when opcode_syscsr_c => -- system/csr access
-- ------------------------------------------------------------
csr.re_nxt <= '1'; -- always read CSR - regardless of actual operation
csr.re_nxt <= csr_acc_valid; -- read CSR if valid access
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_env_c) then -- system
case execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) is
when funct12_ecall_c => -- ECALL
785,17 → 804,17
ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '0'; -- OPB = rs2
ctrl_nxt(ctrl_rf_clear_rs2_c) <= '1'; -- rs2 = 0
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_or_c; -- actual ALU operation = OR
csr.we_nxt <= '1'; -- always write CSR
csr.we_nxt <= csr_acc_valid; -- always write CSR if valid access
when funct3_csrrs_c => -- CSRRS
ctrl_nxt(ctrl_alu_opa_mux_msb_c) <= '1'; -- OPA = csr
ctrl_nxt(ctrl_alu_opb_mux_msb_c) <= '1'; -- OPB = rs1
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_or_c; -- actual ALU operation = OR
csr.we_nxt <= not rs1_is_r0_v; -- write CSR if rs1 is not zero_reg
csr.we_nxt <= (not rs1_is_r0_v) and csr_acc_valid; -- write CSR if rs1 is not zero_reg and if valid access
when funct3_csrrc_c => -- CSRRC
ctrl_nxt(ctrl_alu_opa_mux_msb_c) <= '1'; -- OPA = csr
ctrl_nxt(ctrl_alu_opb_mux_msb_c) <= '1'; -- OPB = rs1
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_bitc_c; -- actual ALU operation = bit clear
csr.we_nxt <= not rs1_is_r0_v; -- write CSR if rs1 is not zero_reg
csr.we_nxt <= (not rs1_is_r0_v) and csr_acc_valid; -- write CSR if rs1 is not zero_reg and if valid access
-- immediate operations --
when funct3_csrrwi_c => -- CSRRWI
ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- OPA = rs1
802,17 → 821,17
ctrl_nxt(ctrl_rf_clear_rs1_c) <= '1'; -- rs1 = 0
ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- OPB = immediate
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_or_c; -- actual ALU operation = OR
csr.we_nxt <= '1'; -- always write CSR
csr.we_nxt <= csr_acc_valid; -- always write CSR if valid access
when funct3_csrrsi_c => -- CSRRSI
ctrl_nxt(ctrl_alu_opa_mux_msb_c) <= '1'; -- OPA = csr
ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- OPB = immediate
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_or_c; -- actual ALU operation = OR
csr.we_nxt <= not rs1_is_r0_v; -- write CSR if UIMM5 is not zero (bits from rs1 filed)
csr.we_nxt <= (not rs1_is_r0_v) and csr_acc_valid; -- write CSR if UIMM5 is not zero (bits from rs1 filed) and if valid access
when funct3_csrrci_c => -- CSRRCI
ctrl_nxt(ctrl_alu_opa_mux_msb_c) <= '1'; -- OPA = csr
ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- OPB = immediate
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_bitc_c; -- actual ALU operation = bit clear
csr.we_nxt <= not rs1_is_r0_v; -- write CSR if UIMM5 is not zero (bits from rs1 filed)
csr.we_nxt <= (not rs1_is_r0_v) and csr_acc_valid; -- write CSR if UIMM5 is not zero (bits from rs1 filed) and if valid access
when others => -- undefined
NULL;
end case;
875,9 → 894,72
end process execute_engine_fsm_comb;
 
 
-- ****************************************************************************************************************************
-- Invalid Instruction / CSR access check
-- ****************************************************************************************************************************
 
 
-- Illegal CSR Access Check ---------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
invalid_csr_access_check: process(execute_engine, csr)
variable is_m_mode_v : std_ulogic;
begin
-- are we in machine mode? --
is_m_mode_v := '0';
if (csr.privilege = m_priv_mode_c) then
is_m_mode_v := '1';
end if;
 
-- check CSR access --
csr_acc_valid <= '0'; -- default
case execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) is
when x"300" => csr_acc_valid <= is_m_mode_v; -- mstatus
when x"301" => csr_acc_valid <= is_m_mode_v; -- misa
when x"304" => csr_acc_valid <= is_m_mode_v; -- mie
when x"305" => csr_acc_valid <= is_m_mode_v; -- mtvev
when x"340" => csr_acc_valid <= is_m_mode_v; -- mscratch
when x"341" => csr_acc_valid <= is_m_mode_v; -- mepc
when x"342" => csr_acc_valid <= is_m_mode_v; -- mcause
when x"343" => csr_acc_valid <= is_m_mode_v; -- mtval
when x"344" => csr_acc_valid <= is_m_mode_v; -- mip
--
when x"3a0" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 1)) and is_m_mode_v; -- pmpacfg0
when x"3a1" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 5)) and is_m_mode_v; -- pmpacfg1
--
when x"3b0" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 1)) and is_m_mode_v; -- pmpaddr0
when x"3b1" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 2)) and is_m_mode_v; -- pmpaddr1
when x"3b2" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 3)) and is_m_mode_v; -- pmpaddr2
when x"3b3" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 4)) and is_m_mode_v; -- pmpaddr3
when x"3b4" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 5)) and is_m_mode_v; -- pmpaddr4
when x"3b5" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 6)) and is_m_mode_v; -- pmpaddr5
when x"3b6" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 7)) and is_m_mode_v; -- pmpaddr6
when x"3b7" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 8)) and is_m_mode_v; -- pmpaddr7
--
when x"c00" => csr_acc_valid <= bool_to_ulogic_f(CSR_COUNTERS_USE); -- cycle
when x"c01" => csr_acc_valid <= bool_to_ulogic_f(CSR_COUNTERS_USE); -- time
when x"c02" => csr_acc_valid <= bool_to_ulogic_f(CSR_COUNTERS_USE); -- instret
when x"c80" => csr_acc_valid <= bool_to_ulogic_f(CSR_COUNTERS_USE); -- cycleh
when x"c81" => csr_acc_valid <= bool_to_ulogic_f(CSR_COUNTERS_USE); -- timeh
when x"c82" => csr_acc_valid <= bool_to_ulogic_f(CSR_COUNTERS_USE); -- instreth
--
when x"b00" => csr_acc_valid <= bool_to_ulogic_f(CSR_COUNTERS_USE) and is_m_mode_v; -- mcycle
when x"b02" => csr_acc_valid <= bool_to_ulogic_f(CSR_COUNTERS_USE) and is_m_mode_v; -- minstret
when x"b80" => csr_acc_valid <= bool_to_ulogic_f(CSR_COUNTERS_USE) and is_m_mode_v; -- mcycleh
when x"b82" => csr_acc_valid <= bool_to_ulogic_f(CSR_COUNTERS_USE) and is_m_mode_v; -- minstreth
--
when x"f11" => csr_acc_valid <= is_m_mode_v; -- mvendorid
when x"f12" => csr_acc_valid <= is_m_mode_v; -- marchid
when x"f13" => csr_acc_valid <= is_m_mode_v; -- mimpid
when x"f14" => csr_acc_valid <= is_m_mode_v; -- mhartid
--
when others => csr_acc_valid <= '0'; -- undefined
end case;
end process invalid_csr_access_check;
 
 
-- Illegal Instruction Check --------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
illegal_instruction_check: process(execute_engine, csr, ctrl_nxt)
illegal_instruction_check: process(execute_engine, csr, ctrl_nxt, csr_acc_valid)
begin
-- illegal instructions are checked in the EXECUTE stage
-- the execute engine will only commit valid instructions
981,33 → 1063,8
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrsi_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrci_c) then
-- valid CSR? --
if (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"300") or -- mstatus
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"301") or -- misa
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"304") or -- mie
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"305") or -- mtvev
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"340") or -- mscratch
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"341") or -- mepc
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"342") or -- mcause
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"343") or -- mtval
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"344") or -- mip
--
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c00") and (CSR_COUNTERS_USE = true)) or -- cycle
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c01") and (CSR_COUNTERS_USE = true)) or -- time
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c02") and (CSR_COUNTERS_USE = true)) or -- instret
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c80") and (CSR_COUNTERS_USE = true)) or -- cycleh
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c81") and (CSR_COUNTERS_USE = true)) or -- timeh
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c82") and (CSR_COUNTERS_USE = true)) or -- instreth
--
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b00") and (CSR_COUNTERS_USE = true)) or -- mcycle
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b02") and (CSR_COUNTERS_USE = true)) or -- minstret
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b80") and (CSR_COUNTERS_USE = true)) or -- mcycleh
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b82") and (CSR_COUNTERS_USE = true)) or -- minstreth
--
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"f11") or -- mvendorid
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"f12") or -- marchid
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"f13") or -- mimpid
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"f14") then -- mhartid
-- valid CSR access? --
if (csr_acc_valid = '1') then
illegal_instruction <= '0';
else
illegal_instruction <= '1';
1230,6 → 1287,10
csr.mepc <= (others => '0');
csr.mcause <= (others => '0');
csr.mtval <= (others => '0');
csr.mpp <= m_priv_mode_c; -- start in MACHINE mode
csr.privilege <= m_priv_mode_c; -- start in MACHINE mode
csr.pmpcfg <= (others => (others => '0'));
csr.pmpaddr <= (others => (others => '0'));
elsif rising_edge(clk_i) then
if (CPU_EXTENSION_RISCV_Zicsr = true) then
-- access --
1239,7 → 1300,7
-- registers that can be modified by user --
if (csr.we = '1') then -- manual update
 
-- Machine CSRs: Standard read/write
-- Machine CSRs --
if (execute_engine.i_reg(31 downto 28) = x"3") then
-- machine trap setup --
if (execute_engine.i_reg(27 downto 24) = x"0") then
1247,6 → 1308,11
when x"0" => -- R/W: mstatus - machine status register
csr.mstatus_mie <= csr_wdata_i(03);
csr.mstatus_mpie <= csr_wdata_i(07);
--
if (CPU_EXTENSION_RISCV_U = true) then -- user mode implemented
csr.mpp(0) <= csr_wdata_i(11) and csr_wdata_i(12);
csr.mpp(1) <= csr_wdata_i(11) and csr_wdata_i(12);
end if;
when x"4" => -- R/W: mie - machine interrupt-enable register
csr.mie_msie <= csr_wdata_i(03); -- machine SW IRQ enable
csr.mie_mtie <= csr_wdata_i(07); -- machine TIMER IRQ enable
1275,6 → 1341,56
NULL;
end case;
end if;
-- machine physical memory protection (pmp) --
if (PMP_USE = true) then
-- pmpcfg --
if (execute_engine.i_reg(27 downto 24) = x"a") then
if (PMP_NUM_REGIONS >= 1) then
if (execute_engine.i_reg(23 downto 20) = x"0") then -- pmpcfg0
for j in 0 to 3 loop -- bytes in pmpcfg CSR
if ((j+1) <= PMP_NUM_REGIONS) then
if (csr.pmpcfg(0+j)(7) = '0') then -- unlocked pmpcfg access
csr.pmpcfg(0+j)(0) <= csr_wdata_i(j*8+0); -- R
csr.pmpcfg(0+j)(1) <= csr_wdata_i(j*8+1); -- W
csr.pmpcfg(0+j)(2) <= csr_wdata_i(j*8+2); -- X
csr.pmpcfg(0+j)(3) <= csr_wdata_i(j*8+3) and csr_wdata_i(j*8+4); -- A_L
csr.pmpcfg(0+j)(4) <= csr_wdata_i(j*8+3) and csr_wdata_i(j*8+4); -- A_H - NAPOT/OFF only
csr.pmpcfg(0+j)(5) <= '0'; -- reserved
csr.pmpcfg(0+j)(6) <= '0'; -- reserved
csr.pmpcfg(0+j)(7) <= csr_wdata_i(j*8+7); -- L
end if;
end if;
end loop; -- j (bytes in CSR)
end if;
end if;
if (PMP_NUM_REGIONS >= 5) then
if (execute_engine.i_reg(23 downto 20) = x"1") then -- pmpcfg1
for j in 0 to 3 loop -- bytes in pmpcfg CSR
if ((j+1+4) <= PMP_NUM_REGIONS) then
if (csr.pmpcfg(4+j)(7) = '0') then -- unlocked pmpcfg access
csr.pmpcfg(4+j)(0) <= csr_wdata_i(j*8+0); -- R
csr.pmpcfg(4+j)(1) <= csr_wdata_i(j*8+1); -- W
csr.pmpcfg(4+j)(2) <= csr_wdata_i(j*8+2); -- X
csr.pmpcfg(4+j)(3) <= csr_wdata_i(j*8+3) and csr_wdata_i(j*8+4); -- A_L
csr.pmpcfg(4+j)(4) <= csr_wdata_i(j*8+3) and csr_wdata_i(j*8+4); -- A_H - NAPOT/OFF only
csr.pmpcfg(4+j)(5) <= '0'; -- reserved
csr.pmpcfg(4+j)(6) <= '0'; -- reserved
csr.pmpcfg(4+j)(7) <= csr_wdata_i(j*8+7); -- L
end if;
end if;
end loop; -- j (bytes in CSR)
end if;
end if;
end if;
-- pmpaddr --
if (execute_engine.i_reg(27 downto 24) = x"b") then
for i in 0 to PMP_NUM_REGIONS-1 loop
if (execute_engine.i_reg(23 downto 20) = std_ulogic_vector(to_unsigned(i, 4))) and (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpaddr access
csr.pmpaddr(i) <= csr_wdata_i;
end if;
end loop; -- i (CSRs)
end if;
end if; -- implement PMP at all?
end if;
 
-- automatic update by hardware --
1302,15 → 1418,27
end if;
 
-- context switch in mstatus --
if (trap_ctrl.env_start_ack = '1') then -- trap handler starting?
csr.mstatus_mie <= '0';
if (csr.mstatus_mpie = '0') then -- prevent loosing the prev MIE state in nested traps
csr.mstatus_mpie <= csr.mstatus_mie;
if (trap_ctrl.env_start_ack = '1') then -- ENTER: trap handler starting?
csr.mstatus_mie <= '0'; -- disable interrupts
csr.mstatus_mpie <= csr.mstatus_mie; -- buffer previous mie state
if (CPU_EXTENSION_RISCV_U = true) then -- implement user mode
csr.privilege <= m_priv_mode_c; -- execute trap in machine mode
csr.mpp <= csr.privilege; -- buffer previous privilege mode
end if;
elsif (trap_ctrl.env_end = '1') then -- return from exception
csr.mstatus_mie <= csr.mstatus_mpie;
elsif (trap_ctrl.env_end = '1') then -- EXIT: return from exception
csr.mstatus_mie <= csr.mstatus_mpie; -- restore global IRQ enable flag
csr.mstatus_mpie <= '1';
if (CPU_EXTENSION_RISCV_U = true) then -- implement user mode
csr.privilege <= csr.mpp; -- go back to previous privilege mode
csr.mpp <= u_priv_mode_c;
end if;
end if;
 
-- user mode NOT implemented --
if (CPU_EXTENSION_RISCV_U = false) then -- implement user mode
csr.privilege <= m_priv_mode_c;
csr.mpp <= m_priv_mode_c;
end if;
end if;
end if;
end if;
1328,15 → 1456,16
 
-- machine trap setup --
when x"300" => -- R/W: mstatus - machine status register
csr_rdata_o(03) <= csr.mstatus_mie; -- MIE
csr_rdata_o(03) <= csr.mstatus_mie; -- MIE
csr_rdata_o(07) <= csr.mstatus_mpie; -- MPIE
csr_rdata_o(11) <= '1'; -- MPP low - M-mode
csr_rdata_o(12) <= '1'; -- MPP high - M-mode
csr_rdata_o(11) <= csr.mpp(0); -- MPP: machine previous privilege mode low
csr_rdata_o(12) <= csr.mpp(1); -- MPP: machine previous privilege mode high
when x"301" => -- R/-: misa - ISA and extensions
csr_rdata_o(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C); -- C CPU extension
csr_rdata_o(04) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- E CPU extension
csr_rdata_o(08) <= not bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- I CPU extension (if not E)
csr_rdata_o(12) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_M); -- M CPU extension
csr_rdata_o(20) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_U); -- U CPU extension
csr_rdata_o(23) <= '1'; -- X CPU extension (non-std extensions)
csr_rdata_o(25) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicsr) and bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zifencei); -- Z CPU extension
csr_rdata_o(30) <= '1'; -- 32-bit architecture (MXL lo)
1372,6 → 1501,111
csr_rdata_o(18) <= trap_ctrl.irq_buf(interrupt_firq_2_c);
csr_rdata_o(19) <= trap_ctrl.irq_buf(interrupt_firq_3_c);
 
-- physical memory protection --
when x"3a0" => -- R/W: pmpcfg0 - physical memory protection configuration register 0
if (PMP_USE = true) then
if (PMP_NUM_REGIONS >= 1) then
csr_rdata_o(07 downto 00) <= csr.pmpcfg(0);
end if;
if (PMP_NUM_REGIONS >= 2) then
csr_rdata_o(15 downto 08) <= csr.pmpcfg(1);
end if;
if (PMP_NUM_REGIONS >= 3) then
csr_rdata_o(23 downto 16) <= csr.pmpcfg(2);
end if;
if (PMP_NUM_REGIONS >= 4) then
csr_rdata_o(31 downto 24) <= csr.pmpcfg(3);
end if;
end if;
when x"3a1" => -- R/W: pmpcfg1 - physical memory protection configuration register 1
if (PMP_USE = true) then
if (PMP_NUM_REGIONS >= 5) then
csr_rdata_o(07 downto 00) <= csr.pmpcfg(4);
end if;
if (PMP_NUM_REGIONS >= 6) then
csr_rdata_o(15 downto 08) <= csr.pmpcfg(5);
end if;
if (PMP_NUM_REGIONS >= 7) then
csr_rdata_o(23 downto 16) <= csr.pmpcfg(6);
end if;
if (PMP_NUM_REGIONS >= 8) then
csr_rdata_o(31 downto 24) <= csr.pmpcfg(7);
end if;
end if;
 
when x"3b0" => -- R/W: pmpaddr0 - physical memory protection address register 0
if (PMP_USE = true) and (PMP_NUM_REGIONS >= 1) then
csr_rdata_o <= pmp_maddr_i(0)(33 downto 2);
if (csr.pmpcfg(0)(4 downto 3) = "00") then -- mode = off
csr_rdata_o(PMP_GRANULARITY-1 downto 0) <= (others => '0'); -- required for granularity check by SW
else -- mode = NAPOT
csr_rdata_o(PMP_GRANULARITY-2 downto 0) <= (others => '1');
end if;
end if;
when x"3b1" => -- R/W: pmpaddr1 - physical memory protection address register 1
if (PMP_USE = true) and (PMP_NUM_REGIONS >= 2) then
csr_rdata_o <= pmp_maddr_i(1)(33 downto 2);
if (csr.pmpcfg(1)(4 downto 3) = "00") then -- mode = off
csr_rdata_o(PMP_GRANULARITY-1 downto 0) <= (others => '0'); -- required for granularity check by SW
else -- mode = NAPOT
csr_rdata_o(PMP_GRANULARITY-2 downto 0) <= (others => '1');
end if;
end if;
when x"3b2" => -- R/W: pmpaddr2 - physical memory protection address register 2
if (PMP_USE = true) and (PMP_NUM_REGIONS >= 3) then
csr_rdata_o <= pmp_maddr_i(2)(33 downto 2);
if (csr.pmpcfg(2)(4 downto 3) = "00") then -- mode = off
csr_rdata_o(PMP_GRANULARITY-1 downto 0) <= (others => '0'); -- required for granularity check by SW
else -- mode = NAPOT
csr_rdata_o(PMP_GRANULARITY-2 downto 0) <= (others => '1');
end if;
end if;
when x"3b3" => -- R/W: pmpaddr3 - physical memory protection address register 3
if (PMP_USE = true) and (PMP_NUM_REGIONS >= 4) then
csr_rdata_o <= pmp_maddr_i(3)(33 downto 2);
if (csr.pmpcfg(3)(4 downto 3) = "00") then -- mode = off
csr_rdata_o(PMP_GRANULARITY-1 downto 0) <= (others => '0'); -- required for granularity check by SW
else -- mode = NAPOT
csr_rdata_o(PMP_GRANULARITY-2 downto 0) <= (others => '1');
end if;
end if;
when x"3b4" => -- R/W: pmpaddr4 - physical memory protection address register 4
if (PMP_USE = true) and (PMP_NUM_REGIONS >= 5) then
csr_rdata_o <= pmp_maddr_i(4)(33 downto 2);
if (csr.pmpcfg(4)(4 downto 3) = "00") then -- mode = off
csr_rdata_o(PMP_GRANULARITY-1 downto 0) <= (others => '0'); -- required for granularity check by SW
else -- mode = NAPOT
csr_rdata_o(PMP_GRANULARITY-2 downto 0) <= (others => '1');
end if;
end if;
when x"3b5" => -- R/W: pmpaddr5 - physical memory protection address register 5
if (PMP_USE = true) and (PMP_NUM_REGIONS >= 6) then
csr_rdata_o <= pmp_maddr_i(5)(33 downto 2);
if (csr.pmpcfg(5)(4 downto 3) = "00") then -- mode = off
csr_rdata_o(PMP_GRANULARITY-1 downto 0) <= (others => '0'); -- required for granularity check by SW
else -- mode = NAPOT
csr_rdata_o(PMP_GRANULARITY-2 downto 0) <= (others => '1');
end if;
end if;
when x"3b6" => -- R/W: pmpaddr6 - physical memory protection address register 6
if (PMP_USE = true) and (PMP_NUM_REGIONS >= 7) then
csr_rdata_o <= pmp_maddr_i(6)(33 downto 2);
if (csr.pmpcfg(6)(4 downto 3) = "00") then -- mode = off
csr_rdata_o(PMP_GRANULARITY-1 downto 0) <= (others => '0'); -- required for granularity check by SW
else -- mode = NAPOT
csr_rdata_o(PMP_GRANULARITY-2 downto 0) <= (others => '1');
end if;
end if;
when x"3b7" => -- R/W: pmpaddr7 - physical memory protection address register 7
if (PMP_USE = true) and (PMP_NUM_REGIONS >= 8) then
csr_rdata_o <= pmp_maddr_i(7)(33 downto 2);
if (csr.pmpcfg(7)(4 downto 3) = "00") then -- mode = off
csr_rdata_o(PMP_GRANULARITY-1 downto 0) <= (others => '0'); -- required for granularity check by SW
else -- mode = NAPOT
csr_rdata_o(PMP_GRANULARITY-2 downto 0) <= (others => '1');
end if;
end if;
 
-- counter and timers --
when x"c00" | x"b00" => -- R/(W): cycle/mcycle: Cycle counter LOW
csr_rdata_o <= csr.mcycle(31 downto 0);
1410,7 → 1644,23
-- time[h] CSR --
systime <= time_i when (CSR_COUNTERS_USE = true) else (others => '0');
 
-- CPU's current privilege level --
priv_mode_o <= csr.privilege;
 
-- PMP output --
pmp_output: process(csr)
begin
pmp_addr_o <= (others => (others => '0'));
pmp_ctrl_o <= (others => (others => '0'));
if (PMP_USE = true) then
for i in 0 to PMP_NUM_REGIONS-1 loop
pmp_addr_o(i) <= csr.pmpaddr(i) & "00";
pmp_ctrl_o(i) <= csr.pmpcfg(i);
end loop; -- i
end if;
end process pmp_output;
 
 
-- RISC-V Counter CSRs --------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
csr_counters: process(rstn_i, clk_i)
/neorv32_package.vhd
41,7 → 41,8
-- Architecture Constants -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant data_width_c : natural := 32; -- data width - FIXED!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01030000"; -- no touchy!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01030500"; -- no touchy!
constant pmp_max_r_c : natural := 8; -- max PMP regions
 
-- Helper Functions -----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
49,12 → 50,17
function cond_sel_natural_f(cond : boolean; val_t : natural; val_f : natural) return natural;
function cond_sel_stdulogicvector_f(cond : boolean; val_t : std_ulogic_vector; val_f : std_ulogic_vector) return std_ulogic_vector;
function bool_to_ulogic_f(cond : boolean) return std_ulogic;
function or_all_f( a : std_ulogic_vector) return std_ulogic;
function and_all_f( a : std_ulogic_vector) return std_ulogic;
function xor_all_f( a : std_ulogic_vector) return std_ulogic;
function or_all_f(a : std_ulogic_vector) return std_ulogic;
function and_all_f(a : std_ulogic_vector) return std_ulogic;
function xor_all_f(a : std_ulogic_vector) return std_ulogic;
function xnor_all_f(a : std_ulogic_vector) return std_ulogic;
function to_hexchar_f(input : std_ulogic_vector(3 downto 0)) return character;
 
-- Internal Types -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
type pmp_ctrl_if_t is array (0 to pmp_max_r_c-1) of std_ulogic_vector(7 downto 0);
type pmp_addr_if_t is array (0 to pmp_max_r_c-1) of std_ulogic_vector(33 downto 0);
 
-- Processor-internal Address Space Layout ------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- Instruction Memory & Data Memory --
361,6 → 367,11
--
constant interrupt_width_c : natural := 7; -- length of this list in bits
 
-- CPU Privilege Modes --------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant m_priv_mode_c : std_ulogic_vector(1 downto 0) := "11"; -- machine mode
constant u_priv_mode_c : std_ulogic_vector(1 downto 0) := "00"; -- user mode
 
-- Clock Generator -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant clk_div2_c : natural := 0;
385,8 → 396,13
CPU_EXTENSION_RISCV_C : boolean := true; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M : boolean := true; -- implement muld/div extension?
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension?
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean := true; -- implement instruction stream sync.?
-- Physical Memory Protection (PMP) --
PMP_USE : boolean := false; -- implement PMP?
PMP_NUM_REGIONS : natural := 4; -- number of regions (max 16)
PMP_GRANULARITY : natural := 15; -- region granularity (1=8B, 2=16B, 3=32B, ...) default is 64k
-- Memory configuration: Instruction memory --
MEM_ISPACE_BASE : std_ulogic_vector(31 downto 0) := x"00000000"; -- base address of instruction memory space
MEM_ISPACE_SIZE : natural := 16*1024; -- total size of instruction memory space in byte
464,8 → 480,13
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M : boolean := false; -- implement muld/div extension?
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension?
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean := true; -- implement instruction stream sync.?
-- Physical Memory Protection (PMP) --
PMP_USE : boolean := false; -- implement PMP?
PMP_NUM_REGIONS : natural := 4; -- number of regions (max 16)
PMP_GRANULARITY : natural := 15; -- region granularity (1=8B, 2=16B, 3=32B, ...) default is 64k
-- Bus Interface --
BUS_TIMEOUT : natural := 15 -- cycles after which a valid bus access will timeout
);
518,8 → 539,13
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M : boolean := false; -- implement muld/div extension?
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension?
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean := true -- implement instruction stream sync.?
CPU_EXTENSION_RISCV_Zifencei : boolean := true; -- implement instruction stream sync.?
-- Physical memory protection (PMP) --
PMP_USE : boolean := false; -- implement physical memory protection?
PMP_NUM_REGIONS : natural := 4; -- number of regions (1..4)
PMP_GRANULARITY : natural := 0 -- granularity (0=none, 1=8B, 2=16B, 3=32B, ...)
);
port (
-- global control --
550,6 → 576,11
firq_i : in std_ulogic_vector(3 downto 0);
-- system time input from MTIME --
time_i : in std_ulogic_vector(63 downto 0); -- current system time
-- physical memory protection --
pmp_addr_o : out pmp_addr_if_t; -- addresses
pmp_maddr_i : in pmp_addr_if_t; -- masked addresses
pmp_ctrl_o : out pmp_ctrl_if_t; -- configs
priv_mode_o : out std_ulogic_vector(1 downto 0); -- current CPU privilege level
-- bus access exceptions --
mar_i : in std_ulogic_vector(data_width_c-1 downto 0); -- memory address register
ma_instr_i : in std_ulogic; -- misaligned instruction address
635,7 → 666,11
component neorv32_cpu_bus
generic (
CPU_EXTENSION_RISCV_C : boolean := true; -- implement compressed extension?
BUS_TIMEOUT : natural := 15 -- cycles after which a valid bus access will timeout
BUS_TIMEOUT : natural := 15; -- cycles after which a valid bus access will timeout
-- Physical memory protection (PMP) --
PMP_USE : boolean := false; -- implement physical memory protection?
PMP_NUM_REGIONS : natural := 4; -- number of regions (1..4)
PMP_GRANULARITY : natural := 0 -- granularity (0=none, 1=8B, 2=16B, 3=32B, ...)
);
port (
-- global control --
660,6 → 695,11
ma_store_o : out std_ulogic; -- misaligned store data address
be_load_o : out std_ulogic; -- bus error on load data access
be_store_o : out std_ulogic; -- bus error on store data access
-- physical memory protection --
pmp_addr_i : in pmp_addr_if_t; -- addresses
pmp_maddr_o : out pmp_addr_if_t; -- masked addresses
pmp_ctrl_i : in pmp_ctrl_if_t; -- configs
priv_mode_i : in std_ulogic_vector(1 downto 0); -- current CPU privilege level
-- instruction bus --
i_bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
i_bus_rdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
1126,9 → 1166,11
variable tmp_v : std_ulogic;
begin
tmp_v := a(a'low);
for i in a'low+1 to a'high loop
tmp_v := tmp_v or a(i);
end loop; -- i
if (a'low < a'high) then -- not null range?
for i in a'low+1 to a'high loop
tmp_v := tmp_v or a(i);
end loop; -- i
end if;
return tmp_v;
end function or_all_f;
 
1138,9 → 1180,11
variable tmp_v : std_ulogic;
begin
tmp_v := a(a'low);
for i in a'low+1 to a'high loop
tmp_v := tmp_v and a(i);
end loop; -- i
if (a'low < a'high) then -- not null range?
for i in a'low+1 to a'high loop
tmp_v := tmp_v and a(i);
end loop; -- i
end if;
return tmp_v;
end function and_all_f;
 
1150,9 → 1194,11
variable tmp_v : std_ulogic;
begin
tmp_v := a(a'low);
for i in a'low+1 to a'high loop
tmp_v := tmp_v xor a(i);
end loop; -- i
if (a'low < a'high) then -- not null range?
for i in a'low+1 to a'high loop
tmp_v := tmp_v xor a(i);
end loop; -- i
end if;
return tmp_v;
end function xor_all_f;
 
1162,9 → 1208,11
variable tmp_v : std_ulogic;
begin
tmp_v := a(a'low);
for i in a'low+1 to a'high loop
tmp_v := tmp_v xnor a(i);
end loop; -- i
if (a'low < a'high) then -- not null range?
for i in a'low+1 to a'high loop
tmp_v := tmp_v xnor a(i);
end loop; -- i
end if;
return tmp_v;
end function xnor_all_f;
 
/neorv32_top.vhd
55,8 → 55,13
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M : boolean := false; -- implement muld/div extension?
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension?
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean := true; -- implement instruction stream sync.?
-- Physical Memory Protection (PMP) --
PMP_USE : boolean := false; -- implement PMP?
PMP_NUM_REGIONS : natural := 4; -- number of regions (max 16)
PMP_GRANULARITY : natural := 15; -- region granularity (1=8B, 2=16B, 3=32B, ...) default is 64k
-- Memory configuration: Instruction memory --
MEM_ISPACE_BASE : std_ulogic_vector(31 downto 0) := x"00000000"; -- base address of instruction memory space
MEM_ISPACE_SIZE : natural := 16*1024; -- total size of instruction memory space in byte
247,11 → 252,6
assert false report "NEORV32 CONFIG ERROR! Core clock frequency (CLOCK_FREQUENCY) not specified." severity error;
end if;
 
-- CSR system not implemented --
if (CPU_EXTENSION_RISCV_Zicsr = false) then
assert false report "NEORV32 CONFIG WARNING! No exception/interrupt/machine features available when CPU_EXTENSION_RISCV_Zicsr = false." severity warning;
end if;
 
-- memory layout notifier --
if (MEM_ISPACE_BASE /= x"00000000") then
assert false report "NEORV32 CONFIG WARNING! Non-default base address for instruction address space. Make sure this is sync with the software framwork." severity warning;
328,8 → 328,13
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 muld/div 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_Zifencei => CPU_EXTENSION_RISCV_Zifencei, -- implement instruction stream sync.?
-- Physical Memory Protection (PMP) --
PMP_USE => PMP_USE, -- implement PMP?
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (max 16)
PMP_GRANULARITY => PMP_GRANULARITY, -- region granularity (1=8B, 2=16B, 3=32B, ...) default is 64k
-- Bus Interface --
BUS_TIMEOUT => MEM_EXT_TIMEOUT -- cycles after which a valid bus access will timeout
)

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.