URL
https://opencores.org/ocsvn/neorv32/neorv32/trunk
Subversion Repositories neorv32
Compare Revisions
- This comparison shows the changes necessary to convert path
/neorv32/trunk/rtl/core
- from Rev 15 to Rev 16
- ↔ Reverse comparison
Rev 15 → Rev 16
/neorv32_cpu.vhd
63,8 → 63,8
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 |
PMP_NUM_REGIONS : natural := 4; -- number of regions (max 8) |
PMP_GRANULARITY : natural := 14; -- minimal 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 |
); |
137,7 → 137,6
|
-- 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 |
|
154,15 → 153,15
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; |
assert false report "NEORV32 CONFIG ERROR! User mode requires CPU_EXTENSION_RISCV_Zicsr extension." 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; |
assert false report "NEORV32 CONFIG ERROR! Physical memory protection (PMP) requires CPU_EXTENSION_RISCV_Zicsr extension." severity error; |
end if; |
-- performance counters requires Zicsr extension -- |
-- performance counters require 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; |
assert false report "NEORV32 CONFIG ERROR! Performance counter CSRs require CPU_EXTENSION_RISCV_Zicsr extension." severity error; |
end if; |
-- PMP regions -- |
if (PMP_NUM_REGIONS > pmp_max_r_c) and (PMP_USE = true) then |
169,8 → 168,8
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; |
if ((PMP_GRANULARITY < 1) or (PMP_GRANULARITY > 32)) and (PMP_USE = true) then |
assert false report "NEORV32 CONFIG ERROR! Invalid PMP granulartiy (0 < G < 33)." severity error; |
end if; |
end if; |
end process sanity_check; |
226,7 → 225,6
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 -- |
360,7 → 358,6
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 -- |
/neorv32_cpu_bus.vhd
75,7 → 75,6
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 -- |
142,14 → 141,17
|
-- 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_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 |
addr_mask : pmp_addr34_t; -- 34-bit physical address |
region_base : pmp_addr_t; -- masked region base address for comparator |
region_i_addr : pmp_addr_t; -- masked instruction access base address for comparator |
region_d_addr : pmp_addr_t; -- masked data access base address for comparator |
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; |
|
411,24 → 413,15
-- Physical Memory Protection (PMP) ------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
-- compute address masks -- |
pmp_masks: process(pmp_addr_i, pmp, pmp_ctrl_i) |
pmp_masks: process(pmp_addr_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; |
for i in PMP_GRANULARITY+1 to 33 loop |
if (i = PMP_GRANULARITY+1) then |
pmp.addr_mask(r)(i) <= '0'; |
else -- 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))); |
end if; |
end loop; -- i |
end loop; -- r |
435,37 → 428,29
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; |
-- compute operands for comparator -- |
pmp_prepare_check: |
for r in 0 to PMP_NUM_REGIONS-1 generate -- iterate over all regions |
-- ignore lowest 3 bits of access addresses -> minimal region size = 8 bytes |
pmp.region_i_addr(r) <= (fetch_pc_i(31 downto 3) & "000") and pmp.addr_mask(r)(33 downto 2); |
pmp.region_d_addr(r) <= (mar(31 downto 3) & "000") and pmp.addr_mask(r)(33 downto 2); |
pmp.region_base(r) <= pmp_addr_i(r)(33 downto 2) and pmp.addr_mask(r)(33 downto 2); |
end generate; -- r |
|
|
-- 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); |
pmp_addr_check: process (pmp) |
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) <= '0'; |
if (pmp.region_i_addr(r)(31 downto PMP_GRANULARITY+2) = pmp.region_base(r)(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) <= '0'; |
if (pmp.region_d_addr(r)(31 downto PMP_GRANULARITY+2) = pmp.region_base(r)(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; |
/neorv32_cpu_control.vhd
92,7 → 92,6
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 -- |
1467,7 → 1466,6
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) |
csr_rdata_o(31) <= '0'; -- 32-bit architecture (MXL hi) |
when x"304" => -- R/W: mie - machine interrupt-enable register |
1535,7 → 1533,7
|
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); |
csr_rdata_o <= csr.pmpaddr(0); |
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 |
1544,7 → 1542,7
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); |
csr_rdata_o <= csr.pmpaddr(1); |
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 |
1553,7 → 1551,7
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); |
csr_rdata_o <= csr.pmpaddr(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 |
1562,7 → 1560,7
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); |
csr_rdata_o <= csr.pmpaddr(3); |
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 |
1571,7 → 1569,7
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); |
csr_rdata_o <= csr.pmpaddr(4); |
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 |
1580,7 → 1578,7
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); |
csr_rdata_o <= csr.pmpaddr(5); |
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 |
1589,7 → 1587,7
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); |
csr_rdata_o <= csr.pmpaddr(6); |
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 |
1598,7 → 1596,7
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); |
csr_rdata_o <= csr.pmpaddr(7); |
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 |
/neorv32_package.vhd
41,7 → 41,7
-- Architecture Constants ----------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
constant data_width_c : natural := 32; -- data width - FIXED! |
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01030500"; -- no touchy! |
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01030501"; -- no touchy! |
constant pmp_max_r_c : natural := 8; -- max PMP regions |
|
-- Helper Functions ----------------------------------------------------------------------- |
401,8 → 401,8
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 |
PMP_NUM_REGIONS : natural := 4; -- number of regions (max 8) |
PMP_GRANULARITY : natural := 14; -- minimal 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 |
485,8 → 485,8
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 |
PMP_NUM_REGIONS : natural := 4; -- number of regions (max 8) |
PMP_GRANULARITY : natural := 14; -- minimal 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 |
); |
578,7 → 578,6
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 -- |
697,7 → 696,6
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 -- |
/neorv32_top.vhd
60,8 → 60,8
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 |
PMP_NUM_REGIONS : natural := 4; -- number of regions (max 8) |
PMP_GRANULARITY : natural := 14; -- minimal 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 |
333,8 → 333,8
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 |
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (max 8) |
PMP_GRANULARITY => PMP_GRANULARITY, -- minimal 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 |
) |