<<<
:sectnums:
=== Control and Status Registers (CSRs)

The following table shows a summary of all available NEORV32 CSRs. The address field defines the CSR address for
the CSR access instructions. The "Name [ASM]" column provides the CSR name aliases that can be used in (inline) assembly.
The "Name [C]" column lists the name aliases that are defined by the NEORV32 core library. These can be used in plain C code.
The "Access" column shows the minimal required privilege mode required for accessing the according CSR (`M` = machine-mode,
`U` = user-mode, `D` = debug-mode) and the read/write capabilities (`RW` = read-write, `RO` = read-only)

.Unused, Reserved, Unimplemented and Disabled CSRs
[NOTE]
All CSRs and CSR bits that are not listed in the table below are _unimplemented_ and are _hardwired to zero_. Additionally,
CSRs that are unavailable ("disabled") because the according ISA extension is not enabled are also considered _unimplemented_
and are also hardwired to zero. Any access to such a CSR will raise an illegal instruction exception. All writable CSRs provide
**WARL** behavior (write all values; read only legal values). Application software should always read back a CSR after writing
to check if the targeted bits can actually be modified.

.NEORV32 Control and Status Registers (CSRs)
[cols="<3,<5,<6,^3,<12"]
[options="header"]
|=======================
| Address | Name [ASM] | Name [C] | Access | Description
5+^| **<<_floating_point_csrs>>**
| 0x001 | <<_fflags>> | `CSR_FFLAGS` | URW | Floating-point accrued exceptions
| 0x002 | <<_frm>>    | `CSR_FRM`    | URW | Floating-point dynamic rounding mode
| 0x003 | <<_fcsr>>   | `CSR_FCSR`   | URW | Floating-point control and status
5+^| **<<_machine_trap_setup_csrs>>**
| 0x300 | <<_mstatus>>    | `CSR_MSTATUS`    | MRW | Machine status register - low word
| 0x301 | <<_misa>>       | `CSR_MISA`       | MRW | Machine CPU ISA and extensions
| 0x304 | <<_mie>>        | `CSR_MIE`        | MRW | Machine interrupt enable register
| 0x305 | <<_mtvec>>      | `CSR_MTVEC`      | MRW | Machine trap-handler base address for ALL traps
| 0x306 | <<_mcounteren>> | `CSR_MCOUNTEREN` | MRW | Machine counter-enable register
| 0x310 | <<_mstatush>>   | `CSR_MSTATUSH`   | MRW | Machine status register - high word
5+^| **<<_machine_configuration_csrs>>**
| 0x30a | <<_menvcfg>>  | `CSR_MENVCFG`  | MRW | Machine environment configuration register - low word
| 0x31a | <<_menvcfgh>> | `CSR_MENVCFGH` | MRW | Machine environment configuration register - high word
5+^| **<<_machine_counter_setup_csrs>>**
| 0x320 | <<_mcountinhibit>>                | `CSR_MCOUNTINHIBIT` | MRW | Machine counter-inhibit register
| 0x321 | <<_mcyclecfgh, `mcyclecfg`>>      | `CSR_MCYCLECFG`     | MRW | Machine cycle counter privilege mode filtering - low word
| 0x322 | <<_minstretcfgh, `minstretcfg`>>  | `CSR_MINSTRETCFG`   | MRW | Machine instret counter privilege mode filtering - low word
| 0x721 | <<_mcyclecfgh, `mcyclecfgh`>>     | `CSR_MCYCLECFGH`    | MRW | Machine cycle counter privilege mode filtering - high word
| 0x722 | <<_minstretcfgh, `minstretcfgh`>> | `CSR_MINSTRETCFGH`  | MRW | Machine instret counter privilege mode filtering - high word
5+^| **<<_machine_trap_handling_csrs>>**
| 0x340 | <<_mscratch>> | `CSR_MSCRATCH` | MRW | Machine scratch register
| 0x341 | <<_mepc>>     | `CSR_MEPC`     | MRW | Machine exception program counter
| 0x342 | <<_mcause>>   | `CSR_MCAUSE`   | MRW | Machine trap cause
| 0x343 | <<_mtval>>    | `CSR_MTVAL`    | MRW | Machine trap value
| 0x344 | <<_mip>>      | `CSR_MIP`      | MRW | Machine interrupt pending register
5+^| **<<_machine_physical_memory_protection_csrs>>**
| 0x3a0 .. 0x303 | <<_pmpcfg, `pmpcfg0`>> .. <<_pmpcfg, `pmpcfg3`>>      | `CSR_PMPCFG0` .. `CSR_PMPCFG3`    | MRW | Physical memory protection configuration registers
| 0x3b0 .. 0x3bf | <<_pmpaddr, `pmpaddr0`>> .. <<_pmpaddr, `pmpaddr15`>> | `CSR_PMPADDR0` .. `CSR_PMPADDR15` | MRW | Physical memory protection address registers
5+^| **<<_trigger_module_csrs>>**
| 0x7a0 | <<_tselect>>  | `CSR_TSELECT`  | MRW | Trigger select register
| 0x7a1 | <<_tdata1>>   | `CSR_TDATA1`   | MRW | Trigger data register 1
| 0x7a2 | <<_tdata2>>   | `CSR_TDATA2`   | MRW | Trigger data register 2
| 0x7a4 | <<_tinfo>>    | `CSR_TINFO`    | MRW | Trigger information register
5+^| **<<_cpu_debug_mode_csrs>>**
| 0x7b0 | <<_dcsr>>      | `CSR_DCSR`      | DRW | Debug control and status register
| 0x7b1 | <<_dpc>>       | `CSR_DPC`       | DRW | Debug program counter
| 0x7b2 | <<_dscratch0>> | `CSR_DSCRATCH0` | DRW | Debug scratch register 0
5+^| **<<_machine_counter_and_timer_csrs>>**
| 0xb00 | <<_mcycleh, `mcycle`>>      | `CSR_MCYCLE`    | MRW | Machine cycle counter low word
| 0xb02 | <<_minstreth, `minstret`>>  | `CSR_MINSTRET`  | MRW | Machine instruction-retired counter low word
| 0xb80 | <<_mcycleh, `mcycleh`>>     | `CSR_MCYCLEH`   | MRW | Machine cycle counter high word
| 0xb82 | <<_minstreth, `minstreth`>> | `CSR_MINSTRETH` | MRW | Machine instruction-retired counter high word
| 0xc00 | <<_cycleh, `cycle`>>        | `CSR_CYCLE`     | URO | Cycle counter low word
| 0xc01 | <<_timeh, `time`>>          | `CSR_TIME`      | URO | System time low word
| 0xc02 | <<_instreth, `instret`>>    | `CSR_INSTRET`   | URO | Instruction-retired counter low word
| 0xc80 | <<_cycleh, `cycleh`>>       | `CSR_CYCLEH`    | URO | Cycle counter high word
| 0xc81 | <<_timeh, `timeh`>>         | `CSR_TIMEH`     | URO | System time high word
| 0xc82 | <<_instreth, `instreth`>>   | `CSR_INSTRETH`  | URO | Instruction-retired counter high word
5+^| **<<_hardware_performance_monitors_hpm_csrs>>**
| 0x323 .. 0x33f | <<_mhpmevent, `mhpmevent3`>> .. <<_mhpmevent, `mhpmevent31`>>             | `CSR_MHPMEVENT3` .. `CSR_MHPMEVENT31`       | MRW | Machine performance-monitoring event select
| 0xb03 .. 0xb1f | <<_mhpmcounterh, `mhpmcounter3`>> .. <<_mhpmcounterh, `mhpmcounter31`>>   | `CSR_MHPMCOUNTER3` .. `CSR_MHPMCOUNTER31`   | MRW | Machine performance-monitoring counter low word
| 0xb83 .. 0xb9f | <<_mhpmcounterh, `mhpmcounter3h`>> .. <<_mhpmcounterh, `mhpmcounter31h`>> | `CSR_MHPMCOUNTER3H` .. `CSR_MHPMCOUNTER31H` | MRW | Machine performance-monitoring counter high word
| 0xc03 .. 0xc1f | <<_hpmcounterh, `hpmcounter3`>> .. <<_hpmcounterh, `hpmcounter31`>>       | `CSR_HPMCOUNTER3` .. `CSR_HPMCOUNTER31`     | URO | Performance-monitoring counter low word
| 0xc83 .. 0xc9f | <<_hpmcounterh, `hpmcounter3h`>> .. <<_hpmcounterh, `hpmcounter31h`>>     | `CSR_HPMCOUNTER3H` .. `CSR_HPMCOUNTER31H`   | URO | Performance-monitoring counter high word
5+^| **<<_machine_information_csrs>>**
| 0xf11 | <<_mvendorid>>  | `CSR_MVENDORID`  | MRO | Machine vendor ID
| 0xf12 | <<_marchid>>    | `CSR_MARCHID`    | MRO | Machine architecture ID
| 0xf13 | <<_mimpid>>     | `CSR_MIMPID`     | MRO | Machine implementation ID / version
| 0xf14 | <<_mhartid>>    | `CSR_MHARTID`    | MRO | Machine hardware thread ID
| 0xf15 | <<_mconfigptr>> | `CSR_MCONFIGPTR` | MRO | Machine configuration pointer register
5+^| **<<_neorv32_specific_csrs>>**
| 0xfc0 | <<_mxisah, `mxisa`>>  | `CSR_MXISA`  | MRO | Extended machine CPU ISA and extensions low word
| 0xfc1 | <<_mxisah, `mxisah`>> | `CSR_MXISAH` | MRO | Extended machine CPU ISA and extensions high word
|=======================


