OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [docs/] [datasheet/] [soc.adoc] - Rev 60

Go to most recent revision | Compare with Previous | Blame | View Log


// ####################################################################################################################
:sectnums:
== NEORV32 Processor (SoC)

The NEORV32 Processor is based on the NEORV32 CPU. Together with common peripheral
interfaces and embedded memories it provides a RISC-V-based full-scale microcontroller-like SoC platform.

image::neorv32_processor.png[align=center]

**Key Features**

* _optional_ processor-internal data and instruction memories (<<_data_memory_dmem,**DMEM**>>/<<_instruction_memory_imem,**IMEM**>>) + cache (<<_processor_internal_instruction_cache_icache,**iCACHE**>>)
* _optional_ internal bootloader (<<_bootloader_rom_bootrom,**BOOTROM**>>) with UART console & SPI flash boot option
* _optional_ machine system timer (<<_machine_system_timer_mtime,**MTIME**>>), RISC-V-compatible
* _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_ 8/16/24/32-bit serial peripheral interface controller (<<_serial_peripheral_interface_controller_spi,**SPI**>>) with 8 dedicated CS lines
* _optional_ two wire serial interface controller (<<_two_wire_serial_interface_controller_twi,**TWI**>>), compatible to the I²C standard
* _optional_ general purpose parallel IO port (<<_general_purpose_input_and_output_port_gpio,**GPIO**>>), 32xOut, 32xIn
* _optional_ 32-bit external bus interface, Wishbone b4 / AXI4-Lite compatible (<<_processor_external_memory_interface_wishbone_axi4_lite,**WISHBONE**>>)
* _optional_ watchdog timer (<<_watchdog_timer_wdt,**WDT**>>)
* _optional_ PWM controller with up to 60 channels & 8-bit duty cycle resolution (<<_pulse_width_modulation_controller_pwm,**PWM**>>)
* _optional_ ring-oscillator-based true random number generator (<<_true_random_number_generator_trng,**TRNG**>>)
* _optional_ custom functions subsystem for custom co-processor extensions (<<_custom_functions_subsystem_cfs,**CFS**>>)
* _optional_ numerically-controlled oscillator (<<_numerically_controlled_oscillator_nco,**NCO**>>) with 3 independent channels
* _optional_ NeoPixel(TM)/WS2812-compatible smart LED interface (<<_smart_led_interface_neoled,**NEOLED**>>)
* _optional_ on-chip debugger with JTAG TAP (<<_on_chip_debugger_ocd,**OCD**>>)
* system configuration information memory to check HW configuration via software (<<_system_configuration_information_memory_sysinfo,**SYSINFO**>>)


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

The following table shows all interface ports of the processor top entity (`rtl/core/neorv32_top.vhd`).
The type of all signals is _std_ulogic_ or _std_ulogic_vector_, respectively.

[TIP]
A wrapper for the NEORV32 Processor setup providing resolved port signals can be found in
`rtl/top_templates/neorv32_top_stdlogic.vhd`.

