<<<
:sectnums:
== NEORV32 Processor (SoC)

The NEORV32 Processor provides a RISC-V-based full-scale microcontroller-like SoC platform
build around the <<_neorv32_central_processing_unit_cpu>>.

.The NEORV32 Processor (Block Diagram)
image::neorv32_processor.png[align=center]

**Section Structure**

* <<_processor_top_entity_signals>> and <<_processor_top_entity_generics>>
* <<_processor_clocking>> and <<_processor_reset>>
* <<_processor_interrupts>>
* <<_address_space>> and <<_boot_configuration>>
* <<_processor_internal_modules>>

**Key Features**

* _optional_ SMP <<_dual_core_configuration>>
* _optional_ data and instruction memories (<<_data_memory_dmem,**DMEM**>>/<<_instruction_memory_imem,**IMEM**>>)
* _optional_ caches (<<_instruction_cache_icache,**I-CACHE**>>, <<_data_cache_dcache,**D-CACHE**>>)
* _optional_ serial memory controller <<_serial_memory_controller_smc,**SMC**>> to map external serial (PS)RAM/flash to the processor address space
* _optional_ internal <<_bootloader>> (<<_bootloader_rom_bootrom,**BOOTROM**>>) with UART console & SPI/TWI flash and SD card boot options
* _optional_ RISC-V-compatible core local interruptor (<<_core_local_interruptor_clint,**CLINT**>>)
* _optional_ two independent universal asynchronous receivers and transmitters (<<_primary_universal_asynchronous_receiver_and_transmitter_uart0,**UART0**>>,
<<_secondary_universal_asynchronous_receiver_and_transmitter_uart1,**UART1**>>) with optional hardware flow control (RTS/CTS)
* _optional_ serial peripheral interface host controller (<<_serial_peripheral_interface_controller_spi,**SPI**>>) with 8 dedicated CS lines
* _optional_ 8-bit serial data device interface (<<_serial_data_interface_controller_spi,**SDI**>>)
* _optional_ two-wire serial interface controller (<<_two_wire_serial_interface_controller_twi,**TWI**>>), compatible to the I²C standard
* _optional_ two-wire serial device controller (<<_two_wire_serial_device_controller_twd,**TWD**>>), compatible to the I²C standard
* _optional_ general purpose parallel IO port (<<_general_purpose_input_and_output_port_gpio,**GPIO**>>), 32 inputs (interrupt capable), 32 outputs
* _optional_ 32-bit external bus interface, Wishbone-compatible (<<_processor_external_bus_interface_xbus,**XBUS**>>), AXI4-compatible bridge available
* _optional_ watchdog timer (<<_watchdog_timer_wdt,**WDT**>>)
* _optional_ PWM controller with up to 32 individual channels (<<_pulse_width_modulation_controller_pwm,**PWM**>>)
* _optional_ ring-oscillator-based true random number generator (<<_true_random_number_generator_trng,**TRNG**>>)
* _optional_ NeoPixel(TM)/WS2812-compatible smart LED interface (<<_smart_led_interface_neoled,**NEOLED**>>)
* _optional_ custom functions subsystem for custom co-processor extensions (<<_custom_functions_subsystem_cfs,**CFS**>>)
* _optional_ general purpose 32-bit timer (<<_general_purpose_timer_gptmr,**GPTMR**>>) with up to 16 individual timer slices
* _optional_ 1-wire serial interface controller (<<_one_wire_serial_interface_controller_onewire,**ONEWIRE**>>), compatible to the 1-wire standard
* _optional_ autonomous direct memory access controller (<<_direct_memory_access_controller_dma,**DMA**>>)
* _optional_ stream link interface (<<_stream_link_interface_slink,**SLINK**>>), AXI4-Stream-compatible
* _optional_ on-chip debugger with JTAG TAP (<<_on_chip_debugger_ocd,**OCD**>>), optional authentication and hardware breakpoint
* _optional_ execution trace buffer to debug program flow (<<_execution_trace_buffer_tracer,**TRACER**>>) via branch tracing
* _optional_ RVFI-compatible <<_execution_trace_port>> for advanced debugging, profiling and verification
* _optional_ system configuration information memory to determine hardware configuration via software (<<_system_configuration_information_memory_sysinfo,**SYSINFO**>>)


<<<
// ####################################################################################################################
:sectnums:
=== Processor Top Entity - Generics

This section lists all configuration generics of the NEORV32 processor top entity (`rtl/neorv32_top.vhd`).
These generics allow to configure the system according to your needs. The generics are
used to control implementation of certain CPU extensions and peripheral modules and even allow to
optimize the system for certain design goals like minimal area or maximum performance.

.Default Values
[NOTE]
All configuration generics provide default values in case they are not explicitly assigned during instantiation.
By default, all configuration options are **disabled**.

.Software Discovery of Configuration
[TIP]
Software can determine the actual CPU configuration via the <<_misa>> and <<_mxisah>> CSRs. The SoC/Processor configuration
can be determined via the <<_system_configuration_information_memory_sysinfo, SYSINFO>> memory-mapped registers.