<<<
// ####################################################################################################################
:sectnums:
==== Floating-Point CSRs

[discrete]
===== **`fflags`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Floating-point accrued exceptions
| Address     | `0x001`
| Reset value | `0x00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>> & <<_zfinx_isa_extension,`Zfinx`>>
| Description | FPU status flags.
|=======================

.`fflags` CSR bits
[cols="^1,^1,<10"]
[options="header",grid="rows"]
|=======================
| Bit | R/W | Function
| 4   | r/w | **NV**: invalid operation
| 3   | r/w | **DZ**: division by zero
| 2   | r/w | **OF**: overflow
| 1   | r/w | **UF**: underflow
| 0   | r/w | **NX**: inexact
|=======================

{empty} +
[discrete]
===== **`frm`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Floating-point dynamic rounding mode
| Address     | `0x002`
| Reset value | `0x00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>> & <<_zfinx_isa_extension,`Zfinx`>>
| Description | The `frm` CSR is used to configure the rounding mode of the FPU.
|=======================

.`frm` CSR bits
[cols="^1,^1,<10"]
[options="header",grid="rows"]
|=======================
| Bit | R/W | Function
| 2:0 | r/w | Rounding mode
|=======================


{empty} +
[discrete]
===== **`fcsr`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Floating-point control and status register
| Address     | `0x003`
| Reset value | `0x00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>> & <<_zfinx_isa_extension,`Zfinx`>>
| Description | The `fcsr` provides combined access to the <<_fflags>> and <<_frm>> flags.
|=======================

.`fcsr` CSR bits
[cols="^1,^1,<10"]
[options="header",grid="rows"]
|=======================
| Bit | R/W | Function
| 7:5 | r/w | Rounding mode (<<_frm>>)
| 4:0 | r/w | Accrued exception flags (<<_fflags>>)
|=======================


<<<
// ####################################################################################################################
:sectnums:
==== Machine Trap Setup CSRs

[discrete]
===== **`mstatus`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine status register - low word
| Address     | `0x300`
| Reset value | `0x00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>>
| Description | The `mstatus` CSR is used to configure general machine environment parameters.
|=======================