[cols="<3,^2,^2,<11"]
[options="header",grid="rows"]
|=======================
| Signal | Width | Dir. | Function
4+^| **Global Control**
| `clk_i` | 1 | in | global clock line, all registers triggering on rising edge
| `rstn_i` | 1 | in | global reset, asynchronous, **low-active**
4+^| **JTAG Access Port for <<_on_chip_debugger_ocd>>**
| `jtag_trst_i` | 1 | in  | TAP reset, low-active (optionalfootnote:[Pull high if not used.])
| `jtag_tck_i ` | 1 | in  | serial clock
| `jtag_tdi_i ` | 1 | in  | serial data input
| `jtag_tdo_o ` | 1 | out | serial data outputfootnote:[If the on-chip debugger is not implemented (_ON_CHIP_DEBUGGER_EN_ = false) `jtag_tdi_i` is directly forwarded to `jtag_tdo_o` to maintain the JTAG chain.]
| `jtag_tms_i ` | 1 | in  | mode select
4+^| **External Bus Interface (<<_processor_external_memory_interface_wishbone_axi4_lite,WISHBONE>>)**
| `wb_tag_o` | 3  | out | tag (access type identifier)
| `wb_adr_o` | 32 | out | destination address
| `wb_dat_i` | 32 | in | write data
| `wb_dat_o` | 32 | out | read data
| `wb_we_o`  | 1  | out | write enable ('0' = read transfer)
| `wb_sel_o` | 4  | out | byte enable
| `wb_stb_o` | 1  | out | strobe
| `wb_cyc_o` | 1  | out | valid cycle
| `wb_lock_o`| 1  | out | exclusive access request
| `wb_ack_i` | 1  | in | transfer acknowledge
| `wb_err_i` | 1  | in | transfer error
4+^| **Advanced Memory Control Signals**
| `fence_o`  | 1 | out | indicates an executed _fence_ instruction
| `fencei_o` | 1 | out | indicates an executed _fencei_ instruction
4+^| **General Purpose Inputs & Outputs (<<_general_purpose_input_and_output_port_gpio,GPIO>>)**
| `gpio_o` | 32 | out | general purpose parallel output
| `gpio_i` | 32 | in | general purpose parallel input
4+^| **Primary Universal Asynchronous Receiver/Transmitter (<<_primary_universal_asynchronous_receiver_and_transmitter_uart0,UART0>>)**
| `uart0_txd_o` | 1 | out | UART0 serial transmitter
| `uart0_rxd_i` | 1 | in | UART0 serial receiver
| `uart0_rts_o` | 1 | out | UART0 RX ready to receive new char
| `uart0_cts_i` | 1 | in | UART0 TX allowed to start sending
4+^| **Primary Universal Asynchronous Receiver/Transmitter (<<_secondary_universal_asynchronous_receiver_and_transmitter_uart1,UART1>>)**
| `uart1_txd_o` | 1 | out | UART1 serial transmitter
| `uart1_rxd_i` | 1 | in | UART1 serial receiver
| `uart1_rts_o` | 1 | out | UART1 RX ready to receive new char
| `uart1_cts_i` | 1 | in | UART1 TX allowed to start sending
4+^| **Serial Peripheral Interface Controller (<<_serial_peripheral_interface_controller_spi,SPI>>)**
| `spi_sck_o` | 1 | out | SPI controller clock line
| `spi_sdo_o` | 1 | out | SPI serial data output
| `spi_sdi_i` | 1 | in | SPI serial data input
| `spi_csn_o` | 8 | out | SPI dedicated chip select (low-active)
4+^| **Two-Wire Interface Controller (<<_two_wire_serial_interface_controller_twi,TWI>>)**
| `twi_sda_io` | 1 | inout | TWI serial data line
| `twi_scl_io` | 1 | inout | TWI serial clock line
4+^| **Custom Functions Subsystem (<<_custom_functions_subsystem_cfs,CFS>>)**
| `cfs_in_i`  | 32 | in | custom CFS input signal conduit
| `cfs_out_o` | 32 | out | custom CFS output signal conduit
4+^| **Pulse-Width Modulation Channels (<<_pulse_width_modulation_controller_pwm,PWM>>)**
| `pwm_o` | 4 | out | pulse-width modulated channels
4+^| **Numerically-Controller Oscillator (<<_numerically_controlled_oscillator_nco,NCO>>)**
| `nco_o` | 3 | out | NCO output channels
4+^| **Smart LED Interface - NeoPixel(TM) compatible (<<_smart_led_interface_neoled,NEOLED>>)**
| `neoled_o` | 1 | out | asynchronous serial data output
4+^| **System time (<<_machine_system_timer_mtime,MTIME>>)**
| `mtime_i` | 64 | in  | machine timer time (to `time[h]` CSRs) from _external MTIME_ unit if the processor-internal _MTIME_ unit is NOT implemented
| `mtime_o` | 64 | out | machine timer time from _internal MTIME_ unit if processor-internal _MTIME_ unit IS implemented
4+^| **<<_processor_interrupts>>**
| `nm_irq_i`    | 1 | in | non-maskable interrupt
| `soc_firq_i`  | 6 | in | platform fast interrupt channels (custom)
| `mtime_irq_i` | 1 | in | machine timer interrupt13 (RISC-V)
| `msw_irq_i`   | 1 | in | machine software interrupt (RISC-V)
| `mext_irq_i`  | 1 | in | machine external interrupt (RISC-V)
|=======================


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

This is a list of all configuration generics of the NEORV32 processor top entity rtl/neorv32_top.vhd.
The generic name is shown in orange, followed by the type in printed in black and concluded by the default
value printed in light gray.

[TIP]
The NEORV32 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.

[TIP]
Privileged software can determine the actual CPU and processor configuration via the `misa` and
`mzext` (see <<_machine_trap_setup>> and <<_neorv32_specific_custom_csrs>>) CSRs and via the memory-mapped _SYSINFO_ module (see <<_system_configuration_information_memory_sysinfo>>),
respectively.

[TIP]
If optional modules (like CPU extensions or peripheral devices) are *not enabled* the according circuitry **will not be synthesized at all**.
Hence, the disabled modules do not increase area and power requirements and do not impact the timing.

**CSR Description**

The description of each CSR provides the following summary:

.Generic description
[cols="4,4,2"]
[frame="all",grid="none"]
|======
| _Generic_ | _type_ | _default value_
3+| _Description_
|======

<<<
// ####################################################################################################################
:sectnums:
==== General

See section <<_system_configuration_information_memory_sysinfo>> for more information.