.NEORV32 Processor Generic List; table abbreviations: the generic type "`suv(x:y)`" is an abbreviation for "`std_ulogic_vector(x downto y)`"
[cols="<3,^2,^2,<8"]
[options="header",grid="rows"]
|=======================
| Name | Type | Default | Description
4+^| **General**
| `CLOCK_FREQUENCY`     | natural   | 0             | The clock frequency of the processor's `clk_i` input port in Hertz (Hz). See <<_processor_clocking>>.
| `TRACE_PORT_EN`       | boolean   | false         | Enable external CPU execution <<_execution_trace_port>>.
| `DUAL_CORE_EN`        | boolean   | false         | Enable the SMP <<_dual_core_configuration>>.
4+^| **<<_boot_configuration>>**
| `BOOT_MODE_SELECT`    | natural   | 0             | Boot mode select; see <<_boot_configuration>>.
| `BOOT_ADDR_CUSTOM`    | suv(31:0) | x"00000000"   | Custom CPU boot address (available if `BOOT_MODE_SELECT` = 1).
4+^| **<<_on_chip_debugger_ocd>>**
| `OCD_EN`              | boolean   | false         | Implement the on-chip debugger and the CPU debug mode (<<_sdext_isa_extension>>).
| `OCD_NUM_HW_TRIGGERS` | natural   | 0             | Number of implemented HW triggers (<<_trigger_module>> / <<_sdtrig_isa_extension>>) for hardware break-/watchpoints (0..16).
| `OCD_AUTHENTICATION`  | boolean   | false         | Implement <<_debug_authentication>> module.
| `OCD_JEDEC_ID`        | suv(10:0) | "00000000000" | JEDEC ID: continuation codes plus vendor ID.
4+^| **CPU <<_instruction_sets_and_extensions>>**
| `RISCV_ISA_C`         | boolean   | false         | Enable <<_c_isa_extension>> (compressed instructions).
| `RISCV_ISA_E`         | boolean   | false         | Enable <<_e_isa_extension>> (reduced register file size).
| `RISCV_ISA_M`         | boolean   | false         | Enable <<_m_isa_extension>> (hardware-based integer multiplication and division).
| `RISCV_ISA_U`         | boolean   | false         | Enable <<_u_isa_extension>> (less-privileged user mode).
| `RISCV_ISA_Zaamo`     | boolean   | false         | Enable <<_zaamo_isa_extension>> (atomic read-modify-write operations).
| `RISCV_ISA_Zalrsc`    | boolean   | false         | Enable <<_zalrsc_isa_extension>> (atomic reservation-set operations).
| `RISCV_ISA_Zba`       | boolean   | false         | Enable <<_zba_isa_extension>> (shifted-add bit-manipulation instructions).
| `RISCV_ISA_Zbb`       | boolean   | false         | Enable <<_zbb_isa_extension>> (basic bit-manipulation instructions).
| `RISCV_ISA_Zbc`       | boolean   | false         | Enable <<_zbc_isa_extension>> (carry-less multiplication instructions).
| `RISCV_ISA_Zbkb`      | boolean   | false         | Enable <<_zbkb_isa_extension>> (scalar cryptography bit manipulation instructions).
| `RISCV_ISA_Zbkc`      | boolean   | false         | Enable <<_zbkc_isa_extension>> (scalar cryptography carry-less multiplication instructions).
| `RISCV_ISA_Zbkx`      | boolean   | false         | Enable <<_zbkx_isa_extension>> (scalar cryptography crossbar permutations).
| `RISCV_ISA_Zbs`       | boolean   | false         | Enable <<_zbs_isa_extension>> (single-bit bit-manipulation instructions).
| `RISCV_ISA_Zcb`       | boolean   | false         | Enable <<_zcb_isa_extension>> (additional code size reduction instruction; builds upon `C`).
| `RISCV_ISA_Zcmop`     | boolean   | false         | Enable <<_zcmop_isa_extension>> (compressed may-be-operations; builds upon `C` and `Zimop`).
| `RISCV_ISA_Zfinx`     | boolean   | false         | Enable <<_zfinx_isa_extension>> (single-precision floating-point unit).
| `RISCV_ISA_Zibi`      | boolean   | false         | Enable <<_zibi_isa_extension>> (CPU base counters).
| `RISCV_ISA_Zicntr`    | boolean   | false         | Enable <<_zicntr_isa_extension>> (CPU base counters).
| `RISCV_ISA_Zicond`    | boolean   | false         | Enable <<_zicond_isa_extension>> (integer conditional instructions).
| `RISCV_ISA_Zihpm`     | boolean   | false         | Enable <<_zihpm_isa_extension>> (hardware performance monitors).
| `RISCV_ISA_Zimop`     | boolean   | false         | Enable <<_zimop_isa_extension>> (may-be-operations).
| `RISCV_ISA_Zknd`      | boolean   | false         | Enable <<_zknd_isa_extension>> (scalar cryptography NIST AES decryption instructions).
| `RISCV_ISA_Zkne`      | boolean   | false         | Enable <<_zkne_isa_extension>> (scalar cryptography NIST AES encryption instructions).
| `RISCV_ISA_Zknh`      | boolean   | false         | Enable <<_zknh_isa_extension>> (scalar cryptography NIST hash instructions).
| `RISCV_ISA_Zksed`     | boolean   | false         | Enable <<_zksed_isa_extension>> (scalar cryptography ShangMi block cyphers).
| `RISCV_ISA_Zksh`      | boolean   | false         | Enable <<_zksh_isa_extension>> (scalar cryptography ShangMi hash functions).
| `RISCV_ISA_Zmmul`     | boolean   | false         | Enable <<_zmmul_isa_extension>> (hardware-based integer multiplication).
| `RISCV_ISA_Smcntrpmf` | boolean   | false         | Enable <<_smcntrpmf_isa_extension>> (counter privilege-mode filtering).
| `RISCV_ISA_Xcfu`      | boolean   | false         | Enable NEORV32-specific <<_xcfu_isa_extension>> (custom RISC-V instructions).
4+^| **<<_cpu_tuning_options>>**
| `CPU_CONSTT_BR_EN`    | boolean   | false         | Implement constant-time branches (same execution times for taken and not-taken branches).
| `CPU_FAST_MUL_EN`     | boolean   | false         | Implement fast but large full-parallel multipliers (trying to infer DSP blocks); see section <<_cpu_arithmetic_logic_unit>>.
| `CPU_FAST_MUL_REGS`   | natural   | 1             | Number of register stages for the fast multiplier (1..3; requires `CPU_FAST_MUL_EN`); see section <<_cpu_arithmetic_logic_unit>>.
| `CPU_FAST_SHIFT_EN`   | boolean   | false         | Implement fast but large full-parallel barrel shifters; see section <<_cpu_arithmetic_logic_unit>>.
| `CPU_RF_ARCH_SEL`     | natural   | 0             | CPU register file implementation style select; see section <<_cpu_register_file>>.
4+^| **Physical Memory Protection (<<_smpmp_isa_extension>>)**
| `PMP_NUM_REGIONS`     | natural   | 0             | Number of implemented PMP regions (0..16).
| `PMP_MIN_GRANULARITY` | natural   | 4             | Minimal region granularity in bytes. Has to be a power of two, min 4.
| `PMP_TOR_MODE_EN`     | boolean   | false         | Implement support for top-of-region (TOR) mode.
| `PMP_NAP_MODE_EN`     | boolean   | false         | Implement support for naturally-aligned power-of-two (NAPOT & NA4) modes.
4+^| **Hardware Performance Monitors (<<_zihpm_isa_extension>>)**
| `HPM_NUM_CNTS`        | natural   | 0             | Number of implemented hardware performance monitor counters (0..29).
| `HPM_CNT_WIDTH`       | natural   | 64            | Total LSB-aligned size of each HPM counter. Min 0, max 64.
4+^| **Internal <<_instruction_memory_imem>>**
| `IMEM_EN`             | boolean   | false         | Implement instruction memory.
| `IMEM_BASE`           | suv(31:0) | x"00000000"   | Base address of the instruction memory (has to be naturally-aligned to its size). Handle with care.
| `IMEM_SIZE`           | natural   | 16*1024       | Size in bytes of the instruction memory (use a power of 2).
| `IMEM_OUTREG_EN`      | boolean   | false         | Add IMEM output register stage (improves mapping/timing at the expense of latency).
4+^| **Internal <<_data_memory_dmem>>**
| `DMEM_EN`             | boolean   | false         | Implement data memory.
| `DMEM_BASE`           | suv(31:0) | x"80000000"   | Base address of the data memory (has to be naturally-aligned to its size). Handle with care.
| `DMEM_SIZE`           | natural   | 8*1024        | Size in bytes of the data memory (use a power of 2).
| `DMEM_OUTREG_EN`      | boolean   | false         | Add DMEM output register stage (improves mapping/timing at the expense of latency).
4+^| **CPU Caches (<<_instruction_cache_icache>> & <<_data_cache_dcache>>)**
| `ICACHE_EN`           | boolean   | false         | Implement the instruction cache ("I$").
| `ICACHE_NUM_BLOCKS`   | natural   | 4             | Number of blocks ("lines"). Has to be a power of two.
| `DCACHE_EN`           | boolean   | false         | Implement the data cache ("D$")
| `DCACHE_NUM_BLOCKS`   | natural   | 4             | Number of blocks ("lines"). Has to be a power of two.
| `CACHE_BLOCK_SIZE`    | natural   | 64            | global cache block size (I$ **and** D$) in bytes. Has to be a power of two, min 4.
| `CACHE_BURSTS_EN`     | boolean   | true          | Enable burst transfers for cache updates.
| `CACHE_UC_BASE`       | suv(31:0) | x"F0000000"   | Base address of uncached address space. Has to be 256MB-aligned.
4+^| **<<_serial_memory_controller_smc>> **
| `SMC_EN`              | boolean   | false         | Implement serial memory controller.
| `SMC_BASE`            | suv(31:0) | x"E0000000"   | serial memory base address. Has to be 256MB-aligned.
4+^| **<<_processor_external_bus_interface_xbus>> (Wishbone / AXI4-Compatible Bridging)**
| `XBUS_EN`             | boolean   | false         | Implement the external bus interface.
| `XBUS_TIMEOUT`        | natural   | 2048          | Number of clock cycles after which an unacknowledged external bus access will auto-terminate (0 = disabled).
| `XBUS_REGSTAGE_EN`    | boolean   | false         | Implement XBUS register stages to ease timing closure.
4+^| **<<_general_purpose_input_and_output_port_gpio>>**
| `IO_GPIO_NUM`         | natural   | 0             | Number of GPIO pairs, max 32.
| `IO_GPIO_DIR_EN`      | boolean   | false         | Enable optional GPIO direction control interface (`gpio_dir_o`).
4+^| **<<_core_local_interruptor_clint>>**
| `IO_CLINT_EN`         | boolean   | false         | Implement CLINT.
4+^| **<<_primary_universal_asynchronous_receiver_and_transmitter_uart0>>**
| `IO_UART0_EN`         | boolean   | false         | Implement UART0.
| `IO_UART0_RX_FIFO`    | natural   | 1             | UART0 RX FIFO depth, has to be a power of two, minimum value is 1, max 32768.
| `IO_UART0_TX_FIFO`    | natural   | 1             | UART0 TX FIFO depth, has to be a power of two, minimum value is 1, max 32768.
4+^| **<<_secondary_universal_asynchronous_receiver_and_transmitter_uart1>>**
| `IO_UART1_EN`         | boolean   | false         | Implement UART1.
| `IO_UART1_RX_FIFO`    | natural   | 1             | UART1 RX FIFO depth, has to be a power of two, minimum value is 1, max 32768.
| `IO_UART1_TX_FIFO`    | natural   | 1             | UART1 TX FIFO depth, has to be a power of two, minimum value is 1, max 32768.
4+^| **<<_serial_peripheral_interface_controller_spi>>**
| `IO_SPI_EN`           | boolean   | false         | Implement SPI controller.
| `IO_SPI_FIFO`         | natural   | 1             | Depth of the SPI FIFO. Has to be a power of two, min 1, max 32768.
4+^| **<<_serial_data_interface_controller_sdi>>**
| `IO_SDI_EN`           | boolean   | false         | Implement SDI controller.
| `IO_SDI_FIFO`         | natural   | 1             | Depth of the SDI FIFO. Has to be a power of two, min 1, max 32768.
4+^| **<<_two_wire_serial_interface_controller_twi>>**
| `IO_TWI_EN`           | boolean   | false         | Implement TWI controller.
| `IO_TWI_FIFO`         | natural   | 1             | Depth of the TWI FIFO. Has to be a power of two, min 1, max 32768.
4+^| **<<_two_wire_serial_device_controller_twd>>**
| `IO_TWD_EN`           | boolean   | false         | Implement TWD controller.
| `IO_TWD_RX_FIFO`      | natural   | 1             | Depth of the TWD RX FIFO. Has to be a power of two, min 1, max 32768.
| `IO_TWD_TX_FIFO`      | natural   | 1             | Depth of the TWD TX FIFO. Has to be a power of two, min 1, max 32768.
4+^| **<<_pulse_width_modulation_controller_pwm>>**
| `IO_PWM_NUM`          | natural   | 0             | Number of PWM channels to implement (0..32).
4+^| **<<_watchdog_timer_wdt>>**
| `IO_WDT_EN`           | boolean   | false         | Implement WDT.
4+^| **<<_true_random_number_generator_trng>>**
| `IO_TRNG_EN`          | boolean   | false         | Implement TRNG.
| `IO_TRNG_FIFO`        | natural   | 1             | Depth of the TRNG data FIFO. Has to be a power of two, min 1, max 32768.
| `IO_TRNG_NUM_RO`      | natural   | 3             | Total number of ring-oscillators.
| `IO_TRNG_NUM_INV`     | natural   | 5             | Number of inverters in first ring-oscillator; has to be odd.
| `IO_TRNG_NUM_RBIT`    | natural   | 64            | Number of raw random bits to process for one output byte; has to be power of 2.
4+^| **<<_custom_functions_subsystem_cfs>>**
| `IO_CFS_EN`           | boolean   | false         | Implement CFS.
4+^| **<<_smart_led_interface_neoled>>**
| `IO_NEOLED_EN`        | boolean   | false         | Implement NEOLED controller.
| `IO_NEOLED_TX_FIFO`   | natural   | 1             | TX FIFO depth of the NEOLED controller. Has to be a power of two, min 1, max 32768.
4+^| **<<_general_purpose_timer_gptmr>>**
| `IO_GPTMR_NUM`        | natural   | 0             | Number of individual GPTMR timer slices (0..16).
4+^| **<<_one_wire_serial_interface_controller_onewire>>**
| `IO_ONEWIRE_EN`       | boolean   | false         | Implement 1-wire controller.
| `IO_ONEWIRE_FIFO`     | natural   | 1             | Depth of the 1-Wire FIFO. Has to be a power of two, min 1, max 32768.
4+^| **<<_direct_memory_access_controller_dma>>**
| `IO_DMA_EN`           | boolean   | false         | Implement DMA controller.
| `IO_DMA_DSC_FIFO`     | natural   | 4             | Depth of the DMA transfer descriptor FIFO. Has to be a power of two, min 4, max 512.
4+^| **<<_stream_link_interface_slink>>**
| `IO_SLINK_EN`         | boolean   | false         | Implement stream link interface (AXI4-Stream-Compatible).
| `IO_SLINK_RX_FIFO`    | natural   | 1             | SLINK RX FIFO depth, has to be a power of two, minimum value is 1, max 32768.
| `IO_SLINK_TX_FIFO`    | natural   | 1             | SLINK TX FIFO depth, has to be a power of two, minimum value is 1, max 32768.
4+^| ** <<_execution_trace_buffer_tracer>>**
| `IO_TRACER_EN`        | boolean   | false         | Implement the trace buffer.
| `IO_TRACER_BUFFER`    | natural   | 1             | Depth of the trace buffer. Has to be a power of two, min 1, max 32768.
| `IO_TRACER_SIMLOG_EN` | boolean   | false         | Write full trace log to file (simulation-only).
|=======================