.`mstatus` CSR bits
[cols="^1,<3,^1,<9"]
[options="header",grid="rows"]
|=======================
| Bit | Name [C] | R/W | Function
| 21    | `CSR_MSTATUS_TW`   | r/w | **TW**: Trap on execution of `wfi` instruction in user mode when set; hardwired to zero if user-mode not implemented
| 17    | `CSR_MSTATUS_MPRV` | r/w | **MPRV**: Effective privilege mode for load/stores; use `MPP` as effective privilege mode when set; hardwired to zero if user-mode not implemented
| 12:11 | `CSR_MSTATUS_MPP_H` : `CSR_MSTATUS_MPP_L` | r/w | **MPP**: Previous machine privilege mode, `11` = machine-mode "M", `00` = user-mode "U"; other values will fall-back to user-mode (if enabled)
| 7     | `CSR_MSTATUS_MPIE` | r/w | **MPIE**: Previous machine-mode interrupt enable flag state
| 3     | `CSR_MSTATUS_MIE`  | r/w | **MIE**: Machine-mode interrupt enable flag
|=======================


{empty} +
[discrete]
===== **`misa`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | ISA and extensions
| Address     | `0x301`
| Reset value | `DEFINED`, according to enabled ISA extensions
| ISA         | <<_zicsr_isa_extension,`Zicsr`>>
| Description | The `misa` CSR provides information regarding the availability of basic RISC-V ISa extensions.
|=======================

[NOTE]
The NEORV32 `misa` CSR is read-only. Hence, active CPU extensions are entirely defined by pre-synthesis configurations
and cannot be switched on/off during runtime. For compatibility reasons any write access to this CSR is simply ignored and
will _not_ cause an illegal instruction exception.

.`misa` CSR bits
[cols="^1,<3,^1,<9"]
[options="header",grid="rows"]
|=======================
| Bit   | Name [C] | R/W | Function
| 31:30 | `CSR_MISA_MXL_HI_EXT` : `CSR_MISA_MXL_LO_EXT` | r/- | **MXL**: 32-bit architecture indicator (always `01`)
| 23    | `CSR_MISA_X_EXT` | r/- | **X**: bit is always set to indicate non-standard / NEORV32-specific extensions
| 20    | `CSR_MISA_U_EXT` | r/- | **U**: CPU extension (user mode) available, set when <<_u_isa_extension>> enabled
| 12    | `CSR_MISA_M_EXT` | r/- | **M**: CPU extension (mul/div) available, set when <<_m_isa_extension>> enabled
| 8     | `CSR_MISA_I_EXT` | r/- | **I**: CPU base ISA, cleared when <<_e_isa_extension>> enabled
| 4     | `CSR_MISA_E_EXT` | r/- | **E**: CPU extension (embedded) available, set when <<_e_isa_extension>> enabled
| 2     | `CSR_MISA_C_EXT` | r/- | **C**: CPU extension (compressed instruction) available, set when <<_c_isa_extension>> enabled
| 1     | `CSR_MISA_B_EXT` | r/- | **B**: CPU extension (bit-manipulation) available, set when <<_b_isa_extension>> enabled
| 0     | `CSR_MISA_A_EXT` | r/- | **A**: CPU extension (atomic memory access) available, set when <<_a_isa_extension>> enabled
|=======================

[TIP]
Machine-mode software can discover available `Z*` sub-extensions (like `Zicsr` or `Zfinx`) by checking the NEORV32-specific
<<_mxisah>> CSRs.


{empty} +
[discrete]
===== **`mie`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine interrupt-enable register
| Address     | `0x304`
| Reset value | `0x00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>>
| Description | The `mie` CSR is used to enable/disable individual interrupt sources.
|=======================

.`mie` CSR bits
[cols="^1,<3,^1,<9"]
[options="header",grid="rows"]
|=======================
| Bit   | Name [C] | R/W | Function
| 31:16 | `CSR_MIE_FIRQ15E` : `CSR_MIE_FIRQ0E` | r/w | Fast interrupt channel 15..0 enable
| 11    | `CSR_MIE_MEIE` | r/w | **MEIE**: Machine _external_ interrupt enable
| 7     | `CSR_MIE_MTIE` | r/w | **MTIE**: Machine _timer_ interrupt enable (from <<_core_local_interruptor_clint>>)
| 3     | `CSR_MIE_MSIE` | r/w | **MSIE**: Machine _software_ interrupt enable (from <<_core_local_interruptor_clint>>)
|=======================


{empty} +
[discrete]
===== **`mtvec`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine trap-handler base address
| Address     | `0x305`
| Reset value | `0x00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>>
| Description | The `mtvec` CSR holds the trap vector configuration.
|=======================