:sectnums!:
===== _CLOCK_FREQUENCY_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **CLOCK_FREQUENCY** | _natural_ | 0
3+| The clock frequency of the processor's `clk_i` input port in Hertz (Hz).
|======


:sectnums!:
===== _BOOTLOADER_EN_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **BOOTLOADER_EN** | _boolean_ | true
3+| Implement the boot ROM, pre-initialized with the bootloader image when true. This will also change the
processor's boot address from the beginning of the instruction memory address space (default =
0x00000000) to the base address of the boot ROM. See section <<_bootloader>> for more information.
|======


:sectnums!:
===== _USER_CODE_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **USER_CODE** | _std_ulogic_vector(31 downto 0)_ | x"00000000"
3+| Custom user code that can be read by software via the _SYSINFO_ module.
|======


:sectnums!:
===== _HW_THREAD_ID_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **HW_THREAD_ID** | _natural_ | 0
3+| The hart ID of the CPU. Can be read via the `mhartid` CSR. Hart IDs must be unique within a system.
|======


:sectnums!:
===== _ON_CHIP_DEBUGGER_EN_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **ON_CHIP_DEBUGGER_EN** | _boolean_ | false
3+| Implement on-chip debugger (OCD). See chapter <<_on_chip_debugger_ocd>>.
|======


// ####################################################################################################################
:sectnums:
==== RISC-V CPU Extensions

See section <<_instruction_sets_and_extensions>> for more information.


:sectnums!:
===== _CPU_EXTENSION_RISCV_A_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **CPU_EXTENSION_RISCV_A** | _boolean_ | false
3+| Implement atomic memory access operations when _true_.
|======


:sectnums!:
===== _CPU_EXTENSION_RISCV_C_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **CPU_EXTENSION_RISCV_C** | _boolean_ | false
3+| Implement compressed instructions (16-bit) when _true_.
|======


:sectnums!:
===== _CPU_EXTENSION_RISCV_E_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **CPU_EXTENSION_RISCV_E** | _boolean_ | false
3+| Implement the embedded CPU extension (only implement the first 16 data registers) when _true_.
|======


:sectnums!:
===== _CPU_EXTENSION_RISCV_M_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **CPU_EXTENSION_RISCV_M** | _boolean_ | false
3+| Implement integer multiplication and division instructions when _true_.
|======


:sectnums!:
===== _CPU_EXTENSION_RISCV_U_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **CPU_EXTENSION_RISCV_U** | _boolean_ | false
3+| Implement less-privileged user mode when _true_.
|======


:sectnums!:
===== _CPU_EXTENSION_RISCV_Zfinx_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **CPU_EXTENSION_RISCV_Zfinx** | _boolean_ | false
3+| Implement the 32-bit single-precision floating-point extension (using integer registers) when _true_. For
more information see section <<_zfinx_single_precision_floating_point_operations>>.
|======


:sectnums!:
===== _CPU_EXTENSION_RISCV_Zicsr_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **CPU_EXTENSION_RISCV_Zicsr** | _boolean_ | true
3+| Implement the control and status register (CSR) access instructions when true. Note: When this option is
disabled, the complete privileged architecture / trap system will be excluded from synthesis. Hence, no interrupts, no exceptions and
no machine information will be available.
|======


:sectnums!:
===== _CPU_EXTENSION_RISCV_Zifencei_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **CPU_EXTENSION_RISCV_Zifencei** | _boolean_ | false
3+| Implement the instruction fetch synchronization instruction _fence.i_. For example, this option is required
for self-modifying code (and/or for i-cache flushes).
|======


// ####################################################################################################################
:sectnums:
==== Extension Options

See section <<_instruction_sets_and_extensions>> for more information.


:sectnums!:
===== _FAST_MUL_EN_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **FAST_MUL_EN** | _boolean_ | false
3+| When this generic is enabled, the multiplier of the `M` extension is realized using DSPs blocks instead of an
iterative bit-serial approach. This generic is only relevant when the multiplier and divider CPU extension is
enabled (<<_cpu_extension_riscv_m>> is _true_).
|======


:sectnums!:
===== _FAST_SHIFT_EN_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **FAST_SHIFT_EN** | _boolean_ | false
3+| When this generic is enabled the shifter unit of the CPU's ALU is implement as fast barrel shifter (requiring
more hardware resources).
|======


:sectnums!:
===== _TINY_SHIFT_EN_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **TINY_SHIFT_EN** | _boolean_ | false
3+| If this generic is enabled the shifter unit of the CPU's ALU is implemented as (slow but tiny) single-bit iterative shifter
(requires up to 32 clock cycles for a shift operations, but reducing hardware footprint). The configuration of
this generic is ignored if <<_fast_shift_en>> is _true_.
|======