<<<
// ####################################################################################################################
:sectnums:
=== Processor Top Entity - Signals

The following table shows the interface signals of the processor top entity (`rtl/core/neorv32_top.vhd`).
All signals are of type `std_ulogic` or `std_ulogic_vector`, respectively. Custom interface type are used only
for the <<_execution_trace_port>> (`trace_*`).

.Default Values of Inputs
[NOTE]
All input signals - except for clock and reset - provide default values in case they are not explicitly assigned
during instantiation. The weak driver strengths of VHDL (`'L'` and `'H'`) are used to model a pull-down or pull-up
resistor for these unconnected inputs. After synthesis, these will result in `0` or `1`, respectively.

.Variable-Sized Ports
[NOTE]
Some peripherals allow to configure the number of channels to-be-implemented by a generic (for example the number
of PWM channels). The according input/output signals have a fixed sized regardless of the actually configured
amount of channels. If less than the maximum number of channels is configured, only the LSB-aligned channels are used:
in case of an _input port_ the remaining bits/channels are left unconnected; in case of an _output port_ the remaining
bits/channels are hardwired to zero.

.Tri-State Interfaces
[NOTE]
Some interfaces (like the TWI, the TWD and the 1-Wire bus) require explicit tri-state drivers in the final top module.

.Input/Output Registers
[NOTE]
By default all output signals are driven by register and all input signals are synchronized into the processor's
clock domain also using registers. However, for ASIC implementations it is recommended to add another register state
to all inputs and output so the synthesis tool can insert an explicit IO (boundary) scan chain.