.`mtvec` CSR bits
[cols="^1,^1,<10"]
[options="header",grid="rows"]
|=======================
| Bit  | R/W | Function
| 31:2 | r/w | **BASE**: in DIRECT mode = 4-byte-aligned base address of trap base handler, _all_ traps jump to `pc = BASE`;
in VECTORED mode = 128-byte-aligned base address of trap vector table, interrupts cause a jump to `pc = BASE + 4 * mcause`
and exceptions a jump to `pc = BASE`.
| 1:0  | r/w | **MODE**: mode configuration, `00` = DIRECT, `01` = VECTORED; other encodings are _reserved_.
|=======================


{empty} +
[discrete]
===== **`mcounteren`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine counter enable
| Address     | `0x306`
| Reset value | `0x00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>> & <<_u_isa_extension,`U`>>
| Description | The `mcounteren` CSR is used to constrain user-mode access to the CPU's counter CSRs.
|=======================

.`mcounteren` CSR bits
[cols="^1,<3,^1,<8"]
[options="header",grid="rows"]
|=======================
| Bit | Name [C] | R/W | Function
| 31:3 | `CSR_MCOUNTEREN_HPM31 : CSR_MCOUNTEREN_HPM3` | r/w | **HPMn**: User-mode is allowed to read according <<_hpmcounterh>> (31:3) CSRs when set
| 2    | `CSR_MCOUNTEREN_IR`                          | r/w | **IR**: User-mode is allowed to read <<_instreth>> CSRs when set
| 1    | `CSR_MCOUNTEREN_TM`                          | r/w | **TM**: User-mode is allowed to read <<_timeh>> CSRs when set
| 0    | `CSR_MCOUNTEREN_CY`                          | r/w | **CY**: User-mode is allowed to read <<_cycleh>> CSRs when set
|=======================


{empty} +
[discrete]
===== **`mstatush`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine status register - high word
| Address     | `0x310`
| Reset value | `0x00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>>
| Description | The features of this CSR are not implemented yet. The register is read-only and always returns zero.
|=======================


<<<
// ####################################################################################################################
:sectnums:
==== Machine Trap Handling CSRs

[discrete]
===== **`mscratch`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Scratch register for machine trap handlers
| Address     | `0x340`
| Reset value | `0x00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>>
| Description | The `mscratch` is a general-purpose machine-mode scratch register.
|=======================


{empty} +
[discrete]
===== **`mepc`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine exception program counter
| Address     | `0x341`
| Reset value | `0x00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>>
| Description | The `mepc` CSR provides the instruction address where execution has stopped/failed when
an interrupt is triggered / an exception is raised. See section <<_traps_exceptions_and_interrupts>> for a list of all legal values.
The `mret` instruction will return to the address stored in `mepc` by automatically moving `mepc` to the program counter.
|=======================

[NOTE]
`mepc[0]` is hardwired to zero. If IALIGN = 32 (i.e. <<_c_isa_extension>> is disabled) then `mepc[1]` is also hardwired to zero.


{empty} +
[discrete]
===== **`mcause`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine trap cause
| Address     | `0x342`
| Reset value | `0x00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>>
| Description | The `mcause` CSRs shows the exact cause of a trap. See section <<_traps_exceptions_and_interrupts>> for a list of all legal values.
|=======================

.`mcause` CSR bits
[cols="^1,^1,<10"]
[options="header",grid="rows"]
|=======================
| Bit  | R/W | Function
| 31   | r/w | **Interrupt**: `1` if the trap is caused by an interrupt (`0` if the trap is caused by an exception)
| 30:5 | r/- | Hardwired to zero
| 4:0  | r/w | **Exception code**: see <<_neorv32_trap_listing>>
|=======================


{empty} +
[discrete]
===== **`mtval`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine trap value
| Address     | `0x343`
| Reset value | `0x00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>>
| Description | The `mtval` CSR provides additional information why a trap was entered. See section <<_traps_exceptions_and_interrupts>> for more information.
|=======================


{empty} +
[discrete]
===== **`mip`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine interrupt pending
| Address     | `0x344`
| Reset value | `0x00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>>
| Description | The `mip` CSR shows currently _pending_ machine-mode interrupt requests. Any write access to this register is ignored.
|=======================

.`mip` CSR bits
[cols="^1,<3,^1,<9"]
[options="header",grid="rows"]
|=======================
| Bit | Name [C] | R/W | Function
| 31:16 | `CSR_MIP_FIRQ15P` : `CSR_MIP_FIRQ0P` | r/- | **FIRQxP**: Fast interrupt channel 15..0 pending, see <<_neorv32_specific_fast_interrupt_requests>>; cleared by source-specific mechanism
| 11    | `CSR_MIP_MEIP`                       | r/- | **MEIP**: Machine _external_ interrupt pending, triggered by `mti_i` top port (see <<_cpu_top_entity_signals>>) or by the processor-internal <<_core_local_interruptor_clint>>; cleared by source-specific mechanism
| 7     | `CSR_MIP_MTIP`                       | r/- | **MTIP**: Machine _timer_ interrupt pending, triggered by `mei_i` top port (see <<_cpu_top_entity_signals>>) or by the processor-internal <<_core_local_interruptor_clint>>; cleared by source-specific mechanism
| 3     | `CSR_MIP_MSIP`                       | r/- | **MSIP**: Machine _software_ interrupt pending, triggered by `msi_i` top port (see <<_cpu_top_entity_signals>>); cleared by source-specific mechanism
|=======================

.FIRQ Channel Mapping
[TIP]
See section <<_neorv32_specific_fast_interrupt_requests>> for the mapping of the FIRQ channels and the according
interrupt-triggering processor module.



<<<
// ####################################################################################################################
:sectnums:
==== Machine Configuration CSRs

[discrete]
===== **`menvcfg`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine environment configuration register - low word
| Address     | `0x30a`
| Reset value | `0x00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>> & <<_u_isa_extension,`U`>>
| Description | Currently, the features of this CSR are not supported. Hence, the entire register is hardwired to all-zero.
|=======================