:sectnums!:
===== _CPU_CNT_WIDTH_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **CPU_CNT_WIDTH** | _natural_ | 0
3+| This generic configures the total size of the CPU's `cycle` and `instret` CSRs (low word + high word).
The maximum value is 64, the minimal is 0. See
section <<_machine_counters_and_timers>> for more information. Note: Configurations with <<_cpu_cnt_width>>
less than 64 are not RISC-V compliant.
|======


// ####################################################################################################################
:sectnums:
==== Physical Memory Protection (PMP)

See section <<_pmp_physical_memory_protection>> for more information.


:sectnums!:
===== _PMP_NUM_REGIONS_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **PMP_NUM_REGIONS** | _natural_ | 0
3+| Total number of implemented protections regions (0..64). If this generics is zero no physical memory
protection logic will be implemented at all. Setting <<_pmp_num_regions>>_ > 0 will set the _CSR_MZEXT_PMP_ flag
in the <<_mzext>> CSR.
|======


:sectnums!:
===== _PMP_MIN_GRANULARITY_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **PMP_MIN_GRANULARITY** | _natural_ | 64*1024
3+| Minimal region granularity in bytes. Has to be a power of two. Has to be at least 8 bytes.
|======


// ####################################################################################################################
:sectnums:
==== Hardware Performance Monitors (HPM)

See section <<_hpm_hardware_performance_monitors>> for more information.


:sectnums!:
===== _HPM_NUM_CNTS_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **HPM_NUM_CNTS** | _natural_ | 0
3+| Total number of implemented hardware performance monitor counters (0..29). If this generics is zero no
hardware performance monitor logic will be implemented at all. Setting <<_hpm_num_cnts>> > 0 will set the _CSR_MZEXT_HPM_ flag
in the <<_mzext>> CSR.
|======


:sectnums!:
===== _HPM_CNT_WIDTH_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **HPM_CNT_WIDTH** | _natural_ | 40
3+| This generic defines the total LSB-aligned size of each HPM counter (size(`[m]hpmcounter*h`) +
size(`[m]hpmcounter*`)). The maximum value is 64, the minimal is 0. If the size is less than 64-bit, the
unused MSB-aligned counter bits are hardwired to zero.
|======


// ####################################################################################################################
:sectnums:
==== Internal Instruction Memory

See sections <<_address_space>> and <<_instruction_memory_imem>> for more information.


:sectnums!:
===== _MEM_INT_IMEM_EN_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **MEM_INT_IMEM_EN** | _boolean_ | true
3+| Implement processor internal instruction memory (IMEM) when _true_.
|======


:sectnums!:
===== _MEM_INT_IMEM_SIZE_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **MEM_INT_IMEM_SIZE** | _natural_ | 16*1024
3+| Size in bytes of the processor internal instruction memory (IMEM). Has no effect when _MEM_INT_IMEM_EN_ is _false_.
|======


:sectnums!:
===== _MEM_INT_IMEM_ROM_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **MEM_INT_IMEM_ROM** | _boolean_ | false
3+| Implement processor-internal instruction memory as read-only memory, which will be initialized with the
application image at synthesis time. Has no effect when _MEM_INT_IMEM_EN_ is _false_.
|======


// ####################################################################################################################
:sectnums:
==== Internal Data Memory

See sections <<_address_space>> and <<_data_memory_dmem>> for more information.


:sectnums!:
===== _MEM_INT_DMEM_EN_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **MEM_INT_DMEM_EN** | _boolean_ | true
3+| Implement processor internal data memory (DMEM) when _true_.
|======


:sectnums!:
===== _MEM_INT_DMEM_SIZE_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **MEM_INT_DMEM_SIZE** | _natural_ | 8*1024
3+| Size in bytes of the processor-internal data memory (DMEM). Has no effect when _MEM_INT_DMEM_EN_ is _false_.
|======


// ####################################################################################################################
:sectnums:
==== Internal Cache Memory

See section <<_processor_internal_instruction_cache_icache>> for more information.


:sectnums!:
===== _ICACHE_EN_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **ICACHE_EN** | _boolean_ | false
3+| Implement processor internal instruction cache when _true_.
|======


:sectnums!:
===== _ICACHE_NUM_BLOCK_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **ICACHE_NUM_BLOCKS** | _natural_ | 4
3+| Number of blocks (cache "pages" or "lines") in the instruction cache. Has to be a power of two. Has no
effect when _ICACHE_DMEM_EN_ is false.
|======


:sectnums!:
===== _ICACHE_BLOCK_SIZE_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **ICACHE_BLOCK_SIZE** | _natural_ | 64
3+| Size in bytes of each block in the instruction cache. Has to be a power of two. Has no effect when
_ICACHE_EN_ is _false_.
|======