.NEORV32 Processor Signal List
[cols="<3,^2,^2,^2,<8"]
[options="header",grid="rows"]
|=======================
| Name | Width | Direction | Default | Description
5+^| **Global Control (<<_processor_clocking>> and <<_processor_reset>>)**
| `clk_i`          |  1 |  in | none  | global clock line, all registers triggering on rising edge
| `rstn_i`         |  1 |  in | none  | global reset, asynchronous, **low-active**
| `rstn_ocd_o`     |  1 | out |   -   | <<_on_chip_debugger_ocd>> reset output, synchronous, **low-active**
| `rstn_wdt_o`     |  1 | out |   -   | <<_watchdog_timer_wdt>> reset output, synchronous, **low-active**
5+^| **<<_execution_trace_port>>**
| `trace_cpu0_o`   |  * | out |   -   | CPU core 0 trace port (type `trace_port_t`).
| `trace_cpu1_o`   |  * | out |   -   | CPU core 1 trace port (type `trace_port_t`).
5+^| **JTAG Access Port for <<_on_chip_debugger_ocd>>**
| `jtag_tck_i`     |  1 |  in | `'L'` | serial clock
| `jtag_tdi_i`     |  1 |  in | `'L'` | serial data input
| `jtag_tdo_o`     |  1 | out |   -   | serial data output
| `jtag_tms_i`     |  1 |  in | `'L'` | mode select
5+^| **<<_serial_memory_controller_smc>>**
| `smc_ioen_o`     |  1 | out |   -   | SMC pin enable, can be used for IO multiplexing
| `smc_sck_o`      |  1 | out |   -   | serial clock
| `smc_csn_o`      |  2 | out |   -   | bank/chip select, low-active
| `smc_sdo_o`      |  1 | out |   -   | serial data output
| `smc_sdi_i`      |  1 |  in | `'L'` | serial data input
5+^| **<<_processor_external_bus_interface_xbus>>**
| `xbus_adr_o`     | 32 | out |   -   | destination address
| `xbus_dat_o`     | 32 | out |   -   | read data
| `xbus_cti_o`     |  3 | out |   -   | cycle type
| `xbus_tag_o`     |  3 | out |   -   | access tag
| `xbus_we_o`      |  1 | out |   -   | write enable ('0' = read transfer)
| `xbus_sel_o`     |  4 | out |   -   | byte enable
| `xbus_stb_o`     |  1 | out |   -   | strobe
| `xbus_cyc_o`     |  1 | out |   -   | valid cycle
| `xbus_dat_i`     | 32 |  in | `'L'` | write data
| `xbus_ack_i`     |  1 |  in | `'L'` | transfer acknowledge
| `xbus_err_i`     |  1 |  in | `'L'` | transfer error
5+^| **<<_stream_link_interface_slink>>**
| `slink_rx_dat_i` | 32 |  in | `'L'` | RX data
| `slink_rx_src_i` |  4 |  in | `'L'` | RX source routing information
| `slink_rx_val_i` |  1 |  in | `'L'` | RX data valid
| `slink_rx_lst_i` |  1 |  in | `'L'` | RX last element of stream
| `slink_rx_rdy_o` |  1 | out |   -   | RX ready to receive
| `slink_tx_dat_o` | 32 | out |   -   | TX data
| `slink_tx_dst_o` |  4 | out |   -   | TX destination routing information
| `slink_tx_val_o` |  1 | out |   -   | TX data valid
| `slink_tx_lst_o` |  1 | out |   -   | TX last element of stream
| `slink_tx_rdy_i` |  1 |  in | `'L'` | TX allowed to send
5+^| **<<_general_purpose_input_and_output_port_gpio>>**
| `gpio_dir_o`     | 32 | out |   -   | general purpose port direction control (`0` = input, `1` = output)
| `gpio_o`         | 32 | out |   -   | general purpose parallel output port
| `gpio_i`         | 32 |  in | `'L'` | general purpose parallel input port (interrupt-capable)
5+^| **<<_primary_universal_asynchronous_receiver_and_transmitter_uart0>>**
| `uart0_txd_o`    |  1 | out |   -   | serial transmitter
| `uart0_rxd_i`    |  1 |  in | `'L'` | serial receiver
| `uart0_rtsn_o`   |  1 | out |   -   | RX ready to receive new char
| `uart0_ctsn_i`   |  1 |  in | `'L'` | TX allowed to start sending, low-active
5+^| **<<_secondary_universal_asynchronous_receiver_and_transmitter_uart1>>**
| `uart1_txd_o`    |  1 | out |   -   | serial transmitter
| `uart1_rxd_i`    |  1 |  in | `'L'` | serial receiver
| `uart1_rtsn_o`   |  1 | out |   -   | RX ready to receive new char
| `uart1_ctsn_i`   |  1 |  in | `'L'` | TX allowed to start sending, low-active
5+^| **<<_serial_peripheral_interface_controller_spi>>**
| `spi_clk_o`      |  1 | out |   -   | controller clock line
| `spi_dat_o`      |  1 | out |   -   | serial data output
| `spi_dat_i`      |  1 |  in | `'L'` | serial data input
| `spi_csn_o`      |  8 | out |   -   | chip select, low-active
5+^| **<<_serial_data_interface_controller_sdi>>**
| `sdi_clk_i`      |  1 |  in | `'L'` | controller clock line
| `sdi_dat_o`      |  1 | out |   -   | serial data output
| `sdi_dat_i`      |  1 |  in | `'L'` | serial data input
| `sdi_csn_i`      |  1 |  in | `'H'` | chip select, low-active
5+^| **<<_two_wire_serial_interface_controller_twi>>**
| `twi_sda_i`      |  1 |  in | `'H'` | serial data line sense input
| `twi_sda_o`      |  1 | out |   -   | serial data line output (pull low only)
| `twi_scl_i`      |  1 |  in | `'H'` | serial clock line sense input
| `twi_scl_o`      |  1 | out |   -   | serial clock line output (pull low only)
5+^| **<<_two_wire_serial_device_controller_twd>>**
| `twd_sda_i`      |  1 |  in | `'H'` | serial data line sense input
| `twd_sda_o`      |  1 | out |   -   | serial data line output (pull low only)
| `twd_scl_i`      |  1 |  in | `'H'` | serial clock line sense input
5+^| **<<_one_wire_serial_interface_controller_onewire>>**
| `onewire_i`      |  1 |  in | `'H'` | 1-wire bus sense input
| `onewire_o`      |  1 | out |   -   | 1-wire bus output (pull low only)
5+^| **<<_pulse_width_modulation_controller_pwm>>**
| `pwm_o`          | 16 | out |   -   | pulse-width modulated channels
5+^| **<<_custom_functions_subsystem_cfs>>**
| `cfs_in_i`       | 256 |  in | `'L'` | custom CFS input signal conduit
| `cfs_out_o`      | 256 | out |   -   | custom CFS output signal conduit
5+^| **<<_smart_led_interface_neoled>>**
| `neoled_o`       |  1 | out |   -   | asynchronous serial data output
5+^| **<<_core_local_interruptor_clint>>**
| `mtime_time_o`   | 64 | out |   -   | CLINT.MTIMER system time output
5+^| **RISC-V Machine-Mode <<_processor_interrupts>>**
| `irq_msi_i`      |  1 |  in | `'L'` | machine software interrupt (RISC-V), high-level-active; available only if CLINT is not enabled
| `irq_mti_i`      |  1 |  in | `'L'` | machine timer interrupt (RISC-V), high-level-active; available only if CLINT is not enabled
| `irq_mei_i`      |  1 |  in | `'L'` | machine external interrupt (RISC-V), high-level-active
|=======================