{empty} +
[discrete]
===== **`menvcfgh`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine environment configuration register - high word
| Address     | `0x31a`
| Reset value | `0x00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>> & <<_u_isa_extension,`U`>>
| Description | Currently, the features of this CSR are not supported. Hence, the entire register is hardwired to all-zero.
|=======================



<<<
// ####################################################################################################################
:sectnums:
==== Machine Physical Memory Protection CSRs

The physical memory protection system is configured via the `PMP_NUM_REGIONS` and `PMP_MIN_GRANULARITY` top entity
generics. `PMP_NUM_REGIONS` defines the total number of implemented regions. Note that the maximum number of regions
is constrained to 16. If trying to access a PMP-related CSR beyond `PMP_NUM_REGIONS` (but below PMP configuration/address
register 16) **no illegal instruction exception** is triggered. The according CSRs are read-only (writes are ignored) and
always return zero. See section <<_smpmp_isa_extension>> for more information.

[discrete]
===== **`pmpcfg`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Physical memory protection region configuration registers
| Address     | `0x3a0` (`pmpcfg0`)
|             | `0x3a1` (`pmpcfg1`)
|             | `0x3a2` (`pmpcfg2`)
|             | `0x3a3` (`pmpcfg3`)
| Reset value | all `0x00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>> & <<_smpmp_isa_extension,`Smpmp`>>
| Description | Configuration of physical memory protection regions. Each region provides an individual 8-bit array in these CSRs.
Note that, depending on `PMP_NUM_REGIONS`, a **maximum** of the lowest 4 configuration registers are physically implemented (`pmpcfg0 .. pmpcfg3`).
All remaining register are hardwired to zero.
|=======================

.`pmpcfg*` CSR Bits
[cols="^1,<2,^1,<11"]
[options="header",grid="rows"]
|=======================
| Bit | Name [C] | R/W | Function
| 7   | `PMPCFG_L`     | r/w | **L**: Lock bit, prevents further write accesses, also enforces access rights in machine-mode, can only be cleared by CPU reset
| 4:3 | `PMPCFG_A_MSB` : `PMPCFG_A_LSB` | r/w | **A**: Mode configuration (`00` = OFF, `01` = TOR, `10` = NA4, `11` = NAPOT)
| 2   | `PMPCFG_X`     | r/w | **X**: Execute permission
| 1   | `PMPCFG_W`     | r/w | **W**: Write permission
| 0   | `PMPCFG_R`     | r/w | **R**: Read permission
|=======================

.Implemented Modes
[NOTE]
In order to reduce the CPU size certain PMP modes (`A` bits) can be excluded from synthesis.
Use the `PMP_TOR_MODE_EN` and `PMP_NAP_MODE_EN` <<_processor_top_entity_generics>> to control
implementation of the according modes.

{empty} +
[discrete]
===== **`pmpaddr`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Physical memory protection region address registers
| Address     | `0x3b0` (`pmpaddr1`)
|             | `0x3b1` (`pmpaddr2`)
|             | `0x3b2` (`pmpaddr3`)
|             | `0x3b3` (`pmpaddr4`)
|             | `0x3b4` (`pmpaddr5`)
|             | `0x3b5` (`pmpaddr6`)
|             | `0x3b6` (`pmpaddr6`)
|             | `0x3b7` (`pmpaddr7`)
|             | `0x3b8` (`pmpaddr8`)
|             | `0x3b9` (`pmpaddr9`)
|             | `0x3ba` (`pmpaddr10`)
|             | `0x3bb` (`pmpaddr11`)
|             | `0x3bc` (`pmpaddr12`)
|             | `0x3bd` (`pmpaddr13`)
|             | `0x3be` (`pmpaddr14`)
|             | `0x3bf` (`pmpaddr15`)
| Reset value | all `0x00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>> & <<_smpmp_isa_extension,`Smpmp`>>
| Description | Region address/boundaries configuration (address/mask bits `33:2`).
Note that, depending on `PMP_NUM_REGIONS`, a **maximum** of the lowest 16 address registers are physically implemented (`pmpaddr0 .. pmpaddr15`).
All remaining register are hardwired to zero.
|=======================

.`pmpaddr*` CSR Bits
[cols="^1,^1,<11"]
[options="header",grid="rows"]
|=======================
| Bit   | R/W | Description
| 29:0  | r/w | address bits `31 downto 2`
| 31:30 | r-w | address bits `33 downto 32`´, hardwired to zero
|=======================


<<<
// ####################################################################################################################
:sectnums:
==== (Machine) Counter and Timer CSRs

[discrete]
===== **`cycle[h]`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Cycle counter
| Address     | `0xc00` (`cycle`)
|             | `0xc80` (`cycleh`)
| Reset value | `0x00000000_00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>> & <<_zicntr_isa_extension,`Zicntr`>>
| Description | The `cycle[h]` CSRs are user-mode shadow copies of the according <<_mcycleh>> CSRs. The user-mode
counter are read-only. Any write access will raise an illegal instruction exception.
|=======================