:sectnums!:
===== _ICACHE_ASSOCIATIVITY_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **ICACHE_ASSOCIATIVITY** | _natural_ | 1
3+| Associativity (= number of sets) of the instruction cache. Has to be a power of two. Allowed configurations:
`1` = 1 set, direct mapped; `2` = 2-way set-associative. Has no effect when _ICACHE_EN_ is _false_.
|======


// ####################################################################################################################
:sectnums:
==== External Memory Interface

See sections <<_address_space>> and <<_processor_external_memory_interface_wishbone_axi4_lite>> for more information.


:sectnums!:
===== _MEM_EXT_EN_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **MEM_EXT_EN** | _boolean_ | false
3+| Implement external bus interface (WISHBONE) when _true_.
|======


:sectnums!:
===== _MEM_EXT_TIMEOUT_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **MEM_EXT_TIMEOUT** | _natural_ | 255
3+| Clock cycles after which a pending external bus access will auto-terminate and raise a bus fault exception. Set to 0 to disable auto-timeout. 
|======


// ####################################################################################################################
:sectnums:
==== Processor Peripheral/IO Modules

See section <<_processor_internal_modules>> for more information.


:sectnums!:
===== _IO_GPIO_EN_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **IO_GPIO_EN** | _boolean_ | true
3+| Implement general purpose input/output port unit (GPIO) when _true_.
See section <<_general_purpose_input_and_output_port_gpio>> for more information.
|======


:sectnums!:
===== _IO_MTIME_EN_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **IO_MTIME_EN** | _boolean_ | true
3+| Implement machine system timer (MTIME) when _true_.
See section <<_machine_system_timer_mtime>> for more information.
|======


:sectnums!:
===== _IO_UART0_EN_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **IO_UART0_EN** | _boolean_ | true
3+| Implement primary universal asynchronous receiver/transmitter (UART0) when _true_.
See section <<_primary_universal_asynchronous_receiver_and_transmitter_uart0>> for
more information.
|======


:sectnums!:
===== _IO_UART1_EN_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **IO_UART1_EN** | _boolean_ | true
3+| Implement secondary universal asynchronous receiver/transmitter (UART1) when _true_. 
See section <<_secondary_universal_asynchronous_receiver_and_transmitter_uart1>> for more information.
|======


:sectnums!:
===== _IO_SPI_EN_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **IO_SPI_EN** | _boolean_ | true
3+| Implement serial peripheral interface controller (SPI) when _true_.
See section <<_serial_peripheral_interface_controller_spi>> for more information.
|======


:sectnums!:
===== _IO_TWI_EN_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **IO_TWI_EN** | _boolean_ | true
3+| Implement two-wire interface controller (TWI) when _true_.
See section <<_two_wire_serial_interface_controller_twi>> for
more information.
|======


:sectnums!:
===== _IO_PWM_NUM_CH_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **IO_PWM_NUM_CH** | _natural_ | 4
3+| Number of pulse-width modulation (PWM) channels (0..60) to implement. The PWM controller is _not_ implemented if zero.
See section <<_pulse_width_modulation_controller_pwm>> for more information.
|======


:sectnums!:
===== _IO_WDT_EN_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **IO_WDT_EN** | _boolean_ | true
3+| Implement watchdog timer (WDT) when _true_. See section <<_watchdog_timer_wdt>> for more
information.
|======


:sectnums!:
===== _IO_TRNG_EN_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **IO_TRNG_EN** | _boolean_ | false
3+| Implement true-random number generator (TRNG) when _true_. See section <<_true_random_number_generator_trng>> for more information.
|======


:sectnums!:
===== _IO_CFS_EN_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **IO_CFS_EN** | _boolean_ | false
3+| Implement custom functions subsystem (CFS) when _true_. See section <<_custom_functions_subsystem_cfs>> for more information.
|======


:sectnums!:
===== _IO_CFS_CONFIG_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **IO_CFS_CONFIG** | _std_ulogic_vector(31 downto 0)_ | 0x"00000000"
3+| This is a "conduit" generic that can be used to pass user-defined CFS implementation flags to the custom
functions subsystem entity. See section <<_custom_functions_subsystem_cfs>> for more information.
|======


:sectnums!:
===== _IO_CFS_IN_SIZE_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **IO_CFS_IN_SIZE** | _positive_ | 32
3+| Defines the size of the CFS input signal conduit (`cfs_in_i`). See section <<_custom_functions_subsystem_cfs>> for more information.
|======


:sectnums!:
===== _IO_CFS_OUT_SIZE_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **IO_CFS_OUT_SIZE** | _positive_ | 32
3+| Defines the size of the CFS output signal conduit (`cfs_out_o`). See section <<_custom_functions_subsystem_cfs>> for more information.
|======


:sectnums!:
===== _IO_NCO_EN_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **IO_NCO_EN** | _boolean_ | true
3+| Implement numerically-controlled oscillator (NCO) when _true_.
See section <<_numerically_controlled_oscillator_nco>> for more information.
|======