<<<
// ####################################################################################################################
:sectnums:
=== Replaceable Modules

Certain NEORV32 SoC modules are designed so that they can be substituted with a custom, external (Verilog) module.
This makes it possible to integrate platform-specific IP, such as technology-specific memory, instead of using the
default/generic RTL implementation. To enable this kind of replacement, the corresponding processor modules follow
a few specific design conventions:

[start=1]
. **Component instantiation**: These modules are instantiated using VHDL's component instantiation syntax rather
than direct entity instantiation. This allows black-box instantiation and late-binding, which is required by the
GHDL-based <<_convert_to_verilog>> flow used by NEORV32.
. **Simple interfaces**: All ports use only the basic `std_ulogic` / `std_ulogic_vector` types.
Custom or composite VHDL types (such as records) are intentionally avoided.
. **Static port widths**: Port widths are fixed and defined at elaboration time;
no generic-dependent or dynamically computed port widths are used.

These properties ensure that the affected modules can be cleanly swapped out for external, technology-specific
implementations without breaking the overall top-level structure or the automated <<_convert_to_verilog>> process.

At this time, the following modules are being considered for possible replacement:

.Modules that can be replaced directly by external (Verilog) IP
[cols="<5,<5,<6"]
[options="header",grid="all"]
|=======================
| Module | File name | Exemplary Verilog substitution module
| Bootloader ROM (<<_bootloader_rom_bootrom,BOOTROM>>)   | `rtl/core/neorv32_bootrom.vhd` | `rtl/verilog/neorv32_bootrom.v`
| Data memory (<<_data_memory_dmem,DMEM>>)               | `rtl/core/neorv32_dmem.vhd`    | `rtl/verilog/neorv32_dmem.v`   
| Instruction memory (<<_instruction_memory_imem,IMEM>>) | `rtl/core/neorv32_imem.vhd`    | `rtl/verilog/neorv32_imem.v`   
|=======================

.Replacing additional modules
[NOTES]
Others modules like peripheral/IO modules (such as the UART) should not be replaced directly. Instead,
the default module should be disabled using the appropriate top generic. Custom modules can be connected,
for example, via the <<_processor_external_bus_interface_xbus>>.


<<<
// ####################################################################################################################
:sectnums:
=== Processor Clocking

The entire system is implemented as fully-synchronous logic design using a single clock domain that is driven
by the top's `clk_i` signal. This clock signal is used by all internal registers and memories. All of them trigger
on the **rising edge** of this clock signal. External "clocks" like the OCD's JTAG clock or the SDI's serial clock
are synchronized into the processor's clock domain before being used as "general logic signal" (and not as a dedicated clock).


==== Peripheral Clocks

Many processor modules like the UARTs or the timers provide a programmable time base for operations. In order to simplify
the hardware, the processor implements a global "clock generator" (`neorv32_sys.vhd`) that provides single-cycle _clock enables_
for certain frequencies which are derived from the main clock. These clock enable signals are synchronous to the system's
main clock. The processor modules can use these enables for sub-main-clock operations while still providing a single
clock domain only.

In total, 8 sub-main-clock signals are available. All processor modules, which feature a time-based configuration, provide a
programmable three-bit prescaler select in their control register to select one of the 8 available clocks. The
mapping of the prescaler select bits to the according clock source is shown in the table below. Here, _f_ represents the
processor main clock from the top entity's `clk_i` signal.

[cols="<3,^1,^1,^1,^1,^1,^1,^1,^1"]
[grid="rows"]
|=======================
| Prescaler bits:  | `0b000` | `0b001` | `0b010` | `0b011` | `0b100` | `0b101` | `0b110` | `0b111`
| Resulting clock: | _f/2_   | _f/4_   | _f/8_   | _f/64_  | _f/128_ | _f/1024_| _f/2048_| _f/4096_
|=======================


<<<
// ####################################################################################################################
:sectnums:
=== Processor Reset

The NEORV32 processor includes a central reset sequencer (`neorv32_sys.vhd`) that handles all reset requests
and controls the internal reset nets. The processor-wide reset ("system reset") can be triggered by any
of the following sources:

* the asynchronous low-active `rstn_i` top entity input signal (external source)
* the <<_on_chip_debugger_ocd>> (internal source)
* the <<_watchdog_timer_wdt>> (internal source)

.Reset Cause
[TIP]
The actual reset cause can be determined via the <<_watchdog_timer_wdt>>.

If any of these sources triggers a reset, the internal system-wide reset will be active for at least 4 clock cycles
ensuring a valid reset of the entire processor (reset sequencer VHDL module: `neorv32_sys_reset`). This system reset is
asserted _asynchronoulsy_ if triggered by the external `rstn_i` signal and is asserted _synchronously_ if triggered by
an internal reset source. However, the system reset is always de-asserted _synchronously_ at the next rising clock edge.

==== Reset Implementation

Internally, only registers that require a defined and controlled processor startup are equipped with a dedicated,
**low-active asynchronous** hardware reset. These include, in particular, state registers of FSMs, control and configuration
registers, and registers of the control logic. The asynchronous reset sets these components to a defined initial state even
when the main clock is not yet available.