{empty} +
[discrete]
===== **`time[h]`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | System time counter
| Address     | `0xc01` (`time`)
|             | `0xc81` (`timeh`)
| Reset value | `0x00000000_00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>> & <<_zicntr_isa_extension,`Zicntr`>>
| Description | The `time[h]` CSRs are user-mode shadow copies the memory-mapped machine timer ("MTIMER)
of the <<_core_local_interruptor_clint>>. These CSR are read-only. Any write access will raise an illegal instruction exception.
|=======================


{empty} +
[discrete]
===== **`instret[h]`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Instructions-retired counter
| Address     | `0xc02` (`instret`)
|             | `0xc82` (`instreth`)
| Reset value | `0x00000000_00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>> & <<_zicntr_isa_extension,`Zicntr`>>
| Description | The `instret[h]` CSRs are user-mode shadow copies of the according <<_minstreth>> CSRs. The user-mode
counter are read-only. Any write access will raise an illegal instruction exception.
|=======================


{empty} +
[discrete]
===== **`mcycle[h]`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine cycle counter
| Address     | `0xb00` (`mcycle`)
|             | `0xb80` (`mcycleh`)
| Reset value | `0x00000000_00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>> & <<_zicntr_isa_extension,`Zicntr`>>
| Description | If not halted via the <<_mcountinhibit>> CSR the `cycle[h]` CSRs will increment with every active CPU clock
cycle (CPU not in <<_sleep_mode>>). These registers are read/write only for machine-mode software.
|=======================


{empty} +
[discrete]
===== **`minstret[h]`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine instructions-retired counter
| Address     | `0xb02` (`minstret`)
|             | `0xb82` (`minstreth`)
| Reset value | `0x00000000_00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>> & <<_zicntr_isa_extension,`Zicntr`>>
| Description | If not halted via the <<_mcountinhibit>> CSR the `minstret[h]` CSRs will increment with every **retired** instruction.
These registers are read/write only for machine-mode software
|=======================

.Instruction Retiring
[NOTE]
According to the RISC-V specification, instructions that trigger an asynchronous exception or
are interrupted by a debug mode or an interrupt request are not considered "retired". Hence, these
events are not counted by `[m]instret[h]`.


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

The actual number of implemented hardware performance monitors is configured via the `HPM_NUM_CNTS` top entity generic,
Note that always all 29 HPM counter and configuration registers (`mhpmcounter*[h]` and `mhpmevent*`) are accessible, but
only the actually configured ones are implemented as "real" physical registers - the remaining ones will be hardwired to zero.
If trying to access an HPM-related CSR beyond `HPM_NUM_CNTS` **no illegal instruction exception is
triggered**. These CSRs are read-only, writes are ignored and reads always return zero.

The total counter width of the HPMs can be configured before synthesis via the `HPM_CNT_WIDTH` generic (0..64-bit).
If `HPM_NUM_CNTS` is less than 64, all remaining MSB-aligned bits are hardwired to zero.


[discrete]
===== **`mhpmevent`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine hardware performance monitor event select
| Address     | `0x323` ... `0x33f` (`mhpmevent3` ... `mhpmevent31`)
| Reset value | all `0x00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>> & <<_zihpm_isa_extension,`Zihpm`>>
| Description | The value in these CSRs define the micro-architectural events that cause an increment of the according `mhpmcounter*[h]` counter(s).
All available events are listed in the table below. If more than one event is enabled, the according counter will increment if _any_ of the enabled
events is observed (logical OR). Note that the counter will only increment by 1 step per clock cycle even if more than one trigger event is observed.
|=======================

.`mhpmevent*` CSR Bits (Micro-Architectural Counter Events)
[cols="^1,<3,^1,<9"]
[options="header",grid="rows"]
|=======================
| Bit | Name [C]                | R/W | Event Description
| 8   | `HPMCNT_EVENT_STORE`    | r/w | memory store operation (read-modify-write AMOs are counted as 1x load + 1x store operation)
| 7   | `HPMCNT_EVENT_LOAD`     | r/w | memory load operation (read-modify-write AMOs are counted as 1x load + 1x store operation)
| 6   | `HPMCNT_EVENT_DELTA`    | r/w | control flow transfer (jump, taken branch, trap entry/exit)
| 5   | `HPMCNT_EVENT_WAIT_LSU` | r/w | memory/bus/cache/etc. delay/wait cycle while executing any load or store operation (caused by a data bus wait cycle))
| 4   | `HPMCNT_EVENT_WAIT_ALU` | r/w | delay/wait cycle caused by a _multi-cycle_ <<_cpu_arithmetic_logic_unit>> operation (e.g. bit-serial shift)
| 3   | `HPMCNT_EVENT_WAIT_DIS` | r/w | instruction dispatch wait cycle (wait for instruction prefetch-buffer refill); caused by a fence instruction, a control flow transfer or a instruction fetch bus wait cycle (e.g. cache miss)
| 2   | `HPMCNT_EVENT_CI`       | r/w | retired compressed instruction (<<_c_isa_extension>>)
| 1   | `HPMCNT_EVENT_IR`       | r/w | retired instruction (16-bit/compressed or 32-bit/uncompressed)
| 0   | `HPMCNT_EVENT_CY`       | r/w | active clock cycle (CPU not in <<_sleep_mode>>)
|=======================

.Atomic Memory Access
[NOTE]
The read-modify-write instructions of the <<_zaamo_isa_extension>> operate as simple load for the CPU hardware.
Hence, they will only trigger `HPMCNT_EVENT_LOAD` and only once.


{empty} +
[discrete]
===== **`mhpmcounter[h]`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine hardware performance monitor (HPM) counter
| Address     | `0xb03` ... `0xb1f` (`mhpmcounter3` ... `mhpmcounter31`)
|             | `0xb83` ... `0xb9f` (`mhpmcounter3h` ... `mhpmcounter31h`)
| Reset value | all `0x00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>> & <<_zihpm_isa_extension,`Zihpm`>>
| Description | If not halted via the <<_mcountinhibit>> CSR the HPM counter CSRs increment whenever the
configured events from the according <<_mhpmevent>> CSR occur. The HPM counter registers are read/write for machine mode
software and are not accessible for lower-privileged software.
|=======================


