Line 43... |
Line 43... |
|
|
entity neorv32_cpu_bus is
|
entity neorv32_cpu_bus is
|
generic (
|
generic (
|
CPU_EXTENSION_RISCV_C : boolean := true; -- implement compressed extension?
|
CPU_EXTENSION_RISCV_C : boolean := true; -- implement compressed extension?
|
-- Physical memory protection (PMP) --
|
-- Physical memory protection (PMP) --
|
PMP_USE : boolean := false -- implement physical memory protection?
|
PMP_USE : boolean := false; -- implement physical memory protection?
|
|
-- Bus Timeout --
|
|
BUS_TIMEOUT : natural := 63 -- cycles after an UNACKNOWLEDGED bus access triggers a bus fault exception
|
);
|
);
|
port (
|
port (
|
-- global control --
|
-- global control --
|
clk_i : in std_ulogic; -- global clock, rising edge
|
clk_i : in std_ulogic; -- global clock, rising edge
|
rstn_i : in std_ulogic := '0'; -- global reset, low-active, async
|
rstn_i : in std_ulogic := '0'; -- global reset, low-active, async
|
Line 134... |
Line 136... |
type bus_arbiter_t is record
|
type bus_arbiter_t is record
|
rd_req : std_ulogic; -- read access in progress
|
rd_req : std_ulogic; -- read access in progress
|
wr_req : std_ulogic; -- write access in progress
|
wr_req : std_ulogic; -- write access in progress
|
err_align : std_ulogic; -- alignment error
|
err_align : std_ulogic; -- alignment error
|
err_bus : std_ulogic; -- bus access error
|
err_bus : std_ulogic; -- bus access error
|
timeout : std_ulogic_vector(index_size_f(bus_timeout_c)-1 downto 0);
|
timeout : std_ulogic_vector(index_size_f(BUS_TIMEOUT)-1 downto 0);
|
end record;
|
end record;
|
signal i_arbiter, d_arbiter : bus_arbiter_t;
|
signal i_arbiter, d_arbiter : bus_arbiter_t;
|
|
|
-- physical memory protection --
|
-- physical memory protection --
|
type pmp_addr_t is array (0 to pmp_num_regions_c-1) of std_ulogic_vector(data_width_c-1 downto 0);
|
type pmp_addr_t is array (0 to pmp_num_regions_c-1) of std_ulogic_vector(data_width_c-1 downto 0);
|
Line 289... |
Line 291... |
if (d_arbiter.wr_req = '0') and (d_arbiter.rd_req = '0') then -- idle
|
if (d_arbiter.wr_req = '0') and (d_arbiter.rd_req = '0') then -- idle
|
d_arbiter.wr_req <= ctrl_i(ctrl_bus_wr_c);
|
d_arbiter.wr_req <= ctrl_i(ctrl_bus_wr_c);
|
d_arbiter.rd_req <= ctrl_i(ctrl_bus_rd_c);
|
d_arbiter.rd_req <= ctrl_i(ctrl_bus_rd_c);
|
d_arbiter.err_align <= d_misaligned;
|
d_arbiter.err_align <= d_misaligned;
|
d_arbiter.err_bus <= '0';
|
d_arbiter.err_bus <= '0';
|
d_arbiter.timeout <= std_ulogic_vector(to_unsigned(bus_timeout_c, index_size_f(bus_timeout_c)));
|
d_arbiter.timeout <= std_ulogic_vector(to_unsigned(BUS_TIMEOUT, index_size_f(BUS_TIMEOUT)));
|
else -- in progress
|
else -- in progress
|
d_arbiter.timeout <= std_ulogic_vector(unsigned(d_arbiter.timeout) - 1);
|
d_arbiter.timeout <= std_ulogic_vector(unsigned(d_arbiter.timeout) - 1);
|
d_arbiter.err_align <= (d_arbiter.err_align or d_misaligned) and (not ctrl_i(ctrl_bus_derr_ack_c));
|
d_arbiter.err_align <= (d_arbiter.err_align or d_misaligned) and (not ctrl_i(ctrl_bus_derr_ack_c));
|
d_arbiter.err_bus <= (d_arbiter.err_bus or (not or_all_f(d_arbiter.timeout)) or d_bus_err_i or
|
d_arbiter.err_bus <= (d_arbiter.err_bus or (not or_all_f(d_arbiter.timeout)) or d_bus_err_i or
|
(st_pmp_fault and d_arbiter.wr_req) or (ld_pmp_fault and d_arbiter.rd_req)) and (not ctrl_i(ctrl_bus_derr_ack_c));
|
(st_pmp_fault and d_arbiter.wr_req) or (ld_pmp_fault and d_arbiter.rd_req)) and (not ctrl_i(ctrl_bus_derr_ack_c));
|
Line 341... |
Line 343... |
-- instruction fetch request --
|
-- instruction fetch request --
|
if (i_arbiter.rd_req = '0') then -- idle
|
if (i_arbiter.rd_req = '0') then -- idle
|
i_arbiter.rd_req <= ctrl_i(ctrl_bus_if_c);
|
i_arbiter.rd_req <= ctrl_i(ctrl_bus_if_c);
|
i_arbiter.err_align <= i_misaligned;
|
i_arbiter.err_align <= i_misaligned;
|
i_arbiter.err_bus <= '0';
|
i_arbiter.err_bus <= '0';
|
i_arbiter.timeout <= std_ulogic_vector(to_unsigned(bus_timeout_c, index_size_f(bus_timeout_c)));
|
i_arbiter.timeout <= std_ulogic_vector(to_unsigned(BUS_TIMEOUT, index_size_f(BUS_TIMEOUT)));
|
else -- in progress
|
else -- in progress
|
i_arbiter.timeout <= std_ulogic_vector(unsigned(i_arbiter.timeout) - 1);
|
i_arbiter.timeout <= std_ulogic_vector(unsigned(i_arbiter.timeout) - 1);
|
i_arbiter.err_align <= (i_arbiter.err_align or i_misaligned) and (not ctrl_i(ctrl_bus_ierr_ack_c));
|
i_arbiter.err_align <= (i_arbiter.err_align or i_misaligned) and (not ctrl_i(ctrl_bus_ierr_ack_c));
|
i_arbiter.err_bus <= (i_arbiter.err_bus or (not or_all_f(i_arbiter.timeout)) or i_bus_err_i or if_pmp_fault) and (not ctrl_i(ctrl_bus_ierr_ack_c));
|
i_arbiter.err_bus <= (i_arbiter.err_bus or (not or_all_f(i_arbiter.timeout)) or i_bus_err_i or if_pmp_fault) and (not ctrl_i(ctrl_bus_ierr_ack_c));
|
if (i_bus_ack_i = '1') or (ctrl_i(ctrl_bus_ierr_ack_c) = '1') then -- wait for normal termination / CPU abort
|
if (i_bus_ack_i = '1') or (ctrl_i(ctrl_bus_ierr_ack_c) = '1') then -- wait for normal termination / CPU abort
|