:sectnums!:
===== _IO_NEOLED_EN_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **IO_NEOLED_EN** | _boolean_ | true
3+| Implement smart LED interface (WS2812 / NeoPixel(TM)-compatible) (NEOLED) when _true_.
See section <<_smart_led_interface_neoled>> for more information.
|======


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

[TIP]
The interrupt request signals have specific `mip` CSR bits (see <<_machine_trap_setup>>), specifc
`mie` CSR bits (see <<_machine_trap_handling>>) and specifc `mcause` CSR trap codes and trap
priorities. For more information (also regarding the signaling protocol) see section <<_traps_exceptions_and_interrupts>>.

**RISC-V Standard Interrupts**

The processor setup features the standard RISC-V interrupt lines for "machine timer interrupt", "machine
software interrupt" and "machine external interrupt". The software and external interrupt lines are available
via the processor's top entity. By default, the timer interrupt is connected to the internal machine timer
MTIME timer unit (<<_machine_system_timer_mtime>>). If this module has not been enabled for
synthesis, the machine timer interrupt is also available via the processor's top entity.

**NEORV32-Specific Fast Interrupt Requests**

As part of the custom/NEORV32-specific CPU extensions, the CPU features 16 fast interrupt request signals
(`FIRQ0` – `FIRQ15`).

The fast interrupt request signals are divided into two groups. The FIRQs with higher priority (FIRQ0 –
FIRQ9) are dedicated for processor-internal usage. The FIRQs with lower priority (FIRQ10 – FIRQ15) are
available for custom usage via the processor's top entity signal `soc_firq_i`.

The mapping of the 16 FIRQ channels is shown in the following table (the channel number corresponds to the FIRQ priority):

.NEORV32 fast interrupt channel mapping
[cols="^1,<2,<7"]
[options="header",grid="rows"]
|=======================
| Channel | Source | Description
| 0       | _WDT_ | watchdog timeout interrupt
| 1       | _CFS_ | custom functions subsystem (CFS) interrupt (user-defined)
| 2       | _UART0_ (RXD) | UART0 data received interrupt (RX complete)
| 3       | _UART0_ (TXD) | UART0 sending done interrupt (TX complete)
| 4       | _UART1_ (RXD) | UART1 data received interrupt (RX complete)
| 5       | _UART1_ (TXD) | UART1 sending done interrupt (TX complete)
| 6       | _SPI_ | SPI transmission done interrupt
| 7       | _TWI_ | TWI transmission done interrupt
| 8       | _GPIO_ | GPIO input pin-change interrupt
| 9       | _NEOLED_ | NEOLED buffer TX empty / not full interrupt
| 10:15   | `soc_firq_i(5:0)` | Custom platform use; available via processor's top signal
|=======================

**Non-Maskable Interrupt**

The NEORV32 features a single non-maskable interrupt source via the `nm_irq_i` top
entity signal that can be used to signal critical system conditions. This interrupt source _cannot_ be disabled. Hence, it does _not_ provide
configuration/status flags in the `mie` and `mip` CSRs. The RISC-V-compatible `mcause` value `0x80000000` is used to indicate the non-maskable interrupt.

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

By default, the total 32-bit (4GB) address space of the NEORV32 Processor is divided into four main regions:

1. Instruction memory (IMEM) space – for instructions and constants.
2. Data memory (DMEM) space – for application runtime data (heap, stack, etc.).
3. Bootloader ROM address space – for the processor-internal bootloader.
4. IO/peripheral address space – for the processor-internal IO/peripheral devices (e.g., UART).

.NEORV32 processor - address space (default configuration)
image::address_space.png[900]

[TIP]
These four memory regions are handled by the linker when compiling a NEORV32 executable.
See section <<_executable_image_format>> for more information.

**Address Space Layout**

The general address space layout consists of two main configuration constants: `ispace_base_c` defining
the base address of the instruction memory address space and `dspace_base_c` defining the base address of
the data memory address space. Both constants are defined in the NEORV32 VHDL package file
`rtl/core/neorv32_package.vhd`:

[source,vhdl]
----
-- Architecture Configuration ----------------------------------------------------
-- ----------------------------------------------------------------------------------
constant ispace_base_c : std_ulogic_vector(31 downto 0) := x"00000000";
constant dspace_base_c : std_ulogic_vector(31 downto 0) := x"80000000";
----

The default configuration assumes the instruction memory address space starting at address _0x00000000_
and the data memory address space starting at _0x80000000_. Both values can be modified for a specific
setup and the address space may overlap or can be completely identical.

The base address of the bootloader (at _0xFFFF0000_) and the IO region (at _0xFFFFFF00_) for the peripheral
devices are also defined in the package and are fixed. These address regions cannot be used for other
applications – even if the bootloader or all IO devices are not implemented.