{empty} +
[discrete]
===== **`hpmcounter[h]`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Hardware performance monitor (HPM) counter
| Address     | `0xc03` ... `0xc1f` (`hpmcounter3` ... `hpmcounter31`)
|             | `0xc83` ... `0xc9f` (`hpmcounter3h` ... `hpmcounter31h`)
| Reset value | all `0x00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>> & <<_zihpm_isa_extension,`Zihpm`>>
| Description | The `hpmcounter[h]` CSRs are user-mode shadow copies of the according <<_mhpmcounterh>> CSRs. The user-mode
counters are read-only. Any write access will raise an illegal instruction exception.
|=======================


<<<
// ####################################################################################################################
:sectnums:
==== Machine Counter Setup CSRs


[discrete]
===== **`mcountinhibit`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine counter-inhibit register
| Address     | `0x320`
| Reset value | `0x00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>>
| Description | Set bit to halt the according counter CSR.
|=======================

.`mcountinhibit` CSR Bits
[cols="^1,<3,^1,<9"]
[options="header",grid="rows"]
|=======================
| Bit | Name [C] | R/W | Description
| 15:3 | `CSR_MCOUNTINHIBIT_HPM3` : `CSR_MCOUNTINHIBIT_HPM15` | r/w | **HPMx**: Set to `1` to halt `[m]hpmcount*[h]`; hardwired to zero if `Zihpm` ISA extension is disabled
| 2    | `CSR_MCOUNTINHIBIT_CY` | r/w | **CY**: Set to `1` to halt `[m]cycle[h]`; hardwired to zero if `Zicntr` ISA extension is disabled
| 1    | -                      | r/- | **TM**: Hardwired to zero as `time[h]` CSRs are not implemented
| 0    | `CSR_MCOUNTINHIBIT_IR` | r/w | **IR**: Set to `1` to halt `[m]instret[h]`; hardwired to zero if `Zicntr` ISA extension is disabled
|=======================


{empty} +
[discrete]
===== **`mcyclecfg[h]`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine cycle counter privilege mode filtering
| Address     | `0x321` (`mcyclecfg`)
|             | `0x721` (`mcyclecfgh`)
| Reset value | all `0x00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>> & <<_zicntr_isa_extension,`Zicntr`>> & <<_smcntrpmf_isa_extension,`Smcntrpmf`>>
| Description | Halt cycle counter when CPU operates in a specific privilege mode.
Note that `mcyclecfg` is hardwired to all-zero.
|=======================

.`mcyclecfgh` CSR Bits
[cols="^1,^3,^1,<9"]
[options="header",grid="rows"]
|=======================
| Bit | Name [C] | R/W | Description
| 30  | `CSR_MCYCLECFGH_MINH` | r/w | **MINH**: Set to `1` to halt `[m]cycle[h]` counter when CPU is in machine-mode
| 28  | `CSR_MCYCLECFGH_UINH` | r/w | **UINH**: Set to `1` to halt `[m]cycle[h]` counter when CPU is in user-mode
|=======================


{empty} +
[discrete]
===== **`minstretcfg[h]`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine instret counter privilege mode filtering
| Address     | `0x322` (`minstretcfg`)
|             | `0x722` (`minstretcfgh`)
| Reset value | all `0x00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>> & <<_zicntr_isa_extension,`Zicntr`>> & <<_smcntrpmf_isa_extension,`Smcntrpmf`>>
| Description | Halt instruction-retired counter when CPU operates in a specific privilege mode.
Note that `minstretcfg` is hardwired to all-zero.
|=======================

.`minstretcfgh` CSR Bits
[cols="^1,^3,^1,<9"]
[options="header",grid="rows"]
|=======================
| Bit | Name [C] | R/W | Description
| 30  | `CSR_MINSTRETCFGH_MINH` | r/w | **MINH**: Set to `1` to halt `[m]instret[h]` counter when CPU is in machine-mode
| 28  | `CSR_MINSTRETCFGH_UINH` | r/w | **UINH**: Set to `1` to halt `[m]instret[h]` counter when CPU is in user-mode
|=======================


<<<
// ####################################################################################################################
:sectnums:
==== Machine Information CSRs

