Add "out-of-band" signals to internal bus interface (#1131)
Some checks failed
Documentation / SW Framework (push) Waiting to run
Documentation / Datasheet (push) Waiting to run
Documentation / Deploy to Releases and Pages (push) Blocked by required conditions
Processor / processor simulation (push) Has been cancelled

This commit is contained in:
stnolting 2024-12-28 06:56:09 +01:00 committed by GitHub
commit a4935d249f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 219 additions and 141 deletions

View file

@ -29,6 +29,7 @@ mimpid = 0x01040312 -> Version 01.04.03.12 -> v1.4.3.12
| Date | Version | Comment | Ticket |
|:----:|:-------:|:--------|:------:|
| 27.12.2024 | 1.10.8.2 | add out-of-band signals to internal request bus | [#1131](https://github.com/stnolting/neorv32/pull/1131) |
| 27.12.2024 | 1.10.8.1 | :warning: replace MTIME by CLINT; :warning: remove `HART_ID` generic | [#1130](https://github.com/stnolting/neorv32/pull/1130) |
| 26.12.2024 | [**:rocket:1.10.8**](https://github.com/stnolting/neorv32/releases/tag/v1.10.8) | **New release** | |
| 23.12.2024 | 1.10.7.9 | :warning: rework IO/peripheral address space; :sparkles: increase device size from 256 bytes to 64kB | [#1126](https://github.com/stnolting/neorv32/pull/1126) |

View file

@ -68,8 +68,6 @@ direction as seen from the CPU.
4+^| **Global Signals**
| `clk_i` | 1 | in | Global clock line, all registers triggering on rising edge.
| `rstn_i` | 1 | in | Global reset, low-active.
| `sleep_o` | 1 | out | CPU is in <<_sleep_mode>> when set.
| `debug_o` | 1 | out | CPU is in <<_cpu_debug_mode,debug mode>> when set.
4+^| **Interrupts (<<_traps_exceptions_and_interrupts>>)**
| `msi_i` | 1 | in | RISC-V machine software interrupt.
| `mei_i` | 1 | in | RISC-V machine external interrupt.
@ -342,7 +340,7 @@ The `wfi` instruction will raise an illegal instruction exception when executed
if `TW` in <<_mstatus>> is set. When executed in debug-mode or during single-stepping `wfi` will behave as
simple `nop` without entering sleep mode.
After executing the `wfi` instruction the CPU's `sleep_o` signal (<<_cpu_top_entity_signals>>) will become set
After executing the `wfi` instruction the `sleep` signal of the CPU's request buses (<<_bus_interface>> will become set
as soon as the CPU has fully halted:
[start=1]
@ -393,15 +391,22 @@ the instruction fetch interface (`i_bus_*` signals) is used for fetching instruc
(`d_bus_*` signals) is used to access data via load and store operations. Each of these interfaces can access an address
space of up to 2^32^ bytes (4GB).
The bus interface uses two custom interface types: `bus_req_t` is used to propagate the bus access **requests**. These
signals are driven by the _accessing_ device (i.e. the CPU core). `bus_rsp_t` is used to return the bus **response** and
is driven by the _accessed_ device or bus system (i.e. a processor-internal memory or IO device).
The bus interface uses two custom interface types: `bus_req_t` is used to propagate the bus access requests downstream
from a host to a device. These signals are driven by the request-issuing device (i.e. the CPU core). Vice versa, `bus_rsp_t`
is used to return the bus response upstream from a device back to the host and is driven by the accessed device or bus system
(i.e. a processor-internal memory or IO device).
The signals of the request bus are split in to two categories: _in-band_ signals and _out-of-band_ signals. In-band
signals always belong to a certain bus transaction and are only valid between `stb` being set and the according response
(`err` or `ack`). being set. In contrast, the out-of-band signals are not associated with any bus transaction and are
always valid when set.
.Bus Interface - Request Bus (`bus_req_t`)
[cols="^1,^1,<6"]
[options="header",grid="rows"]
|=======================
| Signal | Width | Description
3+^| **In-Band Signals**
| `addr` | 32 | Access address (byte addressing)
| `data` | 32 | Write data
| `ben` | 4 | Byte-enable for each byte in `data`
@ -410,7 +415,10 @@ is driven by the _accessed_ device or bus system (i.e. a processor-internal memo
| `src` | 1 | Access source (`0` = instruction fetch, `1` = load/store)
| `priv` | 1 | Set if privileged (M-mode) access
| `rvso` | 1 | Set if current access is a reservation-set operation (`lr` or `sc` instruction, <<_zalrsc_isa_extension>>)
| `fence` | 1 | Data/instruction fence operation; valid without `stb` being set
3+^| **Out-Of-Band Signals**
| `fence` | 1 | Data/instruction fence request; single-shot
| `sleep` | 1 | Set if ALL upstream devices are in <<_sleep_mode>>
| `debug` | 1 | Set if the upstream device is in debug-mode
|=======================
.Bus Interface - Response Bus (`bus_rsp_t`)
@ -444,7 +452,7 @@ The figure below shows three exemplary bus accesses:
. A write access to address `B_addr` writing `wdata` (fastest response; `ACK` arrives right in the next cycle).
. A failing read access to address `C_addr` (slow response; `ERR` arrives after several cycles).
.Three Exemplary Bus Transactions
.Three Exemplary Bus Transactions (showing only in-band signals)
image::bus_interface.png[700]
.Adding Register Stages
@ -478,7 +486,7 @@ and also registers a reservation for the address `addr` (`rvs_valid` becomes set
invalidated (`rvs_valid` is `0`) the store access fails, so `wdata2` is **not** written to address `addr` at all. The failed
operation is indicated by a **1** being returned via `rsp.data` together with `ack`.
.Three Exemplary LR/SC Bus Transactions
.Three Exemplary LR/SC Bus Transactions (showing only in-band signals)
image::bus_interface_atomic.png[700]
.Store-Conditional Status

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Before After
Before After

View file

@ -10,7 +10,6 @@
{name: 'src', wave: 'x0.|.x0.x..|..'},
{name: 'priv', wave: 'x0.|.x0.x..|..'},
{name: 'rvso', wave: 'x0.|.x0.x..|..'},
{name: 'fence', wave: '0....|.....|..'},
],
{},
[

View file

@ -10,7 +10,6 @@
{name: 'src', wave: '0....|.....|.....'},
{name: 'priv', wave: '0....|.....|.....'},
{name: 'rvso', wave: '01..0|.1..0|.1..0', node: '.b.......e....'},
{name: 'fence', wave: '0....|.....|.....'},
],
{},
[

View file

@ -19,14 +19,15 @@ use neorv32.neorv32_package.all;
entity neorv32_bus_switch is
generic (
PORT_A_READ_ONLY : boolean; -- set if port A is read-only
PORT_B_READ_ONLY : boolean -- set if port B is read-only
ROUND_ROBIN_EN : boolean := false; -- enable round-robing scheduling
PORT_A_READ_ONLY : boolean := false; -- set if port A is read-only
PORT_B_READ_ONLY : boolean := false -- set if port B is read-only
);
port (
clk_i : in std_ulogic; -- global clock, rising edge
rstn_i : in std_ulogic; -- global reset, low-active, async
a_lock_i : in std_ulogic; -- exclusive access for port A while set
a_req_i : in bus_req_t; -- host port A request bus (PRIORITIZED)
a_req_i : in bus_req_t; -- host port A request bus
a_rsp_o : out bus_rsp_t; -- host port A response bus
b_req_i : in bus_req_t; -- host port B request bus
b_rsp_o : out bus_rsp_t; -- host port B response bus
@ -38,17 +39,10 @@ end neorv32_bus_switch;
architecture neorv32_bus_switch_rtl of neorv32_bus_switch is
-- access arbiter --
type arbiter_t is record
state, state_nxt : std_ulogic_vector(1 downto 0);
a_req, b_req : std_ulogic;
sel, stb : std_ulogic;
end record;
signal arbiter : arbiter_t;
-- FSM states --
constant IDLE : std_ulogic_vector(1 downto 0) := "00";
constant BUSY_A : std_ulogic_vector(1 downto 0) := "01";
constant BUSY_B : std_ulogic_vector(1 downto 0) := "10";
type state_t is (S_CHECK_A, S_BUSY_A, S_CHECK_B, S_BUSY_B);
signal state, state_nxt : state_t;
signal a_req, b_req : std_ulogic;
signal sel, stb : std_ulogic;
begin
@ -57,86 +51,158 @@ begin
arbiter_sync: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
arbiter.state <= IDLE;
arbiter.a_req <= '0';
arbiter.b_req <= '0';
state <= S_CHECK_A;
a_req <= '0';
b_req <= '0';
elsif rising_edge(clk_i) then
arbiter.state <= arbiter.state_nxt;
arbiter.a_req <= (arbiter.a_req or a_req_i.stb) and (not arbiter.state(0)); -- clear STB buffer in BUSY_A
arbiter.b_req <= (arbiter.b_req or b_req_i.stb) and (not arbiter.state(1)); -- clear STB buffer in BUSY_B
state <= state_nxt;
if (state = S_BUSY_A) then -- clear request
a_req <= '0';
else -- buffer request
a_req <= a_req or a_req_i.stb;
end if;
if (state = S_BUSY_B) then -- clear request
b_req <= '0';
else -- buffer request
b_req <= b_req or b_req_i.stb;
end if;
end if;
end process arbiter_sync;
-- fsm --
arbiter_comb: process(arbiter, a_lock_i, a_req_i, b_req_i, x_rsp_i)
begin
-- defaults --
arbiter.state_nxt <= arbiter.state;
arbiter.sel <= '0';
arbiter.stb <= '0';
-- state machine --
case arbiter.state is
-- Prioritizing Bus Switch ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
arbiter_prioritized:
if not ROUND_ROBIN_EN generate
arbiter_fsm: process(state, a_req, b_req, a_lock_i, a_req_i, b_req_i, x_rsp_i)
begin
-- defaults --
state_nxt <= state;
sel <= '0';
stb <= '0';
when BUSY_A => -- port A access in progress
-- ------------------------------------------------------------
arbiter.sel <= '0';
if (x_rsp_i.err = '1') or (x_rsp_i.ack = '1') then
arbiter.state_nxt <= IDLE;
end if;
-- state machine --
case state is
when BUSY_B => -- port B access in progress
-- ------------------------------------------------------------
arbiter.sel <= '1';
if (x_rsp_i.err = '1') or (x_rsp_i.ack = '1') then
arbiter.state_nxt <= IDLE;
end if;
when S_BUSY_A => -- port A access in progress
-- ------------------------------------------------------------
sel <= '0';
if (x_rsp_i.err = '1') or (x_rsp_i.ack = '1') then
state_nxt <= S_CHECK_A;
end if;
when others => -- IDLE: wait for requests
-- ------------------------------------------------------------
if (a_req_i.stb = '1') or (arbiter.a_req = '1') then -- request from port A (prioritized)?
arbiter.sel <= '0';
arbiter.stb <= '1';
arbiter.state_nxt <= BUSY_A;
elsif ((b_req_i.stb = '1') or (arbiter.b_req = '1')) and (a_lock_i = '0') then -- request from port B?
arbiter.sel <= '1';
arbiter.stb <= '1';
arbiter.state_nxt <= BUSY_B;
end if;
when S_BUSY_B => -- port B access in progress
-- ------------------------------------------------------------
sel <= '1';
if (x_rsp_i.err = '1') or (x_rsp_i.ack = '1') then
state_nxt <= S_CHECK_A;
end if;
end case;
end process arbiter_comb;
when others => -- wait for requests
-- ------------------------------------------------------------
if (a_req_i.stb = '1') or (a_req = '1') then -- request from port A (prioritized)?
sel <= '0';
stb <= '1';
state_nxt <= S_BUSY_A;
elsif ((b_req_i.stb = '1') or (b_req = '1')) and (a_lock_i = '0') then -- request from port B?
sel <= '1';
stb <= '1';
state_nxt <= S_BUSY_B;
end if;
end case;
end process arbiter_fsm;
end generate;
-- Round-Robin Arbiter --------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
arbiter_round_robin:
if ROUND_ROBIN_EN generate
arbiter_fsm: process(state, a_req, b_req, a_req_i, b_req_i, x_rsp_i)
begin
-- defaults --
state_nxt <= state;
sel <= '0';
stb <= '0';
-- state machine --
case state is
when S_CHECK_A => -- check if access from port A
-- ------------------------------------------------------------
sel <= '0';
if (a_req_i.stb = '1') or (a_req = '1') then
stb <= '1';
state_nxt <= S_BUSY_A;
else
state_nxt <= S_CHECK_B;
end if;
when S_BUSY_A => -- port B access in progress
-- ------------------------------------------------------------
sel <= '0';
if (x_rsp_i.err = '1') or (x_rsp_i.ack = '1') then
state_nxt <= S_CHECK_B;
end if;
when S_CHECK_B => -- check if access from port B
-- ------------------------------------------------------------
sel <= '1';
if (b_req_i.stb = '1') or (b_req = '1') then
stb <= '1';
state_nxt <= S_BUSY_B;
else
state_nxt <= S_CHECK_A;
end if;
when S_BUSY_B => -- port B access in progress
-- ------------------------------------------------------------
sel <= '1';
if (x_rsp_i.err = '1') or (x_rsp_i.ack = '1') then
state_nxt <= S_CHECK_A;
end if;
when others => -- undefined
-- ------------------------------------------------------------
state_nxt <= S_CHECK_A;
end case;
end process arbiter_fsm;
end generate;
-- Request Switch -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
x_req_o.addr <= a_req_i.addr when (arbiter.sel = '0') else b_req_i.addr;
x_req_o.rvso <= a_req_i.rvso when (arbiter.sel = '0') else b_req_i.rvso;
x_req_o.priv <= a_req_i.priv when (arbiter.sel = '0') else b_req_i.priv;
x_req_o.src <= a_req_i.src when (arbiter.sel = '0') else b_req_i.src;
x_req_o.rw <= a_req_i.rw when (arbiter.sel = '0') else b_req_i.rw;
x_req_o.fence <= a_req_i.fence or b_req_i.fence; -- propagate any fence operations
x_req_o.addr <= a_req_i.addr when (sel = '0') else b_req_i.addr;
x_req_o.rvso <= a_req_i.rvso when (sel = '0') else b_req_i.rvso;
x_req_o.priv <= a_req_i.priv when (sel = '0') else b_req_i.priv;
x_req_o.src <= a_req_i.src when (sel = '0') else b_req_i.src;
x_req_o.rw <= a_req_i.rw when (sel = '0') else b_req_i.rw;
x_req_o.fence <= a_req_i.fence or b_req_i.fence; -- propagate any fence request
x_req_o.sleep <= a_req_i.sleep and b_req_i.sleep; -- set if ALL upstream devices are in sleep mode
x_req_o.debug <= a_req_i.debug when (sel = '0') else b_req_i.debug;
x_req_o.data <= b_req_i.data when PORT_A_READ_ONLY else
a_req_i.data when PORT_B_READ_ONLY else
a_req_i.data when (arbiter.sel = '0') else b_req_i.data;
x_req_o.data <= b_req_i.data when PORT_A_READ_ONLY else
a_req_i.data when PORT_B_READ_ONLY else
a_req_i.data when (sel = '0') else b_req_i.data;
x_req_o.ben <= b_req_i.ben when PORT_A_READ_ONLY else
a_req_i.ben when PORT_B_READ_ONLY else
a_req_i.ben when (arbiter.sel = '0') else b_req_i.ben;
x_req_o.ben <= b_req_i.ben when PORT_A_READ_ONLY else
a_req_i.ben when PORT_B_READ_ONLY else
a_req_i.ben when (sel = '0') else b_req_i.ben;
x_req_o.stb <= arbiter.stb;
x_req_o.stb <= stb;
-- Response Switch ------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
a_rsp_o.data <= x_rsp_i.data;
a_rsp_o.ack <= x_rsp_i.ack when (arbiter.sel = '0') else '0';
a_rsp_o.err <= x_rsp_i.err when (arbiter.sel = '0') else '0';
a_rsp_o.ack <= x_rsp_i.ack when (sel = '0') else '0';
a_rsp_o.err <= x_rsp_i.err when (sel = '0') else '0';
b_rsp_o.data <= x_rsp_i.data;
b_rsp_o.ack <= x_rsp_i.ack when (arbiter.sel = '1') else '0';
b_rsp_o.err <= x_rsp_i.err when (arbiter.sel = '1') else '0';
b_rsp_o.ack <= x_rsp_i.ack when (sel = '1') else '0';
b_rsp_o.err <= x_rsp_i.err when (sel = '1') else '0';
end neorv32_bus_switch_rtl;
@ -703,10 +769,10 @@ entity neorv32_bus_reservation_set is
rvs_addr_o : out std_ulogic_vector(31 downto 0);
rvs_valid_o : out std_ulogic;
rvs_clear_i : in std_ulogic;
-- core/cpu port --
-- core port --
core_req_i : in bus_req_t;
core_rsp_o : out bus_rsp_t;
-- system ports --
-- system port --
sys_req_o : out bus_req_t;
sys_rsp_i : in bus_rsp_t
);

View file

@ -183,7 +183,7 @@ begin
-- request splitter: cached or direct access --
req_splitter: process(host_req_i, dir_acc_d)
begin
-- default: pass-through of all bus signals --
-- default: pass-through all bus signals --
cache_req <= host_req_i;
dir_req_d <= host_req_i;
-- direct access --
@ -826,7 +826,7 @@ begin
-- Control Engine FSM Comb ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
ctrl_engine_comb: process(state, upret, addr, haddr, baddr, bus_rsp_i, cmd_sync_i, cmd_miss_i, rdata_i, dirty_i)
ctrl_engine_comb: process(state, upret, addr, haddr, baddr, host_req_i, bus_rsp_i, cmd_sync_i, cmd_miss_i, rdata_i, dirty_i)
begin
-- control engine defaults --
state_nxt <= state;
@ -845,13 +845,19 @@ begin
new_o <= '0';
-- bus interface defaults --
bus_req_o <= req_terminate_c; -- all-zero
bus_req_o.addr <= addr.tag & addr.idx & addr.ofs & "00"; -- always word-aligned
bus_req_o.data <= rdata_i;
bus_req_o.ben <= (others => '1'); -- full-word writes only
bus_req_o.src <= '0'; -- cache accesses are always "data" accesses
bus_req_o.priv <= '0'; -- cache accesses are always "unprivileged" accesses
bus_req_o.rvso <= '0'; -- cache accesses can never be a reservation set operation
bus_req_o <= req_terminate_c; -- all-zero
bus_req_o.addr <= addr.tag & addr.idx & addr.ofs & "00"; -- always word-aligned
bus_req_o.data <= rdata_i;
bus_req_o.ben <= (others => '1'); -- full-word writes only
bus_req_o.src <= '0'; -- cache accesses are always data accesses
bus_req_o.priv <= '0'; -- cache accesses are always "unprivileged" accesses
bus_req_o.rvso <= '0'; -- cache accesses can never be a reservation set operation
bus_req_o.debug <= host_req_i.debug;
if (state = S_IDLE) then
bus_req_o.sleep <= host_req_i.sleep;
else
bus_req_o.sleep <= '0';
end if;
-- fsm --
case state is

View file

@ -71,8 +71,6 @@ entity neorv32_cpu is
-- global control --
clk_i : in std_ulogic; -- switchable global clock, rising edge
rstn_i : in std_ulogic; -- global reset, low-active, async
sleep_o : out std_ulogic; -- cpu is in sleep mode when set
debug_o : out std_ulogic; -- cpu is in debug mode when set
-- interrupts --
msi_i : in std_ulogic; -- risc-v machine software interrupt
mei_i : in std_ulogic; -- risc-v machine external interrupt
@ -290,10 +288,6 @@ begin
-- external CSR read-back --
xcsr_rdata_res <= xcsr_rdata_pmp or xcsr_rdata_alu;
-- CPU state --
sleep_o <= ctrl.cpu_sleep;
debug_o <= ctrl.cpu_debug;
-- Register File --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------

View file

@ -362,7 +362,7 @@ begin
((fetch_engine.pc(1) = '0') or (not RISCV_ISA_C)) else '0';
ipb.we(1) <= '1' when (fetch_engine.state = IF_PENDING) and (fetch_engine.resp = '1') else '0';
-- bus access type --
-- bus access meta data --
ibus_req_o.priv <= fetch_engine.priv; -- current effective privilege level
ibus_req_o.data <= (others => '0'); -- read-only
ibus_req_o.ben <= (others => '0'); -- read-only
@ -370,6 +370,8 @@ begin
ibus_req_o.src <= '1'; -- source = instruction fetch
ibus_req_o.rvso <= '0'; -- cannot be a reservation set operation
ibus_req_o.fence <= ctrl.lsu_fence; -- fence operation, valid without STB being set
ibus_req_o.sleep <= sleep_mode; -- sleep mode, valid without STB being set
ibus_req_o.debug <= debug_ctrl.run; -- debug mode, valid without STB being set
-- Instruction Prefetch Buffer (FIFO) -----------------------------------------------------

View file

@ -106,7 +106,9 @@ begin
end process mem_do_reg;
dbus_req_o.src <= '0'; -- 0 = data access
dbus_req_o.fence <= ctrl_i.lsu_fence; -- this is valid without STB being set
dbus_req_o.fence <= ctrl_i.lsu_fence; -- out-of-band: this is valid without STB being set
dbus_req_o.sleep <= ctrl_i.cpu_sleep; -- out-of-band: this is valid without STB being set
dbus_req_o.debug <= ctrl_i.cpu_debug; -- out-of-band: this is valid without STB being set
-- Data Input: Alignment and Sign-Extension -----------------------------------------------

View file

@ -25,7 +25,6 @@ entity neorv32_debug_dm is
-- global control --
clk_i : in std_ulogic; -- global clock line
rstn_i : in std_ulogic; -- global reset line, low-active
cpu_debug_i : in std_ulogic; -- CPU is in debug mode
-- debug module interface (DMI) --
dmi_req_i : in dmi_req_t; -- request
dmi_rsp_o : out dmi_rsp_t; -- response
@ -69,6 +68,7 @@ architecture neorv32_debug_dm_rtl of neorv32_debug_dm is
constant addr_progbuf1_c : std_ulogic_vector(6 downto 0) := "0100001";
constant addr_authdata_c : std_ulogic_vector(6 downto 0) := "0110000";
--constant addr_sbcs_c : std_ulogic_vector(6 downto 0) := "0111000"; -- hardwired to zero
constant addr_haltsum0_c : std_ulogic_vector(6 downto 0) := "1000000";
-- DMI access --
signal dmi_wren, dmi_wren_auth, dmi_rden, dmi_rden_auth : std_ulogic;
@ -666,7 +666,7 @@ begin
end process bus_access;
-- access helpers --
accen <= cpu_debug_i and bus_req_i.stb; -- allow access only when in debug-mode
accen <= bus_req_i.debug and bus_req_i.stb; -- allow access only when in debug-mode
rden <= accen and (not bus_req_i.rw);
wren <= accen and ( bus_req_i.rw);

View file

@ -310,6 +310,8 @@ begin
dma_req_o.addr <= engine.src_addr when (engine.state = S_READ) else engine.dst_addr;
dma_req_o.rvso <= '0'; -- no reservation set operation possible
dma_req_o.fence <= cfg.enable and cfg.fence and engine.done; -- issue FENCE operation when transfer is done
dma_req_o.sleep <= '1' when (engine.state = S_IDLE) else '0'; -- idle = sleep mode
dma_req_o.debug <= '0'; -- can never ever be in debug mode
-- address increment --
address_inc: process(cfg.qsel)

View file

@ -29,7 +29,7 @@ package neorv32_package is
-- Architecture Constants -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01100801"; -- hardware version
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01100802"; -- hardware version
constant archid_c : natural := 19; -- official RISC-V architecture ID
constant XLEN : natural := 32; -- native data path width
@ -129,7 +129,10 @@ package neorv32_package is
src : std_ulogic; -- access source (1=instruction fetch, 0=data access)
priv : std_ulogic; -- set if privileged (machine-mode) access
rvso : std_ulogic; -- set if reservation set operation (atomic LR/SC)
fence : std_ulogic; -- set if fence(.i) operation, single-shot (out-of-band)
-- out-of-band signals --
fence : std_ulogic; -- set if fence(.i) request by upstream device, single-shot
sleep : std_ulogic; -- set if ALL upstream sources are in sleep mode
debug : std_ulogic; -- set if upstream device is in debug mode
end record;
-- bus response --
@ -149,7 +152,9 @@ package neorv32_package is
src => '0',
priv => '0',
rvso => '0',
fence => '0'
fence => '0',
sleep => '1',
debug => '0'
);
-- endpoint (response) termination --

View file

@ -103,7 +103,7 @@ begin
end if;
end process sysinfo_0_write;
-- SYSINFO(1): Internal Memory Configuration (sizes)
-- SYSINFO(1): Misc --
sysinfo(1)(7 downto 0) <= std_ulogic_vector(to_unsigned(index_size_f(MEM_INT_IMEM_SIZE), 8)); -- log2(IMEM size)
sysinfo(1)(15 downto 8) <= std_ulogic_vector(to_unsigned(index_size_f(MEM_INT_DMEM_SIZE), 8)); -- log2(DMEM size)
sysinfo(1)(23 downto 16) <= (others => '0'); -- reserved

View file

@ -298,9 +298,6 @@ architecture neorv32_top_rtl of neorv32_top is
signal clk_gen_en : clk_gen_en_t;
signal clk_gen_en2 : std_ulogic_vector(11 downto 0);
-- CPU status --
signal cpu_debug, cpu_sleep : std_ulogic;
-- debug module interface (DMI) --
signal dmi_req : dmi_req_t;
signal dmi_rsp : dmi_rsp_t;
@ -459,6 +456,26 @@ begin
-- **************************************************************************************************************************
-- Core Complex
-- **************************************************************************************************************************
-- fast interrupt requests (FIRQs) --
cpu_firq(0) <= firq(FIRQ_TWD);
cpu_firq(1) <= firq(FIRQ_CFS);
cpu_firq(2) <= firq(FIRQ_UART0_RX);
cpu_firq(3) <= firq(FIRQ_UART0_TX);
cpu_firq(4) <= firq(FIRQ_UART1_RX);
cpu_firq(5) <= firq(FIRQ_UART1_TX);
cpu_firq(6) <= firq(FIRQ_SPI);
cpu_firq(7) <= firq(FIRQ_TWI);
cpu_firq(8) <= firq(FIRQ_XIRQ);
cpu_firq(9) <= firq(FIRQ_NEOLED);
cpu_firq(10) <= firq(FIRQ_DMA);
cpu_firq(11) <= firq(FIRQ_SDI);
cpu_firq(12) <= firq(FIRQ_GPTMR);
cpu_firq(13) <= firq(FIRQ_ONEWIRE);
cpu_firq(14) <= firq(FIRQ_SLINK_RX);
cpu_firq(15) <= firq(FIRQ_SLINK_TX);
-- CPU core + optional L1 caches --
core_complex:
if true generate
@ -516,8 +533,6 @@ begin
-- global control --
clk_i => clk_i,
rstn_i => rstn_sys,
sleep_o => cpu_sleep,
debug_o => cpu_debug,
-- interrupts --
msi_i => msw_irq,
mei_i => mext_irq_i,
@ -532,26 +547,8 @@ begin
dbus_rsp_i => cpu_d_rsp
);
-- fast interrupt requests (FIRQs) --
cpu_firq(0) <= firq(FIRQ_TWD);
cpu_firq(1) <= firq(FIRQ_CFS);
cpu_firq(2) <= firq(FIRQ_UART0_RX);
cpu_firq(3) <= firq(FIRQ_UART0_TX);
cpu_firq(4) <= firq(FIRQ_UART1_RX);
cpu_firq(5) <= firq(FIRQ_UART1_TX);
cpu_firq(6) <= firq(FIRQ_SPI);
cpu_firq(7) <= firq(FIRQ_TWI);
cpu_firq(8) <= firq(FIRQ_XIRQ);
cpu_firq(9) <= firq(FIRQ_NEOLED);
cpu_firq(10) <= firq(FIRQ_DMA);
cpu_firq(11) <= firq(FIRQ_SDI);
cpu_firq(12) <= firq(FIRQ_GPTMR);
cpu_firq(13) <= firq(FIRQ_ONEWIRE);
cpu_firq(14) <= firq(FIRQ_SLINK_RX);
cpu_firq(15) <= firq(FIRQ_SLINK_TX);
-- CPU Instruction Cache (I-Cache) --------------------------------------------------------
-- CPU L1 Instruction Cache (I-Cache) -----------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_icache_inst_true:
if ICACHE_EN generate
@ -580,7 +577,7 @@ begin
end generate;
-- CPU Data Cache (D-Cache) ---------------------------------------------------------------
-- CPU L1 Data Cache (D-Cache) ------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_dcache_inst_true:
if DCACHE_EN generate
@ -613,13 +610,14 @@ begin
-- -------------------------------------------------------------------------------------------
neorv32_core_bus_switch_inst: entity neorv32.neorv32_bus_switch
generic map (
ROUND_ROBIN_EN => false, -- use prioritizing arbitration
PORT_A_READ_ONLY => false,
PORT_B_READ_ONLY => true -- i-fetch is read-only
)
port map (
clk_i => clk_i,
rstn_i => rstn_sys,
a_lock_i => '0', -- no exclusive accesses for port A
a_lock_i => '0', -- no exclusive accesses
a_req_i => dcache_req, -- prioritized
a_rsp_o => dcache_rsp,
b_req_i => icache_req,
@ -656,13 +654,14 @@ begin
-- -------------------------------------------------------------------------------------------
neorv32_dma_bus_switch_inst: entity neorv32.neorv32_bus_switch
generic map (
ROUND_ROBIN_EN => false, -- use prioritizing arbitration
PORT_A_READ_ONLY => false,
PORT_B_READ_ONLY => false
)
port map (
clk_i => clk_i,
rstn_i => rstn_sys,
a_lock_i => '0', -- no exclusive accesses for port A
a_lock_i => '0', -- no exclusive accesses
a_req_i => core_req, -- prioritized
a_rsp_o => core_rsp,
b_req_i => dma_req,
@ -1151,8 +1150,6 @@ begin
rstn_sys_i => rstn_sys,
bus_req_i => iodev_req(IODEV_WDT),
bus_rsp_o => iodev_rsp(IODEV_WDT),
cpu_debug_i => cpu_debug,
cpu_sleep_i => cpu_sleep,
clkgen_en_o => clk_gen_en(CG_WDT),
clkgen_i => clk_gen,
rstn_o => rstn_wdt
@ -1690,7 +1687,6 @@ begin
port map (
clk_i => clk_i,
rstn_i => rstn_ext,
cpu_debug_i => cpu_debug,
dmi_req_i => dmi_req,
dmi_rsp_o => dmi_rsp,
bus_req_i => iodev_req(IODEV_OCD),

View file

@ -23,8 +23,6 @@ entity neorv32_wdt is
rstn_sys_i : in std_ulogic; -- system reset, low-active
bus_req_i : in bus_req_t; -- bus request
bus_rsp_o : out bus_rsp_t; -- bus response
cpu_debug_i : in std_ulogic; -- CPU is in debug mode
cpu_sleep_i : in std_ulogic; -- CPU is in sleep mode
clkgen_en_o : out std_ulogic; -- enable clock generator
clkgen_i : in std_ulogic_vector(7 downto 0);
rstn_o : out std_ulogic -- timeout reset, low_active, sync
@ -155,8 +153,8 @@ begin
-- valid counter increment? --
cnt_inc <= '1' when ((prsc_tick = '1') and (cnt_started = '1')) and -- clock tick and started
((cpu_debug_i = '0') or (ctrl.dben = '1')) and -- not in debug mode or allowed to run in debug mode
((cpu_sleep_i = '0') or (ctrl.sen = '1')) else '0'; -- not in sleep mode or allowed to run in sleep mode
((bus_req_i.debug = '0') or (ctrl.dben = '1')) and -- not in debug mode or allowed to run in debug mode
((bus_req_i.sleep = '0') or (ctrl.sen = '1')) else '0'; -- not in sleep mode or allowed to run in sleep mode
-- timeout detector --
cnt_timeout <= '1' when (cnt_started = '1') and (cnt = ctrl.timeout) else '0';