In contrast, registers whose contents are not relevant during or immediately after the reset do not have an explicit hardware
reset. This applies, among other things, to memory structures, pipeline registers, data buffers, and synchronizers. The values
contained therein may initially be undefined after the reset. However, reset control, status, and validity signals ensure that
such values are not used before they have been replaced by valid data.

The deliberate omission of reset logic reduces resource requirements and reset fan-out, improves timing characteristics, and
facilitates the mapping of suitable memory structures to FPGA block RAM. As a result, the processor startup remains fully
controlled without creating unnecessary reset structures in components that are purely for data storage.


<<<
// ####################################################################################################################
:sectnums:
=== Processor Interrupts

The system offers several interrupts (IRQs). Some can be used freely, others are reserved for specific tasks.

.Trigger Type
[IMPORTANT]
All interrupt request lines are **level-triggered and high-active**. Once set, the signal should remain high until
the interrupt request is explicitly acknowledged (e.g. by writing to a memory-mapped register).


:sectnums:
==== RISC-V Standard Interrupts

The processor supports the standard RISC-V machine-level interrupts for "machine timer interrupt (MTI)", "machine
software interrupt (MSI)" and "machine external interrupt (MEI)". Their usage is defined by the RISC-V privileged
architecture specification. See CPU section <<_traps_exceptions_and_interrupts>> for more information.

.Processor Top RISC-V Machine-Level Interrupts
[cols="<4,<10"]
[options="header",grid="rows"]
|=======================
| Top signal  | Description
| `irq_msi_i` | Machine software interrupt (`MSI`). This IRQ is only available if the processor-internal <<_core_local_interruptor_clint>> is not implemented.
| `irq_mti_i` | Machine timer interrupt (`MTI`). This IRQ is only available if the processor-internal <<_core_local_interruptor_clint>> is not implemented.
| `irq_mei_i` | Machine external interrupt (`MEI`). This interrupt is always available for custom use.
|=======================


:sectnums:
==== NEORV32-Specific Fast Interrupt Requests

As part of the NEORV32-specific CPU extensions, the processor core features 16 fast interrupt request signals
(`FIRQ0` to `FIRQ15`) with dedicated bits in <<_mip>> and <<_mie>> CSRs and custom <<_mcause>> trap codes.
The FIRQ signals are reserved for _processor-internal_ modules only (for example for the communication
interfaces to signal "available incoming data" or "ready to send new data").

The mapping of the 16 FIRQ channels to the according processor-internal modules is shown in the following
table. The channel number also corresponds to the according FIRQ priority (0 = highest, 15 = lowest):

.NEORV32 Fast Interrupt Request (FIRQ) Mapping
[cols="^3,<7"]
[options="header",grid="rows"]
|=======================
| Channel (priority) | Source
| 0  | _reserved_
| 1  | <<_custom_functions_subsystem_cfs>>
| 2  | <<_primary_universal_asynchronous_receiver_and_transmitter_uart0>>
| 3  | <<_secondary_universal_asynchronous_receiver_and_transmitter_uart1>>
| 4  | <<_two_wire_serial_device_controller_twd>>
| 5  | <<_execution_trace_buffer_tracer>>
| 6  | <<_serial_peripheral_interface_controller_spi>>
| 7  | <<_two_wire_serial_interface_controller_twi>>
| 8  | <<_general_purpose_input_and_output_port_gpio>>
| 9  | <<_smart_led_interface_neoled>>
| 10 | <<_direct_memory_access_controller_dma>>
| 11 | <<_serial_data_interface_controller_sdi>>
| 12 | <<_general_purpose_timer_gptmr>>
| 13 | <<_one_wire_serial_interface_controller_onewire>>
| 14 | <<_stream_link_interface_slink>>
| 15 | <<_true_random_number_generator_trng>>
|=======================


<<<
// ####################################################################################################################
:sectnums:
=== Address Space

As a 32-bit architecture, NEORV32 can access up to 4GB of physical address space. The following figure shows
the **default** address space layout with the according memory capabilities (_physical memory attributes_ "PMAs"):

.NEORV32 Processor Address Space (Default Configuration)
image::address_space.png[900]

The address space layout is highly configurable. Only the very last 2 MB (`0xFFE00000 .. 0xFFFFFFFF`) are exclusively reserved
for the NEORV32's internal memory-mapped peripherals and I/O modules and cannot be repurposed.
The processor-internal <<_instruction_memory_imem>> and <<_data_memory_dmem>> (if enabled), on the other hand,
can be mapped to any address via the configuration generics. The same applies to off-chip serial memory, which can be
mapped via the <<_serial_memory_controller_smc>> to any (256MB-aligned) address.

Accesses to "unmapped" addresses (a.k.a. **the void**) are redirected to the <<_processor_external_bus_interface_xbus>>.
For example, if the processor-internal IMEM is disabled or re-mapped, accesses to the addresses starting at `0x00000000`
are also redirected to the external bus interface. If the external bus interface is not enabled any access to
the void will raise a bus error exception.

By default, all addresses starting at `0xF0000000` are not cached by the CPU caches to provide direct access to memory-mapped
peripherals. However, this address boundary can be lowered by the according configuration generic (`CACHE_UC_BASE`) to
increase the size of the uncached address space.

.Uncached Address Space
[NOTE]
Please note that the uncached address space can only be altered in 256 MB increments. The uncached address space
starts at the configured 256 MB page and always extends to the end of the address space (`0xFFFFFFFF`).


:sectnums:
==== Bus System

The CPU core provides individual interfaces for instruction fetch and data access. Both interface access the same
address space making the core a von-Neumann architecture. Optionally, the two interface can be equipped with data
and/or instruction caches (<<_data_cache_dcache,i-cache>> & <<_instruction_cache_icache,d-cache>>).

The two CPU interfaces are multiplexed by a simple bus switch into a single processor-internal bus. Optionally,
this bus is further multiplexed by another instance of the bus switch so the <<_direct_memory_access_controller_dma>>
can also access the entire address space.

Accesses via the resulting SoC bus are routed by the <<_bus_gateway>> that is used to redirect the access to the
processor-internal <<_instruction_memory_imem>> (if implemented), the processor-internal <<_data_memory_dmem>>
(if implemented), the processor-internal peripheral devices or - if the access does not target any of these - the
<<_processor_external_bus_interface_xbus>>. Accesses to the processor-internal IO/peripheral devices are further
redirected via a dedicated <<_io_switch>>.

.Processor-Internal Bus Architecture
image::neorv32_bus.png[1300]

.Bus System Infrastructure IP
[NOTE]
The individual components of the processor's bus system infrastructure are defined in `rtl/core/neorv32_bus.vhd`.

.Bus Interface
[TIP]
See sections CPU <<_architecture>> and <<_bus_interface>> for more information regarding the CPU bus accesses
and the according protocol.

.SMP Dual-Core Configuration
[TIP]
The dual-core configuration adds a second CPU core complex in parallel to the first one.
See section <<_dual_core_configuration>> for more information.


:sectnums:
==== Bus Gateway