[WARNING]
When using the processor-internal data and/or instruction memories (DMEM/IMEM) and using a non-default
configuration for the `dspace_base_c` and/or `ispace_base_c` base addresses, the
following requirements have to be fulfilled:
**1.** Both base addresses have to be aligned to a 4-byte boundary.
**2.** Both base addresses have to be aligned to the according internal memory sizes.

:sectnums:
==== CPU Data and Instruction Access

The CPU can access all of the 4GB address space from the instruction fetch interface (**I**) and also from the
data access interface (**D**). These two CPU interfaces are multiplexed by a simple bus switch
(`rtl/core/neorv32_busswitch.vhd`) into a _single_ processor-internal bus. All processor-internal
memories, peripherals and also the external memory interface are connected to this bus. Hence, both CPU
interfaces (instruction fetch & data access) have access to the same (**identical**) address space making the
setup a modified von-Neumann architecture.

.Processor-internal bus architecture
image::neorv32_bus.png[1300]

[NOTE]
The internal processor bus might appear as bottleneck. In order to reduce traffic jam on this bus
(when instruction fetch and data interface access the bus at the same time) the instruction fetch of
the CPU is equipped with a prefetch buffer. Instruction fetches can be further buffered using the i-cache.
Furthermore, data accesses (loads and stores) have higher priority than instruction fetch
accesses.

[IMPORTANT]
Please note that all processor-internal components including the peripheral/IO devices can also be
accessed from programs running in less-privileged user mode. For example, if the system relies on
a periodic interrupt from the _MTIME_ timer unit, user-level programs could alter the _MTIME_
configuration corrupting this interrupt. This kind of security issues can be compensated using the
PMP system (see <<_machine_physical_memory_protection>>).

:sectnums:
==== Physical Memory Attributes

The processor setup defines four simple attributes for the four processor-internal address space regions:

* `r` – read access (from CPU data access interface, e.g. via "load")
* `w` – write access (from CPU data access interface, e.g. via "store")
* `x` – execute access (from CPU instruction fetch interface)
* `a` – atomic access (from CPU data access interface)
* `8` – byte (8-bit)-accessible (when writing)
* `16` – half-word (16-bit)-accessible (when writing)
* `32` – word (32-bit)-accessible (when writing)

The following table shows the provided physical memory attributes of each region. Additional attributes (like
denying execute right for certain region of the IMEM) can be provided using the RISC-V <<_machine_physical_memory_protection>> extension.

[cols="^1,^2,^2,^3,^2"]
[options="header",grid="rows"]
|=======================
| # | Region | Base address | Size | Attributes
| 4 | IO/peripheral devices | 0xfffffe00 | 512 bytes | `r/w/a/32`
| 3 | bootloader ROM        | 0xffff0000 | up to 32kB| `r/x/a`
| 2 | DMEM                  | 0x80000000 | up to 2GB (-64kB) | `r/w/x/a/8/16/32`
| 1 | IMEM                  | 0x00000000 | up to 2GB | `r/w/x/a/8/16/32`
|=======================

Only the CPU of the processor has access to the internal memories and IO devices, hence all accesses are
always exclusive. Accessing a memory region in a way that violates the provided attributes will trigger a
load/store/instruction fetch access exception or will return a failed atomic access result, respectively.

The physical memory attributes of memories and/or devices connected via the external bus interface have to
defined by those components or the interconnection fabric.

:sectnums:
==== Internal Memories

The processor can implement internal memories for instructions (IMEM) and data (DMEM), which will be
mapped to FPGA block RAMs. The implementation of these memories is controlled via the boolean
<<_mem_int_imem_en>> and <<_mem_int_dmem_en>> generics.

The size of these memories are configured via the _MEM_INT_IMEM_SIZE_ and _MEM_INT_DMEM_SIZE_
generics (in bytes), respectively. The processor-internal instruction memory (IMEM) can optionally be
implemented as true ROM (<<_mem_int_imem_rom>>), which is initialized with the application code during
synthesis.

If the processor-internal IMEM is implemented, it is located right at the base address of the instruction
address space (default `ispace_base_c` = _0x00000000_). Vice versa, the processor-internal data memory is
located right at the beginning of the data address space (default `dspace_base_c` = _0x80000000_) when
implemented.

:sectnums:
==== External Memory/Bus Interface

Any CPU access (data or instructions), which does not fulfill one of the following conditions, is forwarded
to the <<_processor_external_memory_interface_wishbone_axi4_lite>>:

* access to the processor-internal IMEM and processor-internal IMEM is implemented
* access to the processor-internal DMEM and processor-internal DMEM is implemented
* access to the bootloader ROM and beyond → addresses >= _BOOTROM_BASE_ (default 0xFFFF0000) will never be forwarded to the external memory interface