[discrete]
===== **`mvendorid`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine vendor ID
| Address     | `0xf11`
| Reset value | `0x00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>>
| Description | This register is hardwired to the value provided by the `OCD_JEDEC_ID` <<_processor_top_entity_generics>>
(the upper bits are filled with zeros).
|=======================

.`mvendorid` CSR Bits
[cols="^2,^2,<6"]
[options="header",grid="rows"]
|=======================
| Bits | R/W | Description
| 31:7 | r/- | JEDEC ID bank
| 6:0  | r/- | JEDEC ID offset
|=======================


{empty} +
[discrete]
===== **`marchid`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine architecture ID
| Address     | `0xf12`
| Reset value | `0x00000013`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>>
| Description | The `marchid` CSR is read-only and provides the NEORV32 official RISC-V open-source architecture ID
(decimal: 19, 32-bit hexadecimal: 0x00000013).
|=======================


{empty} +
[discrete]
===== **`mimpid`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine implementation ID
| Address     | `0xf13`
| Reset value | `DEFINED`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>>
| Description | The `mimpid` CSR is read-only and provides the version of the
NEORV32 as BCD-coded number (example: `mimpid = 0x01020312` → 01.02.03.12 → version 1.2.3.12).
|=======================


{empty} +
[discrete]
===== **`mhartid`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine hardware thread ID
| Address     | `0xf14`
| Reset value | `DEFINED`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>>
| Description | The `mhartid` CSR is read-only and provides the core's hart ID. In a multi-core system, the hard
ID of each core is unique and starts at 0 and is incremented continuously.
|=======================


{empty} +
[discrete]
===== **`mconfigptr`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine configuration pointer register
| Address     | `0xf15`
| Reset value | `0x00000000`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>>
| Description | The features of this CSR are not implemented yet. The register is read-only and always returns zero.
|=======================


<<<
// ####################################################################################################################
:sectnums:
==== NEORV32-Specific CSRs

.RISC-V-Compliant Mapping
[NOTE]
NEORV32-specific CSRs are mapped to addresses that are explicitly reserved for custom/implementation-specific use.


[discrete]
===== **`mxisa[h]`**

[cols="<1,<8"]
[grid="none"]
|=======================
| Name        | Machine extended ISA and extensions register
| Address     | `0xfc0` (`mxisa`, low word)
|             | `0xfc1` (`mxisah`, high word)
| Reset value | `DEFINED`
| ISA         | <<_zicsr_isa_extension,`Zicsr`>> & <<_x_isa_extension,`X`>>
| Description | The `mxisa[h]` CSRs are NEORV32-specific read-only CSRs that help machine-mode software to
discover additional ISA (sub-)extensions (beyond the _base_ extensions listed in <<_misa>>).
|=======================

.`mxisa` CSR Bits
[cols="^1,<2,^1,<6"]
[options="header",grid="rows"]
|=======================
| Bit | Name [C] | R/W | Description
| 31  | `CSR_MXISA_SMCNTRPMF` | r/- | <<_smcntrpmf_isa_extension>> available
| 30  | `CSR_MXISA_ZIMOP`     | r/- | <<_zimop_isa_extension>> available
| 29  | `CSR_MXISA_ZIBI`      | r/- | <<_zibi_isa_extension>> available
| 28  | `CSR_MXISA_ZCA`       | r/- | "`C` without floating-point", available when <<_c_isa_extension>> is available
| 27  | `CSR_MXISA_ZCB`       | r/- | <<_zcb_isa_extension>> available
| 26  | `CSR_MXISA_ZALRSC`    | r/- | <<_zalrsc_isa_extension>> available
| 25  | `CSR_MXISA_ZAAMO`     | r/- | <<_zaamo_isa_extension>> available
| 24  | `CSR_MXISA_ZBS`       | r/- | <<_zbs_isa_extension>> available
| 23  | `CSR_MXISA_ZBB`       | r/- | <<_zbb_isa_extension>> available
| 22  | `CSR_MXISA_ZBA`       | r/- | <<_zba_isa_extension>> available
| 21  | `CSR_MXISA_ZKS`       | r/- | <<_zks_isa_extension>> available
| 20  | `CSR_MXISA_ZKSED`     | r/- | <<_zksed_isa_extension>> available
| 19  | `CSR_MXISA_ZKSH`      | r/- | <<_zksh_isa_extension>> available
| 18  | `CSR_MXISA_ZKN`       | r/- | <<_zkn_isa_extension>> available
| 17  | `CSR_MXISA_ZBKC`      | r/- | <<_zbkc_isa_extension>> available
| 16  | `CSR_MXISA_ZBKB`      | r/- | <<_zbkb_isa_extension>> available
| 15  | `CSR_MXISA_ZKNH`      | r/- | <<_zknh_isa_extension>> available
| 14  | `CSR_MXISA_ZKNE`      | r/- | <<_zkne_isa_extension>> available
| 13  | `CSR_MXISA_ZKND`      | r/- | <<_zknd_isa_extension>> available
| 12  | `CSR_MXISA_ZBKX`      | r/- | <<_zbkx_isa_extension>> available
| 11  | `CSR_MXISA_SDTRIG`    | r/- | <<_sdtrig_isa_extension>> available
| 10  | `CSR_MXISA_SDEXT`     | r/- | <<_sdext_isa_extension>> available
|  9  | `CSR_MXISA_ZIHPM`     | r/- | <<_zihpm_isa_extension>> available
|  8  | `CSR_MXISA_SMPMP`     | r/- | <<_smpmp_isa_extension>> available
|  7  | `CSR_MXISA_ZICNTR`    | r/- | <<_zicntr_isa_extension>> available
|  6  | `CSR_MXISA_ZICOND`    | r/- | <<_zicond_isa_extension>> available
|  5  | `CSR_MXISA_ZFINX`     | r/- | <<_zfinx_isa_extension>> available
|  4  | `CSR_MXISA_ZKT`       | r/- | <<_zkt_isa_extension>> available
|  3  | `CSR_MXISA_XCFU`      | r/- | <<_xcfu_isa_extension>> available
|  2  | `CSR_MXISA_ZMMUL`     | r/- | <<_zmmul_isa_extension>> available
|  1  | `CSR_MXISA_ZIFENCEI`  | r/- | <<_zifencei_isa_extension>> available
|  0  | `CSR_MXISA_ZICSR`     | r/- | <<_zicsr_isa_extension>> available
|=======================

.`mxisah` CSR Bits
[cols="^1,<2,^1,<6"]
[options="header",grid="rows"]
|=======================
| Bit | Name [C] | R/W | Description
| 31:2 | -                  | r/- | _reserved_, read as zero
|    1 | `CSR_MXISAH_ZCMOP` | r/- | <<_zcmop_isa_extension>> available
|    0 | `CSR_MXISAH_ZBC`   | r/- | <<_zbc_isa_extension>> available
|=======================