The central bus gateway (VHDL component `neorv32_bus_gateway`) distributes CPU accesses to the two main memory
regions. Depending on the configuration, it routes accesses to:

[start=1]
. <<_instruction_memory_imem>> (if implemented)
. <<_data_memory_dmem>> (if implemented)
. processor-internal IO/peripherals
. <<_processor_external_bus_interface_xbus>> (if implemented)

Additionally, the gateway also provides a <<_bus_monitor_and_timeout, bus monitor>> (aka "the bus keeper") that
_tracks_ all bus transactions to ensure safe and deterministic operations.

:sectnums:
===== Bus Monitor and Timeout

For each single access the bus monitor starts an internal countdown.
The accessed module has to respond to the bus request within a bound time window. For **processor-internal** accesses
this time windows is defined by a constant in the main NEORV32 package file. For **processor-external accesses**
(via the external bus interface) this timeout is defined by the `XBUS_TIMEOUT` top configuration generic.

.Internal Bus Timeout Configuration (package constant in `neorv32_package.vhd`)
[source,vhdl]
----
constant int_bus_tmo_c : natural := 16; -- internal bus timeout window; has to be a power of two
----

.External Bus Timeout Configuration (top generic of `neorv32_top.vhd`)
[source,vhdl]
----
XBUS_TIMEOUT : natural := 2048; -- cycles after a pending bus access auto-terminates (0 = disabled)
----

The according time window defines the maximum number of cycles after which a _non-responding_ bus request will time out
raising a bus access fault exception. For example this can happen when accessing "address space holes" - addresses that
are not mapped to any physical module at all. The specific bus access exception type corresponds to the according access
type (i.e. instruction fetch bus access fault, load bus access fault or store bus access fault).

.Serial Memory Controller Bus Timeout
[NOTE]
The <<_serial_memory_controller_smc>> uses a hard-coded timeout value of 2048 cycles
so that it can complete serial accesses even at the lowest SPI clock speed.


:sectnums:
==== IO Switch

The IO switch (VHDL component `neorv32_bus_io_switch`) decodes accesses to the _procesor-internal IO/peripheral_
address space. This 2MB address space is used to map all NEORV32 peripherals (like UART, SPI, timers, etc.),
the bootloader ROM and the on-chip debugger. Each device occupies an address range of 64kB; so up to 32 individual
devices can be mapped. The according address map is defined in the main VHDL package file (`rtl/core/neorv32_package.vhd`).


:sectnums:
==== Atomic Memory Operations Controller

The CPU's <<_a_isa_extension>> adds support for atomic memory accesses. These atomic memory accesses are handles by
dedicated modules of the processor bus system. The SoC bus that is driven by the CPU core(s) is fed through two
atomic memory controller modules that handle read-modify-write operations as well as reservation-set operation:

[cols="<3,<3,<4"]
[options="header",grid="rows"]
|=======================
| Hardware Module | CPU ISA Extensions | Description
| `neorv32_bus_amo_rmw` | <<_zaamo_isa_extension>>  | <<_atomic_read_modify_write_controller>>
| `neorv32_bus_amo_rvs` | <<_zalrsc_isa_extension>> | <<_atomic_reservation_set_controller>>
|=======================

.Direct/Non-Caches Atomic Accesses
[IMPORTANT]
Atomic operations **always bypass** the CPU's <<_data_cache_dcache, data cache>>
using direct/uncached accesses. Care must be taken to maintain data <<_memory_coherence>>.

.Physical Memory Attributes
[NOTE]
Atomic memory operations can be executed targeting _any_ address. This also includes
cached memory, memory-mapped IO devices and processor-external address spaces.

===== Atomic Read-Modify-Write Controller

This modules converts a single read-modify-write (RMW) memory operations request into two consecutive and
atomic bus transactions. For each request, the controller executes an atomic set of three operations:

.Simplified AMO Controller Operation
[cols="^1,<3,<6"]
[options="header",grid="rows"]
|=======================
| Step | Pseudo Code | Description
| 1    | `tmp1 <= MEM[address];` | Perform a read operation from the targeted memory
address and temporarily store the loaded data into an internal buffer (`tmp1`).
| 2    | `tmp2 <= tmp1 OP cpu_wdata;` | The buffered data from the first step is processed
using the write data provided by the CPU. The result is stored to another temporary internal buffer (`tmp2`).
| 3    | `MEM[address] <= tmp2;` `cpu_rdata <= tmp1;` | The data from the second buffer (`tmp2`) is
written to the addressed memory location. In parallel, the data from the first buffer (`tmp1` = original
content of the accessed address) is sent back to the requesting CPU.
|=======================

===== Atomic Reservation-Set Controller

In NEORV32 a reservation is defined by a 64-byte address granule that provides a guarding mechanism to support
atomic accesses (as specified by the RISC-V <<_zalrsc_isa_extension>>). A new reservation is registered by the
`LR` instruction. The address provided by this instruction defines the 64-byte-aligned memory region that is
monitored for exclusive accesses. The according `SC` instruction evaluates the state of this reservation. If the
reservation is still valid (same owner core / issueing core and same address granule) the write access performed by
the `SC` instruction is finally executed and the instruction returns a _success_ state (i.e. `rd = 0`). If the
reservation has been invalidated or does not match, the `SC` instruction will not update main memory and will return
a _failed_ state (i.e. `rd = 1`).

[IMPORTANT]
In either case, the `SC` instruction issues a downstream bus access to main memory (converted to a READ in case
of failure) to allow the detection of access faults for the target address also for failed `SC` instructions
which is required by the RISC-V specs.

The reservation-set controller implements a single reservation set per instance with a fixed granularity of 64 bytes.
Each reservation tracks the owning core's ID and the aligned base address. A reservation is invalidated only when a
write access targets the same 64-byte address granule - read accesses, instruction fetches, and `fence[.i]` instructions
do not affect the reservation state.

The reservation-set controller is shared by both cores in the SMP <<_dual_core_configuration>>.
To ensure forward progress during concurrent atomic sequences, a turn-based arbitration mechanism is implemented:

[start=1]
. An `LR` instruction can create (or update) a reservation if no reservation is active, if the requesting core already
owns the current reservation, or if it is the requesting core's "turn" (priority).
. A successful `SC` flips the turn, ensuring that the other core receives priority for its next `LR` attempt.
. A failed `SC` from the owning core also clears the reservation, preventing stale reservations from blocking progress.

This guarantees atomic accesses and mutually exclusive access without starvation.

.External Reservations
[WARNING]
Note that the reservation-set controller cannot track memory accesses outside of the NEORV32 processor
(i.e. atomic accesses via the external bus interface) that are executed by processor-external agents.


:sectnums:
==== Memory Coherence

Depending on the configuration, the NEORV32 memory hierarchy provides several levels/layers of memory.

[start=1]
. The CPU execution pipeline and its _instruction prefetch buffer_ (<<_cpu_front_end>>)
. The optional <<_data_cache_dcache>> and <<_instruction_cache_icache>>
. Processor-internal and processor-external memories (depending on setup configuration)

