add fence signal to CPU bus (#800)

This commit is contained in:
stnolting 2024-02-09 19:58:12 +01:00 committed by GitHub
commit 83bfb56b49
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 159 additions and 207 deletions

View file

@ -30,6 +30,7 @@ mimpid = 0x01040312 -> Version 01.04.03.12 -> v1.4.3.12
| Date | Version | Comment | Link |
|:----:|:-------:|:--------|:----:|
| 09.02.2024 | 1.9.4.7 | :warning: integrate fence signal into CPU bus, remove top entity's fence signals | (#800)[https://github.com/stnolting/neorv32/pull/800] |
| 09.02.2024 | 1.9.4.6 | :sparkles: add configurable XIP cache | [#799](https://github.com/stnolting/neorv32/pull/799) |
| 09.02.2024 | 1.9.4.5 | :bug: close further illegal compressed instruction encoding loopholes | [#797](https://github.com/stnolting/neorv32/pull/797) |
| 04.02.2024 | 1.9.4.4 | :bug: fix minor bug: CPU instruction bus privilege signal did not remain stable during the entire request | [#792](https://github.com/stnolting/neorv32/pull/792) |

View file

@ -11,8 +11,9 @@ RISC-V _User_ and _Privileged Architecture_ specifications.
**Section Structure**
* <<_architecture>>, <<_full_virtualization>> and <<_risc_v_compatibility>>
* <<_risc_v_compatibility>>
* <<_cpu_top_entity_signals>> and <<_cpu_top_entity_generics>>
* <<_architecture>> and <<_full_virtualization>>
* <<_instruction_sets_and_extensions>> and <<_custom_functions_unit_cfu>>
* <<_control_and_status_registers_csrs>>
* <<_traps_exceptions_and_interrupts>>
@ -56,6 +57,74 @@ be emulated. The NEORV32 <<_core_libraries>> provide an emulation wrapper for th
instructions that is based on LR/SC pairs. A demo/program can be found in `sw/example/atomic_test`.
<<<
// ####################################################################################################################
:sectnums:
=== CPU Top Entity - Signals
The following table shows all interface signals of the CPU top entity `rtl/core/neorv32_cpu.vhd`. The
type of all signals is _std_ulogic_ or _std_ulogic_vector_, respectively. The "Dir." column shows the signal
direction as seen from the CPU.
.NEORV32 CPU Signal List
[cols="<3,^3,^1,<5"]
[options="header", grid="rows"]
|=======================
| Signal | Width/Type | Dir | Description
4+^| **Global Signals**
| `clk_i` | 1 | in | Global clock line, all registers triggering on rising edge, this clock can be switched off during <<_sleep_mode>>
| `clk_aux_i` | 1 | in | Always-on clock, used to keep the the sleep control active when `clk_i` is switched off
| `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
| `mti_i` | 1 | in | RISC-V machine timer interrupt
| `firq_i` | 16 | in | Custom fast interrupt request signals
| `dbi_i` | 1 | in | Request CPU to halt and enter debug mode (RISC-V <<_on_chip_debugger_ocd>>)
4+^| **Instruction <<_bus_interface>>**
| `ibus_req_o` | `bus_req_t` | out | Instruction fetch bus request
| `ibus_rsp_i` | `bus_rsp_t` | in | Instruction fetch bus response
4+^| **Data <<_bus_interface>>**
| `dbus_req_o` | `bus_req_t` | out | Data access (load/store) bus request
| `dbus_rsp_i` | `bus_rsp_t` | in | Data access (load/store) bus response
|=======================
.Bus Interface Protocol
[TIP]
See section <<_bus_interface>> for the instruction fetch and data access interface protocol and the
according interface types (`bus_req_t` and `bus_rsp_t`).
<<<
// ####################################################################################################################
:sectnums:
=== CPU Top Entity - Generics
Most of the CPU configuration generics are a subset of the actual Processor configuration generics
(see section <<_processor_top_entity_generics>>). and are not listed here. However, the CPU provides
some _specific_ generics that are used to configure the CPU for the NEORV32 processor setup. These generics
are assigned by the processor setup only and are not available for user defined configuration.
The specific generics are listed below.
.Table Abbreviations
[NOTE]
The generic type "suv(x:y)" defines a `std_ulogic_vector(x downto y)`.
.NEORV32 CPU-Exclusive Generic List
[cols="<4,^2,<8"]
[options="header",grid="rows"]
|=======================
| Name | Type | Description
| `CPU_BOOT_ADDR` | suv(31:0) | CPU reset address. See section <<_address_space>>.
| `CPU_DEBUG_PARK_ADDR` | suv(31:0) | "Park loop" entry address for the <<_on_chip_debugger_ocd>>, has to be 4-byte aligned.
| `CPU_DEBUG_EXC_ADDR` | suv(31:0) | "Exception" entry address for the <<_on_chip_debugger_ocd>>, has to be 4-byte aligned.
| `CPU_EXTENSION_RISCV_Sdext` | boolean | Implement RISC-V-compatible "debug" CPU operation mode required for the <<_on_chip_debugger_ocd>>.
| `CPU_EXTENSION_RISCV_Sdtrig` | boolean | Implement RISC-V-compatible trigger module. See section <<_on_chip_debugger_ocd>>.
|=======================
<<<
// ####################################################################################################################
:sectnums:
@ -252,15 +321,16 @@ is driven by the _accessed_ device or bus system (i.e. a processor-internal memo
[cols="^1,^1,<6"]
[options="header",grid="rows"]
|=======================
| Signal | Width | Description
| `addr` | 32 | Access address (byte addressing)
| `data` | 32 | Write data
| `ben` | 4 | Byte-enable for each byte in `data`
| `stb` | 1 | Request trigger ("strobe", single-shot)
| `rw` | 1 | Access direction (`0` = read, `1` = write)
| `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 (atomic `lr` or `sc` instruction)
| Signal | Width | Description
| `addr` | 32 | Access address (byte addressing)
| `data` | 32 | Write data
| `ben` | 4 | Byte-enable for each byte in `data`
| `stb` | 1 | Request trigger ("strobe", single-shot)
| `rw` | 1 | Access direction (`0` = read, `1` = write)
| `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 (atomic `lr` or `sc` instruction)
| `fence` | 1 | Data/instruction fence operation; valid without `stb` being set
|=======================
.Bus Interface - Response Bus (`bus_rsp_t`)
@ -336,76 +406,6 @@ image::bus_interface_atomic.png[700]
The "normal" load data mechanism is used to return success/failure of the `sc.w` instruction to the CPU (via the LSB of `rsp.data`).
<<<
// ####################################################################################################################
:sectnums:
=== CPU Top Entity - Signals
The following table shows all interface signals of the CPU top entity `rtl/core/neorv32_cpu.vhd`. The
type of all signals is _std_ulogic_ or _std_ulogic_vector_, respectively. The "Dir." column shows the signal
direction as seen from the CPU.
.NEORV32 CPU Signal List
[cols="<3,^3,^1,<5"]
[options="header", grid="rows"]
|=======================
| Signal | Width/Type | Dir | Description
4+^| **Global Signals**
| `clk_i` | 1 | in | Global clock line, all registers triggering on rising edge, this clock can be switched off during <<_sleep_mode>>
| `clk_aux_i` | 1 | in | Always-on clock, used to keep the the sleep control active when `clk_i` is switched off
| `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
| `ifence_o` | 1 | out | instruction fence (`fence.i` instruction )
| `dfence_o` | 1 | out | data fence (`fence` instruction )
4+^| **Interrupts (<<_traps_exceptions_and_interrupts>>)**
| `msi_i` | 1 | in | RISC-V machine software interrupt
| `mei_i` | 1 | in | RISC-V machine external interrupt
| `mti_i` | 1 | in | RISC-V machine timer interrupt
| `firq_i` | 16 | in | Custom fast interrupt request signals
| `dbi_i` | 1 | in | Request CPU to halt and enter debug mode (RISC-V <<_on_chip_debugger_ocd>>)
4+^| **Instruction <<_bus_interface>>**
| `ibus_req_o` | `bus_req_t` | out | Instruction fetch bus request
| `ibus_rsp_i` | `bus_rsp_t` | in | Instruction fetch bus response
4+^| **Data <<_bus_interface>>**
| `dbus_req_o` | `bus_req_t` | out | Data access (load/store) bus request
| `dbus_rsp_i` | `bus_rsp_t` | in | Data access (load/store) bus response
|=======================
.Bus Interface Protocol
[TIP]
See section <<_bus_interface>> for the instruction fetch and data access interface protocol and the
according interface types (`bus_req_t` and `bus_rsp_t`).
<<<
// ####################################################################################################################
:sectnums:
=== CPU Top Entity - Generics
Most of the CPU configuration generics are a subset of the actual Processor configuration generics
(see section <<_processor_top_entity_generics>>). and are not listed here. However, the CPU provides
some _specific_ generics that are used to configure the CPU for the NEORV32 processor setup. These generics
are assigned by the processor setup only and are not available for user defined configuration.
The specific generics are listed below.
.Table Abbreviations
[NOTE]
The generic type "suv(x:y)" defines a `std_ulogic_vector(x downto y)`.
.NEORV32 CPU-Exclusive Generic List
[cols="<4,^2,<8"]
[options="header",grid="rows"]
|=======================
| Name | Type | Description
| `CPU_BOOT_ADDR` | suv(31:0) | CPU reset address. See section <<_address_space>>.
| `CPU_DEBUG_PARK_ADDR` | suv(31:0) | "Park loop" entry address for the <<_on_chip_debugger_ocd>>, has to be 4-byte aligned.
| `CPU_DEBUG_EXC_ADDR` | suv(31:0) | "Exception" entry address for the <<_on_chip_debugger_ocd>>, has to be 4-byte aligned.
| `CPU_EXTENSION_RISCV_Sdext` | boolean | Implement RISC-V-compatible "debug" CPU operation mode required for the <<_on_chip_debugger_ocd>>.
| `CPU_EXTENSION_RISCV_Sdtrig` | boolean | Implement RISC-V-compatible trigger module. See section <<_on_chip_debugger_ocd>>.
|=======================
<<<
// ####################################################################################################################
:sectnums:
@ -586,18 +586,11 @@ The `I` ISA extensions is the base RISC-V integer ISA that is always enabled.
| Illegal inst. | - | 3
|=======================
.`fence` Instruction - Predecessor and Successor Bits
.`fence` Instruction
[NOTE]
The `fence` instruction word's _predecessor_ and _successor_ bits (used for memory ordering) are not evaluated
by the hardware at all.
.`fence` Instruction - How it works
[NOTE]
CPU-internally, the `fence` instruction does not perform any operation inside the CPU. It only sets the
top's `d_bus_fence_o` signal high for one cycle to inform the memory system a `fence` instruction has been
executed. Any flags within the `fence` instruction word are ignore by the hardware. However, the `d_bus_fence_o`
signal is connected to the <<_processor_internal_data_cache_dcache>>. Hence, executing the `fence` instruction
will clear/flush the data cache and resynchronize it with main memory.
by the hardware at all. For the NEORV32 the `fence` instruction behaves exactly like the `fence.i` instruction
(see <<_zifencei_isa_extension>>).
.`wfi` Instruction
[NOTE]
@ -653,10 +646,11 @@ RISC-V specs. Also, custom trap codes for <<_mcause>> are implemented.
The `Zifencei` CPU extension allows manual synchronization of the instruction stream. This extension is always enabled.
The `fence.i` instruction resets the CPU's front-end (instruction fetch) and flushes the prefetch buffer.
This allows a clean re-fetch of modified instructions from memory. Also, the top's `i_bus_fencei_o` signal is set
high for one cycle to inform the memory system (like the <<_processor_internal_instruction_cache_icache>> to perform a flush/reload.
Any additional flags within the `fence.i` instruction word are ignored by the hardware.
.NEORV32 Fence Instructions
[NOTE]
The NEORV32 treats both fence instructions (`fence` = data fence, `fence.i` = instruction fence) in exactly the same way.
Both instructions cause a flush of the CPU's instruction prefetch buffer and also send a fence request via the system
bus (see <<_bus_interface>>). This system bus fence operation will, for example, clear/flush all downstream caches.
.Instructions and Timing
[cols="<2,<4,<3"]

View file

@ -105,9 +105,6 @@ Some interfaces (like the TWI and the 1-Wire bus) require tri-state drivers in t
| `slink_tx_dat_o` | 32 | out | - | TX data
| `slink_tx_val_o` | 1 | out | - | TX data valid
| `slink_tx_rdy_i` | 1 | in | `'L'` | TX allowed to send
5+^| **Advanced Memory Control Signals**
| `fence_o` | 1 | out | - | set if `fence` instruction is being executed
| `fencei_o` | 1 | out | - | set if `fence.i` instruction is being executed
5+^| **<<_execute_in_place_module_xip>>**
| `xip_csn_o` | 1 | out | - | chip select, low-active
| `xip_clk_o` | 1 | out | - | serial clock

View file

@ -24,13 +24,12 @@ equal to 4 bytes) and `DCACHE_NUM_BLOCKS` (the total amount of cache blocks; has
equal to 1) generics. The data cache provides only a single set, hence it is direct-mapped.
**Cached/Unached Accesses**
**Cached/Uncached Accesses**
The data cache provides direct accesses (= uncached) to memory in order to access memory-mapped IO (like the
processor-internal IO/peripheral modules). All accesses that target the address range from `0xF0000000` to `0xFFFFFFFF`
will not be cached at all (see section <<_address_space>>).
.Caching Internal Memories
[NOTE]
The data cache is intended to accelerate data access to **processor-external** memories
@ -39,8 +38,7 @@ when using only processor-internal data and instruction memories.
.Manual Cache Clear/Reload
[NOTE]
By executing the `fence` instruction (<<_i_isa_extension>>) the cache is cleared and a reload from
main memory is triggered.
By executing the `fence(.i)` instruction the cache is cleared and a reload from main memory is triggered.
.Retrieve Cache Configuration from Software
[TIP]

View file

@ -27,13 +27,12 @@ set-associative) generics. If the cache associativity is greater than one the LR
used) is used.
**Cached/Unached Accesses**
**Cached/Uncached Accesses**
The data cache provides direct accesses (= uncached) to memory in order to access memory-mapped IO (like the
processor-internal IO/peripheral modules). All accesses that target the address range from `0xF0000000` to `0xFFFFFFFF`
will not be cached at all (see section <<_address_space>>).
.Caching Internal Memories
[NOTE]
The instruction cache is intended to accelerate instruction fetches from **processor-external** memories
@ -42,8 +41,7 @@ when using only processor-internal data and instruction memories.
.Manual Cache Clear/Reload
[NOTE]
By executing the `fence.i` instruction (<<_zifencei_isa_extension>>) the cache is cleared and a reload from
main memory is triggered. This also allows to implement self-modifying code.
By executing the `fence(.i)` instruction the cache is cleared and a reload from main memory is triggered.
.Retrieve Cache Configuration from Software
[TIP]

View file

@ -175,6 +175,9 @@ cache layout:
When the cache is implemented, the XIP module operates in **burst mode** utilizing the flash's _incremental read_ capabilities.
Thus, several bytes (= `XIP_CACHE_BLOCK_SIZE`) are read consecutively from the flash using a single read command.
The XIP cache is cleared when the XIP module is disabled (`XIP_CTRL_EN = 0`), when XIP mode is disabled
(`XIP_CTRL_XIP_EN = 0`) or when the CPU issues a `fence(.i)` instruction.
**Register Map**

View file

@ -79,8 +79,6 @@ entity neorv32_cpu is
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
ifence_o : out std_ulogic; -- instruction fence
dfence_o : out std_ulogic; -- data fence
-- interrupts --
msi_i : in std_ulogic; -- risc-v machine software interrupt
mei_i : in std_ulogic; -- risc-v machine external interrupt
@ -257,10 +255,6 @@ begin
sleep_o <= ctrl.cpu_sleep; -- set when CPU is sleeping (after WFI)
debug_o <= ctrl.cpu_debug; -- set when CPU is in debug mode
-- instruction/data fence --
ifence_o <= ctrl.lsu_fencei;
dfence_o <= ctrl.lsu_fence;
-- Register File --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------

View file

@ -432,12 +432,13 @@ begin
ipb.we(1) <= '1' when (fetch_engine.state = IF_PENDING) and (fetch_engine.resp = '1') else '0';
-- bus access type --
bus_req_o.priv <= fetch_engine.priv; -- current effective privilege level
bus_req_o.data <= (others => '0'); -- read-only
bus_req_o.ben <= (others => '0'); -- read-only
bus_req_o.rw <= '0'; -- read-only
bus_req_o.src <= '1'; -- source = instruction fetch
bus_req_o.rvso <= '0'; -- cannot be a reservation set operation
bus_req_o.priv <= fetch_engine.priv; -- current effective privilege level
bus_req_o.data <= (others => '0'); -- read-only
bus_req_o.ben <= (others => '0'); -- read-only
bus_req_o.rw <= '0'; -- read-only
bus_req_o.src <= '1'; -- source = instruction fetch
bus_req_o.rvso <= '0'; -- cannot be a reservation set operation
bus_req_o.fence <= ctrl.lsu_fence; -- fence(.i) operation
-- Instruction Prefetch Buffer (FIFO) -----------------------------------------------------
@ -1009,9 +1010,8 @@ begin
if (trap_ctrl.exc_buf(exc_illegal_c) = '1') then -- abort if illegal instruction
execute_engine.state_nxt <= DISPATCH;
else
ctrl_nxt.lsu_fence <= not execute_engine.ir(instr_funct3_lsb_c); -- data fence
ctrl_nxt.lsu_fencei <= execute_engine.ir(instr_funct3_lsb_c); -- instruction fence
execute_engine.state_nxt <= RESTART; -- reset instruction fetch + IPB (only required for fence.i)
ctrl_nxt.lsu_fence <= '1'; -- NOTE: fence == fence.i
execute_engine.state_nxt <= RESTART; -- reset instruction fetch + IPB (actually only required for fence.i)
end if;
when BRANCH => -- update next_PC on taken branches and jumps
@ -1134,8 +1134,7 @@ begin
ctrl_o.lsu_req <= ctrl.lsu_req;
ctrl_o.lsu_rw <= ctrl.lsu_rw;
ctrl_o.lsu_mo_we <= '1' when (execute_engine.state = MEM_REQ) else '0'; -- write memory output registers (data & address)
ctrl_o.lsu_fence <= ctrl.lsu_fence;
ctrl_o.lsu_fencei <= ctrl.lsu_fencei;
ctrl_o.lsu_fence <= ctrl.lsu_fence; -- fence(.i)
ctrl_o.lsu_priv <= csr.mstatus_mpp when (csr.mstatus_mprv = '1') else csr.privilege_eff; -- effective privilege level for loads/stores in M-mode
-- instruction word bit fields --

View file

@ -124,6 +124,9 @@ begin
-- source identifier --
bus_req_o.src <= '0'; -- 0 = data access
-- data/instruction fence(.i)
bus_req_o.fence <= ctrl_i.lsu_fence;
-- Data Output - Alignment and Byte Enable ------------------------------------------------
-- -------------------------------------------------------------------------------------------

View file

@ -50,7 +50,6 @@ entity neorv32_dcache is
port (
clk_i : in std_ulogic; -- global clock, rising edge
rstn_i : in std_ulogic; -- global reset, low-active, async
clear_i : in std_ulogic; -- cache clear
cpu_req_i : in bus_req_t; -- request bus
cpu_rsp_o : out bus_rsp_t; -- response bus
bus_req_o : out bus_req_t; -- request bus
@ -156,7 +155,7 @@ begin
-- Control Engine FSM Comb ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
ctrl_engine_comb: process(ctrl, cache, clear_i, cpu_req_i, bus_rsp_i)
ctrl_engine_comb: process(ctrl, cache, cpu_req_i, bus_rsp_i)
begin
-- control defaults --
ctrl.state_nxt <= ctrl.state;
@ -164,7 +163,7 @@ begin
-- request buffer --
ctrl.req_buf_nxt <= ctrl.req_buf or cpu_req_i.stb;
ctrl.clear_buf_nxt <= ctrl.clear_buf or clear_i;
ctrl.clear_buf_nxt <= ctrl.clear_buf or cpu_req_i.fence;
-- cache defaults --
cache.clear <= '0';

View file

@ -324,10 +324,11 @@ begin
irq_o <= engine.done and config.enable; -- no interrupt if transfer was aborted
-- bus output --
dma_req_o.priv <= priv_mode_m_c; -- privileged access
dma_req_o.src <= '0'; -- source = data access
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.priv <= priv_mode_m_c; -- privileged access
dma_req_o.src <= '0'; -- source = data access
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 <= '0'; -- DMA cannot trigger a fence
-- address increment --
address_inc: process(config.qsel)

View file

@ -51,7 +51,6 @@ entity neorv32_icache is
port (
clk_i : in std_ulogic; -- global clock, rising edge
rstn_i : in std_ulogic; -- global reset, low-active, async
clear_i : in std_ulogic; -- cache clear
cpu_req_i : in bus_req_t; -- request bus
cpu_rsp_o : out bus_rsp_t; -- response bus
bus_req_o : out bus_req_t; -- request bus
@ -158,13 +157,13 @@ begin
-- Control Engine FSM Comb ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
ctrl_engine_fsm_comb: process(ctrl, cache, clear_i, cpu_req_i, bus_rsp_i)
ctrl_engine_fsm_comb: process(ctrl, cache, cpu_req_i, bus_rsp_i)
begin
-- control defaults --
ctrl.state_nxt <= ctrl.state;
ctrl.addr_reg_nxt <= ctrl.addr_reg;
ctrl.req_buf_nxt <= ctrl.req_buf or cpu_req_i.stb;
ctrl.clear_buf_nxt <= ctrl.clear_buf or clear_i; -- buffer clear request from CPU
ctrl.clear_buf_nxt <= ctrl.clear_buf or cpu_req_i.fence;
-- cache defaults --
cache.clear <= '0';

View file

@ -133,21 +133,22 @@ begin
-- 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.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.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.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.stb <= arbiter.stb;
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.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.stb <= arbiter.stb;
-- Response Switch ------------------------------------------------------------------------

View file

@ -56,7 +56,7 @@ package neorv32_package is
-- Architecture Constants -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01090406"; -- hardware version
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01090407"; -- hardware version
constant archid_c : natural := 19; -- official RISC-V architecture ID
constant XLEN : natural := 32; -- native data path width
@ -152,14 +152,15 @@ package neorv32_package is
-- -------------------------------------------------------------------------------------------
-- bus request --
type bus_req_t is record
addr : std_ulogic_vector(31 downto 0); -- access address
data : std_ulogic_vector(31 downto 0); -- write data
ben : std_ulogic_vector(03 downto 0); -- byte enable
stb : std_ulogic; -- request strobe (single-shot)
rw : std_ulogic; -- 0=read, 1=write
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)
addr : std_ulogic_vector(31 downto 0); -- access address
data : std_ulogic_vector(31 downto 0); -- write data
ben : std_ulogic_vector(03 downto 0); -- byte enable
stb : std_ulogic; -- request strobe (single-shot)
rw : std_ulogic; -- 0=read, 1=write
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; -- fence(.i) operation, independent of STB
end record;
-- bus response --
@ -171,14 +172,15 @@ package neorv32_package is
-- source (request) termination --
constant req_terminate_c : bus_req_t := (
addr => (others => '0'),
data => (others => '0'),
ben => (others => '0'),
stb => '0',
rw => '0',
src => '0',
priv => '0',
rvso => '0'
addr => (others => '0'),
data => (others => '0'),
ben => (others => '0'),
stb => '0',
rw => '0',
src => '0',
priv => '0',
rvso => '0',
fence => '0'
);
-- endpoint (response) termination --
@ -527,8 +529,7 @@ package neorv32_package is
lsu_req : std_ulogic; -- trigger memory access request
lsu_rw : std_ulogic; -- 0: read access, 1: write access
lsu_mo_we : std_ulogic; -- memory address and data output register write enable
lsu_fence : std_ulogic; -- fence operation
lsu_fencei : std_ulogic; -- fence.i operation
lsu_fence : std_ulogic; -- fence(.i) operation
lsu_priv : std_ulogic; -- effective privilege level for load/store
-- instruction word --
ir_funct3 : std_ulogic_vector(02 downto 0); -- funct3 bit field
@ -559,7 +560,6 @@ package neorv32_package is
lsu_rw => '0',
lsu_mo_we => '0',
lsu_fence => '0',
lsu_fencei => '0',
lsu_priv => '0',
ir_funct3 => (others => '0'),
ir_funct12 => (others => '0'),
@ -873,9 +873,6 @@ package neorv32_package is
slink_tx_dat_o : out std_ulogic_vector(31 downto 0);
slink_tx_val_o : out std_ulogic;
slink_tx_rdy_i : in std_ulogic := 'L';
-- Advanced memory control signals --
fence_o : out std_ulogic;
fencei_o : out std_ulogic;
-- XIP (execute in-place via SPI) signals (available if XIP_EN = true) --
xip_csn_o : out std_ulogic;
xip_clk_o : out std_ulogic;

View file

@ -186,11 +186,7 @@ entity neorv32_top is
slink_rx_rdy_o : out std_ulogic; -- RX ready to receive
slink_tx_dat_o : out std_ulogic_vector(31 downto 0); -- TX output data
slink_tx_val_o : out std_ulogic; -- TX valid output
slink_tx_rdy_i : in std_ulogic := 'L'; -- TX ready to send
-- Advanced memory control signals --
fence_o : out std_ulogic; -- indicates an executed FENCE operation
fencei_o : out std_ulogic; -- indicates an executed FENCEI operation
slink_tx_rdy_i : in std_ulogic := 'L'; -- TX ready to send
-- XIP (execute in place via SPI) signals (available if XIP_EN = true) --
xip_csn_o : out std_ulogic; -- chip-select, low-active
@ -298,10 +294,7 @@ architecture neorv32_top_rtl of neorv32_top is
signal cg_en : cg_en_t;
-- CPU status --
signal cpu_debug : std_ulogic; -- cpu is in debug mode
signal cpu_sleep : std_ulogic; -- cpu is in sleep mode
signal i_fence : std_ulogic; -- instruction fence
signal d_fence : std_ulogic; -- data fence
signal cpu_debug, cpu_sleep : std_ulogic; -- cpu is in debug/sleep mode
-- debug module interface (DMI) --
signal dmi_req : dmi_req_t;
@ -358,8 +351,8 @@ begin
-- say hello --
assert false report
"The NEORV32 RISC-V Processor, " &
"version 0x" & to_hstring32_f(hw_version_c) & ", " &
"[NEORV32] The NEORV32 RISC-V Processor " &
"(version 0x" & to_hstring32_f(hw_version_c) & "), " &
"github.com/stnolting/neorv32" severity note;
-- show main SoC configuration --
@ -556,8 +549,6 @@ begin
rstn_i => rstn_sys,
sleep_o => cpu_sleep,
debug_o => cpu_debug,
ifence_o => i_fence,
dfence_o => d_fence,
-- interrupts --
msi_i => msw_irq_i,
mei_i => mext_irq_i,
@ -572,10 +563,6 @@ begin
dbus_rsp_i => cpu_d_rsp
);
-- advanced memory control --
fence_o <= d_fence;
fencei_o <= i_fence;
-- fast interrupt requests (FIRQs) --
cpu_firq(00) <= firq.wdt; -- highest priority
cpu_firq(01) <= firq.cfs;
@ -609,7 +596,6 @@ begin
port map (
clk_i => clk_cpu,
rstn_i => rstn_sys,
clear_i => i_fence,
cpu_req_i => cpu_i_req,
cpu_rsp_o => cpu_i_rsp,
bus_req_o => icache_req,
@ -637,7 +623,6 @@ begin
port map (
clk_i => clk_cpu,
rstn_i => rstn_sys,
clear_i => d_fence,
cpu_req_i => cpu_d_req,
cpu_rsp_o => cpu_d_rsp,
bus_req_o => dcache_req,

View file

@ -279,8 +279,8 @@ begin
bus_req_o => xip_req,
bus_rsp_i => xip_rsp
);
-- clear cache when entire module or XIP-mode is disabled --
cache_clear <= '1' when (ctrl(ctrl_enable_c) = '0') or (ctrl(ctrl_xip_enable_c) = '0') else '0';
-- clear cache when entire module or XIP-mode is disabled or on global FENCE operation --
cache_clear <= '1' when (ctrl(ctrl_enable_c) = '0') or (ctrl(ctrl_xip_enable_c) = '0') or (xip_req_i.fence = '1') else '0';
end generate;
neorv32_xip_cache_inst_false:

View file

@ -151,10 +151,6 @@ entity neorv32_top_avalonmm is
writedata_o : out std_logic_vector(31 downto 0);
readdata_i : in std_logic_vector(31 downto 0) := (others => '0');
-- Advanced memory control signals (available if MEM_EXT_EN = true) --
fence_o : out std_ulogic; -- indicates an executed FENCE operation
fencei_o : out std_ulogic; -- indicates an executed FENCEI operation
-- XIP (execute in place via SPI) signals (available if IO_XIP_EN = true) --
xip_csn_o : out std_ulogic; -- chip-select, low-active
xip_clk_o : out std_ulogic; -- serial clock
@ -350,10 +346,6 @@ begin
wb_ack_i => wb_ack_i,
wb_err_i => wb_err_i,
-- Advanced memory control signals (available if MEM_EXT_EN = true) --
fence_o => fence_o,
fencei_o => fencei_o,
-- XIP (execute in place via SPI) signals (available if IO_XIP_EN = true) --
xip_csn_o => xip_csn_o,
xip_clk_o => xip_clk_o,

View file

@ -458,9 +458,6 @@ begin
slink_tx_dat_o => s0_axis_tdata_int, -- TX output data
slink_tx_val_o => s0_axis_tvalid_int, -- TX valid output
slink_tx_rdy_i => s0_axis_tready_int, -- TX ready to send
-- Advanced memory control signals (available if MEM_EXT_EN = true) --
fence_o => open, -- indicates an executed FENCE operation
fencei_o => open, -- indicates an executed FENCEI operation
-- XIP (execute in place via SPI) signals (available if IO_XIP_EN = true) --
xip_csn_o => xip_csn_o_int, -- chip-select, low-active
xip_clk_o => xip_clk_o_int, -- serial clock

View file

@ -336,9 +336,6 @@ begin
slink_tx_dat_o => slink_dat, -- TX output data
slink_tx_val_o => slink_val, -- TX valid output
slink_tx_rdy_i => slink_rdy, -- TX ready to send
-- Advanced memory control signals (available if MEM_EXT_EN = true) --
fence_o => open, -- indicates an executed FENCE operation
fencei_o => open, -- indicates an executed FENCEI operation
-- XIP (execute in place via SPI) signals (available if XIP_EN = true) --
xip_csn_o => open, -- chip-select, low-active
xip_clk_o => open, -- serial clock

View file

@ -284,9 +284,6 @@ begin
slink_tx_dat_o => slink_dat, -- TX output data
slink_tx_val_o => slink_val, -- TX valid output
slink_tx_rdy_i => slink_rdy, -- TX ready to send
-- Advanced memory control signals (available if MEM_EXT_EN = true) --
fence_o => open, -- indicates an executed FENCE operation
fencei_o => open, -- indicates an executed FENCEI operation
-- XIP (execute in place via SPI) signals (available if XIP_EN = true) --
xip_csn_o => open, -- chip-select, low-active
xip_clk_o => open, -- serial clock