URL
https://opencores.org/ocsvn/neorv32/neorv32/trunk
Subversion Repositories neorv32
Compare Revisions
- This comparison shows the changes necessary to convert path
/neorv32/trunk
- from Rev 14 to Rev 15
- ↔ Reverse comparison
Rev 14 → Rev 15
/docs/figures/neorv32_cpu.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/docs/figures/neorv32_processor.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/docs/NEORV32.pdf
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/rtl/core/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 |
/rtl/core/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; |
/rtl/core/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) |
/rtl/core/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; |
|
/rtl/core/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 |
) |
/rtl/top_templates/neorv32_test_setup.vhd
77,8 → 77,13
CPU_EXTENSION_RISCV_C => false, -- implement compressed extension? |
CPU_EXTENSION_RISCV_E => false, -- implement embedded RF extension? |
CPU_EXTENSION_RISCV_M => false, -- implement muld/div extension? |
CPU_EXTENSION_RISCV_U => false, -- implement user mode extension? |
CPU_EXTENSION_RISCV_Zicsr => true, -- implement CSR system? |
CPU_EXTENSION_RISCV_Zifencei => true, -- implement instruction stream sync.? |
-- Physical Memory Protection (PMP) -- |
PMP_USE => false, -- implement PMP? |
PMP_NUM_REGIONS => 4, -- number of regions (max 16) |
PMP_GRANULARITY => 15, -- region granularity (1=8B, 2=16B, 3=32B, ...) default is 64k |
-- Memory configuration: Instruction memory -- |
MEM_ISPACE_BASE => x"00000000", -- base address of instruction memory space |
MEM_ISPACE_SIZE => 16*1024, -- total size of instruction memory space in byte |
/sim/vivado/neorv32_tb_behav.wcfg
12,15 → 12,15
</db_ref> |
</db_ref_list> |
<zoom_setting> |
<ZoomStartTime time="1345742867fs"></ZoomStartTime> |
<ZoomEndTime time="1345761168fs"></ZoomEndTime> |
<Cursor1Time time="1345799367fs"></Cursor1Time> |
<ZoomStartTime time="1400827333fs"></ZoomStartTime> |
<ZoomEndTime time="1401034534fs"></ZoomEndTime> |
<Cursor1Time time="1400917733fs"></Cursor1Time> |
</zoom_setting> |
<column_width_setting> |
<NameColumnWidth column_width="178"></NameColumnWidth> |
<ValueColumnWidth column_width="116"></ValueColumnWidth> |
<ValueColumnWidth column_width="108"></ValueColumnWidth> |
</column_width_setting> |
<WVObjectSize size="142" /> |
<WVObjectSize size="132" /> |
<wvobject type="divider" fp_name="divider273"> |
<obj_property name="label">CPU: Control.FETCH</obj_property> |
<obj_property name="DisplayName">label</obj_property> |
69,7 → 69,6
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/ipb" type="array"> |
<obj_property name="ElementShortName">ipb</obj_property> |
<obj_property name="ObjectShortName">ipb</obj_property> |
<obj_property name="isExpanded"></obj_property> |
</wvobject> |
<wvobject type="divider" fp_name="divider273"> |
<obj_property name="label">CPU: Control.EXE</obj_property> |
159,6 → 158,10
<obj_property name="ElementShortName">illegal_instruction</obj_property> |
<obj_property name="ObjectShortName">illegal_instruction</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/csr_acc_valid" type="logic"> |
<obj_property name="ElementShortName">csr_acc_valid</obj_property> |
<obj_property name="ObjectShortName">csr_acc_valid</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/illegal_register" type="logic"> |
<obj_property name="ElementShortName">illegal_register</obj_property> |
<obj_property name="ObjectShortName">illegal_register</obj_property> |
171,70 → 174,6
<obj_property name="ElementShortName">execute_engine</obj_property> |
<obj_property name="ObjectShortName">execute_engine</obj_property> |
<obj_property name="isExpanded"></obj_property> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.state" type="other"> |
<obj_property name="ElementShortName">.state</obj_property> |
<obj_property name="ObjectShortName">.state</obj_property> |
<obj_property name="CustomSignalColor">#FFA500</obj_property> |
<obj_property name="UseCustomSignalColor">true</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.state_nxt" type="other"> |
<obj_property name="ElementShortName">.state_nxt</obj_property> |
<obj_property name="ObjectShortName">.state_nxt</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.i_reg" type="array"> |
<obj_property name="ElementShortName">.i_reg[31:0]</obj_property> |
<obj_property name="ObjectShortName">.i_reg[31:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.i_reg_nxt" type="array"> |
<obj_property name="ElementShortName">.i_reg_nxt[31:0]</obj_property> |
<obj_property name="ObjectShortName">.i_reg_nxt[31:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.is_ci" type="logic"> |
<obj_property name="ElementShortName">.is_ci</obj_property> |
<obj_property name="ObjectShortName">.is_ci</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.is_ci_nxt" type="logic"> |
<obj_property name="ElementShortName">.is_ci_nxt</obj_property> |
<obj_property name="ObjectShortName">.is_ci_nxt</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.is_jump" type="logic"> |
<obj_property name="ElementShortName">.is_jump</obj_property> |
<obj_property name="ObjectShortName">.is_jump</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.is_jump_nxt" type="logic"> |
<obj_property name="ElementShortName">.is_jump_nxt</obj_property> |
<obj_property name="ObjectShortName">.is_jump_nxt</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.branch_taken" type="logic"> |
<obj_property name="ElementShortName">.branch_taken</obj_property> |
<obj_property name="ObjectShortName">.branch_taken</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.pc" type="array"> |
<obj_property name="ElementShortName">.pc[31:0]</obj_property> |
<obj_property name="ObjectShortName">.pc[31:0]</obj_property> |
<obj_property name="CustomSignalColor">#FFFFFF</obj_property> |
<obj_property name="UseCustomSignalColor">true</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.pc_nxt" type="array"> |
<obj_property name="ElementShortName">.pc_nxt[31:0]</obj_property> |
<obj_property name="ObjectShortName">.pc_nxt[31:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.next_pc" type="array"> |
<obj_property name="ElementShortName">.next_pc[31:0]</obj_property> |
<obj_property name="ObjectShortName">.next_pc[31:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.last_pc" type="array"> |
<obj_property name="ElementShortName">.last_pc[31:0]</obj_property> |
<obj_property name="ObjectShortName">.last_pc[31:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.sleep" type="logic"> |
<obj_property name="ElementShortName">.sleep</obj_property> |
<obj_property name="ObjectShortName">.sleep</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.sleep_nxt" type="logic"> |
<obj_property name="ElementShortName">.sleep_nxt</obj_property> |
<obj_property name="ObjectShortName">.sleep_nxt</obj_property> |
</wvobject> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/CPU_EXTENSION_RISCV_C" type="other"> |
<obj_property name="ElementShortName">CPU_EXTENSION_RISCV_C</obj_property> |
273,6 → 212,99
<obj_property name="ElementShortName">csr</obj_property> |
<obj_property name="ObjectShortName">csr</obj_property> |
<obj_property name="isExpanded"></obj_property> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/csr.we" type="logic"> |
<obj_property name="ElementShortName">.we</obj_property> |
<obj_property name="ObjectShortName">.we</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/csr.we_nxt" type="logic"> |
<obj_property name="ElementShortName">.we_nxt</obj_property> |
<obj_property name="ObjectShortName">.we_nxt</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/csr.re" type="logic"> |
<obj_property name="ElementShortName">.re</obj_property> |
<obj_property name="ObjectShortName">.re</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/csr.re_nxt" type="logic"> |
<obj_property name="ElementShortName">.re_nxt</obj_property> |
<obj_property name="ObjectShortName">.re_nxt</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/csr.mstatus_mie" type="logic"> |
<obj_property name="ElementShortName">.mstatus_mie</obj_property> |
<obj_property name="ObjectShortName">.mstatus_mie</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/csr.mstatus_mpie" type="logic"> |
<obj_property name="ElementShortName">.mstatus_mpie</obj_property> |
<obj_property name="ObjectShortName">.mstatus_mpie</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/csr.mie_msie" type="logic"> |
<obj_property name="ElementShortName">.mie_msie</obj_property> |
<obj_property name="ObjectShortName">.mie_msie</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/csr.mie_meie" type="logic"> |
<obj_property name="ElementShortName">.mie_meie</obj_property> |
<obj_property name="ObjectShortName">.mie_meie</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/csr.mie_mtie" type="logic"> |
<obj_property name="ElementShortName">.mie_mtie</obj_property> |
<obj_property name="ObjectShortName">.mie_mtie</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/csr.mie_firqe" type="array"> |
<obj_property name="ElementShortName">.mie_firqe[3:0]</obj_property> |
<obj_property name="ObjectShortName">.mie_firqe[3:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/csr.mpp" type="array"> |
<obj_property name="ElementShortName">.mpp[1:0]</obj_property> |
<obj_property name="ObjectShortName">.mpp[1:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/csr.privilege" type="array"> |
<obj_property name="ElementShortName">.privilege[1:0]</obj_property> |
<obj_property name="ObjectShortName">.privilege[1:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/csr.mepc" type="array"> |
<obj_property name="ElementShortName">.mepc[31:0]</obj_property> |
<obj_property name="ObjectShortName">.mepc[31:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/csr.mcause" type="array"> |
<obj_property name="ElementShortName">.mcause[31:0]</obj_property> |
<obj_property name="ObjectShortName">.mcause[31:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/csr.mtvec" type="array"> |
<obj_property name="ElementShortName">.mtvec[31:0]</obj_property> |
<obj_property name="ObjectShortName">.mtvec[31:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/csr.mtval" type="array"> |
<obj_property name="ElementShortName">.mtval[31:0]</obj_property> |
<obj_property name="ObjectShortName">.mtval[31:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/csr.mscratch" type="array"> |
<obj_property name="ElementShortName">.mscratch[31:0]</obj_property> |
<obj_property name="ObjectShortName">.mscratch[31:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/csr.mcycle" type="array"> |
<obj_property name="ElementShortName">.mcycle[32:0]</obj_property> |
<obj_property name="ObjectShortName">.mcycle[32:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/csr.minstret" type="array"> |
<obj_property name="ElementShortName">.minstret[32:0]</obj_property> |
<obj_property name="ObjectShortName">.minstret[32:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/csr.mcycleh" type="array"> |
<obj_property name="ElementShortName">.mcycleh[19:0]</obj_property> |
<obj_property name="ObjectShortName">.mcycleh[19:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/csr.minstreth" type="array"> |
<obj_property name="ElementShortName">.minstreth[19:0]</obj_property> |
<obj_property name="ObjectShortName">.minstreth[19:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/csr.pmpcfg" type="array"> |
<obj_property name="ElementShortName">.pmpcfg[0:3][7:0]</obj_property> |
<obj_property name="ObjectShortName">.pmpcfg[0:3][7:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/csr.pmpaddr" type="array"> |
<obj_property name="ElementShortName">.pmpaddr[0:3][31:0]</obj_property> |
<obj_property name="ObjectShortName">.pmpaddr[0:3][31:0]</obj_property> |
<obj_property name="isExpanded"></obj_property> |
</wvobject> |
</wvobject> |
<wvobject type="divider" fp_name="divider139"> |
<obj_property name="label">CPU: RegFile</obj_property> |
286,18 → 318,6
<obj_property name="label">CPU: ALU</obj_property> |
<obj_property name="DisplayName">label</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/clk_i" type="logic"> |
<obj_property name="ElementShortName">clk_i</obj_property> |
<obj_property name="ObjectShortName">clk_i</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/rstn_i" type="logic"> |
<obj_property name="ElementShortName">rstn_i</obj_property> |
<obj_property name="ObjectShortName">rstn_i</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/ctrl_i" type="array"> |
<obj_property name="ElementShortName">ctrl_i[49:0]</obj_property> |
<obj_property name="ObjectShortName">ctrl_i[49:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/rs1_i" type="array"> |
<obj_property name="ElementShortName">rs1_i[31:0]</obj_property> |
<obj_property name="ObjectShortName">rs1_i[31:0]</obj_property> |
330,22 → 350,6
<obj_property name="ElementShortName">res_o[31:0]</obj_property> |
<obj_property name="ObjectShortName">res_o[31:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cp0_data_i" type="array"> |
<obj_property name="ElementShortName">cp0_data_i[31:0]</obj_property> |
<obj_property name="ObjectShortName">cp0_data_i[31:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cp0_valid_i" type="logic"> |
<obj_property name="ElementShortName">cp0_valid_i</obj_property> |
<obj_property name="ObjectShortName">cp0_valid_i</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cp1_data_i" type="array"> |
<obj_property name="ElementShortName">cp1_data_i[31:0]</obj_property> |
<obj_property name="ObjectShortName">cp1_data_i[31:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cp1_valid_i" type="logic"> |
<obj_property name="ElementShortName">cp1_valid_i</obj_property> |
<obj_property name="ObjectShortName">cp1_valid_i</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/wait_o" type="logic"> |
<obj_property name="ElementShortName">wait_o</obj_property> |
<obj_property name="ObjectShortName">wait_o</obj_property> |
362,66 → 366,6
<obj_property name="ElementShortName">opc[31:0]</obj_property> |
<obj_property name="ObjectShortName">opc[31:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/add_res" type="array"> |
<obj_property name="ElementShortName">add_res[31:0]</obj_property> |
<obj_property name="ObjectShortName">add_res[31:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/alu_res" type="array"> |
<obj_property name="ElementShortName">alu_res[31:0]</obj_property> |
<obj_property name="ObjectShortName">alu_res[31:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cmp_opx" type="array"> |
<obj_property name="ElementShortName">cmp_opx[32:0]</obj_property> |
<obj_property name="ObjectShortName">cmp_opx[32:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cmp_opy" type="array"> |
<obj_property name="ElementShortName">cmp_opy[32:0]</obj_property> |
<obj_property name="ObjectShortName">cmp_opy[32:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cmp_sub" type="array"> |
<obj_property name="ElementShortName">cmp_sub[32:0]</obj_property> |
<obj_property name="ObjectShortName">cmp_sub[32:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/sub_res" type="array"> |
<obj_property name="ElementShortName">sub_res[31:0]</obj_property> |
<obj_property name="ObjectShortName">sub_res[31:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cmp_equal" type="logic"> |
<obj_property name="ElementShortName">cmp_equal</obj_property> |
<obj_property name="ObjectShortName">cmp_equal</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cmp_less" type="logic"> |
<obj_property name="ElementShortName">cmp_less</obj_property> |
<obj_property name="ObjectShortName">cmp_less</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cp_cmd_ff" type="logic"> |
<obj_property name="ElementShortName">cp_cmd_ff</obj_property> |
<obj_property name="ObjectShortName">cp_cmd_ff</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cp_run" type="logic"> |
<obj_property name="ElementShortName">cp_run</obj_property> |
<obj_property name="ObjectShortName">cp_run</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cp_start" type="logic"> |
<obj_property name="ElementShortName">cp_start</obj_property> |
<obj_property name="ObjectShortName">cp_start</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cp_busy" type="logic"> |
<obj_property name="ElementShortName">cp_busy</obj_property> |
<obj_property name="ObjectShortName">cp_busy</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cp_rb_ff0" type="logic"> |
<obj_property name="ElementShortName">cp_rb_ff0</obj_property> |
<obj_property name="ObjectShortName">cp_rb_ff0</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/cp_rb_ff1" type="logic"> |
<obj_property name="ElementShortName">cp_rb_ff1</obj_property> |
<obj_property name="ObjectShortName">cp_rb_ff1</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_alu_inst/shifter" type="array"> |
<obj_property name="ElementShortName">shifter</obj_property> |
<obj_property name="ObjectShortName">shifter</obj_property> |
</wvobject> |
<wvobject type="divider" fp_name="divider367"> |
<obj_property name="label">CPU: BUS_UNIT</obj_property> |
<obj_property name="DisplayName">label</obj_property> |
481,23 → 425,302
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/i_arbiter" type="array"> |
<obj_property name="ElementShortName">i_arbiter</obj_property> |
<obj_property name="ObjectShortName">i_arbiter</obj_property> |
<obj_property name="isExpanded"></obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/d_arbiter" type="array"> |
<obj_property name="ElementShortName">d_arbiter</obj_property> |
<obj_property name="ObjectShortName">d_arbiter</obj_property> |
<obj_property name="isExpanded"></obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/cpu_i" type="array"> |
<obj_property name="ElementShortName">cpu_i</obj_property> |
<obj_property name="ObjectShortName">cpu_i</obj_property> |
<obj_property name="isExpanded"></obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/cpu_d" type="array"> |
<obj_property name="ElementShortName">cpu_d</obj_property> |
<obj_property name="ObjectShortName">cpu_d</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/PMP_USE" type="other"> |
<obj_property name="ElementShortName">PMP_USE</obj_property> |
<obj_property name="ObjectShortName">PMP_USE</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/PMP_NUM_REGIONS" type="other"> |
<obj_property name="ElementShortName">PMP_NUM_REGIONS</obj_property> |
<obj_property name="ObjectShortName">PMP_NUM_REGIONS</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/PMP_GRANULARITY" type="other"> |
<obj_property name="ElementShortName">PMP_GRANULARITY</obj_property> |
<obj_property name="ObjectShortName">PMP_GRANULARITY</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp" type="array"> |
<obj_property name="ElementShortName">pmp</obj_property> |
<obj_property name="ObjectShortName">pmp</obj_property> |
<obj_property name="isExpanded"></obj_property> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp.addr_mask" type="array"> |
<obj_property name="ElementShortName">.addr_mask[0:3][33:0]</obj_property> |
<obj_property name="ObjectShortName">.addr_mask[0:3][33:0]</obj_property> |
<obj_property name="isExpanded"></obj_property> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp.addr_mask[0]" type="array"> |
<obj_property name="ElementShortName">[0][33:0]</obj_property> |
<obj_property name="ObjectShortName">[0][33:0]</obj_property> |
<obj_property name="Radix">BINARYRADIX</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp.addr_mask[1]" type="array"> |
<obj_property name="ElementShortName">[1][33:0]</obj_property> |
<obj_property name="ObjectShortName">[1][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp.addr_mask[2]" type="array"> |
<obj_property name="ElementShortName">[2][33:0]</obj_property> |
<obj_property name="ObjectShortName">[2][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp.addr_mask[3]" type="array"> |
<obj_property name="ElementShortName">[3][33:0]</obj_property> |
<obj_property name="ObjectShortName">[3][33:0]</obj_property> |
</wvobject> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp.i_match" type="array"> |
<obj_property name="ElementShortName">.i_match[3:0]</obj_property> |
<obj_property name="ObjectShortName">.i_match[3:0]</obj_property> |
<obj_property name="isExpanded"></obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp.d_match" type="array"> |
<obj_property name="ElementShortName">.d_match[3:0]</obj_property> |
<obj_property name="ObjectShortName">.d_match[3:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp.if_fault" type="array"> |
<obj_property name="ElementShortName">.if_fault[3:0]</obj_property> |
<obj_property name="ObjectShortName">.if_fault[3:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp.ld_fault" type="array"> |
<obj_property name="ElementShortName">.ld_fault[3:0]</obj_property> |
<obj_property name="ObjectShortName">.ld_fault[3:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp.st_fault" type="array"> |
<obj_property name="ElementShortName">.st_fault[3:0]</obj_property> |
<obj_property name="ObjectShortName">.st_fault[3:0]</obj_property> |
</wvobject> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_addr_i" type="array"> |
<obj_property name="ElementShortName">pmp_addr_i[0:15][33:0]</obj_property> |
<obj_property name="ObjectShortName">pmp_addr_i[0:15][33:0]</obj_property> |
<obj_property name="isExpanded"></obj_property> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_addr_i[0]" type="array"> |
<obj_property name="ElementShortName">[0][33:0]</obj_property> |
<obj_property name="ObjectShortName">[0][33:0]</obj_property> |
<obj_property name="Radix">BINARYRADIX</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_addr_i[1]" type="array"> |
<obj_property name="ElementShortName">[1][33:0]</obj_property> |
<obj_property name="ObjectShortName">[1][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_addr_i[2]" type="array"> |
<obj_property name="ElementShortName">[2][33:0]</obj_property> |
<obj_property name="ObjectShortName">[2][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_addr_i[3]" type="array"> |
<obj_property name="ElementShortName">[3][33:0]</obj_property> |
<obj_property name="ObjectShortName">[3][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_addr_i[4]" type="array"> |
<obj_property name="ElementShortName">[4][33:0]</obj_property> |
<obj_property name="ObjectShortName">[4][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_addr_i[5]" type="array"> |
<obj_property name="ElementShortName">[5][33:0]</obj_property> |
<obj_property name="ObjectShortName">[5][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_addr_i[6]" type="array"> |
<obj_property name="ElementShortName">[6][33:0]</obj_property> |
<obj_property name="ObjectShortName">[6][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_addr_i[7]" type="array"> |
<obj_property name="ElementShortName">[7][33:0]</obj_property> |
<obj_property name="ObjectShortName">[7][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_addr_i[8]" type="array"> |
<obj_property name="ElementShortName">[8][33:0]</obj_property> |
<obj_property name="ObjectShortName">[8][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_addr_i[9]" type="array"> |
<obj_property name="ElementShortName">[9][33:0]</obj_property> |
<obj_property name="ObjectShortName">[9][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_addr_i[10]" type="array"> |
<obj_property name="ElementShortName">[10][33:0]</obj_property> |
<obj_property name="ObjectShortName">[10][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_addr_i[11]" type="array"> |
<obj_property name="ElementShortName">[11][33:0]</obj_property> |
<obj_property name="ObjectShortName">[11][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_addr_i[12]" type="array"> |
<obj_property name="ElementShortName">[12][33:0]</obj_property> |
<obj_property name="ObjectShortName">[12][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_addr_i[13]" type="array"> |
<obj_property name="ElementShortName">[13][33:0]</obj_property> |
<obj_property name="ObjectShortName">[13][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_addr_i[14]" type="array"> |
<obj_property name="ElementShortName">[14][33:0]</obj_property> |
<obj_property name="ObjectShortName">[14][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_addr_i[15]" type="array"> |
<obj_property name="ElementShortName">[15][33:0]</obj_property> |
<obj_property name="ObjectShortName">[15][33:0]</obj_property> |
</wvobject> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_maddr_o" type="array"> |
<obj_property name="ElementShortName">pmp_maddr_o[0:15][33:0]</obj_property> |
<obj_property name="ObjectShortName">pmp_maddr_o[0:15][33:0]</obj_property> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_maddr_o[0]" type="array"> |
<obj_property name="ElementShortName">[0][33:0]</obj_property> |
<obj_property name="ObjectShortName">[0][33:0]</obj_property> |
<obj_property name="Radix">BINARYRADIX</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_maddr_o[1]" type="array"> |
<obj_property name="ElementShortName">[1][33:0]</obj_property> |
<obj_property name="ObjectShortName">[1][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_maddr_o[2]" type="array"> |
<obj_property name="ElementShortName">[2][33:0]</obj_property> |
<obj_property name="ObjectShortName">[2][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_maddr_o[3]" type="array"> |
<obj_property name="ElementShortName">[3][33:0]</obj_property> |
<obj_property name="ObjectShortName">[3][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_maddr_o[4]" type="array"> |
<obj_property name="ElementShortName">[4][33:0]</obj_property> |
<obj_property name="ObjectShortName">[4][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_maddr_o[5]" type="array"> |
<obj_property name="ElementShortName">[5][33:0]</obj_property> |
<obj_property name="ObjectShortName">[5][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_maddr_o[6]" type="array"> |
<obj_property name="ElementShortName">[6][33:0]</obj_property> |
<obj_property name="ObjectShortName">[6][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_maddr_o[7]" type="array"> |
<obj_property name="ElementShortName">[7][33:0]</obj_property> |
<obj_property name="ObjectShortName">[7][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_maddr_o[8]" type="array"> |
<obj_property name="ElementShortName">[8][33:0]</obj_property> |
<obj_property name="ObjectShortName">[8][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_maddr_o[9]" type="array"> |
<obj_property name="ElementShortName">[9][33:0]</obj_property> |
<obj_property name="ObjectShortName">[9][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_maddr_o[10]" type="array"> |
<obj_property name="ElementShortName">[10][33:0]</obj_property> |
<obj_property name="ObjectShortName">[10][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_maddr_o[11]" type="array"> |
<obj_property name="ElementShortName">[11][33:0]</obj_property> |
<obj_property name="ObjectShortName">[11][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_maddr_o[12]" type="array"> |
<obj_property name="ElementShortName">[12][33:0]</obj_property> |
<obj_property name="ObjectShortName">[12][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_maddr_o[13]" type="array"> |
<obj_property name="ElementShortName">[13][33:0]</obj_property> |
<obj_property name="ObjectShortName">[13][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_maddr_o[14]" type="array"> |
<obj_property name="ElementShortName">[14][33:0]</obj_property> |
<obj_property name="ObjectShortName">[14][33:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_maddr_o[15]" type="array"> |
<obj_property name="ElementShortName">[15][33:0]</obj_property> |
<obj_property name="ObjectShortName">[15][33:0]</obj_property> |
</wvobject> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_ctrl_i" type="array"> |
<obj_property name="ElementShortName">pmp_ctrl_i[0:15][7:0]</obj_property> |
<obj_property name="ObjectShortName">pmp_ctrl_i[0:15][7:0]</obj_property> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_ctrl_i[0]" type="array"> |
<obj_property name="ElementShortName">[0][7:0]</obj_property> |
<obj_property name="ObjectShortName">[0][7:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_ctrl_i[1]" type="array"> |
<obj_property name="ElementShortName">[1][7:0]</obj_property> |
<obj_property name="ObjectShortName">[1][7:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_ctrl_i[2]" type="array"> |
<obj_property name="ElementShortName">[2][7:0]</obj_property> |
<obj_property name="ObjectShortName">[2][7:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_ctrl_i[3]" type="array"> |
<obj_property name="ElementShortName">[3][7:0]</obj_property> |
<obj_property name="ObjectShortName">[3][7:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_ctrl_i[4]" type="array"> |
<obj_property name="ElementShortName">[4][7:0]</obj_property> |
<obj_property name="ObjectShortName">[4][7:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_ctrl_i[5]" type="array"> |
<obj_property name="ElementShortName">[5][7:0]</obj_property> |
<obj_property name="ObjectShortName">[5][7:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_ctrl_i[6]" type="array"> |
<obj_property name="ElementShortName">[6][7:0]</obj_property> |
<obj_property name="ObjectShortName">[6][7:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_ctrl_i[7]" type="array"> |
<obj_property name="ElementShortName">[7][7:0]</obj_property> |
<obj_property name="ObjectShortName">[7][7:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_ctrl_i[8]" type="array"> |
<obj_property name="ElementShortName">[8][7:0]</obj_property> |
<obj_property name="ObjectShortName">[8][7:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_ctrl_i[9]" type="array"> |
<obj_property name="ElementShortName">[9][7:0]</obj_property> |
<obj_property name="ObjectShortName">[9][7:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_ctrl_i[10]" type="array"> |
<obj_property name="ElementShortName">[10][7:0]</obj_property> |
<obj_property name="ObjectShortName">[10][7:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_ctrl_i[11]" type="array"> |
<obj_property name="ElementShortName">[11][7:0]</obj_property> |
<obj_property name="ObjectShortName">[11][7:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_ctrl_i[12]" type="array"> |
<obj_property name="ElementShortName">[12][7:0]</obj_property> |
<obj_property name="ObjectShortName">[12][7:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_ctrl_i[13]" type="array"> |
<obj_property name="ElementShortName">[13][7:0]</obj_property> |
<obj_property name="ObjectShortName">[13][7:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_ctrl_i[14]" type="array"> |
<obj_property name="ElementShortName">[14][7:0]</obj_property> |
<obj_property name="ObjectShortName">[14][7:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/pmp_ctrl_i[15]" type="array"> |
<obj_property name="ElementShortName">[15][7:0]</obj_property> |
<obj_property name="ObjectShortName">[15][7:0]</obj_property> |
</wvobject> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/priv_mode_i" type="array"> |
<obj_property name="ElementShortName">priv_mode_i[1:0]</obj_property> |
<obj_property name="ObjectShortName">priv_mode_i[1:0]</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/if_pmp_fault" type="logic"> |
<obj_property name="ElementShortName">if_pmp_fault</obj_property> |
<obj_property name="ObjectShortName">if_pmp_fault</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/ld_pmp_fault" type="logic"> |
<obj_property name="ElementShortName">ld_pmp_fault</obj_property> |
<obj_property name="ObjectShortName">ld_pmp_fault</obj_property> |
</wvobject> |
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/st_pmp_fault" type="logic"> |
<obj_property name="ElementShortName">st_pmp_fault</obj_property> |
<obj_property name="ObjectShortName">st_pmp_fault</obj_property> |
</wvobject> |
<wvobject type="divider" fp_name="divider298"> |
<obj_property name="label">BUS_CROSSBAR</obj_property> |
<obj_property name="DisplayName">label</obj_property> |
/sim/neorv32_tb.vhd
134,8 → 134,13
CPU_EXTENSION_RISCV_C => true, -- implement compressed extension? |
CPU_EXTENSION_RISCV_E => false, -- implement embedded RF extension? |
CPU_EXTENSION_RISCV_M => true, -- implement muld/div extension? |
CPU_EXTENSION_RISCV_U => true, -- implement user mode extension? |
CPU_EXTENSION_RISCV_Zicsr => true, -- implement CSR system? |
CPU_EXTENSION_RISCV_Zifencei => true, -- implement instruction stream sync.? |
-- Physical Memory Protection (PMP) -- |
PMP_USE => true, -- implement PMP? |
PMP_NUM_REGIONS => 4, -- number of regions (max 16) |
PMP_GRANULARITY => 15, -- region granularity (1=8B, 2=16B, 3=32B, ...) default is 64k |
-- Memory configuration: Instruction memory -- |
MEM_ISPACE_BASE => x"00000000", -- base address of instruction memory space |
MEM_ISPACE_SIZE => 16*1024, -- total size of instruction memory space in byte |
/sw/example/cpu_test/main.c
74,8 → 74,11
void test_fail(void); |
|
// Global variables (also test initialization of global vars here) |
/// Global counter for failing tests |
int cnt_fail = 0; |
/// Global counter for successful tests |
int cnt_ok = 0; |
/// Global counter for total number of tests |
int cnt_test = 0; |
|
|
96,6 → 99,7
int main() { |
|
register uint32_t tmp_a; |
uint32_t i; |
volatile uint32_t dummy_dst __attribute__((unused)); |
|
union { |
181,7 → 185,7
#if (PROBING_MEM_TEST == 1) |
cnt_test++; |
|
register uint32_t dmem_probe_addr = neorv32_cpu_csr_read(CSR_MISPACEBASE); |
register uint32_t dmem_probe_addr = SYSINFO_ISPACE_BASE; |
uint32_t dmem_probe_cnt = 0; |
|
while(1) { |
193,9 → 197,9
dmem_probe_cnt++; |
} |
|
neorv32_uart_printf("%u bytes (should be %u bytes) ", dmem_probe_cnt, neorv32_cpu_csr_read(CSR_MISPACESIZE)); |
neorv32_uart_printf("@ 0x%x ", neorv32_cpu_csr_read(CSR_MISPACEBASE)); |
if (dmem_probe_cnt == neorv32_cpu_csr_read(CSR_MISPACESIZE)) { |
neorv32_uart_printf("%u bytes (should be %u bytes) ", dmem_probe_cnt, SYSINFO_ISPACE_SIZE); |
neorv32_uart_printf("@ 0x%x ", SYSINFO_ISPACE_BASE); |
if (dmem_probe_cnt == SYSINFO_ISPACE_SIZE) { |
test_ok(); |
} |
else { |
213,7 → 217,7
#if (PROBING_MEM_TEST == 1) |
cnt_test++; |
|
register uint32_t imem_probe_addr = neorv32_cpu_csr_read(CSR_MDSPACEBASE); |
register uint32_t imem_probe_addr =SYSINFO_DSPACE_BASE; |
uint32_t imem_probe_cnt = 0; |
|
while(1) { |
225,9 → 229,9
imem_probe_cnt++; |
} |
|
neorv32_uart_printf("%u bytes (should be %u bytes) ", imem_probe_cnt, neorv32_cpu_csr_read(CSR_MDSPACESIZE)); |
neorv32_uart_printf("@ 0x%x ", neorv32_cpu_csr_read(CSR_MDSPACEBASE)); |
if (imem_probe_cnt == neorv32_cpu_csr_read(CSR_MDSPACESIZE)) { |
neorv32_uart_printf("%u bytes (should be %u bytes) ", imem_probe_cnt, SYSINFO_DSPACE_SIZE); |
neorv32_uart_printf("@ 0x%x ", SYSINFO_DSPACE_BASE); |
if (imem_probe_cnt == SYSINFO_DSPACE_SIZE) { |
test_ok(); |
} |
else { |
623,6 → 627,8
test_fail(); |
} |
#endif |
// no more mtime interrupts |
neorv32_wdt_disable(); |
} |
else { |
neorv32_uart_printf("skipped (WDT not implemented)\n"); |
633,7 → 639,7
// Test WFI ("sleep") instructions, wakeup via MTIME |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_uart_printf("WFI: "); |
neorv32_uart_printf("WFI (MTIME): "); |
|
if (neorv32_mtime_available()) { |
cnt_test++; |
652,6 → 658,8
test_ok(); |
} |
#endif |
// no more mtime interrupts |
neorv32_mtime_set_timecmp(-1); |
} |
else { |
neorv32_uart_printf("skipped (MTIME not implemented)\n"); |
658,8 → 666,182
} |
|
|
// ---------------------------------------------------------- |
// Test invalid CSR access in user mode |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_uart_printf("USR INV_CSR: "); |
|
// skip if U-mode is not implemented |
if (neorv32_cpu_csr_read(CSR_MISA) & (1<<CPU_MISA_U_EXT)) { |
|
cnt_test++; |
|
// switch to user mode (hart will be back in MACHINE mode when trap handler returns) |
neorv32_cpu_goto_user_mode(); |
{ |
// access to mstatus not allowed for user mode programs |
neorv32_cpu_csr_read(CSR_MSTATUS); |
} |
|
#if (DETAILED_EXCEPTION_DEBUG==0) |
if (exception_handler_answer == TRAP_CODE_I_ILLEGAL) { |
test_ok(); |
} |
else { |
test_fail(); |
} |
#endif |
} |
else { |
neorv32_uart_printf("skipped (not possible when U-EXT disabled)\n"); |
} |
|
|
// ---------------------------------------------------------- |
// Test RTE debug handler |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_uart_printf("RTE DB TEST: "); |
|
cnt_test++; |
|
// uninstall custom handler and use default RTE debug handler |
neorv32_rte_exception_uninstall(RTE_TRAP_I_ILLEGAL); |
|
// trigger illegal instruction exception |
neorv32_cpu_csr_read(0xfff); // CSR not available |
|
neorv32_uart_printf(" "); |
if (exception_handler_answer == 0xFFFFFFFF) { |
test_ok(); |
} |
else { |
test_fail(); |
neorv32_uart_printf("answer: 0x%x", exception_handler_answer); |
} |
|
// restore original handler |
neorv32_rte_exception_install(RTE_TRAP_I_ILLEGAL, global_trap_handler); |
|
|
// ---------------------------------------------------------- |
// Test physical memory protection |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_uart_printf("\nPhysical memory protection: "); |
|
// check if PMP is implemented |
neorv32_cpu_csr_read(0x3a0); |
if (exception_handler_answer == TRAP_CODE_I_ILLEGAL) { |
neorv32_uart_printf("test skipped (PMP not implemented)\n"); |
} |
else { |
neorv32_uart_printf("implemented\n"); |
|
// find out number of regions |
for (i=0; i<16; i++) { |
exception_handler_answer = 0xFFFFFFFF; |
switch (i) { |
case 0: neorv32_cpu_csr_read(0x3b0); break; |
case 1: neorv32_cpu_csr_read(0x3b1); break; |
case 2: neorv32_cpu_csr_read(0x3b2); break; |
case 3: neorv32_cpu_csr_read(0x3b3); break; |
case 4: neorv32_cpu_csr_read(0x3b4); break; |
case 5: neorv32_cpu_csr_read(0x3b5); break; |
case 6: neorv32_cpu_csr_read(0x3b6); break; |
case 7: neorv32_cpu_csr_read(0x3b7); break; |
case 8: neorv32_cpu_csr_read(0x3b8); break; |
case 9: neorv32_cpu_csr_read(0x3b9); break; |
case 10: neorv32_cpu_csr_read(0x3ba); break; |
case 11: neorv32_cpu_csr_read(0x3bb); break; |
case 12: neorv32_cpu_csr_read(0x3bc); break; |
case 13: neorv32_cpu_csr_read(0x3bd); break; |
case 14: neorv32_cpu_csr_read(0x3be); break; |
case 15: neorv32_cpu_csr_read(0x3bf); break; |
default: break; |
} |
if (exception_handler_answer == TRAP_CODE_I_ILLEGAL) { |
break; |
} |
} |
neorv32_uart_printf("Regions: %u\n", i); |
|
|
// check granulartiy |
neorv32_cpu_csr_write(0x3a0, 0); |
neorv32_cpu_csr_write(0x3b0, 0xffffffff); |
uint32_t pmp_test_g = neorv32_cpu_csr_read(0x3b0); |
|
// find least-significat set bit |
for (i=31; i>=0; i--) { |
if (((pmp_test_g >> i) & 1) == 0) { |
break; |
} |
} |
neorv32_uart_printf("Min granulartiy: %u bytes per region\n", 1<<(i+2)); |
|
|
// test available modes |
neorv32_uart_printf("Mode TOR: "); |
neorv32_cpu_csr_write(0x3a0, 0x08); |
if ((neorv32_cpu_csr_read(0x3a0) & 0xFF) == 0x08) { |
neorv32_uart_printf("available\n"); |
} |
else { |
neorv32_uart_printf("not implemented\n"); |
} |
|
neorv32_uart_printf("Mode NA4: "); |
neorv32_cpu_csr_write(0x3a0, 0x10); |
if ((neorv32_cpu_csr_read(0x3a0) & 0xFF) == 0x10) { |
neorv32_uart_printf("available\n"); |
} |
else { |
neorv32_uart_printf("not implemented\n"); |
} |
|
neorv32_uart_printf("Mode NAPOT: "); |
neorv32_cpu_csr_write(0x3a0, 0x18); |
if ((neorv32_cpu_csr_read(0x3a0) & 0xFF) == 0x18) { |
neorv32_uart_printf("available\n"); |
} |
else { |
neorv32_uart_printf("not implemented\n"); |
} |
|
|
// test user mode access fault |
neorv32_cpu_csr_write(0x3b0, 0x00007fff); // 64k area @ 0x00000000 |
neorv32_cpu_csr_write(0x3a0, 0b00011100); // NAPOT, execute permission, NO load permission |
|
neorv32_uart_printf("U-mode protected load fault test: "); |
cnt_test++; |
|
exception_handler_answer = 0xFFFFFFFF; |
|
// switch to user mode (hart will be back in MACHINE mode when trap handler returns) |
neorv32_cpu_goto_user_mode(); |
{ |
// load from protected area |
asm volatile ("lw zero, 0(zero)"); |
} |
|
#if (DETAILED_EXCEPTION_DEBUG==0) |
if (exception_handler_answer == TRAP_CODE_L_ACCESS) { |
neorv32_uart_printf("ok\n"); |
cnt_ok++; |
} |
else { |
neorv32_uart_printf("fail\n"); |
cnt_fail++; |
} |
#endif |
} |
|
|
|
// ---------------------------------------------------------- |
// Final test reports |
// ---------------------------------------------------------- |
neorv32_uart_printf("\n\nTests: %i\nOK: %i\nFAIL: %i\n\n", cnt_test, cnt_ok, cnt_fail); |
682,6 → 864,10
void global_trap_handler(void) { |
|
exception_handler_answer = neorv32_cpu_csr_read(CSR_MCAUSE); |
|
// hack: always come back in MACHINE MODE |
register uint32_t mask = (1<<CPU_MSTATUS_MPP_H) | (1<<CPU_MSTATUS_MPP_L); |
asm volatile ("csrrs zero, mstatus, %[input_j]" : : [input_j] "r" (mask)); |
} |
|
|
703,3 → 889,4
neorv32_uart_printf("fail\n"); |
cnt_fail++; |
} |
|
/sw/lib/include/neorv32.h
68,6 → 68,18
CSR_MTVAL = 0x343, /**< 0x343 - mtval (r/w): Machine bad address or instruction */ |
CSR_MIP = 0x344, /**< 0x344 - mip (r/w): Machine interrupt pending register */ |
|
CSR_PMPCFG0 = 0x3a0, /**< 0x3a0 - pmpcfg0 (r/w): Physical memory protection configuration register 0 */ |
CSR_PMPCFG1 = 0x3a1, /**< 0x3a1 - pmpcfg1 (r/w): Physical memory protection configuration register 1 */ |
|
CSR_PMPADDR0 = 0x3b0, /**< 0x3b0 - pmpaddr0 (r/w): Physical memory protection address register 0 */ |
CSR_PMPADDR1 = 0x3b1, /**< 0x3b1 - pmpaddr1 (r/w): Physical memory protection address register 1 */ |
CSR_PMPADDR2 = 0x3b2, /**< 0x3b2 - pmpaddr2 (r/w): Physical memory protection address register 2 */ |
CSR_PMPADDR3 = 0x3b3, /**< 0x3b3 - pmpaddr3 (r/w): Physical memory protection address register 3 */ |
CSR_PMPADDR4 = 0x3b4, /**< 0x3b4 - pmpaddr4 (r/w): Physical memory protection address register 4 */ |
CSR_PMPADDR5 = 0x3b5, /**< 0x3b5 - pmpaddr5 (r/w): Physical memory protection address register 5 */ |
CSR_PMPADDR6 = 0x3b6, /**< 0x3b6 - pmpaddr6 (r/w): Physical memory protection address register 6 */ |
CSR_PMPADDR7 = 0x3b7, /**< 0x3b7 - pmpaddr7 (r/w): Physical memory protection address register 7 */ |
|
CSR_MCYCLE = 0xb00, /**< 0xb00 - mcycle (r/w): Machine cycle counter low word */ |
CSR_MINSTRET = 0xb02, /**< 0xb02 - minstret (r/w): Machine instructions-retired counter low word */ |
CSR_MCYCLEH = 0xb80, /**< 0xb80 - mcycleh (r/w): Machine cycle counter high word - only 20-bit wide!*/ |
92,8 → 104,10
* CPU <b>mstatus</b> CSR (r/w): Machine status (RISC-V spec.) |
**************************************************************************/ |
enum NEORV32_CPU_MSTATUS_enum { |
CPU_MSTATUS_MIE = 3, /**< CPU mstatus CSR (3): Machine interrupt enable bit (r/w) */ |
CPU_MSTATUS_MPIE = 7 /**< CPU mstatus CSR (7): Machine previous interrupt enable bit (r/w) */ |
CPU_MSTATUS_MIE = 3, /**< CPU mstatus CSR (3): Machine interrupt enable bit (r/w) */ |
CPU_MSTATUS_MPIE = 7, /**< CPU mstatus CSR (7): Machine previous interrupt enable bit (r/w) */ |
CPU_MSTATUS_MPP_L = 11, /**< CPU mstatus CSR (11): Machine previous privilege mode bit low (r/w) */ |
CPU_MSTATUS_MPP_H = 12 /**< CPU mstatus CSR (12): Machine previous privilege mode bit high (r/w) */ |
}; |
|
|
104,7 → 118,6
CPU_MIE_MSIE = 3, /**< CPU mie CSR (3): Machine software interrupt enable (r/w) */ |
CPU_MIE_MTIE = 7, /**< CPU mie CSR (7): Machine timer interrupt enable bit (r/w) */ |
CPU_MIE_MEIE = 11, /**< CPU mie CSR (11): Machine external interrupt enable bit (r/w) */ |
|
CPU_MIE_FIRQ0E = 16, /**< CPU mie CSR (16): Fast interrupt channel 0 enable bit (r/w) */ |
CPU_MIE_FIRQ1E = 17, /**< CPU mie CSR (17): Fast interrupt channel 1 enable bit (r/w) */ |
CPU_MIE_FIRQ2E = 18, /**< CPU mie CSR (18): Fast interrupt channel 2 enable bit (r/w) */ |
131,10 → 144,11
* CPU <b>misa</b> CSR (r/w): Machine instruction set extensions (RISC-V spec.) |
**************************************************************************/ |
enum NEORV32_CPU_MISA_enum { |
CPU_MISA_C_EXT = 2, /**< CPU misa CSR (2): C: Compressed instructions CPU extension available (r/-), can be switched on/off */ |
CPU_MISA_C_EXT = 2, /**< CPU misa CSR (2): C: Compressed instructions CPU extension available (r/-)*/ |
CPU_MISA_E_EXT = 4, /**< CPU misa CSR (3): E: Embedded CPU extension available (r/-) */ |
CPU_MISA_I_EXT = 8, /**< CPU misa CSR (8): I: Base integer ISA CPU extension available (r/-) */ |
CPU_MISA_M_EXT = 12, /**< CPU misa CSR (12): M: Multiplier/divider CPU extension available (r/-), can be switched on/off */ |
CPU_MISA_M_EXT = 12, /**< CPU misa CSR (12): M: Multiplier/divider CPU extension available (r/-)*/ |
CPU_MISA_U_EXT = 20, /**< CPU misa CSR (20): U: User mode CPU extension available (r/-)*/ |
CPU_MISA_X_EXT = 23, /**< CPU misa CSR (23): X: Non-standard CPU extension available (r/-) */ |
CPU_MISA_Z_EXT = 25, /**< CPU misa CSR (25): Z: Privileged architecture CPU extension(s) available (r/-) */ |
CPU_MISA_MXL_LO_EXT = 30, /**< CPU misa CSR (30): MXL.lo: CPU data width (r/-) */ |
/sw/lib/include/neorv32_cpu.h
51,6 → 51,7
void neorv32_cpu_set_minstret(uint64_t value); |
uint64_t neorv32_cpu_get_systime(void); |
void neorv32_cpu_delay_ms(uint32_t time_ms); |
void __attribute__((naked)) neorv32_cpu_goto_user_mode(void); |
|
|
/**********************************************************************//** |
/sw/lib/source/neorv32_cpu.c
237,3 → 237,20
} |
} |
|
|
/**********************************************************************//** |
* Switch from privilege mode MACHINE to privilege mode USER. |
* |
* @note This function requires the U extension to be implemented. |
**************************************************************************/ |
void __attribute__((naked)) neorv32_cpu_goto_user_mode(void) { |
|
register uint32_t mask = (1<<CPU_MSTATUS_MPP_H) | (1<<CPU_MSTATUS_MPP_L); |
mask = ~mask; |
asm volatile ("csrrc zero, mstatus, %[input_j]" : : [input_j] "r" (mask)); |
|
// return and switch to user mode |
asm volatile ("csrw mepc, ra"); |
asm volatile ("mret"); |
} |
|
/sw/lib/source/neorv32_rte.c
211,32 → 211,11
**************************************************************************/ |
static void __neorv32_rte_debug_exc_handler(void) { |
|
neorv32_uart_printf("\n\n<< NEORV32 Runtime Environment >>\n"); |
// intro |
neorv32_uart_printf("<RTE> "); |
|
neorv32_uart_printf("System time: 0x%x_%x\n", neorv32_cpu_csr_read(CSR_TIMEH), neorv32_cpu_csr_read(CSR_TIME)); |
|
// cause |
register uint32_t trap_cause = neorv32_cpu_csr_read(CSR_MCAUSE); |
register uint32_t trap_addr = neorv32_cpu_csr_read(CSR_MEPC); |
register uint32_t trap_inst; |
|
asm volatile ("lh %[result], 0(%[input_i])" : [result] "=r" (trap_inst) : [input_i] "r" (trap_addr)); |
|
|
if (trap_cause & 0x80000000) { |
neorv32_uart_printf("INTERRUPT"); |
} |
else { |
neorv32_uart_printf("EXCEPTION"); |
if ((trap_inst & 3) == 3) { |
trap_addr -= 4; |
} |
else { |
trap_addr -= 2; |
} |
} |
neorv32_uart_printf(" at instruction address: 0x%x\n", trap_addr); |
|
neorv32_uart_printf("Cause: "); |
switch (trap_cause) { |
case TRAP_CODE_I_MISALIGNED: neorv32_uart_printf("Instruction address misaligned"); break; |
case TRAP_CODE_I_ACCESS: neorv32_uart_printf("Instruction access fault"); break; |
257,18 → 236,21
default: neorv32_uart_printf("Unknown (0x%x)", trap_cause); break; |
} |
|
// fault address |
neorv32_uart_printf("\nFaulting instruction (low half word): 0x%x", trap_inst); |
// address |
register uint32_t trap_addr = neorv32_cpu_csr_read(CSR_MEPC); |
register uint32_t trap_inst; |
|
if ((trap_inst & 3) != 3) { |
neorv32_uart_printf(" (decompressed)\n"); |
asm volatile ("lh %[result], 0(%[input_i])" : [result] "=r" (trap_inst) : [input_i] "r" (trap_addr)); |
|
if ((trap_cause & 0x80000000) == 0) { |
if ((trap_inst & 3) == 3) { |
trap_addr -= 4; |
} |
else { |
trap_addr -= 2; |
} |
} |
|
neorv32_uart_printf("\nMTVAL: 0x%x\n", neorv32_cpu_csr_read(CSR_MTVAL)); |
|
neorv32_uart_printf("Trying to resume application @ 0x%x...", neorv32_cpu_csr_read(CSR_MEPC)); |
|
neorv32_uart_printf("\n<</NEORV32 Runtime Environment >>\n\n"); |
neorv32_uart_printf(" @0x%x, MTVAL=0x%x </RTE>", trap_addr, neorv32_cpu_csr_read(CSR_MTVAL)); |
} |
|
|
326,11 → 308,14
} |
neorv32_uart_printf("(0x%x)\n", tmp); |
|
// Clock speed |
neorv32_uart_printf("Clock speed: %u Hz\n", SYSINFO_CLK); |
|
// Misc |
neorv32_uart_printf("\n-- System --\n"); |
neorv32_uart_printf("Clock: %u Hz\n", SYSINFO_CLK); |
|
|
// Memory configuration |
neorv32_uart_printf("\n-- Memory Configuration --\n"); |
neorv32_uart_printf("\n-- Processor Memory Configuration --\n"); |
|
uint32_t size = SYSINFO_ISPACE_SIZE; |
uint32_t base = SYSINFO_ISPACE_BASE; |
353,7 → 338,8
__neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_EXT)); |
|
// peripherals |
neorv32_uart_printf("\n-- Peripherals --\n"); |
neorv32_uart_printf("\n-- Processor Peripherals --\n"); |
|
tmp = SYSINFO_FEATURES; |
|
neorv32_uart_printf("GPIO: "); |
/README.md
21,8 → 21,8
## Introduction |
|
The **NEORV32 processor** is a customizable full-scale mikrocontroller-like processor system based on the RISC-V-compliant |
`rv32i` NEORV32 CPU with optional `M`, `E`, `C` and `Zicsr` and `Zifencei` extensions. The CPU was built from scratch and |
is compliant to the *Unprivileged ISA Specification Version 2.2* and a subset of the *Privileged Architecture |
`rv32i` NEORV32 CPU with optional `M`, `E`, `C` and `U`, `Zicsr` and `Zifencei` extensions and optional physical memory protection (PMP). |
The CPU was built from scratch and is compliant to the *Unprivileged ISA Specification Version 2.2* and a subset of the *Privileged Architecture |
Specification Version 1.12-draft*. |
|
The **processor** is intended as auxiliary processor within a larger SoC designs or as stand-alone |
45,7 → 45,18
|
For more information take a look a the [![NEORV32 datasheet](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/figures/PDF_32.png) NEORV32 datasheet](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/NEORV32.pdf). |
|
### Key Features |
|
- RISC-V-compliant `rv32i` CPU with optional `C`, `E`, `M`, `U`, `Zicsr`, `rv32Zifencei` and PMP (physical memory protection) extensions |
- GCC-based toolchain ([pre-compiled rv32i and rv32 etoolchains available](https://github.com/stnolting/riscv_gcc_prebuilt)) |
- Application compilation based on [GNU makefiles](https://github.com/stnolting/neorv32/blob/master/sw/example/blink_led/makefile) |
- [Doxygen-based](https://github.com/stnolting/neorv32/blob/master/docs/doxygen_makefile_sw) documentation of the software framework: available on [GitHub pages](https://stnolting.github.io/neorv32/files.html) |
- Detailed [datasheet](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/NEORV32.pdf) (pdf) |
- Completely described in behavioral, platform-independent VHDL – no primitives, macros, etc. |
- Fully synchronous design, no latches, no gated clocks |
- Small hardware footprint and high operating frequency |
- Highly configurable CPU and processor setup |
|
### Design Principles |
|
* From zero to main(): Completely open source and documented. |
75,20 → 86,21
* `misa` CSR is read-only - no dynamic enabling/disabling of implemented CPU extensions during runtime |
* `mcause` CSR is read-only |
* The `[m]cycleh` and `[m]instreth` CSR counters are only 20-bit wide (in contrast to original 32-bit) |
* The physical memory protection (**PMP**) only supports `NAPOT` mode and only up to 8 regions |
|
|
### Custom CPU Extensions |
|
The custom extensions are always enabled and are indicated via the `X` bit in the `misa` CSR. |
|
* Four *fast interrupt* request channels with according control/status bits in `mie` and `mip` and custom exception codes in `mcause` |
|
|
### To-Do / Wish List |
|
- Add instructions how to use the NEORV32 CPU without the processor surroundings |
- Add AXI / AXI-Lite bridges |
- Option to use DSP-based multiplier in `M` extension (would be so much faster) |
- Synthesis results for more platforms |
- Implement user mode (`U` extension) |
- Port Dhrystone benchmark |
- Implement atomic operations (`A` extension) and floating-point operations (`F` extension) |
- Maybe port an RTOS (like [Zephyr](https://github.com/zephyrproject-rtos/zephyr), [freeRTOS](https://www.freertos.org) or [RIOT](https://www.riot-os.org)) |
102,28 → 114,20
|
![neorv32 Overview](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/figures/neorv32_processor.png) |
|
- RISC-V-compliant `rv32i` CPU with optional `C`, `E`, `M`, `Zicsr` and `rv32Zifencei` extensions |
- GCC-based toolchain ([pre-compiled rv32i and rv32 etoolchains available](https://github.com/stnolting/riscv_gcc_prebuilt)) |
- Application compilation based on [GNU makefiles](https://github.com/stnolting/neorv32/blob/master/sw/example/blink_led/makefile) |
- [Doxygen-based](https://github.com/stnolting/neorv32/blob/master/docs/doxygen_makefile_sw) documentation of the software framework: available on [GitHub pages](https://stnolting.github.io/neorv32/files.html) |
- Detailed [datasheet](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/NEORV32.pdf) (pdf) |
- Completely described in behavioral, platform-independent VHDL – no primitives, macros, etc. |
- Fully synchronous design, no latches, no gated clocks |
- Small hardware footprint and high operating frequency |
- Highly customizable processor configuration |
- _Optional_ processor-internal data and instruction memories (DMEM/IMEM) |
- _Optional_ internal bootloader with UART console and automatic SPI flash boot option |
- _Optional_ machine system timer (MTIME), RISC-V-compliant |
- _Optional_ universal asynchronous receiver and transmitter (UART) |
- _Optional_ 8/16/24/32-bit serial peripheral interface controller (SPI) with 8 dedicated chip select lines |
- _Optional_ two wire serial interface controller (TWI), compatible to the I²C standard |
- _Optional_ general purpose parallel IO port (GPIO), 16xOut & 16xIn, with pin-change interrupt |
- _Optional_ 32-bit external bus interface, Wishbone b4 compliant (WISHBONE) |
- _Optional_ watchdog timer (WDT) |
- _Optional_ PWM controller with 4 channels and 8-bit duty cycle resolution (PWM) |
- _Optional_ GARO-based true random number generator (TRNG) |
- _Optional_ dummy device (DEVNULL) (can be used for *fast* simulation console output) |
- System configuration information memory to check hardware configuration by software (SYSINFO) |
Highly customizable processor configuration: |
- Optional processor-internal data and instruction memories (DMEM/IMEM) |
- Optional internal bootloader with UART console and automatic SPI flash boot option |
- Optional machine system timer (MTIME), RISC-V-compliant |
- Optional universal asynchronous receiver and transmitter (UART) |
- Optional 8/16/24/32-bit serial peripheral interface controller (SPI) with 8 dedicated chip select lines |
- Optional two wire serial interface controller (TWI), compatible to the I²C standard |
- Optional general purpose parallel IO port (GPIO), 16xOut & 16xIn, with pin-change interrupt |
- Optional 32-bit external bus interface, Wishbone b4 compliant (WISHBONE) |
- Optional watchdog timer (WDT) |
- Optional PWM controller with 4 channels and 8-bit duty cycle resolution (PWM) |
- Optional GARO-based true random number generator (TRNG) |
- Optional dummy device (DEVNULL) (can be used for *fast* simulation console output) |
- System configuration information memory to check hardware configuration by software (SYSINFO) |
|
### CPU Features |
|
140,7 → 144,8
**General**: |
* Modified Harvard architecture (separate CPU interfaces for data and instructions; single processor-bus via bus switch) |
* Two stages in-order pipeline (FETCH, EXECUTE); each stage uses a multi-cycle processing scheme |
* No hardware support of unaligned accesses - they will trigger and exception |
* No hardware support of unaligned accesses - they will trigger an exception |
* Privilege levels: `machine` mode, `user` mode (if enabled via `U` extension) |
|
|
**RV32I base instruction set** (`I` extension): |
178,19 → 183,27
* Store address misaligned |
* Store access fault |
* Environment call from M-mode (via `ecall` instruction) |
* Machine timer interrupt `mti` (via MTIME unit) |
* Machine external interrupt `mei` (via CLIC unit) |
* Machine timer interrupt `mti` (via processor's MTIME unit) |
* Machine software interrupt `msi` (via external signal) |
* Machine external interrupt `mei` (via external signal) |
* Four fast interrupt requests (custom extension) |
|
**Privileged architecture / User mode** (`U` extension, requires `Zicsr` extension): |
* Privilege levels: `M-mode` (Machine mode) + `U-Mode` (User mode) |
|
**Privileged architecture / FENCE.I** (`Zifencei` extension): |
* System instructions: `FENCE.I` |
* System instructions: `FENCEI` |
|
**Physical memory protection** (`PMP`, requires `Zicsr` extension): |
* Additional machine CSRs: `pmpcfgx` `pmpaddrx` |
|
|
## FPGA Implementation Results |
|
This chapter shows exemplary implementation results of the NEORV32 processor for an **Intel Cyclone IV EP4CE22F17C6N FPGA** on |
a DE0-nano board. The design was synthesized using **Intel Quartus Prime Lite 19.1** ("balanced implementation"). The timing |
information is derived from the Timing Analyzer / Slow 1200mV 0C Model. If not otherwise specified, the default configuration |
of the processor's generics is assumed. No constraints were used at all. |
of the CPU's generics is assumed (no PMP). No constraints were used at all. |
|
### CPU |
|
229,7 → 242,7
### Exemplary FPGA Setups |
|
Exemplary implementation results for different FPGA platforms. The processor setup uses *all provided peripherals*, |
no external memory interface and only internal instruction and data memories. IMEM uses 16kB and DMEM uses 8kB memory space. The setup's top entity connects most of the |
no external memory interface, no PMP and only internal instruction and data memories. IMEM uses 16kB and DMEM uses 8kB memory space. The setup's top entity connects most of the |
processor's [top entity](https://github.com/stnolting/neorv32/blob/master/rtl/core/neorv32_top.vhd) signals |
to FPGA pins - except for the Wishbone bus and the interrupt signals. |
|
325,8 → 338,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 |
406,8 → 424,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 |
); |
469,8 → 492,8
To build the toolchain by yourself, follow the official [build instructions](https://github.com/riscv/riscv-gnu-toolchain. |
Make sure to use the `ilp32` or `ilp32e` ABI. |
|
Alternatively, you can download a prebuilt toolchain. I have uploaded the toolchain(s) I am using to GitHub. This toolchain |
has been compiled on a 64-bit x86 Ubuntu (Ubuntu on Windows, actually). Download the toolchain of choice: |
**Alternatively**, you can download a prebuilt toolchain. I have uploaded the toolchains I am using to GitHub. These toolchains |
were compiled on a 64-bit x86 Ubuntu 20.04 LTS (Ubuntu on Windows, actually). Download the toolchain of choice: |
|
[https://github.com/stnolting/riscv_gcc_prebuilt](https://github.com/stnolting/riscv_gcc_prebuilt) |
|