The external bus interface is available when the <<_mem_ext_en>> generic is _true_. If this interface is
deactivated, any access exceeding the internal memories or peripheral devices will trigger a bus access fault
exception. If <<_mem_ext_timeout>> is greater than zero any external bus access that is not acknowledged or terminated
within <<_mem_ext_timeout>> clock cycles will auto-timeout and raise the according bus fault exception.



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

Basically, the processor is a SoC consisting of the NEORV32 CPU, peripheral/IO devices, embedded
memories, an external memory interface and a bus infrastructure to interconnect all units. Additionally, the
system implements an internal reset generator and a global clock generator/divider.

**Internal Reset Generator**

Most processor-internal modules – except for the CPU and the watchdog timer – do not have a dedicated
reset signal. However, all devices can be reset by software by clearing the corresponding unit's control
register. The automatically included application start-up code (`crt0.S`) will perform a software-reset of all
modules to ensure a clean system reset state.

The hardware reset signal of the processor can either be
triggered via the external reset pin (`rstn_i`, low-active) or by the internal watchdog timer (if implemented).
Before the external reset signal is applied to the system, it is extended to have a minimal duration of eight
clock cycles.

**Internal Clock Divider**

An internal clock divider generates 8 clock signals derived from the processor's main clock input `clk_i`.
These derived clock signals are not actual _clock signals_. Instead, they are derived from a simple counter and
are used as "clock enable" signal by the different processor modules. Thus, the whole design operates using
only the main clock signal (single clock domain). Some of the processor peripherals like the Watchdog or the
UARTs can select one of the derived clock enabled signals for their internal operation. If none of the
connected modules require a clock signal from the divider, it is automatically deactivated to reduce dynamic
power.

The peripheral devices, which feature a time-based configuration, provide a three-bit prescaler select in their
according control register to select one out of the eight available clocks. The mapping of the prescaler select
bits to the actually obtained clock are 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_
|=======================

**Peripheral / IO Devices**

The processor-internal peripheral/IO devices are located at the end of the 32-bit address space at base
address _0xFFFFFE00_. A region of 512 bytes is reserved for this devices. Hence, all peripheral/IO devices are
accessed using a memory-mapped scheme. A special linker script as well as the NEORV32 core software
library abstract the specific memory layout for the user.

[IMPORTANT]
When accessing an IO device that hast not been implemented (via the according _IO_x_EN_ generic), a
load/store access fault exception is triggered.

[IMPORTANT]
The peripheral/IO devices can only be written in full-word mode (i.e. 32-bit). Byte or half-word
(8/16-bit) writes will trigger a store access fault exception. Read accesses are not size constrained.
Processor-internal memories as well as modules connected to the external memory interface can still
be written with a byte-wide granularity.

[TIP]
You should use the provided core software library to interact with the peripheral devices. This
prevents incompatibilities with future versions, since the hardware driver functions handle all the
register and register bit accesses.

[TIP]
Most of the IO devices do not have a hardware reset. Instead, the devices are reset via software by
writing zero to the unit's control register. A general software-based reset of all devices is done by the
application start-up code `crt0.S`.

**Nomenclature for the Peripheral / IO Devices Listing**

Each peripheral device chapter features a register map showing accessible control and data registers of the
according device including the implemented control and status bits. You can directly interact with these
registers/bits via the provided _C-code defines_. These defines are set in the main processor core library
include file `sw/lib/include/neorv32.h`. The registers and/or register bits, which can be accessed
directly using plain C-code, are marked with a "[C]".

Not all registers or register bits can be arbitrarily read/written. The following read/write access types are
available:

* `r/w` registers / bits can be read and written
* `r/-` registers / bits are read-only; any write access to them has no effect
* `-/w` these registers / bits are write-only; they auto-clear in the next cycle and are always read as zero

[TIP]
Bits / registers that are not listed in the register map tables are not (yet) implemented. These registers
/ bits are always read as zero. A write access to them has no effect, but user programs should only
write zero to them to keep compatible with future extension.

[TIP]
When writing to read-only registers, the access is nevertheless acknowledged, but no actual data is
written. When reading data from a write-only register the result is undefined.


include::soc_imem.adoc[]

include::soc_dmem.adoc[]

include::soc_bootrom.adoc[]

include::soc_icache.adoc[]

include::soc_wishbone.adoc[]

include::soc_gpio.adoc[]

include::soc_wdt.adoc[]

include::soc_mtime.adoc[]

include::soc_uart.adoc[]

include::soc_spi.adoc[]

include::soc_twi.adoc[]

include::soc_pwm.adoc[]

include::soc_trng.adoc[]

include::soc_cfs.adoc[]

include::soc_nco.adoc[]

include::soc_neoled.adoc[]

include::soc_sysinfo.adoc[]


Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.