NEORV32 features up to three bus hosts: up to two CPU cores and the <<_direct_memory_access_controller_dma>>.
Since the levels of the memory hierarchy are transparent to the software, special care must be taken
to ensure memory coherence is maintained throughout the entire system/application. Note that coherence
and especially cache synchronization is **not** performed automatically by the hardware itself as there
is no snooping implemented. NEORV32 supports two RISC-V memory ordering instructions that are used for
manual memory synchronization:

* `fence`: Flush the CPU's data cache: modified ("dirty")
blocks are copied back to main memory; all clean blocks are invalidated so that the next CPU access to
any block results in a cache miss that reloads the cache with up-to-date data from main memory.
* `fence.i`: Perform the same operations as `fence` (i.e. flushing the data
cache), but also clear the CPU's instruction prefetch buffer and instruction cache. The next instruction
cache access therefore results in a miss that fetches up-to-date data from main memory.

.Weak Coherence Model
[IMPORTANT]
The NEORV32-specific implementation of the `fence[.i]` ordering instructions only provides a rather **weak**
coherence model. A core's `fence` just orders all memory accesses towards main memory. Hence, they _can_ become
visible by other agents (the secondary CPU core, the DMA, processor-external modules) if these agents also
synchronize (e.g. reload) their cache(s).

Atomic memory accesses also require special attention. All atomic memory accesses bypass the CPU caches.
However, in this case, the caches explicitly ensure memory coherence. If the address of an atomic memory
access is cached, the corresponding line is first written back to main memory if it has been modified.
Afterward, the corresponding line is invalidated, and the atomic access is executed as a cache bypass.
The next access to the atomic address bypasses the cache if it is again an atomic memory operation.
Normal memory accesses result in a cache miss (since the corresponding line was automatically invalidated
previously), so that the cache is reloaded with current data from main memory.

.C-Language `_Atomic` Variables
[NOTE]
Using plain `_Atomic` access (e.g., `_Atomic int counter = 0;`) defaults to GCC's `memory_order_seq_cst`
builtin, which inserts fence instructions _before_ and _after_ the access. This is the safest but slowest option.

<<<
// ####################################################################################################################
:sectnums:
=== Boot Configuration

The NEORV32 processor provides pre-defined boot configurations to adjust system start-up to
the requirements of the application. The actual boot configuration is defined by the `BOOT_MODE_SELECT`
generic (see <<_processor_top_entity_generics>>).
For the SMP dual-core CPU configuration boot procedure see section <<_dual_core_boot>>.

.NEORV32 Boot Configurations
[cols="^2,^2,^2,<6"]
[options="header",grid="rows"]
|=======================
| `BOOT_MODE_SELECT` | Name           | Boot address               | Description
| 0 (default)        | Bootloader     | Base of internal BOOTROM   | Implement the processor-internal <<_bootloader_rom_bootrom>> as pre-initialized ROM and boot from there.
| 1                  | Custom Address | `BOOT_ADDR_CUSTOM` generic | Start booting at user-defined address (`BOOT_ADDR_CUSTOM` top generic).
| 2                  | IMEM Image     | Base of internal IMEM      | Implement the processor-internal <<_instruction_memory_imem>> as pre-initialized ROM and boot from there.
|=======================


:sectnums:
==== Booting via Bootloader

This is the default configuration. When selected, the processor-internal <<_bootloader_rom_bootrom>> is enabled.
This ROM contains the executable image (`rtl/core/neorv32_bootrom_image.vhd`) of the default NEORV32 <<_bootloader>>
that will be executed right after reset. The bootloader provides an interactive user console for executable upload as
well as an automatic mode to boot from external (SPI) flash memory.

If the processor-internal <<_instruction_memory_imem>> is enabled it will be implemented as _blank_ RAM.


:sectnums:
==== Boot from Custom Address

This is the most flexible boot configuration as it allows the user to specify a custom boot address via the
`BOOT_ADDR_CUSTOM` generic. Note that this address has to be aligned to 4-byte boundary. The processor will
start executing from the defined address right after reset. For example, this boot configuration ca be used to
execute a _custom bootloader_ from a memory that is attached via the <<_processor_external_bus_interface_xbus>>.

For this configuration the processor-internal <<_bootloader_rom_bootrom>> is not enabled / implement at all.
If the processor-internal <<_instruction_memory_imem>> is enabled it will be implemented as _blank_ RAM.


:sectnums:
==== Boot IMEM Image

This configuration will implement the <<_instruction_memory_imem>> as _pre-initialized ROM_. The ROM is
initialized during synthesis with the according application image file (`rtl/core/neorv32_imem_image.vhd`).
After reset, the CPU will directly start executing this image. Since the IMEM is implemented as ROM, the
executable cannot be altered at runtime at all.

For this configuration the <<_bootloader_rom_bootrom>> is not enabled / implement at all.
Note that this boot configuration requires the IMEM to be enabled (`IMEM_EN` = true).

.Simulation Setup
[TIP]
This boot configuration is handy for simulations as the application software is executed right away without the
need for an explicit initialization / executable upload.


<<<
// ####################################################################################################################
:sectnums:
=== Processor-Internal Modules

.Full-Word Write Accesses Only
[NOTE]
Unless otherwise specified, all peripheral/IO devices should only be accessed using full-word accesses (i.e. 32-bit).

.IO Module Address Space
[NOTE]
Each peripheral/IO module occupies an address space of 64kB bytes. Most devices do not fully utilize this
address space and will mirror the available memory-mapped registers across the device's address space.
However, only the specified memory-mapped registers addresses should be used.

.Unimplemented Modules / Address Holes
[NOTE]
When accessing an IO device that has not been implemented (disabled via the according generic)
or when accessing an address that is actually unused, a load/store access fault exception is raised.

.Writing to Read-Only Registers
[NOTE]
Unless otherwise specified, writing to registers that are listed as read-only does not trigger an exception
as the write access is just ignored by the corresponding hardware module.

.Module Interrupts
[NOTE]
Several peripheral/IO devices provide some kind of interrupt. These interrupts are mapped to the CPU's
<<_custom_fast_interrupt_request_lines>>. See section <<_processor_interrupts>> for more information.

.CMSIS System Description View (SVD)
[TIP]
A CMSIS-compatible **System View Description (SVD)** file including all peripherals is available in `sw/svd`.

include::soc_imem.adoc[]

include::soc_dmem.adoc[]

include::soc_bootrom.adoc[]

include::soc_icache.adoc[]

include::soc_dcache.adoc[]

include::soc_smc.adoc[]

include::soc_dma.adoc[]

include::soc_xbus.adoc[]

include::soc_slink.adoc[]

include::soc_gpio.adoc[]

include::soc_wdt.adoc[]

include::soc_clint.adoc[]

include::soc_uart.adoc[]

include::soc_spi.adoc[]

include::soc_sdi.adoc[]

include::soc_twi.adoc[]

include::soc_twd.adoc[]

include::soc_onewire.adoc[]

include::soc_pwm.adoc[]

include::soc_trng.adoc[]

include::soc_cfs.adoc[]

include::soc_neoled.adoc[]

include::soc_gptmr.adoc[]

include::soc_tracer.adoc[]

include::soc_sysinfo.adoc[]
