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

Subversion Repositories neorv32

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /neorv32/trunk
    from Rev 72 to Rev 73
    Reverse comparison

Rev 72 → Rev 73

/docs/datasheet/cpu.adoc
3,10 → 3,21
 
image::neorv32_cpu_block.png[width=600,align=center]
 
**Section Structure**
 
* <<_architecture>>, <<_full_virtualization>> and <<_risc_v_compatibility>>
* <<_cpu_top_entity_signals>> and <<_cpu_top_entity_generics>>
* <<_instruction_sets_and_extensions>>, <<_custom_functions_unit_cfu>> and <<_instruction_timing>>
* <<_control_and_status_registers_csrs>>
* <<_traps_exceptions_and_interrupts>>
* <<_bus_interface>>
 
 
**Key Features**
 
* 32-bit multi-cycle in-order `rv32` RISC-V CPU
* Optional RISC-V extensions:
* 32-bit little-endian, multi-cycle, in-order `rv32` RISC-V CPU
* Compatible to the RISC-V. **Privileged Architecture - Machine ISA Version 1.12** specifications
* Available <<_instruction_sets_and_extensions>>:
** `A` - atomic memory access operations
** `B` - bit-manipulation instructions
** `C` - 16-bit compressed instructions
22,18 → 33,15
** `Zmmul` - integer multiplication hardware
** `Zxcfu` - custom instructions extension
** `PMP` - physical memory protection
** `Debug` - debug mode (part of the on.chip debugger) including hardware trigger module
* Compatible to the RISC-V user specifications and a subset of the RISC-V privileged architecture specifications - passes the official RISC-V Architecture Tests (v2+)
** `Debug` - <<_cpu_debug_mode>> (part of the on.chip debugger) including hardware <<_trigger_module>>
* <<_risc_v_compatibility>>: Compatible to the RISC-V user specifications and a subset of the RISC-V privileged architecture specifications - passes the official RISC-V Architecture Tests (v2+)
* Official RISC-V open-source architecture ID
* Standard RISC-V interrupts (_external_, _timer_, _software_) plus 16 _fast_ interrupts
* Supports _all_ of the machine-level traps from the RISC-V specifications (including bus access exceptions and all unimplemented/illegal/malformed instructions)
* Supports _all_ of the machine-level <<_traps_exceptions_and_interrupts>> from the RISC-V specifications (including bus access exceptions and all unimplemented/illegal/malformed instructions)
** This is a special aspect on _execution safety_ by <<_full_virtualization>>
** Standard RISC-V interrupts (_external_, _timer_, _software_) plus 16 custom _fast_ interrupts
* Optional physical memory configuration (PMP), compatible to the RISC-V specifications
* Optional hardware performance monitors (HPM) for application benchmarking
* Separated interfaces for instruction fetch and data access (merged into a single processor bus))
* little-endian byte order
* Configurable hardware reset
* No hardware support of unaligned data/instruction accesses - they will trigger an exception.
* Separated <<_bus_interface>>s for instruction fetch and data access
 
[NOTE]
It is recommended to use the **NEORV32 Processor** as default top instance even if you only want to use the actual
251,19 → 259,20
:sectnums:
==== RISC-V Incompatibility Issues and Limitations
 
This list shows the currently identified issues regarding full RISC-V-compatibility. More specific information
can be found in section <<_instruction_sets_and_extensions>>.
This list shows the currently identified issues regarding full RISC-V-compatibility.
 
.Read-Only "Read-Write" CSRs
[IMPORTANT]
The <<_misa>> and <<_mtval>> CSRs in the NEORV32 are _read-only_.
Any machine-mode write access to them is ignored and will _not_ cause any exceptions or side-effects to maintain
RISC-V compatibility.
Any machine-mode write access to them is ignored and will _not_ cause any exceptions or
side-effects to maintain RISC-V compatibility.
 
.Physical Memory Protection
[IMPORTANT]
The physical memory protection (see section <<_machine_physical_memory_protection_csrs>>)
only supports the modes _OFF_ and _NAPOT_ yet and a minimal granularity of 8 bytes per region.
The RISC-V-compatible NEORV32 <<_machine_physical_memory_protection_csrs>> only implements the **TOR**
(top of region) mode and only up to 16 PMP regions. Furthermore, the <<_pmpcfg>>'s _lock bits_ only lock
the according PMP entry and not the entries below. All region rules are checked in parallel **without**
prioritization so for identical memory regions the most restrictive PMP rule will be enforced.
 
.Atomic Memory Operations
[IMPORTANT]
270,7 → 279,13
The `A` CPU extension only implements the `lr.w` and `sc.w` instructions yet.
However, these instructions are sufficient to emulate all further atomic memory operations.
 
.No HW-Support of Misaligned Memory Accesses
[WARNING]
The CPU does not support the resolution of unaligned memory access by the hardware. This is not a
RISC-V-compatibility issue but an important thing to know. Any kind of unaligned memory access
will raise an exception to allow a software-based emulation.
 
 
<<<
// ####################################################################################################################
:sectnums:
284,14 → 299,14
[cols="<2,^1,^1,<6"]
[options="header", grid="rows"]
|=======================
| Signal | Width | Dir. | Function
| Signal | Width | Dir. | Description
4+^| **Global Signals**
| `clk_i` | 1 | in | global clock line, all registers triggering on rising edge
| `rstn_i` | 1 | in | global reset, low-active
| `sleep_o` | 1 | out | CPU is in sleep mode when set
| `debug_o` | 1 | out | CPU is in debug mode when set
4+^| **Instruction Bus Interface (<<_bus_interface>>)**
| `i_bus_addr_o` | 32 | out | destination address
4+^| **Instruction <<_bus_interface>>**
| `i_bus_addr_o` | 32 | out | access address
| `i_bus_rdata_i` | 32 | in | read data
| `i_bus_wdata_o` | 32 | out | write data (always zero)
| `i_bus_ben_o` | 4 | out | byte enable
300,10 → 315,10
| `i_bus_lock_o` | 1 | out | exclusive access request (always zero)
| `i_bus_ack_i` | 1 | in | bus transfer acknowledge from accessed peripheral
| `i_bus_err_i` | 1 | in | bus transfer terminate from accessed peripheral
| `i_bus_fence_o` | 1 | out | indicates an executed _fence.i_ instruction
| `i_bus_priv_o` | 2 | out | current CPU privilege level
4+^| **Data Bus Interface (<<_bus_interface>>)**
| `d_bus_addr_o` | 32 | out | destination address
| `i_bus_fence_o` | 1 | out | indicates an executed `fence.i` instruction
| `i_bus_priv_o` | 1 | out | current _effective_ CPU privilege level (`0` user, `1` machine or debug)
4+^| **Data <<_bus_interface>>**
| `d_bus_addr_o` | 32 | out | access address
| `d_bus_rdata_i` | 32 | in | read data
| `d_bus_wdata_o` | 32 | out | write data
| `d_bus_ben_o` | 4 | out | byte enable
312,15 → 327,15
| `d_bus_lock_o` | 1 | out | exclusive access request
| `d_bus_ack_i` | 1 | in | bus transfer acknowledge from accessed peripheral
| `d_bus_err_i` | 1 | in | bus transfer terminate from accessed peripheral
| `d_bus_fence_o` | 1 | out | indicates an executed _fence_ instruction
| `d_bus_priv_o` | 2 | out | current CPU privilege level
4+^| **System Time (see <<_timeh>> CSR)**
| `time_i` | 64 | in | system time input (from MTIME)
| `d_bus_fence_o` | 1 | out | indicates an executed `fence` instruction
| `d_bus_priv_o` | 1 | out | current _effective_ CPU privilege level (`0` user, `1` machine or debug)
4+^| **System Time (for <<_timeh>> CSR)**
| `time_i` | 64 | in | system time input from <<_machine_system_timer_mtime>>
4+^| **Interrupts, RISC-V-compatible (<<_traps_exceptions_and_interrupts>>)**
| `msw_irq_i` | 1 | in | RISC-V machine software interrupt
| `mext_irq_i` | 1 | in | RISC-V machine external interrupt
| `mtime_irq_i` | 1 | in | RISC-V machine timer interrupt
4+^| **Fast Interrupts, NEORV32-specific (<<_traps_exceptions_and_interrupts>>)**
4+^| **Interrupts, NEORV32-specific (<<_traps_exceptions_and_interrupts>>)**
| `firq_i` | 16 | in | fast interrupt request signals
4+^| **Enter Debug Mode Request (<<_on_chip_debugger_ocd>>)**
| `db_halt_req_i` | 1 | in | request CPU to halt and enter debug mode
339,7 → 354,7
[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **CPU_BOOT_ADDR** | _std_ulogic_vector(31 downto 0)_ | -
| **CPU_BOOT_ADDR** | _std_ulogic_vector(31 downto 0)_ | _no default value_
3+| This address defines the reset address at which the CPU starts fetching instructions after reset. In terms of the NEORV32 processor, this
generic is configured with the base address of the bootloader ROM (default) or with the base address of the processor-internal instruction
memory (IMEM) if the bootloader is disabled (_INT_BOOTLOADER_EN_ = _false_). See section <<_address_space>> for more information.
348,7 → 363,7
[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **CPU_DEBUG_ADDR** | _std_ulogic_vector(31 downto 0)_ | -
| **CPU_DEBUG_ADDR** | _std_ulogic_vector(31 downto 0)_ | _no default value_
3+| This address defines the entry address for the "execution based" on-chip debugger. By default, this generic is configured with the base address
of the debugger memory. See section <<_on_chip_debugger_ocd>> for more information.
|======
356,7 → 371,7
[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **CPU_EXTENSION_RISCV_DEBUG** | _boolean_ | -
| **CPU_EXTENSION_RISCV_DEBUG** | _boolean_ | _no default value_
3+| Implement RISC-V-compatible "debug" CPU operation mode. See section <<_cpu_debug_mode>> for more information.
|======
 
515,11 → 530,16
 
[NOTE]
By default, multiplication and division operations are executed in a bit-serial approach.
Alternatively, the multiplier core can be implemented using DSP blocks if the `FAST_MUL_EN`
Alternatively, the multiplier core can be implemented using DSP blocks if the <<_fast_mul_en>>
generic is _true_ allowing faster execution. Multiplications and divisions
always require a fixed amount of cycles to complete - regardless of the input operands.
 
[NOTE]
Regardless of the setting of the <<_fast_mul_en>> generic
multiplication and division instructions operate _independently_ of the input operands.
Hence, there is **no early completion** of multiply by one/zero and divide by zero operations.
 
 
==== **`Zmmul`** - Integer Multiplication
 
This is a _sub-extension_ of the `M` ISA extension. It implements the multiplication-only operations
549,15 → 569,19
peripheral/IO devices) can be constrained via the physical memory protection (_PMP_).
Any kind of privilege rights violation will raise an exception to allow <<_full_virtualization>>.
 
Additional CSRs:
 
* <<_mcounteren>> - machine counter enable to constrain user-mode access to timer/counter CSRs
 
 
==== **`X`** - NEORV32-Specific (Custom) Extensions
 
The NEORV32-specific extensions are always enabled and are indicated by the set `X` bit in the <<_misa>> CSR.
 
The most important points of the NEORV32-specific extensions are:
* The CPU provides 16 _fast interrupt_ interrupts (`FIRQ)`, which are controlled via custom bits in the `mie`
and <<_mip>> CSR. This extension is mapped to CSR bits, that are available for custom use (according to the
RISC-V specs). Also, custom trap codes for <<_mcause>> are implemented.
* The CPU provides 16 _fast interrupt_ interrupts (`FIRQ`), which are controlled via custom bits in the <<_mie>>
and <<_mip>> CSRs. These extensions are mapped to CSR bits, that are available for custom use according to the
RISC-V specs. Also, custom trap codes for <<_mcause>> are implemented.
* All undefined/unimplemented/malformed/illegal instructions do raise an illegal instruction exception (see <<_full_virtualization>>).
* There are <<_neorv32_specific_csrs>>.
 
584,8 → 608,14
* sign-injection: `fsgnj.s` `fsgnjn.s` `fsgnjx.s`
* number classification: `fclass.s`
 
* additional CSRs: <<_fcsr>>, <<_frm>>, <<_fflags>>
* compressed instructions: `c.flw` `c.flwsp` `c.fsw` `c.fswsp`
 
Additional CSRs:
 
* <<_fcsr>> - FPU control register
* <<_frm>> - rounding mode control
* <<_fflags>> - FPU status flags
 
[WARNING]
Fused multiply-add instructions `f[n]m[add/sub].s` are not supported!
Division `fdiv.s` and square root `fsqrt.s` instructions are not supported yet!
623,13 → 653,15
However, access privileges are still enforced so these instruction variants _do_ cause side-effects
(the RISC-V spec. state that these combinations "_shall_ not cause any side-effects").
 
[NOTE]
** `wfi` Instruction **
 
The "wait for interrupt instruction" `wfi` acts like a sleep command. When executed, the CPU is
halted until a valid interrupt request occurs. To wake up again, the according interrupt source has to
halted until a valid interrupt request occurs. To wake up again, at least one interrupt source has to
be enabled via the <<_mie>> CSR and the global interrupt enable flag in <<_mstatus>> has to be set.
The `wfi` instruction may also be executed in user-mode without causing an exception as <<_mstatus>> bit
`TW` (timeout wait) is _hardwired_ to zero.
 
If the <<_mstatus>> `TW` bis is cleared the `wfi` instruction is also allowed to execute when in user-mode.
This is always the case if user-mode is not implemented. If the `TW` bit is set the execution of `wfi` in
user-mode will raise an illegal instruction exception.
 
 
==== **`Zicntr`** CPU Base Counters
639,6 → 671,12
these counters. Section <<_machine_counter_and_timer_csrs>> shows a list of all `Zicntr`-related CSRs.
These are available if the `Zicntr` ISA extensions is enabled via the <<_cpu_extension_riscv_zicntr>> generic.
 
Additional CSRs:
 
* <<_cycleh>>, <<_mcycleh>> - cycle counter
* <<_instreth>>, <<_minstreth>> - instructions-retired counter
* <<_timeh>> - system _wall-clock_ time
 
[NOTE]
Disabling the `Zicntr` extension does not remove the `time[h]`-driving MTIME unit.
 
645,7 → 683,6
If `Zicntr` is disabled, all accesses to the according counter CSRs will raise an illegal instruction exception.
 
 
 
==== **`Zihpm`** Hardware Performance Monitors
 
In additions to the base cycle, instructions-retired and time counters the NEORV32 CPU provides
655,25 → 692,22
CSR defines the architectural events that lead to an increment of the associated HPM counter.
 
The HPM counters are available if the `Zihpm` ISA extensions is enabled via the <<_cpu_extension_riscv_zihpm>> generic.
The actual number of implemented HPM counters is defined by the <<_hpm_num_cnts>> generic.
 
Depending on the configuration the following additional CSR are available:
Additional CSRs:
 
* counters: `mhpmcounter*[h]` (3..31, depending on `HPM_NUM_CNTS`)
* event configuration: `mhpmevent*` (3..31, depending on `HPM_NUM_CNTS`)
* <<_mhpmevent>> 3..31 (depending on <<_hpm_num_cnts>>) - event configuration CSRs
* <<_mhpmcounterh>> 3..31 (depending on <<_hpm_num_cnts>>) - counter CSRs
 
[IMPORTANT]
The HPM counter CSR can only be accessed in machine-mode. Hence, the according <<_mcounteren>> CSR bits
The HPM counter CSRs can only be accessed in machine-mode. Hence, the according <<_mcounteren>> CSR bits
are always zero and read-only. Any access from less-privileged modes will raise an illegal instruction
exception.
 
[TIP]
Auto-increment of the HPMs can be individually deactivated via the <<_mcountinhibit>> CSR.
Auto-increment of the HPMs can be deactivated individually via the <<_mcountinhibit>> CSR.
 
[TIP]
For a list of all HPM-related CSRs and all provided event configurations
see section <<_hardware_performance_monitors_hpm>>.
 
 
==== **`Zifencei`** Instruction Stream Synchronization
 
The `Zifencei` CPU extension is implemented if the <<_cpu_extension_riscv_zifencei>> configuration
713,31 → 747,59
 
==== **`PMP`** Physical Memory Protection
 
The NEORV32 physical memory protection (PMP) is compatible to the RISC-V PMP specifications. It can be used
to constrain memory read/write/execute rights for each available privilege level.
The NEORV32 physical memory protection (PMP) provides an elementary memory protection mechanism that can be used
to constrain read, write and execute rights of arbitrary memory regions. The PMP is compatible
to the _RISC-V Privileged Architecture Specifications_. For detailed information see the according spec.'s sections.
 
The NEORV32 PMP only supports _NAPOT_ mode yet and a minimal region size (granularity) of 8 bytes. Larger
minimal sizes can be configured via the top `PMP_MIN_GRANULARITY` generic to reduce hardware requirements.
The physical memory protection system is implemented when the `PMP_NUM_REGIONS` configuration generic is >0.
In this case the following additional CSRs are available:
[IMPORTANT]
The NEORV32 PMP only supports **TOR** (top of region) mode, which basically is a "base-and-bound" concept, and only
up to 16 PMP regions.
 
* `pmpcfg*` (0..15, depending on configuration): PMP configuration registers
* `pmpaddr*` (0..63, depending on configuration): PMP address registers
The physical memory protection logic is implemented if the <<_pmp_num_regions>> configuration generic is greater
than zero. This generic also defines the total number of available configurable protection
regions. The minimal granularity of a protected region is defined by the <<_pmp_min_granularity>> generic. Larger
granularity will reduce hardware complexity but will also decrease granularity as the minimal region sizes increases.
The default value is 4 bytes, which allows a minimal region size of 4 bytes.
 
If implemented the PMP provides the following additional CSRs:
 
* <<_pmpcfg>> 0..3 (depending on configuration) - PMP configuration registers, 4 entries per CSR
* <<_pmpaddr>> 0..15 (depending on configuration) - PMP address registers
 
 
**Operation Summary**
 
Any CPU access address (from the instruction fetch or data access interface) is tested if it matches _any_
of the specified PMP regions. If there is a match, the configured access rights are enforced:
 
* a write access (store) will fail if no **write** attribute is set
* a read access (load) will fail if no **read** attribute is set
* an instruction fetch access will fail if no **execute** attribute is set
 
If an access to a protected region does not have the according access rights it will raise the according
instruction/load/store _bus access fault_ exception.
 
By default, all PMP checks are enforced for user-mode only. However, PMP rules can also be enforced for
machine-mode when the according PMP region has the "LOCK" bit set. This will also prevent any write access
to according region's PMP CSRs until the CPU is reset.
 
.Rule Prioritization
[IMPORTANT]
All rules are checked in parallel **without** prioritization so for identical memory regions the most restrictive
PMP rule will be enforced.
 
.PMP Example Program
[TIP]
See section <<_machine_physical_memory_protection_csrs>> for more information regarding the PMP CSRs.
A simple PMP example program can be found in `sw/example/demo_pmp`.
 
The actual number of regions and the minimal region granularity are defined via the top entity
`PMP_MIN_GRANULARITY` and `PMP_NUM_REGIONS` generics. `PMP_MIN_GRANULARITY` defines the minimal available
granularity of each region in bytes. `PMP_NUM_REGIONS` defines the total number of implemented regions and thus, the
number of available `pmpcfg*` and `pmpaddr*` CSRs.
 
When implementing more PMP regions that a _certain critical limit_ *an additional register stage
is automatically inserted* into the CPU's memory interfaces to reduce critical path length. Unfortunately, this will also
increase the latency of instruction fetches and data access by +1 cycle.
**Impact on Critical Path**
 
The critical limit can be adapted for custom use by a constant from the main VHDL package file
(`rtl/core/neorv32_package.vhd`). The default value is 8:
When implementing more PMP regions that a "_certain critical limit_" an **additional register stage** is automatically
inserted into the CPU's memory interfaces to keep impact on the critical path as short as minimal as possible.
Unfortunately, this will also increase the latency of instruction fetches and data access by one cycle.
The _critical limit_ can be modified by a constant from the main VHDL package file
(`rtl/core/neorv32_package.vhd`, default value = 8):
 
[source,vhdl]
----
745,33 → 807,17
constant pmp_num_regions_critical_c : natural := 8;
----
 
**Operation**
[TIP]
Reducing the minimal PMP region size / granularity via the <<_pmp_min_granularity>> to entity generic
will also reduce hardware utilization and impact on critical path.
 
Any CPU memory access address (from the instruction fetch or data access interface) is tested if it is accessing _any_
of the specified PMP regions(configured via `pmpaddr*` and enabled via `pmpcfg*`). If an
address matches one of these regions, the configured access rights (attributes in `pmpcfg*`) are enforced:
 
* a write access (store) will fail if no write attribute is set
* a read access (load) will fail if no read attribute is set
* an instruction fetch access will fail if no execute attribute is set
<<<
// ####################################################################################################################
 
If an access to a protected region does not have the according access rights it will raise the according
instruction/load/store _access fault_ exception.
include::cpu_cfu.adoc[]
 
By default, all PMP checks are enforced for user-level programs only. If you wish to enforce the physical
memory protection also for machine-level programs you need to set the _locked bit_ in the according
`pmpcfg*` configuration CSR.
 
[IMPORTANT]
After updating the address configuration registers `pmpaddr*` the system requires up to 33 cycles for
internal (iterative) computations before the configuration becomes valid.
 
[NOTE]
For more information regarding RISC-V physical memory protection see the official _The RISC-V
Instruction Set Manual - Volume II: Privileged Architecture_ specifications.
 
 
 
<<<
// ####################################################################################################################
:sectnums:
789,41 → 835,43
[options="header", grid="rows"]
|=======================
| Class | ISA | Instruction(s) | Execution cycles
| ALU | `I/E` | `addi` `slti` `sltiu` `xori` `ori` `andi` `add` `sub` `slt` `sltu` `xor` `or` `and` `lui` `auipc` | 2
| ALU | `C` | `c.addi4spn` `c.nop` `c.addi` `c.li` `c.addi16sp` `c.lui` `c.andi` `c.sub` `c.xor` `c.or` `c.and` `c.add` `c.mv` | 2
| ALU | `I/E` | `slli` `srli` `srai` `sll` `srl` `sra` | 3 + SAfootnote:[Shift amount.]/4 + SA%4; FAST_SHIFTfootnote:[Barrel shift when `FAST_SHIFT_EN` is enabled.]: 4; TINY_SHIFTfootnote:[Serial shift when `TINY_SHIFT_EN` is enabled.]: 2..32
| ALU | `C` | `c.srli` `c.srai` `c.slli` | 3 + SAfootnote:[Shift amount (0..31).]; FAST_SHIFTfootnote:[Barrel shifter when `FAST_SHIFT_EN` is enabled.]:
| Branches | `I/E` | `beq` `bne` `blt` `bge` `bltu` `bgeu` | Taken: 5 + MLfootnote:[Memory latency.]; Not taken: 3
| Branches | `C` | `c.beqz` `c.bnez` | Taken: 5 + MLfootnote:[Memory latency.]; Not taken: 3
| Jumps / Calls | `I/E` | `jal` `jalr` | 4 + ML
| Jumps / Calls | `C` | `c.jal` `c.j` `c.jr` `c.jalr` | 4 + ML
| Memory access | `I/E` | `lb` `lh` `lw` `lbu` `lhu` `sb` `sh` `sw` | 4 + ML
| Memory access | `C` | `c.lw` `c.sw` `c.lwsp` `c.swsp` | 4 + ML
| Memory access | `A` | `lr.w` `sc.w` | 4 + ML
| Multiplication | `M` | `mul` `mulh` `mulhsu` `mulhu` | 2+32+2; FAST_MULfootnote:[DSP-based multiplication; enabled via `FAST_MUL_EN`.]: 4
| Division | `M` | `div` `divu` `rem` `remu` | 2+32+2
| CSR access | `Zicsr` | `csrrw` `csrrs` `csrrc` `csrrwi` `csrrsi` `csrrci` | 4
| System | `I/E`+`Zicsr` | `ecall` `ebreak` | 4
| System | `I/E` | `fence` | 3
| System | `C`+`Zicsr` | `c.break` | 4
| System | `Zicsr` | `mret` `wfi` | 5
| System | `Zifencei` | `fence.i` | 3 + ML
| ALU | `I/E` | `addi` `slti` `sltiu` `xori` `ori` `andi` `add` `sub` `slt` `sltu` `xor` `or` `and` `lui` `auipc` | 2
| ALU | `C` | `c.addi4spn` `c.nop` `c.addi` `c.li` `c.addi16sp` `c.lui` `c.andi` `c.sub` `c.xor` `c.or` `c.and` `c.add` `c.mv` | 2
| ALU | `I/E` | `slli` `srli` `srai` `sll` `srl` `sra` | 3 + SAfootnote:[Shift amount.]/4 + SA%4; FAST_SHIFTfootnote:[Barrel shift when `FAST_SHIFT_EN` is enabled.]: 4; TINY_SHIFTfootnote:[Serial shift when `TINY_SHIFT_EN` is enabled.]: 2..32
| ALU | `C` | `c.srli` `c.srai` `c.slli` | 3 + SAfootnote:[Shift amount (0..31).]; FAST_SHIFTfootnote:[Barrel shifter when `FAST_SHIFT_EN` is enabled.]:
| Branches | `I/E` | `beq` `bne` `blt` `bge` `bltu` `bgeu` | Taken: 5 + MLfootnote:[Memory latency.]; Not taken: 3
| Branches | `C` | `c.beqz` `c.bnez` | Taken: 5 + MLfootnote:[Memory latency.]; Not taken: 3
| Jumps / Calls | `I/E` | `jal` `jalr` | 4 + ML
| Jumps / Calls | `C` | `c.jal` `c.j` `c.jr` `c.jalr` | 4 + ML
| Memory access | `I/E` | `lb` `lh` `lw` `lbu` `lhu` `sb` `sh` `sw` | 4 + ML
| Memory access | `C` | `c.lw` `c.sw` `c.lwsp` `c.swsp` | 4 + ML
| Memory access | `A` | `lr.w` `sc.w` | 4 + ML
| Multiplication | `M` | `mul` `mulh` `mulhsu` `mulhu` | 2+32+2; FAST_MULfootnote:[DSP-based multiplication; enabled via `FAST_MUL_EN`.]: 4
| Division | `M` | `div` `divu` `rem` `remu` | 2+32+2
| CSR access | `Zicsr` | `csrrw` `csrrs` `csrrc` `csrrwi` `csrrsi` `csrrci` | 3
| System | `I/E` | `fence` | 3
| System | `Zicsr` | `ecall` `ebreak` | 3
| System | `Zicsr`+`C` | `c.break` | 3
| System | `Zicsr` | `mret` `wfi` | 6
| System | `Zifencei` | `fence.i` | 3 + ML
| Floating-point - artihmetic | `Zfinx` | `fadd.s` | 110
| Floating-point - artihmetic | `Zfinx` | `fsub.s` | 112
| Floating-point - artihmetic | `Zfinx` | `fmul.s` | 22
| Floating-point - compare | `Zfinx` | `fmin.s` `fmax.s` `feq.s` `flt.s` `fle.s` | 13
| Floating-point - misc | `Zfinx` | `fsgnj.s` `fsgnjn.s` `fsgnjx.s` `fclass.s` | 12
| Floating-point - compare | `Zfinx` | `fmin.s` `fmax.s` `feq.s` `flt.s` `fle.s` | 13
| Floating-point - misc | `Zfinx` | `fsgnj.s` `fsgnjn.s` `fsgnjx.s` `fclass.s` | 12
| Floating-point - conversion | `Zfinx` | `fcvt.w.s` `fcvt.wu.s` | 47
| Floating-point - conversion | `Zfinx` | `fcvt.s.w` `fcvt.s.wu` | 48
| Bit-manipulation - arithmetic/logic | `B(Zbb)` | `sext.b` `sext.h` `min` `minu` `max` `maxu` `andn` `orn` `xnor` `zext`(pack) `rev8`(grevi) `orc.b`(gorci) | 3
| Bit-manipulation - arithmetic/logic | `B(Zba)` | `sh1add` `sh2add` `sh3add` | 3
| Bit-manipulation - shifts | `B(Zbb)` | `clz` `ctz` | 3 + 0..32
| Bit-manipulation - shifts | `B(Zbb)` | `cpop` | 3 + 32
| Bit-manipulation - shifts | `B(Zbb)` | `rol` `ror` `rori` | 3 + SA
| Bit-manipulation - single-bit | `B(Zbs)` | `sbset[i]` `sbclr[i]` `sbinv[i]` `sbext[i]` | 3
| Bit-manipulation - shifted-add | `B(Zba)` | `sh1add` `sh2add` `sh3add` | 3
| Bit-manipulation - arithmetic/logic | `B(Zbb)` | `sext.b` `sext.h` `min` `minu` `max` `maxu` `andn` `orn` `xnor` `zext`(pack) `rev8`(grevi) `orc.b`(gorci) | 3
| Bit-manipulation - arithmetic/logic | `B(Zba)` | `sh1add` `sh2add` `sh3add` | 3
| Bit-manipulation - shifts | `B(Zbb)` | `clz` `ctz` | 3 + 0..32
| Bit-manipulation - shifts | `B(Zbb)` | `cpop` | 3 + 32
| Bit-manipulation - shifts | `B(Zbb)` | `rol` `ror` `rori` | 3 + SA
| Bit-manipulation - single-bit | `B(Zbs)` | `sbset[i]` `sbclr[i]` `sbinv[i]` `sbext[i]` | 3
| Bit-manipulation - shifted-add | `B(Zba)` | `sh1add` `sh2add` `sh3add` | 3
| Bit-manipulation - carry-less multiply | `B(Zbc)` | `clmul` `clmulh` `clmulr` | 3 + 32
| CFU: custom instructions | `Zxcfu` | - | min. 4
| Custom instructions (CFU) | `Zxcfu` | - | min. 4
| | | |
| _Illegal instructions_ | `Zicsr` | - | 2
|=======================
 
[NOTE]
867,8 → 915,8
.Interrupt Signal Requirements - Fast Interrupt Requests
[IMPORTANT]
The NEORV32-specific FIRQ request lines are triggered by a one-shot high-level (i.e. rising edge). Each request is buffered in the CPU control
unit until the channel is either disabled (by clearing the according <<_mie>> CSR bit) or the request is explicitly cleared (by setting
the according <<_mip>> CSR bit).
unit until the channel is either disabled (by clearing the according <<_mie>> CSR bit) or the request is explicitly cleared (by writing
zero to the according <<_mip>> CSR bit).
 
.Instruction Atomicity
[NOTE]
878,7 → 926,7
 
 
:sectnums:
==== Memory Access Exceptions
===== Memory Access Exceptions
 
If a load operation causes any exception, the instruction's destination register is
_not written_ at all. Load exceptions caused by a misalignment or a physical memory protection fault do not
887,7 → 935,7
 
 
:sectnums:
==== Custom Fast Interrupt Request Lines
===== Custom Fast Interrupt Request Lines
 
As a custom extension, the NEORV32 CPU features 16 fast interrupt request (FIRQ) lines via the `firq_i` CPU top
entity signals. These interrupts have custom configuration and status flags in the <<_mie>> and <<_mip>> CSRs and also
894,11 → 942,8
provide custom trap codes in <<_mcause>>. These FIRQs are reserved for NEORV32 processor-internal usage only.
 
 
 
<<<
// ####################################################################################################################
:sectnums:
==== NEORV32 Trap Listing
===== NEORV32 Trap Listing
 
The following table shows all traps that are currently supported by the NEORV32 CPU. It also shows the prioritization
and the CSR side-effects. A more detailed description of the actual trap triggering events is provided in a further table.
911,50 → 956,51
 
The "Prio." column shows the priority of each trap. The highest priority is 1. The "`mcause`" column shows the
cause ID of the according trap that is written to <<_mcause>> CSR. The "[RISC-V]" columns show the interrupt/exception code value from the
official RISC-V privileged architecture manual. The "[C]" names are defined by the NEORV32 core library (the runtime environment _RTE_) and can
be used in plain C code. The "`mepc`" and "`mtval`" columns show the value written to
<<_mepc>> and <<_mtval>> CSRs when a trap is triggered:
official RISC-V privileged architecture spec. The "ID [C]" names are defined by the NEORV32 core library (the runtime environment _RTE_) and can
be used in plain C code. The "`mepc`" and "`mtval`" columns show the value written to <<_mepc>> and <<_mtval>> CSRs when a trap is triggered:
 
* _I-PC_ - address of interrupted instruction (instruction has not been execute/completed yet)
* _B-ADR_- bad memory access address that cause the trap
* _PC_ - address of instruction that caused the trap
* _0_ - zero
* _Inst_ - the faulting instruction itself
* **IPC** - address of interrupted instruction (instruction has not been executed yet)
* **PC** - address of instruction that caused the trap
* **ADR** - bad memory access address that caused the trap
* **INST** - the faulting instruction word itself
* **0** - zero
 
.NEORV32 Trap Listing
[cols="3,6,5,14,11,4,4"]
[options="header",grid="rows"]
|=======================
| Prio. | `mcause` | [RISC-V] | ID [C] | Cause | `mepc` | `mtval`
| 1 | `0x00000000` | 0.0 | _TRAP_CODE_I_MISALIGNED_ | instruction address misaligned | _B-ADR_ | _PC_
| 2 | `0x00000001` | 0.1 | _TRAP_CODE_I_ACCESS_ | instruction access fault | _B-ADR_ | _PC_
| 3 | `0x00000002` | 0.2 | _TRAP_CODE_I_ILLEGAL_ | illegal instruction | _PC_ | _Inst_
| 4 | `0x0000000B` | 0.11 | _TRAP_CODE_MENV_CALL_ | environment call from M-mode (`ecall` in machine-mode) | _PC_ | _PC_
| 5 | `0x00000008` | 0.8 | _TRAP_CODE_UENV_CALL_ | environment call from U-mode (`ecall` in user-mode) | _PC_ | _PC_
| 6 | `0x00000003` | 0.3 | _TRAP_CODE_BREAKPOINT_ | breakpoint (`ebreak`) | _PC_ | _PC_
| 7 | `0x00000006` | 0.6 | _TRAP_CODE_S_MISALIGNED_ | store address misaligned | _B-ADR_ | _B-ADR_
| 8 | `0x00000004` | 0.4 | _TRAP_CODE_L_MISALIGNED_ | load address misaligned | _B-ADR_ | _B-ADR_
| 9 | `0x00000007` | 0.7 | _TRAP_CODE_S_ACCESS_ | store access fault | _B-ADR_ | _B-ADR_
| 10 | `0x00000005` | 0.5 | _TRAP_CODE_L_ACCESS_ | load access fault | _B-ADR_ | _B-ADR_
| 11 | `0x80000010` | 1.16 | _TRAP_CODE_FIRQ_0_ | fast interrupt request channel 0 | _I-PC_ | _0_
| 12 | `0x80000011` | 1.17 | _TRAP_CODE_FIRQ_1_ | fast interrupt request channel 1 | _I-PC_ | _0_
| 13 | `0x80000012` | 1.18 | _TRAP_CODE_FIRQ_2_ | fast interrupt request channel 2 | _I-PC_ | _0_
| 14 | `0x80000013` | 1.19 | _TRAP_CODE_FIRQ_3_ | fast interrupt request channel 3 | _I-PC_ | _0_
| 15 | `0x80000014` | 1.20 | _TRAP_CODE_FIRQ_4_ | fast interrupt request channel 4 | _I-PC_ | _0_
| 16 | `0x80000015` | 1.21 | _TRAP_CODE_FIRQ_5_ | fast interrupt request channel 5 | _I-PC_ | _0_
| 17 | `0x80000016` | 1.22 | _TRAP_CODE_FIRQ_6_ | fast interrupt request channel 6 | _I-PC_ | _0_
| 18 | `0x80000017` | 1.23 | _TRAP_CODE_FIRQ_7_ | fast interrupt request channel 7 | _I-PC_ | _0_
| 19 | `0x80000018` | 1.24 | _TRAP_CODE_FIRQ_8_ | fast interrupt request channel 8 | _I-PC_ | _0_
| 20 | `0x80000019` | 1.25 | _TRAP_CODE_FIRQ_9_ | fast interrupt request channel 9 | _I-PC_ | _0_
| 21 | `0x8000001a` | 1.26 | _TRAP_CODE_FIRQ_10_ | fast interrupt request channel 10 | _I-PC_ | _0_
| 22 | `0x8000001b` | 1.27 | _TRAP_CODE_FIRQ_11_ | fast interrupt request channel 11 | _I-PC_ | _0_
| 23 | `0x8000001c` | 1.28 | _TRAP_CODE_FIRQ_12_ | fast interrupt request channel 12 | _I-PC_ | _0_
| 24 | `0x8000001d` | 1.29 | _TRAP_CODE_FIRQ_13_ | fast interrupt request channel 13 | _I-PC_ | _0_
| 25 | `0x8000001e` | 1.30 | _TRAP_CODE_FIRQ_14_ | fast interrupt request channel 14 | _I-PC_ | _0_
| 26 | `0x8000001f` | 1.31 | _TRAP_CODE_FIRQ_15_ | fast interrupt request channel 15 | _I-PC_ | _0_
| 27 | `0x8000000B` | 1.11 | _TRAP_CODE_MEI_ | machine external interrupt | _I-PC_ | _0_
| 28 | `0x80000003` | 1.3 | _TRAP_CODE_MSI_ | machine software interrupt | _I-PC_ | _0_
| 29 | `0x80000007` | 1.7 | _TRAP_CODE_MTI_ | machine timer interrupt | _I-PC_ | _0_
| Prio. | `mcause` | [RISC-V] | ID [C] | Cause | `mepc` | `mtval`
7+^| **Synchronous Exceptions**
| 1 | `0x00000000` | 0.0 | _TRAP_CODE_I_MISALIGNED_ | instruction address misaligned | **PC** | **ADR**
| 2 | `0x00000001` | 0.1 | _TRAP_CODE_I_ACCESS_ | instruction access bus fault | **PC** | **ADR**
| 3 | `0x00000002` | 0.2 | _TRAP_CODE_I_ILLEGAL_ | illegal instruction | **PC** | **INST**
| 4 | `0x0000000B` | 0.11 | _TRAP_CODE_MENV_CALL_ | environment call from M-mode | **PC** | **0**
| 5 | `0x00000008` | 0.8 | _TRAP_CODE_UENV_CALL_ | environment call from U-mode | **PC** | **0**
| 6 | `0x00000003` | 0.3 | _TRAP_CODE_BREAKPOINT_ | breakpoint instruction | **PC** | **PC**
| 7 | `0x00000006` | 0.6 | _TRAP_CODE_S_MISALIGNED_ | store address misaligned | **PC** | **ADR**
| 8 | `0x00000004` | 0.4 | _TRAP_CODE_L_MISALIGNED_ | load address misaligned | **PC** | **ADR**
| 9 | `0x00000007` | 0.7 | _TRAP_CODE_S_ACCESS_ | store access bus fault | **PC** | **ADR**
| 10 | `0x00000005` | 0.5 | _TRAP_CODE_L_ACCESS_ | load access bus fault | **PC** | **ADR**
7+^| **Asynchronous Exceptions (Interrupts)**
| 11 | `0x80000010` | 1.16 | _TRAP_CODE_FIRQ_0_ | fast interrupt request channel 0 | **IPC** | **0**
| 12 | `0x80000011` | 1.17 | _TRAP_CODE_FIRQ_1_ | fast interrupt request channel 1 | **IPC** | **0**
| 13 | `0x80000012` | 1.18 | _TRAP_CODE_FIRQ_2_ | fast interrupt request channel 2 | **IPC** | **0**
| 14 | `0x80000013` | 1.19 | _TRAP_CODE_FIRQ_3_ | fast interrupt request channel 3 | **IPC** | **0**
| 15 | `0x80000014` | 1.20 | _TRAP_CODE_FIRQ_4_ | fast interrupt request channel 4 | **IPC** | **0**
| 16 | `0x80000015` | 1.21 | _TRAP_CODE_FIRQ_5_ | fast interrupt request channel 5 | **IPC** | **0**
| 17 | `0x80000016` | 1.22 | _TRAP_CODE_FIRQ_6_ | fast interrupt request channel 6 | **IPC** | **0**
| 18 | `0x80000017` | 1.23 | _TRAP_CODE_FIRQ_7_ | fast interrupt request channel 7 | **IPC** | **0**
| 19 | `0x80000018` | 1.24 | _TRAP_CODE_FIRQ_8_ | fast interrupt request channel 8 | **IPC** | **0**
| 20 | `0x80000019` | 1.25 | _TRAP_CODE_FIRQ_9_ | fast interrupt request channel 9 | **IPC** | **0**
| 21 | `0x8000001a` | 1.26 | _TRAP_CODE_FIRQ_10_ | fast interrupt request channel 10 | **IPC** | **0**
| 22 | `0x8000001b` | 1.27 | _TRAP_CODE_FIRQ_11_ | fast interrupt request channel 11 | **IPC** | **0**
| 23 | `0x8000001c` | 1.28 | _TRAP_CODE_FIRQ_12_ | fast interrupt request channel 12 | **IPC** | **0**
| 24 | `0x8000001d` | 1.29 | _TRAP_CODE_FIRQ_13_ | fast interrupt request channel 13 | **IPC** | **0**
| 25 | `0x8000001e` | 1.30 | _TRAP_CODE_FIRQ_14_ | fast interrupt request channel 14 | **IPC** | **0**
| 26 | `0x8000001f` | 1.31 | _TRAP_CODE_FIRQ_15_ | fast interrupt request channel 15 | **IPC** | **0**
| 27 | `0x8000000B` | 1.11 | _TRAP_CODE_MEI_ | machine external interrupt (MEI) | **IPC** | **0**
| 28 | `0x80000003` | 1.3 | _TRAP_CODE_MSI_ | machine software interrupt (MSI) | **IPC** | **0**
| 29 | `0x80000007` | 1.7 | _TRAP_CODE_MTI_ | machine timer interrupt (MTI) | **IPC** | **0**
|=======================
 
 
965,12 → 1011,12
[options="header",grid="rows"]
|=======================
| Trap ID [C] | Triggered when ...
| _TRAP_CODE_I_MISALIGNED_ | fetching an 32-bit instruction word that is not 32-bit-aligned (_see note below!_)
| _TRAP_CODE_I_MISALIGNED_ | fetching a 32-bit instruction word that is not 32-bit-aligned (_see note below!_)
| _TRAP_CODE_I_ACCESS_ | bus timeout or bus error during instruction word fetch
| _TRAP_CODE_I_ILLEGAL_ | trying to execute an invalid instruction word (malformed or not supported) or on a privilege violation
| _TRAP_CODE_MENV_CALL_ | executing `ecall` instruction in machine-mode
| _TRAP_CODE_UENV_CALL_ | executing `ecall` instruction in user-mode
| _TRAP_CODE_BREAKPOINT_ | executing `ebreak` instruction (or triggered by on-chip debugger)
| _TRAP_CODE_BREAKPOINT_ | executing `ebreak` instruction
| _TRAP_CODE_S_MISALIGNED_ | storing data to an address that is not naturally aligned to the data size (byte, half, word) being stored
| _TRAP_CODE_L_MISALIGNED_ | loading data from an address that is not naturally aligned to the data size (byte, half, word) being loaded
| _TRAP_CODE_S_ACCESS_ | bus timeout or bus error during load data operation
1042,6 → 1088,7
An error indicated by the `*_bus_err_i` signal will raise the according "instruction bus access fault" or
"load/store bus access fault" exception.
 
 
**Minimal Response Latency**
 
The transfer can be completed directly in the same cycle as it was initiated (via the `*_bus_re_o` or `*_bus_we_o`
1049,12 → 1096,14
critical path such "asynchronous" completion should be avoided. The default NEORV32 processor-internal modules provide
exactly **one cycle delay** between initiation and completion of transfers.
 
 
**Maximal Response Latency**
 
Processor-internal peripherals or memories do not have to respond within one cycle after a bus request has been initiated.
However, the bus transaction has to be completed (= acknowledged) within a certain **response time window**. This time window
is defined by the global `max_proc_int_response_time_c` constant (default = 15 cycles; processor's VHDL package file `rtl/neorv32_package.vhd`).
It defines the maximum number of cycles after which an _unacknowledged_ (`*_bus_ack_i` or `*_bus_err_i` both not set) processor-internal bus
It defines the maximum number of cycles after which an _unacknowledged_ (`*_bus_ack_i` or `*_bus_err_i` signal from the **processor-internal bus**
both not set) processor-internal bus
transfer will time out and raises a **bus fault exception**. The <<_internal_bus_monitor_buskeeper>> keeps track of all _internal_ bus
transactions to enforce this time window.
 
1063,6 → 1112,13
Note that **the bus keeper does not track external accesses via the external memory bus interface**. However,
the external memory bus interface also provides an _optional_ bus timeout (see section <<_processor_external_memory_interface_wishbone_axi4_lite>>).
 
.Interface Response
[NOTE]
Please note that any CPU access via the data or instruction interface has to be terminated either by asserting the
CPU's *_bus_ack_i` or `*_bus_err_i` signal. Otherwise the CPU will be stalled permanently. The BUSKEEPER ensures that
any kind of access is always properly terminated.
 
 
**Exemplary Bus Accesses**
 
.Example bus accesses: see read/write access description below
1074,6 → 1130,7
| Read access | Write access
|=======================
 
 
**Write Access**
 
For a write access, the access address (`bus_addr_o`), the data to be written (`bus_wdata_o`) and the byte
1082,6 → 1139,7
cycle after issuing. Here, the transaction is successful and the peripheral sets the `bus_ack_i` signal several
cycles after issuing.
 
 
**Read Access**
 
For a read access, the accessed address (`bus_addr_o`) is set when `bus_re_o` goes high. The address is kept
1090,6 → 1148,7
the bus transaction is completed (here, the transaction is successful and the peripheral sets the `bus_ack_i`
signal).
 
 
**Access Boundaries**
 
The instruction interface will always access memory on word (= 32-bit) boundaries even if fetching
1096,6 → 1155,7
compressed (16-bit) instructions. The data interface can access memory on byte (= 8-bit), half-word (= 16-
bit) and word (= 32-bit) boundaries.
 
 
**Exclusive (Atomic) Access**
 
The CPU can access memory in an exclusive manner by generating a load-reservate and store-conditional
1121,6 → 1181,7
For more information regarding the SoC-level behavior and requirements of atomic operations see
section <<_processor_external_memory_interface_wishbone_axi4_lite>>.
 
 
**Memory Barriers**
 
Whenever the CPU executes a _fence_ instruction, the according interface signal is set high for one cycle
1139,6 → 1200,7
dedicated hardware reset**. "Uncritical registers" in this context means that the initial value of these registers
after power-up is not relevant for a defined CPU boot process.
 
 
**Rationale**
 
A good example to illustrate the concept of uncritical registers is a pipelined processing engine. Each stage
1150,6 → 1212,7
control the actual operation (in contrast to the status register). This makes the pipeline data registers from
this example "uncritical registers".
 
 
**NEORV32 CPU Reset**
 
In terms of the NEORV32 CPU, there are several pipeline registers, state machine registers and even status
1164,6 → 1227,7
because the global interrupt enabled flag in the status register (`mstatsus(mie)`) _do_ provide a dedicated
hardware reset setting this bit to low (globally disabling interrupts).
 
 
**Reset Configuration**
 
Most CPU-internal register do provide an asynchronous reset in the VHDL code, but the "don't care" value
1178,9 → 1242,3
-- FALSE=reset value is irrelevant (might simplify HW), default; TRUE=defined LOW reset value
constant dedicated_reset_c : boolean := false;
----
 
 
<<<
// ####################################################################################################################
 
include::cpu_cfu.adoc[]
/docs/datasheet/cpu_csr.adoc
85,8 → 85,8
| 0x343 | <<_mtval>> | _CSR_MTVAL_ | r/- | Machine bad address or instruction | `R`
| 0x344 | <<_mip>> | _CSR_MIP_ | r/w | Machine interrupt pending register | `X`
6+^| **<<_machine_physical_memory_protection_csrs>>**
| 0x3a0 .. 0x3af | <<_pmpcfg, `pmpcfg0`>> .. <<_pmpcfg, `pmpcfg15`>> | _CSR_PMPCFG0_ .. _CSR_PMPCFG15_ | r/w | Physical memory protection config. for region 0..63 | `C`
| 0x3b0 .. 0x3ef | <<_pmpaddr, `pmpaddr0`>> .. <<_pmpaddr, `pmpaddr63`>> | _CSR_PMPADDR0_ .. _CSR_PMPADDR63_ | r/w | Physical memory protection addr. register region 0..63 |
| 0x3a0 .. 0x3af | <<_pmpcfg, `pmpcfg0`>> .. <<_pmpcfg, `pmpcfg3`>> | _CSR_PMPCFG0_ .. _CSR_PMPCFG3_ | r/w | Physical memory protection config. for region 0..15 | `C`
| 0x3b0 .. 0x3ef | <<_pmpaddr, `pmpaddr0`>> .. <<_pmpaddr, `pmpaddr15`>> | _CSR_PMPADDR0_ .. _CSR_PMPADDR15_ | r/w | Physical memory protection addr. register region 0..15 |
6+^| **<<_machine_counter_and_timer_csrs>>**
| 0xb00 | <<_mcycleh, `mcycle`>> | _CSR_MCYCLE_ | r/w | Machine cycle counter low word |
| 0xb02 | <<_minstreth, `minstret`>> | _CSR_MINSTRET_ | r/w | Machine instruction-retired counter low word |
220,9 → 220,10
[options="header",grid="rows"]
|=======================
| Bit | Name [C] | R/W | Function
| 12:11 | _CSR_MSTATUS_MPP_H_ : _CSR_MSTATUS_MPP_L_ | r/w | Previous machine privilege level, 11 = machine (M) level, 00 = user (U) level
| 7 | _CSR_MSTATUS_MPIE_ | r/w | Previous machine global interrupt enable flag state
| 3 | _CSR_MSTATUS_MIE_ | r/w | Machine global interrupt enable flag
| 21 | _CSR_MSTATUS_TW_ | r/w | **TW**: Disallows execution of `wfi` instruction in user 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 level, 11 = machine (M) level, 00 = user (U) level
| 7 | _CSR_MSTATUS_MPIE_ | r/w | **MPIE**: Previous machine global interrupt enable flag state
| 3 | _CSR_MSTATUS_MIE_ | r/w | **MIE**: Machine global interrupt enable flag
|=======================
 
When entering an exception/interrupt, the `MIE` flag is copied to `MPIE` and cleared afterwards. When leaving
251,14 → 252,14
[options="header",grid="rows"]
|=======================
| Bit | Name [C] | R/W | Function
| 31:30 | _CSR_MISA_MXL_HI_EXT_ : _CSR_MISA_MXL_LO_EXT_ | r/- | 32-bit architecture indicator (always _01_)
| 23 | _CSR_MISA_X_EXT_ | r/- | `X` extension bit is always set to indicate custom non-standard extensions
| 20 | _CSR_MISA_U_EXT_ | r/- | `U` CPU extension (user mode) available, set when _CPU_EXTENSION_RISCV_U_ enabled
| 12 | _CSR_MISA_M_EXT_ | r/- | `M` CPU extension (mul/div) available, set when _CPU_EXTENSION_RISCV_M_ enabled
| 8 | _CSR_MISA_I_EXT_ | r/- | `I` CPU base ISA, cleared when _CPU_EXTENSION_RISCV_E_ enabled
| 4 | _CSR_MISA_E_EXT_ | r/- | `E` CPU extension (embedded) available, set when _CPU_EXTENSION_RISCV_E_ enabled
| 2 | _CSR_MISA_C_EXT_ | r/- | `C` CPU extension (compressed instruction) available, set when _CPU_EXTENSION_RISCV_C_ enabled
| 0 | _CSR_MISA_A_EXT_ | r/- | `A` CPU extension (atomic memory access) available, set when _CPU_EXTENSION_RISCV_A_ enabled
| 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**: extension bit is always set to indicate custom non-standard extensions
| 20 | _CSR_MISA_U_EXT_ | r/- | **U**: CPU extension (user mode) available, set when _CPU_EXTENSION_RISCV_U_ enabled
| 12 | _CSR_MISA_M_EXT_ | r/- | **M**: CPU extension (mul/div) available, set when _CPU_EXTENSION_RISCV_M_ enabled
| 8 | _CSR_MISA_I_EXT_ | r/- | **I**: CPU base ISA, cleared when _CPU_EXTENSION_RISCV_E_ enabled
| 4 | _CSR_MISA_E_EXT_ | r/- | **E**: CPU extension (embedded) available, set when _CPU_EXTENSION_RISCV_E_ enabled
| 2 | _CSR_MISA_C_EXT_ | r/- | **C**: CPU extension (compressed instruction) available, set when _CPU_EXTENSION_RISCV_C_ enabled
| 0 | _CSR_MISA_A_EXT_ | r/- | **A**: CPU extension (atomic memory access) available, set when _CPU_EXTENSION_RISCV_A_ enabled
|=======================
 
[TIP]
286,9 → 287,9
|=======================
| 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 | Machine _external_ interrupt enable
| 7 | _CSR_MIE_MTIE_ | r/w | Machine _timer_ interrupt enable (from _MTIME_)
| 3 | _CSR_MIE_MSIE_ | r/w | Machine _software_ interrupt enable
| 11 | _CSR_MIE_MEIE_ | r/w | **MEIE**: Machine _external_ interrupt enable
| 7 | _CSR_MIE_MTIE_ | r/w | **MTIE**: Machine _timer_ interrupt enable (from _MTIME_)
| 3 | _CSR_MIE_MSIE_ | r/w | **MSIE**: Machine _software_ interrupt enable
|=======================
 
 
310,8 → 311,8
[options="header",grid="rows"]
|=======================
| Bit | R/W | Function
| 31:2 | r/w | 4-byte aligned base address of trap base handler
| 1:0 | r/- | Always zero
| 31:2 | r/w | **BASE**: 4-byte aligned base address of trap base handler
| 1:0 | r/- | **MODE**: Always zero; BASE defined entry for _all_ traps
|=======================
 
 
335,12 → 336,18
|=======================
| Bit | Name [C] | R/W | Function
| 31:3 | `0` | r/- | Always zero: user-level code is **not** allowed to read HPM counters
| 2 | _CSR_MCOUNTEREN_IR_ | r/w | User-level code is allowed to read `cycle[h]` CSRs when set
| 1 | _CSR_MCOUNTEREN_TM_ | r/w | User-level code is allowed to read `time[h]` CSRs when set
| 0 | _CSR_MCOUNTEREN_CY_ | r/w | User-level code is allowed to read `instret[h]` CSRs when set
| 2 | _CSR_MCOUNTEREN_IR_ | r/w | **IR**: User-level code is allowed to read `cycle[h]` CSRs when set
| 1 | _CSR_MCOUNTEREN_TM_ | r/w | **TM**: User-level code is allowed to read `time[h]` CSRs when set
| 0 | _CSR_MCOUNTEREN_CY_ | r/w | **CY**: User-level code is allowed to read `instret[h]` CSRs when set
|=======================
 
.HPM Access
[NOTE]
Bits 3 to 31 are used to control user-level access to the <<_hardware_performance_monitors_hpm_csrs>>. In the NEORV32
CPU these bits are hardwired to zero. Hence, user-level software cannot access the HPMs. Accordingly, the
`pmcounter*[h]` CSRs are **not** implemented and any access will raise an illegal instruction exception.
 
 
:sectnums!:
===== **`mstatush`**
 
353,13 → 360,8
execution state information. The NEORV32 `mstatush` CSR is read-only and all bits are hardwired to zero.
|=======================
 
[NOTE]
The NEORV32 `mstatush` CSR is not a physical register. All write access are ignored and all read accesses will always
return zero. However, any access will not raise an illegal instruction exception. The CSR address is implemented
in order to comply with the RISC-V privilege architecture specs.
 
 
 
<<<
// ####################################################################################################################
:sectnums:
406,9 → 408,9
[options="header",grid="rows"]
|=======================
| Bit | R/W | Function
| 31 | r/w | `1` if the trap is caused by an interrupt (`0` if the trap is caused by an exception)
| 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/- | _Reserved_, read as zero
| 4:0 | r/w | Trap ID, see <<_neorv32_trap_listing>>
| 4:0 | r/w | **Trap ID**: see <<_neorv32_trap_listing>>
|=======================
 
:sectnums!:
450,8 → 452,8
3+| The `mip` CSR is compatible to the RISC-V specifications and also provides custom extensions. It shows currently _pending_ interrupts.
The bits for the standard RISC-V interrupts are read-only. Hence, these interrupts cannot be cleared using the `mip` register and must
be cleared/acknowledged within the according interrupt-generating device.
The upper 16 bits represent the status of the CPU's fast interrupt request lines (FIRQ). Once triggered, these _have to be cleared_ again by setting
the according `mip` bit in the interrupt handler routine to clear the current interrupt request.
The upper 16 bits represent the status of the CPU's fast interrupt request lines (FIRQ). Once triggered, these bit have to be cleared manually by
writing zero to the according `mip` bits (in the interrupt handler routine) to clear the current interrupt request.
|=======================
 
.Machine interrupt pending register
459,31 → 461,36
[options="header",grid="rows"]
|=======================
| Bit | Name [C] | R/W | Function
| 31:16 | _CSR_MIP_FIRQ15P_ : _CSR_MIP_FIRQ0P_ | r/w | fast interrupt channel 15..0 pending; cleared request by writing 1
| 11 | _CSR_MIP_MEIP_ | r/- | machine _external_ interrupt pending; _cleared by user-defined mechanism_
| 7 | _CSR_MIP_MTIP_ | r/- | machine _timer_ interrupt pending; cleared by incrementing MTIME's time compare register
| 3 | _CSR_MIP_MSIP_ | r/- | machine _software_ interrupt pending; _cleared by user-defined mechanism_
| 31:16 | _CSR_MIP_FIRQ15P_ : _CSR_MIP_FIRQ0P_ | r/c | **FIRQxP**: Fast interrupt channel 15..0 pending; cleared request by writing 1
| 11 | _CSR_MIP_MEIP_ | r/- | **MEIP**: Machine _external_ interrupt pending; _cleared by user-defined mechanism_
| 7 | _CSR_MIP_MTIP_ | r/- | **MTIP**: Machine _timer_ interrupt pending; cleared by incrementing MTIME's time compare register
| 3 | _CSR_MIP_MSIP_ | r/- | **MSIP**: Machine _software_ interrupt pending; _cleared by user-defined 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 Physical Memory Protection CSRs
 
The available physical memory protection logic is configured via the _PMP_NUM_REGIONS_ and
_PMP_MIN_GRANULARITY_ top entity generics. _PMP_NUM_REGIONS_ defines the number of implemented
protection regions and thus, the availability of the according `pmpcfg*` and `pmpaddr*` CSRs.
The available physical memory protection logic is configured via the <<_pmp_num_regions>> and
<<_pmp_min_granularity>> top entity generics. <<_pmp_num_regions>> defines the number of implemented
protection regions and thus, the implementation of the available _PMP entries_. Each PMP entry consists of an
8-bit `pmpcfg` CSR entry and a complete `pmpaddr*` CSR.
See section <<_pmp_physical_memory_protection>> for more information.
 
[NOTE]
If trying to access an PMP-related CSR beyond _PMP_NUM_REGIONS_ **no illegal instruction
If trying to access an PMP-related CSR beyond <<_pmp_num_regions>> **no illegal instruction
exception** is triggered. The according CSRs are read-only (writes are ignored) and always return zero.
However, any access beyond `pmpcfg3` or `pmpaddr15`, which are the last physically implemented registers if
<<_pmp_num_regions>> == 16, will raise an illegal instruction exception as these CSRs are not implemented at all.
 
[IMPORTANT]
The RISC-V-compatible NEORV32 physical memory protection only implements the **NAPOT**
(naturally aligned power-of-two region) mode yet with a minimal region granularity of 8 bytes.
 
 
:sectnums!:
===== **`pmpcfg`**
 
490,27 → 497,32
[cols="4,27,>7"]
[frame="topbot",grid="none"]
|=======================
| 0x3a0 - 0x3af| **Physical memory protection configuration registers** | `pmpcfg0` - `pmpcfg15`
| 0x3a0 - 0x3a3| **Physical memory protection configuration registers** | `pmpcfg0` - `pmpcfg3`
3+| Reset value: _0x00000000_
3+| The `pmpcfg*` CSRs are compatible to the RISC-V specifications. They are used to configure the protected
regions, where each `pmpcfg*` CSR provides configuration bits for four regions. The following bits (for the
first PMP configuration entry) are implemented (all remaining bits are always zero and are read-only):
regions, where each `pmpcfg*` CSR provides configuration bits for four regions (8-bit per region).
The actual number of available `pmpcfg` CSRs and CSR entries is defined by the <<_pmp_num_regions>> generic.
|=======================
 
.Physical memory protection configuration register entry
.Physical memory protection configuration register layout (1 entry out of 4)
[cols="^1,^3,^1,<11"]
[options="header",grid="rows"]
|=======================
| Bit | RISC-V name | R/W | Function
| 7 | _L_ | r/w | lock bit, can only be cleared by CPU reset
| 6:5 | - | r/- | reserved, read as zero
| 4:3 | _A_ | r/w | mode configuration; only OFF (`00`) and NAPOT (`11`) are supported
| 2 | _X_ | r/w | execute permission
| 1 | _W_ | r/w | write permission
| 0 | _R_ | r/w | read permission
| 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
| 6:5 | - | r/- | _reserved_, read as zero
| 4 | _PMPCFG_A_MSB_ | r/- .2+<| **A**: Mode configuration; only **OFF** (`00`) and **TOR** (`01`) modes are supported, any other value will map back to OFF/TOR
as the MSB is hardwired to zero
| 3 | _PMPCFG_A_LSB_ | r/w
| 2 | _PMPCFG_X_ | r/w | **X**: Execute permission
| 1 | _PMPCFG_W_ | r/w | **W**: Write permission
| 0 | _PMPCFG_R_ | r/w | **R**: Read permission
|=======================
 
[WARNING]
Setting the lock bit `L` **only locks the according PMP entry** and not the PMP entries below!
 
 
:sectnums!:
===== **`pmpaddr`**
 
517,14 → 529,24
[cols="4,27,>7"]
[frame="topbot",grid="none"]
|=======================
| 0x3b0 - 0x3ef| **Physical memory protection address registers** | `pmpaddr0` - `pmpaddr63`
| 0x3b0 - 0x3bf| **Physical memory protection address registers** | `pmpaddr0` - `pmpaddr15`
3+| Reset value: _UNDEFINED_
3+| The `pmpaddr*` CSRs are compatible to the RISC-V specifications. They are used to configure the PMP region's base
address and the region size.
3+| The `pmpaddr*` CSRs are compatible to the RISC-V specifications. They are used to configure bits 33:2 of the PMP region's
physical memory address. The actual number of available `pmpaddr` CSRs is defined by the <<_pmp_num_regions>> generic.
|=======================
 
.Physical memory protection address register layout
[cols="^6,^3,<7"]
[options="header",grid="rows"]
|=======================
| Bit | R/W | Function
| 31:30 | r/- | Hardwired to zero
| 29 : _log2(PMP_MIN_GRANULARITY)-2_ | r/w | Bits 31 downto _log2(PMP_MIN_GRANULARITY)_ of the region's address
| _log2(PMP_MIN_GRANULARITY)-2_ : 0 | r/- | Hardwired to zero
|=======================
 
[NOTE]
When configuring PMP make sure to set `pmpaddr*` before activating the according region via
When configuring the PMP make sure to set `pmpaddr*` before activating the according region via
`pmpcfg*`. When changing the PMP configuration, deactivate the according region via `pmpcfg*`
before modifying `pmpaddr*`.
 
653,7 → 675,7
If trying to access an HPM-related CSR beyond <<_hpm_num_cnts>> **no illegal instruction exception is
triggered**. The according CSRs are read-only (writes are ignored) and always return zero.
 
[IMPORTANT]
[NOTE]
The HPM system only allows machine-mode access. Hence, `hpmcounter*[h]` CSR are not implemented
and any access (even) from machine mode will raise an exception. Furthermore, the according bits of <<_mcounteren>>
used to configure user-mode access to `hpmcounter*[h]` are hard-wired to zero.
684,14 → 706,10
the architectural events that cause the according `mhpmcounter*[h]` counters to increment. All available events are
listed in the table below. If more than one event is selected, 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 event is observed. If the CPU is in sleep mode, no HPM counter will increment
cycle even if more than one event is observed. If the CPU is in sleep or debug mode, no HPM counter will increment
at all.
|=======================
 
The available hardware performance logic is configured via the _HPM_NUM_CNTS_ top entity generic.
_HPM_NUM_CNTS_ defines the number of implemented performance monitors and thus, the availability of the
according `mhpmcounter*[h]` and `mhpmevent*` CSRs.
 
.HPM event selector
[cols="^1,<3,^1,<5"]
[options="header",grid="rows"]
699,18 → 717,18
| Bit | Name [C] | R/W | Event
| 0 | _HPMCNT_EVENT_CY_ | r/w | active clock cycle (not in sleep)
| 1 | - | r/- | _not implemented, always read as zero_
| 2 | _HPMCNT_EVENT_IR_ | r/w | retired instruction
| 2 | _HPMCNT_EVENT_IR_ | r/w | retired instruction (compressed or uncompressed)
| 3 | _HPMCNT_EVENT_CIR_ | r/w | retired compressed instruction
| 4 | _HPMCNT_EVENT_WAIT_IF_ | r/w | instruction fetch memory wait cycle (if more than 1 cycle memory latency)
| 5 | _HPMCNT_EVENT_WAIT_II_ | r/w | instruction issue pipeline wait cycle (if more than 1 cycle latency), caused by pipelines flushes (like taken branches)
| 6 | _HPMCNT_EVENT_WAIT_MC_ | r/w | multi-cycle ALU operation wait cycle
| 7 | _HPMCNT_EVENT_LOAD_ | r/w | load operation
| 8 | _HPMCNT_EVENT_STORE_ | r/w | store operation
| 7 | _HPMCNT_EVENT_LOAD_ | r/w | memory data load operation
| 8 | _HPMCNT_EVENT_STORE_ | r/w | memory data store operation
| 9 | _HPMCNT_EVENT_WAIT_LS_ | r/w | load/store memory wait cycle (if more than 1 cycle memory latency)
| 10 | _HPMCNT_EVENT_JUMP_ | r/w | unconditional jump
| 11 | _HPMCNT_EVENT_BRANCH_ | r/w | conditional branch (taken or not taken)
| 12 | _HPMCNT_EVENT_TBRANCH_ | r/w | taken conditional branch
| 13 | _HPMCNT_EVENT_TRAP_ | r/w | entered trap
| 13 | _HPMCNT_EVENT_TRAP_ | r/w | entered trap (synchronous exception or interrupt)
| 14 | _HPMCNT_EVENT_ILLEGAL_ | r/w | illegal instruction exception
|=======================
 
754,9 → 772,9
[options="header",grid="rows"]
|=======================
| Bit | Name [C] | R/W | Event
| 0 | _CSR_MCOUNTINHIBIT_IR_ | r/w | the `[m]instret[h]` CSRs will auto-increment with each committed instruction when set
| 2 | _CSR_MCOUNTINHIBIT_IR_ | r/w | the `[m]cycle[h]` CSRs will auto-increment with each clock cycle (if CPU is not in sleep state) when set
| 3:31 | _CSR_MCOUNTINHIBIT_HPM3_ _: _CSR_MCOUNTINHIBIT_HPM31_ | r/w | the `mhpmcount*[h]` CSRs will auto-increment according to the configured `mhpmevent*` selector
| 0 | _CSR_MCOUNTINHIBIT_IR_ | r/w | **IR**: The `[m]instret[h]` CSRs will auto-increment with each committed instruction when set
| 2 | _CSR_MCOUNTINHIBIT_CY_ | r/w | **CY**: The `[m]cycle[h]` CSRs will auto-increment with each clock cycle (if CPU is not in sleep state) when set
| 3:31 | _CSR_MCOUNTINHIBIT_HPM3_ : _CSR_MCOUNTINHIBIT_HPM31_ | r/w | **HPMx**: The `mhpmcount*[h]` CSRs will auto-increment according to the configured `mhpmevent*` selector
|=======================
 
 
/docs/datasheet/overview.adoc
19,11 → 19,8
of the CoreMark MCU benchmark and the official RISC-V architecture test suite. RISC-V GCC is used as
default toolchain (https://github.com/stnolting/riscv-gcc-prebuilt[prebuilt toolchains are also provided]).
 
[TIP]
Check out the processor's **https://stnolting.github.io/neorv32/ug[online User Guide]**
that provides hands-on tutorials to get you started.
The project's change log is available in https://github.com/stnolting/neorv32/blob/main/CHANGELOG.md[CHANGELOG.md]
in the root directory of the NEORV32 repository. Please also check out the <<_legal>> section.
 
 
**Structure**
33,9 → 30,24
. <<_neorv32_central_processing_unit_cpu>>
. <<_software_framework>>
. <<_on_chip_debugger_ocd>>
. <<_legal>>
 
 
**Annotations**
 
[WARNING]
Warning
 
[IMPORTANT]
Important
 
[NOTE]
Note
 
[TIP]
Tip
 
 
<<<
// ####################################################################################################################
 
213,7 → 225,10
:sectnums:
=== FPGA Implementation Results
 
This chapter shows _exemplary_ implementation results of the NEORV32 CPU and NEORV32 Processor.
This section shows _exemplary_ FPGA implementation results for the NEORV32 CPU and NEORV32 Processor modules.
Note that certain configuration options might also have an impact on other configuration options. Furthermore,
this report cannot cover all possible option combinations. Hence, the presented implementation results are
just _exemplary_. If not otherwise mentioned all implementations use the default generic configurations.
 
:sectnums:
==== CPU
221,26 → 236,43
[cols="<2,<8"]
[grid="topbot"]
|=======================
| Top entity: | `rtl/core/neorv32_cpu.vhd`
| FPGA: | Intel Cyclone IV E `EP4CE22F17C6`
| Toolchain: | Quartus Prime 20.1.0
| HW version: | `1.6.8.3`
| Top entity: | `rtl/core/neorv32_cpu.vhd`
| FPGA: | Intel Cyclone IV E `EP4CE22F17C6`
| Toolchain: | Quartus Prime Lite 21.1
| Constraints: | **no timing constraints**, "_balanced optimization_", f~max~ from "_Slow 1200mV 0C Model_"
|=======================
 
[cols="<5,>1,>1,>1,>1,>1"]
[cols="<6,>1,>1,>1,>1,>1"]
[options="header",grid="rows"]
|=======================
| CPU | LEs | FFs | MEM bits | DSPs | _f~max~_
| `rv32i` | 806 | 359 | 1024 | 0 | 125 MHz
| `rv32i_Zicsr_Zicntr` | 1729 | 813 | 1024 | 0 | 124 MHz
| `rv32im_Zicsr_Zicntr` | 2269 | 1055 | 1024 | 0 | 124 MHz
| `rv32imc_Zicsr_Zicntr` | 2501 | 1070 | 1024 | 0 | 124 MHz
| `rv32imac_Zicsr_Zicntr` | 2511 | 1074 | 1024 | 0 | 124 MHz
| `rv32imacu_Zicsr_Zicntr` | 2521 | 1079 | 1024 | 0 | 124 MHz
| `rv32imacu_Zicsr_Zicntr_Zifencei` | 2522 | 1079 | 1024 | 0 | 122 MHz
| `rv32imacu_Zicsr_Zicntr_Zifencei_Zfinx` | 3807 | 1731 | 1024 | 7 | 116 MHz
| `rv32imacu_Zicsr_Zicntr_Zifencei_Zfinx_DebugMode` | 3974 | 1815 | 1024 | 7 | 116 MHz
| CPU ISA Configuration | LEs | FFs | MEM bits | DSPs | _f~max~_
| `rv32e` | 900 | 388 | 512 | 0 | 121 MHz
| `rv32i` | 904 | 388 | 1024 | 0 | 121 MHz
| `rv32i_Zicsr` | 1425 | 673 | 1024 | 0 | 118 MHz
| `rv32i_Zicsr_Zicntr` | 1778 | 803 | 1024 | 0 | 118 MHz
| `rv32im_Zicsr_Zicntr` | 2244 | 978 | 1024 | 0 | 118 MHz
| `rv32ima_Zicsr_Zicntr` | 2267 | 982 | 1024 | 0 | 118 MHz
| `rv32imac_Zicsr_Zicntr` | 2453 | 994 | 1024 | 0 | 118 MHz
| `rv32imacb_Zicsr_Zicntr` | 3270 | 1249 | 1024 | 0 | 118 MHz
| `rv32imacbu_Zicsr_Zicntr` | 3286 | 1254 | 1024 | 0 | 118 MHz
| `rv32imacbu_Zicsr_Zicntr_Zifencei` | 3278 | 1254 | 1024 | 0 | 118 MHz
| `rv32imacbu_Zicsr_Zicntr_Zifencei_Zfinx` | 4536 | 1906 | 1024 | 7 | 115 MHz
| `rv32imacbu_Zicsr_Zicntr_Zifencei_Zfinx_DebugMode` | 5989 | 2416 | 1024 | 7 | 110 MHz
|=======================
 
.**RISC-V Compliance**
[NOTE]
The `Zicsr` ISA extension implements the privileged machine architecture
(see <<_zicsr_control_and_status_register_access_privileged_architecture>>). The `Zicntr` ISA
extension implements the basic counters and timers (see <<_zicntr_cpu_base_counters>>). Both
extensions are _mandatory_ in order to comply with the RISC-V architecture specifications.
 
[NOTE]
The table above does not show _all_ CPU ISA extensions. More sophisticated and application-specific
options like PMP and HMP are not included in this overview.
 
.Goal-Driven Optimization
[TIP]
The CPU provides further options to reduce the area footprint (for example by constraining the CPU-internal
counter sizes) or to increase performance (for example by using a barrel-shifter; at cost of extra hardware).
249,48 → 281,54
 
 
:sectnums:
==== Processor Modules
==== Processor - Modules
 
[cols="<2,<8"]
[grid="topbot"]
|=======================
| HW version: | `1.6.8.3`
| Top entity: | `rtl/core/neorv32_top.vhd`
| FPGA: | Intel Cyclone IV E `EP4CE22F17C6`
| Toolchain: | Quartus Prime 20.1.0
| Toolchain: | Quartus Prime Lite 21.1
| Constraints: | **no timing constraints**, "_balanced optimization_"
|=======================
 
.Hardware utilization by the processor modules (mandatory core modules in **bold**)
.Hardware utilization by processor module (mandatory modules highlighted in **bold**)
[cols="<2,<8,>1,>1,>2,>1"]
[options="header",grid="rows"]
|=======================
| Module | Description | LEs | FFs | MEM bits | DSPs
| Boot ROM | Bootloader ROM (4kB) | 2 | 1 | 32768 | 0
| **BUSKEEPER** | Processor-internal bus monitor | 9 | 6 | 0 | 0
| **BUSSWITCH** | Bus multiplexer for CPU instr. and data interface | 63 | 8 | 0 | 0
| CFS | Custom functions subsystemfootnote:[Resource utilization depends on actually implemented custom functionality.] | - | - | - | -
| DMEM | Processor-internal data memory (8kB) | 19 | 2 | 65536 | 0
| DM | On-chip debugger - debug module | 493 | 240 | 0 | 0
| DTM | On-chip debugger - debug transfer module (JTAG) | 254 | 218 | 0 | 0
| GPIO | General purpose input/output ports | 134 | 161 | 0 | 0
| iCACHE | Instruction cache (1x4 blocks, 256 bytes per block) | 2 21| 156 | 8192 | 0
| IMEM | Processor-internal instruction memory (16kB) | 13 | 2 | 131072 | 0
| MTIME | Machine system timer | 319 | 167 | 0 | 0
| NEOLED | Smart LED Interface (NeoPixel/WS28128) [FIFO_depth=1] | 226 | 182 | 0 | 0
| SLINK | Stream link interface (2xRX, 2xTX, FIFO_depth=1) | 208 | 181 | 0 | 0
| PWM | Pulse_width modulation controller (4 channels) | 71 | 69 | 0 | 0
| SPI | Serial peripheral interface | 148 | 127 | 0 | 0
| **SYSINFO** | System configuration information memory | 14 | 11 | 0 | 0
| TRNG | True random number generator | 89 | 76 | 0 | 0
| TWI | Two-wire interface | 77 | 43 | 0 | 0
| UART0/1 | Universal asynchronous receiver/transmitter 0/1 | 183 | 132 | 0 | 0
| WDT | Watchdog timer | 53 | 43 | 0 | 0
| WISHBONE | External memory interface | 114 | 110 | 0 | 0
| XIRQ | External interrupt controller (32 channels) | 241 | 201 | 0 | 0
| GPTMR | General Purpose Timer | 153 | 107 | 0 | 0
| XIP | Execute in place module | 305 | 243 | 0 | 0
| Module | Description | LEs | FFs | MEM bits | DSPs
| Boot ROM | Bootloader ROM (4kB) | 3 | 2 | 32768 | 0
| **BUSKEEPER** | Processor-internal bus monitor | 28 | 15 | 0 | 0
| **BUSSWITCH** | Bus multiplexer for CPU instr. and data interface | 69 | 8 | 0 | 0
| CFS | Custom functions subsystemfootnote:[Resource utilization depends on custom design logic.] | - | - | - | -
| DM | On-chip debugger - debug module | 473 | 240 | 0 | 0
| DTM | On-chip debugger - debug transfer module (JTAG) | 259 | 221 | 0 | 0
| DMEM | Processor-internal data memory (8kB) | 18 | 2 | 65536 | 0
| GPIO | General purpose input/output ports | 102 | 98 | 0 | 0
| GPTMR | General Purpose Timer | 153 | 105 | 0 | 0
| iCACHE | Instruction cache (2x4 blocks, 64 bytes per block) | 417 | 297 | 4096 | 0
| IMEM | Processor-internal instruction memory (16kB) | 12 | 2 | 131072 | 0
| MTIME | Machine system timer | 345 | 166 | 0 | 0
| NEOLED | Smart LED Interface (NeoPixel/WS28128) (FIFO_depth=1) | 227 | 184 | 0 | 0
| PWM | Pulse_width modulation controller (8 channels) | 128 | qq7 | 0 | 0
| SLINK | Stream link interface (2xRX, 2xTX, FIFO_depth=1) | 136 | 116 | 0 | 0
| SPI | Serial peripheral interface | 114 | 94 | 0 | 0
| **SYSINFO** | System configuration information memory | 13 | 11 | 0 | 0
| TRNG | True random number generator | 89 | 79 | 0 | 0
| TWI | Two-wire interface | 77 | 43 | 0 | 0
| UART0, UART1 | Universal asynchronous receiver/transmitter 0/1 (FIFO_depth=1) | 195 | 143 | 0 | 0
| WDT | Watchdog timer | 61 | 46 | 0 | 0
| WISHBONE | External memory interface | 120 | 112 | 0 | 0
| XIP | Execute in place module | 318 | 244 | 0 | 0
| XIRQ | External interrupt controller (32 channels) | 245 | 200 | 0 | 0
|=======================
 
[NOTE]
Note that not all IOs were actually connected to FPGA pins (for example some GPIO inputs and outputs)
when generating these reports.
 
 
<<<
:sectnums:
==== Exemplary Setups
337,7 → 375,7
| _performance_ (`rv32imc_Zicsr` + perf. options) | 95.23 | **0.9523** | **3.54**
|=======================
 
[IMPORTANT]
[NOTE]
The CoreMark results were generated using a `rv32i` toolchain. This toolchain supports standard extensions
like `M` and `C` but the built-in libraries only use the base `I` ISA.
 
344,16 → 382,10
[NOTE]
The "_performance_" CPU configuration uses the <<_fast_mul_en>> and <<_fast_shift_en>> options.
 
[NOTE]
The NEORV32 CPU is based on a multi-cycle architecture. Each instruction is executed in a sequence of
several consecutive micro operations.
 
[NOTE]
The average CPI (cycles per instruction) depends on the instruction mix of a specific applications and also on
the available CPU extensions. The average CPI is computed by dividing the total number of required clock cycles
(only the timed core to avoid distortion due to IO wait cycles) by the number of executed instructions
(`[m]instret[h]` CSRs).
 
[TIP]
More information regarding the execution time of each implemented instruction can be found in
(`[m]instret[h]` CSRs). More information regarding the execution time of each implemented instruction can be found in
chapter <<_instruction_timing>>.
/docs/datasheet/soc.adoc
490,7 → 490,7
[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
3+| Total number of implemented protection regions (0..16). If this generics is zero no physical memory
protection logic will be implemented at all.
|======
 
501,8 → 501,9
[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.
| **PMP_MIN_GRANULARITY** | _natural_ | 4
3+| Minimal region granularity in bytes. Has to be a power of two and has to be at least 4 bytes. A larger granularity
will reduce hardware utilization and impact on critical path but will also reduce the minimal region size.
|======
 
 
1101,7 → 1102,7
.Trigger type
[IMPORTANT]
The fast interrupt request channels become pending after being triggering by **a rising edge**. A pending FIRQ has to
be explicitly cleared by setting the according <<_mip>> CSR bit.
be explicitly cleared by writing zero to the according <<_mip>> CSR bit.
 
 
:sectnums:
1160,7 → 1161,7
.Trigger type
[IMPORTANT]
The fast interrupt request channels become pending after being triggering by **a rising edge**. A pending FIRQ has to
be explicitly cleared by setting the according <<_mip>> CSR bit.
be explicitly cleared by writing zero to the according <<_mip>> CSR bit.
 
 
 
1247,43 → 1248,6
 
 
:sectnums:
==== Physical Memory Attributes
 
The processor setup defines fixed attributes for the four processor-internal address space regions.
Accessing a memory region in a way that violates any of these attributes will raise an according
access exception..
 
* `r` - read access (from CPU data access interface, "loads")
* `w` - write access (from CPU data access interface, "stores")
* `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)
 
[NOTE]
Read accesses (loads and instruction fetches) can always access data in
word, half-word (for instruction fetch only if `C` extension is enabled)
and byte (not for instruction fetch) quantities (requiring an accordingly aligned address).
 
[TIP]
The following table shows the _default hardware-defined_ physical memory attributes of each main address space region.
Additional user-defined attributes (for example certain read/write/execute rights for specific address space regions) can be
provided using the RISC-V <<_machine_physical_memory_protection_csrs>>.
 
[cols="^1,^2,^2,^3,^2"]
[options="header",grid="rows"]
|=======================
| # | Region | Base address | Size | Attributes
| 5 | IO/peripheral devices | 0xfffffe00 | 512 bytes | `r/w/a/32`
| 4 | On-chip debugger | 0xfffff800 | 512 bytes | `r/w/x/32`
| 3 | Bootloader ROM | 0xffff0000 | up to 32kB | `r/x/a`
| 2 | DMEM | 0x80000000 | up to "2GB" | `r/w/x/a/8/16/32`
| 1 | IMEM | 0x00000000 | up to 2GB | `r/w/x/a/8/16/32`
|=======================
 
 
:sectnums:
==== Memory Configuration
 
The NEORV32 Processor was designed to provide maximum flexibility for the memory configuration.
1453,22 → 1417,26
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.
 
.Address Space Mapping
[IMPORTANT]
The base address of each component/module has to be aligned to the
total size of the module's occupied address space! The occupied address space
has to be a power of two (minimum 4 bytes)! Address spaces must not overlap!
 
.Full-Word Write Accesses Only
[IMPORTANT]
When accessing an IO device that hast not been implemented (via the according 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
All 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.
 
.Unimplemented Modules
[NOTE]
When accessing an IO device that hast not been implemented (via the according generic), a
load/store access fault exception is triggered.
 
.Hardware Reset
[NOTE]
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`.
/docs/datasheet/soc_buskeeper.adoc
46,28 → 46,11
the CPU's PMP logic).
 
 
**NULL Address Check**
 
The bus keeper can ensure that no accesses are permitted to NULL addresses (`addr = 0x00000000`). These kind of
access often occur when using uninitialized pointers. If the _BUSKEEPER_NULL_CHECK_EN_ bit is set, any access to
address zero (instruction fetch, load data, store data) will raise an according bus exception. This flag
automatically clears on a hardware reset.
 
If a NULL address access has been detected the _BUSKEEPER_ERR_FLAG_ flag is set and the _BUSKEEPER_ERR_TYPE_
flag is cleared indicating a "Device Error".
 
[NOTE]
Address 0 is normally used by the IMEM and contains boot code instructions that are executed _once_ right after
hardware reset. Hence, activating the bus keeper's NULL check in application code will not corrupt code execution
at all.
 
 
.BUSKEEPER register map (`struct NEORV32_BUSKEEPER`)
[cols="<2,<2,<4,^1,<4"]
[options="header",grid="all"]
|=======================
| Address | Name [C] | Bit(s), Name [C] | R/W | Function
.3+<| `0xffffff7C` .3+<| `NEORV32_BUSKEEPER.CTRL` <|`0` _BUSKEEPER_ERR_TYPE_ ^| r/- | Bus error type, valid if _BUSKEEPER_ERR_FLAG_
<|`16` _BUSKEEPER_NULL_CHECK_EN_ ^| r/w <| Enable NULL address check when set
<|`31` _BUSKEEPER_ERR_FLAG_ ^| r/- <| Sticky error flag, clears after read or write access
.2+<| `0xffffff7C` .2+<| `NEORV32_BUSKEEPER.CTRL` <|`0` _BUSKEEPER_ERR_TYPE_ ^| r/- <| Bus error type, valid if _BUSKEEPER_ERR_FLAG_
<|`31` _BUSKEEPER_ERR_FLAG_ ^| r/c <| Sticky error flag, clears after read or write access
|=======================
/docs/datasheet/soc_cfs.adoc
20,10 → 20,10
**Theory of Operation**
 
The custom functions subsystem is meant for implementing custom and application-specific logic.
The CFS provides up to 32x 32-bit memory-mapped
The CFS provides up to 32x 32-bit memory-mapped read/write
registers (`REG`, see register map below) that can be accessed by the CPU via normal load/store operations.
The actual functionality of these register has to be defined by the hardware designer. Furthermore, the CFS
provides two IO conduits to implement custom module- or chip-external interfaces.
provides two IO conduits to implement custom on-chip or off-chip interfaces.
 
In contrast to connecting custom hardware accelerators via external memory interfaces (like SPI or the processor's
external bus interface), the CFS provide a convenient, low-latency and tightly-coupled extension and
47,13 → 47,14
**CFS Software Access**
 
The CFS memory-mapped registers can be accessed by software using the provided C-language aliases (see
register map table below). Note that all interface registers provide 32-bit access data of type `uint32_t`.
register map table below). Note that all interface registers are declared as 32-bit words of type `uint32_t`.
 
.CFS Software Access Example
[source,c]
----
// C-code CFS usage example
NEORV32_CFS.REG[0] = (uint32_t)some_data_array(i); // write to CFS register 0
uint32_t temp = NEORV32_CFS.REG[20]; // read from CFS register 20
int temp = (int)NEORV32_CFS.REG[20]; // read from CFS register 20
----
 
[TIP]
63,8 → 64,8
**CFS Interrupt**
 
The CFS provides a single high-level-triggered interrupt request signal mapped to the CPU's fast interrupt channel 1.
Once triggered, the interrupt becomes pending (if enabled in the `mis` CSR) and has to be explicitly cleared again by setting
the according `mip` CSR bit. See section <<_processor_interrupts>> for more information.
Once triggered, the interrupt becomes pending (if enabled in the `mis` CSR) and has to be explicitly cleared again by
writing zero to the according <<_mip>> CSR bit. See section <<_processor_interrupts>> for more information.
 
 
**CFS Configuration Generic**
/docs/datasheet/soc_gptmr.adoc
9,7 → 9,7
| Software driver file(s): | neorv32_gptmr.c |
| | neorv32_gptmr.h |
| Top entity port: | none |
| Configuration generics: | _IO_GPTMR_EN_ | implement timer when _true_
| Configuration generics: | _IO_GPTMR_EN_ | implement general purpose timer when _true_
| CPU interrupts: | fast IRQ channel 12 | transmission done interrupt (see <<_processor_interrupts>>)
|=======================
 
47,7 → 47,7
**Timer Interrupt**
 
The timer interrupt is triggered when the timer is enabled and `COUNT` matches `THRES`. The interrupt
remains pending until explicitly cleared by writing the according `mip` CSR bit.
remains pending until explicitly cleared by writing zero to the according <<_mip>> CSR bit.
 
 
.GPTMR register map (`struct NEORV32_GPTMR`)
/docs/datasheet/soc_neoled.adoc
173,8 → 173,8
In this case software can write up to _IO_NEOLED_TX_FIFO_/2 new data words to `DATA` without checking the FIFO
status flags. If _NEOLED_CTRL_IRQ_CONF_ is set, an interrupt is generated whenever the TX FIFO _becomes_ empty.
 
One the NEOLED interrupt has been triggered and became pending, it has to explicitly cleared again by setting the
according `mip` CSR bit.
One the NEOLED interrupt has been triggered and became pending, it has to explicitly cleared again by
writing zero to according <<_mip>> CSR bit.
 
[NOTE]
The _NEOLED_CTRL_IRQ_CONF_ is hardwired to one if _IO_NEOLED_TX_FIFO_ = 1 (-> IRQ if FIFO is empty).
/docs/datasheet/soc_slink.adoc
144,8 → 144,8
* If a link's interrupt mode flag is `0` an IRQ is generated when the link's FIFO _becomes_ not full ("space left in FIFO for new TX data").
* If a link's interrupt mode flag is `1` an IRQ is generated when the link's FIFO _becomes_ less than half-full ("SW can send _SLINK_TX_FIFO_/2 data words without checking any flags").
 
Once the SLINK's RX or TX interrupt has become pending, it has to be explicitly cleared again by setting the according
`mip` CSR bit.
Once the SLINK's RX or TX interrupt has become pending, it has to be explicitly cleared again by writing
zero to the according <<_mip>> CSR bit.
 
[IMPORTANT]
The interrupt configuration register `NEORV32_SLINK.IRQ` should we written _before_ the SLINK
/docs/datasheet/soc_spi.adoc
115,7 → 115,7
 
The SPI module provides a single interrupt to signal "transmission done" to the CPU. Whenever the SPI
module completes the current transfer operation, the interrupt is triggered and has to be explicitly cleared again
by setting the according `mip` CSR bit.
by writing zero to the according <<_mip>> CSR bit.
 
 
.SPI register map (`struct NEORV32_SPI`)
/docs/datasheet/soc_trng.adoc
21,7 → 21,7
oscillator concept as physical entropy source. Hence, voltage, thermal and also semiconductor manufacturing
fluctuations are used to provide a true physical entropy source.
 
The TRNG is based on the neoTRNG[https://github.com/stnolting/neoTRNG], which is a "spin-off project" of the
The TRNG is based on the _neoTRNG_, which is a "spin-off project" of the
NEORV32 processor. The TRNG uses the default neoTRNG configuration, which showed very good results in the
`dieharder` battery of random number tests. More detailed information about the neoTRNG, it's architecture and a
detailed evaluation of the random number quality can be found it it's repository: https://github.com/stnolting/neoTRNG
/docs/datasheet/soc_twi.adoc
74,8 → 74,8
 
The SPI module provides a single interrupt to signal "operation done" to the CPU. Whenever the TWI
module completes the current operation (generate stop condition, generate start conditions or transfer byte),
the interrupt is triggered. Once triggered, the interrupt has to be explicitly cleared again by setting the according
`mip` CSR bit.
the interrupt is triggered. Once triggered, the interrupt has to be explicitly cleared again by
writing zero to the according <<_mip>> CSR bit.
 
 
.TWI register map (`struct NEORV32_TWI`)
/docs/datasheet/soc_uart.adoc
129,8 → 129,8
in the TX FIFO _becomes_ free (-> _UART_CTRL_TX_FULL_ clears). If _UART_CTRL_TX_IRQ_ is `1` the TX interrupt goes pending
when the RX FIFO _becomes_ less than half-full (-> _UART_CTRL_TX_HALF_ clears).
 
Once the RX or TX interrupt has become pending, it has to be explicitly cleared again by setting the
according `mip` CSR bit.
Once the RX or TX interrupt has become pending, it has to be explicitly cleared again by
writing zero to the according <<_mip>> CSR bit.
 
 
**Simulation Mode**
/docs/datasheet/soc_wdt.adoc
9,7 → 9,7
| Software driver file(s): | neorv32_wdt.c |
| | neorv32_wdt.h |
| Top entity port: | none |
| Configuration generics: | _IO_WDT_EN_ | implement GPIO port when _true_
| Configuration generics: | _IO_WDT_EN_ | implement watchdog when _true_
| CPU interrupts: | fast IRQ channel 0 | watchdog timer overflow (see <<_processor_interrupts>>)
|=======================
 
46,7 → 46,7
any time by setting the _WDT_CTRL_FORCE_ bit. The watchdog is reset by setting the _WDT_CTRL_RESET_ bit.
 
A watchdog interrupt can only occur if the watchdog is enabled and interrupt mode is enabled.
A triggered interrupt has to be cleared again by setting the according `mip` CSR bit.
A triggered interrupt has to be cleared again by writing zero to the according <<_mip>> CSR bit.
 
The cause of the last action of the watchdog can be determined via the _WDT_CTRL_RCAUSE_ flag. If this flag is
zero, the processor has been reset via the external reset signal. If this flag is set the last system reset was
/docs/datasheet/soc_xirq.adoc
43,8 → 43,8
The CPU can use the ID from `SCR` to service IRQ according to their priority. To acknowledge the according
interrupt the CPU can write `1 << SCR` to `IPR`.
 
In order to clear a pending FIRQ interrupt from the external interrupt controller again, the according `mip` CSR bit has
to be set. Additionally, the XIRQ interrupt has to be acknowledged by writing _any_
In order to clear a pending FIRQ interrupt from the external interrupt controller again, the according <<_mip>> CSR bit has
to be cleared. Additionally, the XIRQ interrupt has to be acknowledged by writing _any_
value to the interrupt source register `SRC`.
 
[NOTE]
/docs/datasheet/software.adoc
445,44 → 445,48
The `crt0.S` start-up performs the following operations:
 
[start=1]
. Initialize all integer registers `x1 - x31` (or jsut `x1 - x15` when using the `E` CPU extension) to a defined value.
. Initialize the global pointer `gp` and the stack pointer `sp` according to the `.data` segment layout provided by the linker script.
. Initialize all CPU core CSRs and also install a default "dummy" trap handler for _all_ traps. This handler catches all traps during the early boot phase.
. Clear IO area: Write zero to all memory-mapped registers within the IO region (`iodev` section). If certain devices have not been implemented, a bus access fault exception will occur. This exception is captured by the dummy trap handler.
. Initialize all integer registers `x1 - x31` (or just `x1 - x15` when using the `E` CPU extension) to a defined value.
. Initialize the global pointer `gp` and the stack pointer `sp` according to the <<_ram_layout>> provided by the linker script.
. Initialize all CPU core CSRs and also install a default "dummy" trap handler for _all_ traps. This handler catches all traps
during the early boot phase.
. All interrupt sources are disabled and all pending interrupts are cleared.
. Clear all counter CSRs and stop auto-increment.
. Clear IO area: Write zero to all memory-mapped registers within the IO region (`iodev` section). If certain devices have not
been implemented, a bus access fault exception will occur. This exception is captured by the dummy trap handler.
. Clear the `.bss` section defined by the linker script.
. Copy read-only data from the `.text` section to the `.data` section to set initialized variables.
. Call the application's `main` function (with _no_ arguments: `argc` = `argv` = 0).
. If the `main` function returns `crt0` can call an "after-main handler" (see below)
. If there is no after-main handler or after returning from the after-main handler the processor goes to an endless sleep mode (using a simple loop or via the `wfi` instruction if available).
. If the main function returns...
** the return value is copied to the <<_mscratch>> CSR to allow inspection by the on-chip debugger.
** an optional <<_after_main_handler>> is called (if defined at all).
** the last step the CPU does is entering endless sleep mode (using the `wfi` instruction).
 
:sectnums:
===== After-Main Handler
 
If the application's `main()` function actually returns, an _after main handler_ can be executed. This handler can be a normal function
since the C runtime is still available when executed. If this handler uses any kind of peripheral/IO modules make sure these are
already initialized within the application or you have to initialize them _inside_ the handler.
If the application's `main()` function actually returns, an _after main handler_ can be executed. This handler is a "normal" function
as the C runtime is still available when executed. If this handler uses any kind of peripheral/IO modules make sure these are
already initialized within the application. Otherwise you have to initialize them _inside_ the handler.
 
.After-main handler - function prototype
[source,c]
----
int __neorv32_crt0_after_main(int32_t return_code);
void __neorv32_crt0_after_main(int32_t return_code);
----
 
The function has exactly one argument (`return_code`) that provides the _return value_ of the application's main function.
For instance, this variable contains _-1_ if the main function returned with `return -1;`. The return value of the
`__neorv32_crt0_after_main` function is irrelevant as there is no further "software instance" executed afterwards that can check this.
However, the on-chip debugger could still evaluate the return value of the after-main handler.
For instance, this variable contains `-1` if the main function returned with `return -1;`. The after-main handler itself does
not provide a return value.
 
A simple UARt output can be used to inform the user when the application's main function returns
A simple UART output can be used to inform the user when the application's main function returns
(this example assumes that UART0 has been already properly configured in the actual application):
 
.After-main handler - simple example
[source,c]
----
int __neorv32_crt0_after_main(int32_t return_code) {
void __neorv32_crt0_after_main(int32_t return_code) {
 
neorv32_uart0_printf("\n<RTE> main function returned with exit code %i. </RTE>\n", return_code); <1>
return 0;
}
----
<1> Use `<RTE>` here to make clear this is a message comes from the runtime environment.
/docs/figures/neorv32_cpu.png Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
/docs/references/riscv-privileged.pdf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
/docs/references/riscv-spec.pdf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
/docs/attrs.adoc
2,7 → 2,7
:email: stnolting@gmail.com
:keywords: neorv32, risc-v, riscv, fpga, soft-core, vhdl, microcontroller, cpu, soc, processor, gcc, openocd, gdb
:description: A size-optimized, customizable and open-source full-scale 32-bit RISC-V soft-core CPU and SoC written in platform-independent VHDL.
:revnumber: v1.6.8
:revnumber: v1.6.9
:doctype: book
:sectnums:
:stem:
/docs/neorv32-theme.yml
18,7 → 18,7
border-width: 1
recto:
left:
content: '*The NEORV32 Processor*'
content: '*The NEORV32 RISC-V Processor*'
right:
content: '*Visit on https://github.com/stnolting/neorv32[GitHub]*'
verso:
/rtl/core/neorv32_application_image.vhd
1,6 → 1,6
-- The NEORV32 RISC-V Processor, https://github.com/stnolting/neorv32
-- Auto-generated memory init file (for APPLICATION) from source file <blink_led/main.bin>
-- Size: 3400 bytes
-- Size: 3392 bytes
 
library ieee;
use ieee.std_logic_1164.all;
17,14 → 17,14
00000003 => x"80000197",
00000004 => x"7f418193",
00000005 => x"00000517",
00000006 => x"12050513",
00000006 => x"11850513",
00000007 => x"30551073",
00000008 => x"34151073",
00000009 => x"30001073",
00000010 => x"30401073",
00000011 => x"30601073",
00000012 => x"ffa00593",
00000013 => x"32059073",
00000011 => x"34401073",
00000012 => x"32001073",
00000013 => x"30601073",
00000014 => x"b0001073",
00000015 => x"b8001073",
00000016 => x"b0201073",
34,833 → 34,831
00000020 => x"00000293",
00000021 => x"00000313",
00000022 => x"00000393",
00000023 => x"00000713",
00000024 => x"00000793",
00000025 => x"00000813",
00000026 => x"00000893",
00000027 => x"00000913",
00000028 => x"00000993",
00000029 => x"00000a13",
00000030 => x"00000a93",
00000031 => x"00000b13",
00000032 => x"00000b93",
00000033 => x"00000c13",
00000034 => x"00000c93",
00000035 => x"00000d13",
00000036 => x"00000d93",
00000037 => x"00000e13",
00000038 => x"00000e93",
00000039 => x"00000f13",
00000040 => x"00000f93",
00000041 => x"00000417",
00000042 => x"d5c40413",
00000043 => x"00000497",
00000044 => x"f5448493",
00000045 => x"00042023",
00000046 => x"00440413",
00000047 => x"fe941ce3",
00000048 => x"80000597",
00000049 => x"f4058593",
00000050 => x"87418613",
00000051 => x"00c5d863",
00000052 => x"00058023",
00000053 => x"00158593",
00000054 => x"ff5ff06f",
00000055 => x"00001597",
00000056 => x"c6c58593",
00000057 => x"80000617",
00000058 => x"f1c60613",
00000059 => x"80000697",
00000060 => x"f1468693",
00000061 => x"00d65c63",
00000062 => x"00058703",
00000063 => x"00e60023",
00000064 => x"00158593",
00000065 => x"00160613",
00000066 => x"fedff06f",
00000067 => x"00000513",
00000068 => x"00000593",
00000069 => x"06c000ef",
00000070 => x"34051073",
00000071 => x"00000093",
00000072 => x"00008463",
00000073 => x"000080e7",
00000074 => x"30047073",
00000075 => x"10500073",
00000076 => x"ffdff06f",
00000077 => x"ff810113",
00000078 => x"00812023",
00000079 => x"00912223",
00000080 => x"34202473",
00000081 => x"02044663",
00000082 => x"34102473",
00000083 => x"00041483",
00000084 => x"0034f493",
00000085 => x"00240413",
00000086 => x"34141073",
00000087 => x"00300413",
00000088 => x"00941863",
00000089 => x"34102473",
00000090 => x"00240413",
00000091 => x"34141073",
00000092 => x"00012403",
00000093 => x"00412483",
00000094 => x"00810113",
00000095 => x"30200073",
00000096 => x"00005537",
00000097 => x"ff010113",
00000098 => x"00000613",
00000099 => x"00000593",
00000100 => x"b0050513",
00000101 => x"00112623",
00000102 => x"57c000ef",
00000103 => x"694000ef",
00000104 => x"00050c63",
00000105 => x"500000ef",
00000106 => x"00001537",
00000107 => x"a8050513",
00000108 => x"628000ef",
00000109 => x"020000ef",
00000110 => x"00001537",
00000111 => x"a5c50513",
00000112 => x"618000ef",
00000113 => x"00c12083",
00000114 => x"00100513",
00000115 => x"01010113",
00000116 => x"00008067",
00000117 => x"ff010113",
00000118 => x"00000513",
00000119 => x"00000593",
00000120 => x"00112623",
00000121 => x"00812423",
00000122 => x"658000ef",
00000123 => x"00000513",
00000124 => x"00150413",
00000125 => x"00000593",
00000126 => x"0ff57513",
00000127 => x"644000ef",
00000128 => x"0c800513",
00000129 => x"64c000ef",
00000130 => x"00040513",
00000131 => x"fe5ff06f",
00000132 => x"fc010113",
00000133 => x"02112e23",
00000134 => x"02512c23",
00000135 => x"02612a23",
00000136 => x"02712823",
00000137 => x"02a12623",
00000138 => x"02b12423",
00000139 => x"02c12223",
00000140 => x"02d12023",
00000141 => x"00e12e23",
00000142 => x"00f12c23",
00000143 => x"01012a23",
00000144 => x"01112823",
00000145 => x"01c12623",
00000146 => x"01d12423",
00000147 => x"01e12223",
00000148 => x"01f12023",
00000149 => x"34102773",
00000150 => x"34071073",
00000151 => x"342027f3",
00000152 => x"0407c463",
00000153 => x"00071683",
00000154 => x"00300593",
00000155 => x"0036f693",
00000156 => x"00270613",
00000157 => x"00b69463",
00000158 => x"00470613",
00000159 => x"34161073",
00000160 => x"00b00713",
00000161 => x"00f77663",
00000162 => x"47c00793",
00000163 => x"0500006f",
00000164 => x"00001737",
00000165 => x"00279793",
00000166 => x"a9c70713",
00000167 => x"00e787b3",
00000168 => x"0007a783",
00000169 => x"00078067",
00000170 => x"80000737",
00000171 => x"ffd74713",
00000172 => x"00e787b3",
00000173 => x"01c00713",
00000174 => x"fcf768e3",
00000175 => x"00001737",
00000176 => x"00279793",
00000177 => x"acc70713",
00000178 => x"00e787b3",
00000179 => x"0007a783",
00000180 => x"00078067",
00000181 => x"800007b7",
00000182 => x"0007a783",
00000183 => x"000780e7",
00000184 => x"03c12083",
00000185 => x"03812283",
00000186 => x"03412303",
00000187 => x"03012383",
00000188 => x"02c12503",
00000189 => x"02812583",
00000190 => x"02412603",
00000191 => x"02012683",
00000192 => x"01c12703",
00000193 => x"01812783",
00000194 => x"01412803",
00000195 => x"01012883",
00000196 => x"00c12e03",
00000197 => x"00812e83",
00000198 => x"00412f03",
00000199 => x"00012f83",
00000200 => x"04010113",
00000201 => x"30200073",
00000202 => x"800007b7",
00000203 => x"0047a783",
00000204 => x"fadff06f",
00000205 => x"8081a783",
00000206 => x"fa5ff06f",
00000207 => x"80c1a783",
00000208 => x"f9dff06f",
00000209 => x"8101a783",
00000210 => x"f95ff06f",
00000211 => x"8141a783",
00000212 => x"f8dff06f",
00000213 => x"8181a783",
00000214 => x"f85ff06f",
00000215 => x"81c1a783",
00000216 => x"f7dff06f",
00000217 => x"8201a783",
00000218 => x"f75ff06f",
00000219 => x"8241a783",
00000220 => x"f6dff06f",
00000221 => x"8281a783",
00000222 => x"f65ff06f",
00000223 => x"82c1a783",
00000224 => x"f5dff06f",
00000225 => x"8301a783",
00000226 => x"f55ff06f",
00000227 => x"8341a783",
00000228 => x"f4dff06f",
00000229 => x"8381a783",
00000230 => x"f45ff06f",
00000231 => x"83c1a783",
00000232 => x"f3dff06f",
00000233 => x"8401a783",
00000234 => x"f35ff06f",
00000235 => x"8441a783",
00000236 => x"f2dff06f",
00000237 => x"8481a783",
00000238 => x"f25ff06f",
00000239 => x"84c1a783",
00000240 => x"f1dff06f",
00000241 => x"8501a783",
00000242 => x"f15ff06f",
00000243 => x"8541a783",
00000244 => x"f0dff06f",
00000245 => x"8581a783",
00000246 => x"f05ff06f",
00000247 => x"85c1a783",
00000248 => x"efdff06f",
00000249 => x"8601a783",
00000250 => x"ef5ff06f",
00000251 => x"8641a783",
00000252 => x"eedff06f",
00000253 => x"8681a783",
00000254 => x"ee5ff06f",
00000255 => x"86c1a783",
00000256 => x"eddff06f",
00000257 => x"8701a783",
00000258 => x"ed5ff06f",
00000259 => x"fe010113",
00000260 => x"01212823",
00000261 => x"00050913",
00000262 => x"00001537",
00000263 => x"00912a23",
00000264 => x"b4050513",
00000265 => x"000014b7",
00000266 => x"00812c23",
00000267 => x"01312623",
00000268 => x"00112e23",
00000269 => x"01c00413",
00000270 => x"3a0000ef",
00000271 => x"d3848493",
00000272 => x"ffc00993",
00000273 => x"008957b3",
00000274 => x"00f7f793",
00000275 => x"00f487b3",
00000276 => x"0007c503",
00000277 => x"ffc40413",
00000278 => x"368000ef",
00000279 => x"ff3414e3",
00000280 => x"01c12083",
00000281 => x"01812403",
00000282 => x"01412483",
00000283 => x"01012903",
00000284 => x"00c12983",
00000285 => x"02010113",
00000286 => x"00008067",
00000287 => x"ff010113",
00000288 => x"00112623",
00000289 => x"00812423",
00000290 => x"00912223",
00000291 => x"278000ef",
00000292 => x"1c050863",
00000293 => x"00001537",
00000294 => x"b4450513",
00000295 => x"33c000ef",
00000296 => x"34202473",
00000297 => x"00900713",
00000298 => x"00f47793",
00000299 => x"03078493",
00000300 => x"00f77463",
00000301 => x"05778493",
00000302 => x"00b00793",
00000303 => x"0087ee63",
00000304 => x"00001737",
00000305 => x"00241793",
00000306 => x"d0870713",
00000307 => x"00e787b3",
00000308 => x"0007a783",
00000309 => x"00078067",
00000310 => x"800007b7",
00000311 => x"00b78713",
00000312 => x"14e40e63",
00000313 => x"02876a63",
00000314 => x"00378713",
00000315 => x"12e40c63",
00000316 => x"00778793",
00000317 => x"12f40e63",
00000318 => x"00001537",
00000319 => x"ca450513",
00000320 => x"2d8000ef",
00000321 => x"00040513",
00000322 => x"f05ff0ef",
00000323 => x"00100793",
00000324 => x"08f40c63",
00000325 => x"0280006f",
00000326 => x"ff07c793",
00000327 => x"00f407b3",
00000328 => x"00f00713",
00000329 => x"fcf76ae3",
00000330 => x"00001537",
00000331 => x"c9450513",
00000332 => x"2a8000ef",
00000333 => x"00048513",
00000334 => x"288000ef",
00000335 => x"ffd47413",
00000336 => x"00500793",
00000337 => x"06f40263",
00000338 => x"00001537",
00000339 => x"ce850513",
00000340 => x"288000ef",
00000341 => x"34002573",
00000342 => x"eb5ff0ef",
00000343 => x"00001537",
00000344 => x"cf050513",
00000345 => x"274000ef",
00000346 => x"34302573",
00000347 => x"ea1ff0ef",
00000348 => x"00812403",
00000349 => x"00c12083",
00000350 => x"00412483",
00000351 => x"00001537",
00000352 => x"cfc50513",
00000353 => x"01010113",
00000354 => x"2500006f",
00000355 => x"00001537",
00000356 => x"b4c50513",
00000357 => x"244000ef",
00000358 => x"fb1ff06f",
00000359 => x"00001537",
00000360 => x"b6c50513",
00000361 => x"234000ef",
00000362 => x"f7c02783",
00000363 => x"0a07d463",
00000364 => x"0017f793",
00000365 => x"08078a63",
00000366 => x"00001537",
00000367 => x"cbc50513",
00000368 => x"fd5ff06f",
00000369 => x"00001537",
00000370 => x"b8850513",
00000371 => x"fc9ff06f",
00000372 => x"00001537",
00000373 => x"b9c50513",
00000374 => x"fbdff06f",
00000375 => x"00001537",
00000376 => x"ba850513",
00000377 => x"fb1ff06f",
00000378 => x"00001537",
00000379 => x"bc050513",
00000380 => x"fb5ff06f",
00000381 => x"00001537",
00000382 => x"bd450513",
00000383 => x"f99ff06f",
00000384 => x"00001537",
00000385 => x"bf050513",
00000386 => x"f9dff06f",
00000387 => x"00001537",
00000388 => x"c0450513",
00000389 => x"f81ff06f",
00000390 => x"00001537",
00000391 => x"c2450513",
00000392 => x"f75ff06f",
00000393 => x"00001537",
00000394 => x"c4450513",
00000395 => x"f69ff06f",
00000396 => x"00001537",
00000397 => x"c6050513",
00000398 => x"f5dff06f",
00000399 => x"00001537",
00000400 => x"c7850513",
00000401 => x"f51ff06f",
00000402 => x"00001537",
00000403 => x"ccc50513",
00000404 => x"f45ff06f",
00000405 => x"00001537",
00000406 => x"cdc50513",
00000407 => x"f39ff06f",
00000408 => x"00c12083",
00000409 => x"00812403",
00000410 => x"00412483",
00000411 => x"01010113",
00000412 => x"00008067",
00000413 => x"01f00793",
00000414 => x"02a7e263",
00000415 => x"800007b7",
00000416 => x"00078793",
00000417 => x"00251513",
00000418 => x"00a78533",
00000419 => x"47c00793",
00000420 => x"00f52023",
00000421 => x"00000513",
00000023 => x"00000813",
00000024 => x"00000893",
00000025 => x"00000913",
00000026 => x"00000993",
00000027 => x"00000a13",
00000028 => x"00000a93",
00000029 => x"00000b13",
00000030 => x"00000b93",
00000031 => x"00000c13",
00000032 => x"00000c93",
00000033 => x"00000d13",
00000034 => x"00000d93",
00000035 => x"00000e13",
00000036 => x"00000e93",
00000037 => x"00000f13",
00000038 => x"00000f93",
00000039 => x"00000417",
00000040 => x"d6440413",
00000041 => x"00000497",
00000042 => x"f5c48493",
00000043 => x"00042023",
00000044 => x"00440413",
00000045 => x"fe941ce3",
00000046 => x"00001597",
00000047 => x"c8858593",
00000048 => x"80000617",
00000049 => x"f4060613",
00000050 => x"80000697",
00000051 => x"f3868693",
00000052 => x"00d65c63",
00000053 => x"00058703",
00000054 => x"00e60023",
00000055 => x"00158593",
00000056 => x"00160613",
00000057 => x"fedff06f",
00000058 => x"80000717",
00000059 => x"f1870713",
00000060 => x"87418793",
00000061 => x"00f75863",
00000062 => x"00070023",
00000063 => x"00170713",
00000064 => x"ff5ff06f",
00000065 => x"00000513",
00000066 => x"00000593",
00000067 => x"06c000ef",
00000068 => x"34051073",
00000069 => x"00000093",
00000070 => x"00008463",
00000071 => x"000080e7",
00000072 => x"30047073",
00000073 => x"10500073",
00000074 => x"0000006f",
00000075 => x"ff810113",
00000076 => x"00812023",
00000077 => x"00912223",
00000078 => x"34202473",
00000079 => x"02044663",
00000080 => x"34102473",
00000081 => x"00041483",
00000082 => x"0034f493",
00000083 => x"00240413",
00000084 => x"34141073",
00000085 => x"00300413",
00000086 => x"00941863",
00000087 => x"34102473",
00000088 => x"00240413",
00000089 => x"34141073",
00000090 => x"00012403",
00000091 => x"00412483",
00000092 => x"00810113",
00000093 => x"30200073",
00000094 => x"00005537",
00000095 => x"ff010113",
00000096 => x"00000613",
00000097 => x"00000593",
00000098 => x"b0050513",
00000099 => x"00112623",
00000100 => x"57c000ef",
00000101 => x"694000ef",
00000102 => x"00050c63",
00000103 => x"500000ef",
00000104 => x"00001537",
00000105 => x"a7850513",
00000106 => x"628000ef",
00000107 => x"020000ef",
00000108 => x"00001537",
00000109 => x"a5450513",
00000110 => x"618000ef",
00000111 => x"00c12083",
00000112 => x"00100513",
00000113 => x"01010113",
00000114 => x"00008067",
00000115 => x"ff010113",
00000116 => x"00000513",
00000117 => x"00000593",
00000118 => x"00112623",
00000119 => x"00812423",
00000120 => x"658000ef",
00000121 => x"00000513",
00000122 => x"00150413",
00000123 => x"00000593",
00000124 => x"0ff57513",
00000125 => x"644000ef",
00000126 => x"0c800513",
00000127 => x"64c000ef",
00000128 => x"00040513",
00000129 => x"fe5ff06f",
00000130 => x"fc010113",
00000131 => x"02112e23",
00000132 => x"02512c23",
00000133 => x"02612a23",
00000134 => x"02712823",
00000135 => x"02a12623",
00000136 => x"02b12423",
00000137 => x"02c12223",
00000138 => x"02d12023",
00000139 => x"00e12e23",
00000140 => x"00f12c23",
00000141 => x"01012a23",
00000142 => x"01112823",
00000143 => x"01c12623",
00000144 => x"01d12423",
00000145 => x"01e12223",
00000146 => x"01f12023",
00000147 => x"34102773",
00000148 => x"34071073",
00000149 => x"342027f3",
00000150 => x"0407c463",
00000151 => x"00075683",
00000152 => x"00300593",
00000153 => x"0036f693",
00000154 => x"00270613",
00000155 => x"00b69463",
00000156 => x"00470613",
00000157 => x"34161073",
00000158 => x"00b00713",
00000159 => x"00f77663",
00000160 => x"47400793",
00000161 => x"0500006f",
00000162 => x"00001737",
00000163 => x"00279793",
00000164 => x"a9470713",
00000165 => x"00e787b3",
00000166 => x"0007a783",
00000167 => x"00078067",
00000168 => x"80000737",
00000169 => x"ffd74713",
00000170 => x"00e787b3",
00000171 => x"01c00713",
00000172 => x"fcf768e3",
00000173 => x"00001737",
00000174 => x"00279793",
00000175 => x"ac470713",
00000176 => x"00e787b3",
00000177 => x"0007a783",
00000178 => x"00078067",
00000179 => x"800007b7",
00000180 => x"0007a783",
00000181 => x"000780e7",
00000182 => x"03c12083",
00000183 => x"03812283",
00000184 => x"03412303",
00000185 => x"03012383",
00000186 => x"02c12503",
00000187 => x"02812583",
00000188 => x"02412603",
00000189 => x"02012683",
00000190 => x"01c12703",
00000191 => x"01812783",
00000192 => x"01412803",
00000193 => x"01012883",
00000194 => x"00c12e03",
00000195 => x"00812e83",
00000196 => x"00412f03",
00000197 => x"00012f83",
00000198 => x"04010113",
00000199 => x"30200073",
00000200 => x"800007b7",
00000201 => x"0047a783",
00000202 => x"fadff06f",
00000203 => x"8081a783",
00000204 => x"fa5ff06f",
00000205 => x"80c1a783",
00000206 => x"f9dff06f",
00000207 => x"8101a783",
00000208 => x"f95ff06f",
00000209 => x"8141a783",
00000210 => x"f8dff06f",
00000211 => x"8181a783",
00000212 => x"f85ff06f",
00000213 => x"81c1a783",
00000214 => x"f7dff06f",
00000215 => x"8201a783",
00000216 => x"f75ff06f",
00000217 => x"8241a783",
00000218 => x"f6dff06f",
00000219 => x"8281a783",
00000220 => x"f65ff06f",
00000221 => x"82c1a783",
00000222 => x"f5dff06f",
00000223 => x"8301a783",
00000224 => x"f55ff06f",
00000225 => x"8341a783",
00000226 => x"f4dff06f",
00000227 => x"8381a783",
00000228 => x"f45ff06f",
00000229 => x"83c1a783",
00000230 => x"f3dff06f",
00000231 => x"8401a783",
00000232 => x"f35ff06f",
00000233 => x"8441a783",
00000234 => x"f2dff06f",
00000235 => x"8481a783",
00000236 => x"f25ff06f",
00000237 => x"84c1a783",
00000238 => x"f1dff06f",
00000239 => x"8501a783",
00000240 => x"f15ff06f",
00000241 => x"8541a783",
00000242 => x"f0dff06f",
00000243 => x"8581a783",
00000244 => x"f05ff06f",
00000245 => x"85c1a783",
00000246 => x"efdff06f",
00000247 => x"8601a783",
00000248 => x"ef5ff06f",
00000249 => x"8641a783",
00000250 => x"eedff06f",
00000251 => x"8681a783",
00000252 => x"ee5ff06f",
00000253 => x"86c1a783",
00000254 => x"eddff06f",
00000255 => x"8701a783",
00000256 => x"ed5ff06f",
00000257 => x"fe010113",
00000258 => x"01212823",
00000259 => x"00050913",
00000260 => x"00001537",
00000261 => x"00912a23",
00000262 => x"b3850513",
00000263 => x"000014b7",
00000264 => x"00812c23",
00000265 => x"01312623",
00000266 => x"00112e23",
00000267 => x"01c00413",
00000268 => x"3a0000ef",
00000269 => x"d3048493",
00000270 => x"ffc00993",
00000271 => x"008957b3",
00000272 => x"00f7f793",
00000273 => x"00f487b3",
00000274 => x"0007c503",
00000275 => x"ffc40413",
00000276 => x"368000ef",
00000277 => x"ff3414e3",
00000278 => x"01c12083",
00000279 => x"01812403",
00000280 => x"01412483",
00000281 => x"01012903",
00000282 => x"00c12983",
00000283 => x"02010113",
00000284 => x"00008067",
00000285 => x"ff010113",
00000286 => x"00112623",
00000287 => x"00812423",
00000288 => x"00912223",
00000289 => x"278000ef",
00000290 => x"1c050863",
00000291 => x"00001537",
00000292 => x"b3c50513",
00000293 => x"33c000ef",
00000294 => x"34202473",
00000295 => x"00900713",
00000296 => x"00f47793",
00000297 => x"03078493",
00000298 => x"00f77463",
00000299 => x"05778493",
00000300 => x"00b00793",
00000301 => x"0087ee63",
00000302 => x"00001737",
00000303 => x"00241793",
00000304 => x"d0070713",
00000305 => x"00e787b3",
00000306 => x"0007a783",
00000307 => x"00078067",
00000308 => x"800007b7",
00000309 => x"00b78713",
00000310 => x"14e40e63",
00000311 => x"02876a63",
00000312 => x"00378713",
00000313 => x"12e40c63",
00000314 => x"00778793",
00000315 => x"12f40e63",
00000316 => x"00001537",
00000317 => x"c9c50513",
00000318 => x"2d8000ef",
00000319 => x"00040513",
00000320 => x"f05ff0ef",
00000321 => x"00100793",
00000322 => x"08f40c63",
00000323 => x"0280006f",
00000324 => x"ff07c793",
00000325 => x"00f407b3",
00000326 => x"00f00713",
00000327 => x"fcf76ae3",
00000328 => x"00001537",
00000329 => x"c8c50513",
00000330 => x"2a8000ef",
00000331 => x"00048513",
00000332 => x"288000ef",
00000333 => x"ffd47413",
00000334 => x"00500793",
00000335 => x"06f40263",
00000336 => x"00001537",
00000337 => x"ce050513",
00000338 => x"288000ef",
00000339 => x"34002573",
00000340 => x"eb5ff0ef",
00000341 => x"00001537",
00000342 => x"ce850513",
00000343 => x"274000ef",
00000344 => x"34302573",
00000345 => x"ea1ff0ef",
00000346 => x"00812403",
00000347 => x"00c12083",
00000348 => x"00412483",
00000349 => x"00001537",
00000350 => x"cf450513",
00000351 => x"01010113",
00000352 => x"2500006f",
00000353 => x"00001537",
00000354 => x"b4450513",
00000355 => x"244000ef",
00000356 => x"fb1ff06f",
00000357 => x"00001537",
00000358 => x"b6450513",
00000359 => x"234000ef",
00000360 => x"f7c02783",
00000361 => x"0a07d463",
00000362 => x"0017f793",
00000363 => x"08078a63",
00000364 => x"00001537",
00000365 => x"cb450513",
00000366 => x"fd5ff06f",
00000367 => x"00001537",
00000368 => x"b8050513",
00000369 => x"fc9ff06f",
00000370 => x"00001537",
00000371 => x"b9450513",
00000372 => x"fbdff06f",
00000373 => x"00001537",
00000374 => x"ba050513",
00000375 => x"fb1ff06f",
00000376 => x"00001537",
00000377 => x"bb850513",
00000378 => x"fb5ff06f",
00000379 => x"00001537",
00000380 => x"bcc50513",
00000381 => x"f99ff06f",
00000382 => x"00001537",
00000383 => x"be850513",
00000384 => x"f9dff06f",
00000385 => x"00001537",
00000386 => x"bfc50513",
00000387 => x"f81ff06f",
00000388 => x"00001537",
00000389 => x"c1c50513",
00000390 => x"f75ff06f",
00000391 => x"00001537",
00000392 => x"c3c50513",
00000393 => x"f69ff06f",
00000394 => x"00001537",
00000395 => x"c5850513",
00000396 => x"f5dff06f",
00000397 => x"00001537",
00000398 => x"c7050513",
00000399 => x"f51ff06f",
00000400 => x"00001537",
00000401 => x"cc450513",
00000402 => x"f45ff06f",
00000403 => x"00001537",
00000404 => x"cd450513",
00000405 => x"f39ff06f",
00000406 => x"00c12083",
00000407 => x"00812403",
00000408 => x"00412483",
00000409 => x"01010113",
00000410 => x"00008067",
00000411 => x"01f00793",
00000412 => x"02a7e263",
00000413 => x"800007b7",
00000414 => x"00078793",
00000415 => x"00251513",
00000416 => x"00a78533",
00000417 => x"47400793",
00000418 => x"00f52023",
00000419 => x"00000513",
00000420 => x"00008067",
00000421 => x"00100513",
00000422 => x"00008067",
00000423 => x"00100513",
00000424 => x"00008067",
00000425 => x"ff010113",
00000426 => x"00112623",
00000427 => x"00812423",
00000428 => x"00912223",
00000429 => x"21000793",
00000430 => x"30579073",
00000431 => x"00000413",
00000432 => x"01d00493",
00000433 => x"00040513",
00000434 => x"00140413",
00000435 => x"0ff47413",
00000436 => x"fa5ff0ef",
00000437 => x"fe9418e3",
00000438 => x"00c12083",
00000439 => x"00812403",
00000440 => x"f6002e23",
00000441 => x"00412483",
00000442 => x"01010113",
00000443 => x"00008067",
00000444 => x"f9402583",
00000445 => x"f9002503",
00000446 => x"f9402783",
00000447 => x"fef59ae3",
00000448 => x"00008067",
00000449 => x"fe802503",
00000450 => x"01255513",
00000451 => x"00157513",
00000452 => x"00008067",
00000453 => x"ff010113",
00000454 => x"00812423",
00000455 => x"00912223",
00000456 => x"00112623",
00000457 => x"fa002023",
00000458 => x"fe002783",
00000459 => x"00058413",
00000460 => x"00151593",
00000461 => x"00078513",
00000462 => x"00060493",
00000463 => x"274000ef",
00000464 => x"01051513",
00000465 => x"000017b7",
00000466 => x"01055513",
00000467 => x"00000713",
00000468 => x"ffe78793",
00000469 => x"04a7e463",
00000470 => x"0034f793",
00000471 => x"00347413",
00000472 => x"fff50513",
00000473 => x"01479793",
00000474 => x"01641413",
00000475 => x"00f567b3",
00000476 => x"0087e7b3",
00000477 => x"01871713",
00000478 => x"00c12083",
00000479 => x"00812403",
00000423 => x"ff010113",
00000424 => x"00112623",
00000425 => x"00812423",
00000426 => x"00912223",
00000427 => x"20800793",
00000428 => x"30579073",
00000429 => x"00000413",
00000430 => x"01d00493",
00000431 => x"00040513",
00000432 => x"00140413",
00000433 => x"0ff47413",
00000434 => x"fa5ff0ef",
00000435 => x"fe9418e3",
00000436 => x"00c12083",
00000437 => x"00812403",
00000438 => x"f6002e23",
00000439 => x"00412483",
00000440 => x"01010113",
00000441 => x"00008067",
00000442 => x"f9402583",
00000443 => x"f9002503",
00000444 => x"f9402783",
00000445 => x"fef59ae3",
00000446 => x"00008067",
00000447 => x"fe802503",
00000448 => x"01255513",
00000449 => x"00157513",
00000450 => x"00008067",
00000451 => x"ff010113",
00000452 => x"00812423",
00000453 => x"00912223",
00000454 => x"00112623",
00000455 => x"fa002023",
00000456 => x"fe002783",
00000457 => x"00058413",
00000458 => x"00151593",
00000459 => x"00078513",
00000460 => x"00060493",
00000461 => x"274000ef",
00000462 => x"01051513",
00000463 => x"000017b7",
00000464 => x"01055513",
00000465 => x"00000713",
00000466 => x"ffe78793",
00000467 => x"04a7e463",
00000468 => x"0034f793",
00000469 => x"00347413",
00000470 => x"fff50513",
00000471 => x"01479793",
00000472 => x"01641413",
00000473 => x"00f567b3",
00000474 => x"0087e7b3",
00000475 => x"01871713",
00000476 => x"00c12083",
00000477 => x"00812403",
00000478 => x"00e7e7b3",
00000479 => x"10000737",
00000480 => x"00e7e7b3",
00000481 => x"10000737",
00000482 => x"00e7e7b3",
00000483 => x"faf02023",
00000484 => x"00412483",
00000485 => x"01010113",
00000486 => x"00008067",
00000487 => x"ffe70693",
00000488 => x"0fd6f693",
00000489 => x"00069a63",
00000490 => x"00355513",
00000491 => x"00170713",
00000492 => x"0ff77713",
00000493 => x"fa1ff06f",
00000494 => x"00155513",
00000495 => x"ff1ff06f",
00000496 => x"00040737",
00000497 => x"fa002783",
00000498 => x"00e7f7b3",
00000499 => x"fe079ce3",
00000500 => x"faa02223",
00000501 => x"00008067",
00000502 => x"ff010113",
00000503 => x"00812423",
00000504 => x"01212023",
00000505 => x"00112623",
00000506 => x"00912223",
00000507 => x"00050413",
00000508 => x"00a00913",
00000509 => x"00044483",
00000510 => x"00140413",
00000511 => x"00049e63",
00000512 => x"00c12083",
00000513 => x"00812403",
00000514 => x"00412483",
00000515 => x"00012903",
00000516 => x"01010113",
00000517 => x"00008067",
00000518 => x"01249663",
00000519 => x"00d00513",
00000520 => x"fa1ff0ef",
00000521 => x"00048513",
00000522 => x"f99ff0ef",
00000523 => x"fc9ff06f",
00000524 => x"fe802503",
00000525 => x"01055513",
00000526 => x"00157513",
00000527 => x"00008067",
00000528 => x"fc000793",
00000529 => x"00a7a423",
00000530 => x"00b7a623",
00000531 => x"00008067",
00000532 => x"fe010113",
00000533 => x"00a12623",
00000534 => x"fe002503",
00000535 => x"3e800593",
00000536 => x"00112e23",
00000537 => x"00812c23",
00000538 => x"00912a23",
00000539 => x"144000ef",
00000540 => x"00c12603",
00000541 => x"00000693",
00000542 => x"00000593",
00000543 => x"09c000ef",
00000544 => x"fe802783",
00000545 => x"00020737",
00000546 => x"00050413",
00000547 => x"00e7f7b3",
00000548 => x"00058493",
00000549 => x"02078e63",
00000550 => x"e59ff0ef",
00000551 => x"00850433",
00000552 => x"00a43533",
00000553 => x"009584b3",
00000554 => x"009504b3",
00000555 => x"e45ff0ef",
00000556 => x"fe95eee3",
00000557 => x"00b49463",
00000558 => x"fe856ae3",
00000559 => x"01c12083",
00000560 => x"01812403",
00000561 => x"01412483",
00000562 => x"02010113",
00000563 => x"00008067",
00000564 => x"01c59493",
00000565 => x"00455513",
00000566 => x"00a4e533",
00000567 => x"00050a63",
00000568 => x"00050863",
00000569 => x"fff50513",
00000570 => x"00000013",
00000571 => x"ff1ff06f",
00000572 => x"fcdff06f",
00000573 => x"00050613",
00000574 => x"00000513",
00000575 => x"0015f693",
00000576 => x"00068463",
00000577 => x"00c50533",
00000578 => x"0015d593",
00000579 => x"00161613",
00000580 => x"fe0596e3",
00000581 => x"00008067",
00000582 => x"00050313",
00000583 => x"ff010113",
00000584 => x"00060513",
00000585 => x"00068893",
00000586 => x"00112623",
00000587 => x"00030613",
00000588 => x"00050693",
00000589 => x"00000713",
00000590 => x"00000793",
00000591 => x"00000813",
00000592 => x"0016fe13",
00000593 => x"00171e93",
00000594 => x"000e0c63",
00000595 => x"01060e33",
00000596 => x"010e3833",
00000597 => x"00e787b3",
00000598 => x"00f807b3",
00000599 => x"000e0813",
00000600 => x"01f65713",
00000601 => x"0016d693",
00000602 => x"00eee733",
00000603 => x"00161613",
00000604 => x"fc0698e3",
00000605 => x"00058663",
00000606 => x"f7dff0ef",
00000607 => x"00a787b3",
00000608 => x"00088a63",
00000609 => x"00030513",
00000610 => x"00088593",
00000611 => x"f69ff0ef",
00000612 => x"00f507b3",
00000613 => x"00c12083",
00000614 => x"00080513",
00000615 => x"00078593",
00000616 => x"01010113",
00000617 => x"00008067",
00000618 => x"06054063",
00000619 => x"0605c663",
00000620 => x"00058613",
00000621 => x"00050593",
00000622 => x"fff00513",
00000623 => x"02060c63",
00000624 => x"00100693",
00000625 => x"00b67a63",
00000626 => x"00c05863",
00000627 => x"00161613",
00000628 => x"00169693",
00000629 => x"feb66ae3",
00000630 => x"00000513",
00000631 => x"00c5e663",
00000632 => x"40c585b3",
00000633 => x"00d56533",
00000634 => x"0016d693",
00000635 => x"00165613",
00000636 => x"fe0696e3",
00000637 => x"00008067",
00000638 => x"00008293",
00000639 => x"fb5ff0ef",
00000640 => x"00058513",
00000641 => x"00028067",
00000642 => x"40a00533",
00000643 => x"00b04863",
00000481 => x"faf02023",
00000482 => x"00412483",
00000483 => x"01010113",
00000484 => x"00008067",
00000485 => x"ffe70693",
00000486 => x"0fd6f693",
00000487 => x"00069a63",
00000488 => x"00355513",
00000489 => x"00170713",
00000490 => x"0ff77713",
00000491 => x"fa1ff06f",
00000492 => x"00155513",
00000493 => x"ff1ff06f",
00000494 => x"00040737",
00000495 => x"fa002783",
00000496 => x"00e7f7b3",
00000497 => x"fe079ce3",
00000498 => x"faa02223",
00000499 => x"00008067",
00000500 => x"ff010113",
00000501 => x"00812423",
00000502 => x"01212023",
00000503 => x"00112623",
00000504 => x"00912223",
00000505 => x"00050413",
00000506 => x"00a00913",
00000507 => x"00044483",
00000508 => x"00140413",
00000509 => x"00049e63",
00000510 => x"00c12083",
00000511 => x"00812403",
00000512 => x"00412483",
00000513 => x"00012903",
00000514 => x"01010113",
00000515 => x"00008067",
00000516 => x"01249663",
00000517 => x"00d00513",
00000518 => x"fa1ff0ef",
00000519 => x"00048513",
00000520 => x"f99ff0ef",
00000521 => x"fc9ff06f",
00000522 => x"fe802503",
00000523 => x"01055513",
00000524 => x"00157513",
00000525 => x"00008067",
00000526 => x"fc000793",
00000527 => x"00a7a423",
00000528 => x"00b7a623",
00000529 => x"00008067",
00000530 => x"fe010113",
00000531 => x"00a12623",
00000532 => x"fe002503",
00000533 => x"3e800593",
00000534 => x"00112e23",
00000535 => x"00812c23",
00000536 => x"00912a23",
00000537 => x"144000ef",
00000538 => x"00c12603",
00000539 => x"00000693",
00000540 => x"00000593",
00000541 => x"09c000ef",
00000542 => x"fe802783",
00000543 => x"00020737",
00000544 => x"00050413",
00000545 => x"00e7f7b3",
00000546 => x"00058493",
00000547 => x"02078e63",
00000548 => x"e59ff0ef",
00000549 => x"00850433",
00000550 => x"00a43533",
00000551 => x"009584b3",
00000552 => x"009504b3",
00000553 => x"e45ff0ef",
00000554 => x"fe95eee3",
00000555 => x"00b49463",
00000556 => x"fe856ae3",
00000557 => x"01c12083",
00000558 => x"01812403",
00000559 => x"01412483",
00000560 => x"02010113",
00000561 => x"00008067",
00000562 => x"01c59493",
00000563 => x"00455513",
00000564 => x"00a4e533",
00000565 => x"00050a63",
00000566 => x"00050863",
00000567 => x"fff50513",
00000568 => x"00000013",
00000569 => x"ff1ff06f",
00000570 => x"fcdff06f",
00000571 => x"00050613",
00000572 => x"00000513",
00000573 => x"0015f693",
00000574 => x"00068463",
00000575 => x"00c50533",
00000576 => x"0015d593",
00000577 => x"00161613",
00000578 => x"fe0596e3",
00000579 => x"00008067",
00000580 => x"00050313",
00000581 => x"ff010113",
00000582 => x"00060513",
00000583 => x"00068893",
00000584 => x"00112623",
00000585 => x"00030613",
00000586 => x"00050693",
00000587 => x"00000713",
00000588 => x"00000793",
00000589 => x"00000813",
00000590 => x"0016fe13",
00000591 => x"00171e93",
00000592 => x"000e0c63",
00000593 => x"01060e33",
00000594 => x"010e3833",
00000595 => x"00e787b3",
00000596 => x"00f807b3",
00000597 => x"000e0813",
00000598 => x"01f65713",
00000599 => x"0016d693",
00000600 => x"00eee733",
00000601 => x"00161613",
00000602 => x"fc0698e3",
00000603 => x"00058663",
00000604 => x"f7dff0ef",
00000605 => x"00a787b3",
00000606 => x"00088a63",
00000607 => x"00030513",
00000608 => x"00088593",
00000609 => x"f69ff0ef",
00000610 => x"00f507b3",
00000611 => x"00c12083",
00000612 => x"00080513",
00000613 => x"00078593",
00000614 => x"01010113",
00000615 => x"00008067",
00000616 => x"06054063",
00000617 => x"0605c663",
00000618 => x"00058613",
00000619 => x"00050593",
00000620 => x"fff00513",
00000621 => x"02060c63",
00000622 => x"00100693",
00000623 => x"00b67a63",
00000624 => x"00c05863",
00000625 => x"00161613",
00000626 => x"00169693",
00000627 => x"feb66ae3",
00000628 => x"00000513",
00000629 => x"00c5e663",
00000630 => x"40c585b3",
00000631 => x"00d56533",
00000632 => x"0016d693",
00000633 => x"00165613",
00000634 => x"fe0696e3",
00000635 => x"00008067",
00000636 => x"00008293",
00000637 => x"fb5ff0ef",
00000638 => x"00058513",
00000639 => x"00028067",
00000640 => x"40a00533",
00000641 => x"00b04863",
00000642 => x"40b005b3",
00000643 => x"f9dff06f",
00000644 => x"40b005b3",
00000645 => x"f9dff06f",
00000646 => x"40b005b3",
00000647 => x"00008293",
00000648 => x"f91ff0ef",
00000649 => x"40a00533",
00000650 => x"00028067",
00000651 => x"00008293",
00000652 => x"0005ca63",
00000653 => x"00054c63",
00000654 => x"f79ff0ef",
00000655 => x"00058513",
00000656 => x"00028067",
00000657 => x"40b005b3",
00000658 => x"fe0558e3",
00000659 => x"40a00533",
00000660 => x"f61ff0ef",
00000661 => x"40b00533",
00000662 => x"00028067",
00000663 => x"6f727245",
00000664 => x"4e202172",
00000665 => x"5047206f",
00000666 => x"75204f49",
00000667 => x"2074696e",
00000668 => x"746e7973",
00000669 => x"69736568",
00000670 => x"2164657a",
00000671 => x"0000000a",
00000672 => x"6e696c42",
00000673 => x"676e696b",
00000674 => x"44454c20",
00000675 => x"6d656420",
00000676 => x"7270206f",
00000677 => x"6172676f",
00000678 => x"00000a6d",
00000679 => x"000002d4",
00000680 => x"00000328",
00000681 => x"00000334",
00000682 => x"0000033c",
00000683 => x"00000344",
00000684 => x"0000034c",
00000685 => x"00000354",
00000686 => x"0000035c",
00000687 => x"00000364",
00000688 => x"00000288",
00000689 => x"00000288",
00000690 => x"0000036c",
00000691 => x"00000374",
00000692 => x"00000288",
00000693 => x"00000288",
00000694 => x"00000288",
00000695 => x"0000037c",
00000696 => x"00000288",
00000697 => x"00000288",
00000698 => x"00000288",
00000699 => x"00000384",
00000700 => x"00000288",
00000701 => x"00000288",
00000702 => x"00000288",
00000703 => x"00000288",
00000704 => x"0000038c",
00000705 => x"00000394",
00000706 => x"0000039c",
00000707 => x"000003a4",
00000708 => x"000003ac",
00000709 => x"000003b4",
00000710 => x"000003bc",
00000711 => x"000003c4",
00000712 => x"000003cc",
00000713 => x"000003d4",
00000714 => x"000003dc",
00000715 => x"000003e4",
00000716 => x"000003ec",
00000717 => x"000003f4",
00000718 => x"000003fc",
00000719 => x"00000404",
00000720 => x"00007830",
00000721 => x"4554523c",
00000722 => x"0000203e",
00000723 => x"74736e49",
00000724 => x"74637572",
00000725 => x"206e6f69",
00000726 => x"72646461",
00000727 => x"20737365",
00000728 => x"6173696d",
00000729 => x"6e67696c",
00000730 => x"00006465",
00000731 => x"74736e49",
00000732 => x"74637572",
00000733 => x"206e6f69",
00000734 => x"65636361",
00000735 => x"66207373",
00000736 => x"746c7561",
00000737 => x"00000000",
00000738 => x"656c6c49",
00000739 => x"206c6167",
00000740 => x"74736e69",
00000741 => x"74637572",
00000742 => x"006e6f69",
00000743 => x"61657242",
00000744 => x"696f706b",
00000745 => x"0000746e",
00000746 => x"64616f4c",
00000747 => x"64646120",
00000748 => x"73736572",
00000749 => x"73696d20",
00000750 => x"67696c61",
00000751 => x"0064656e",
00000752 => x"64616f4c",
00000753 => x"63636120",
00000754 => x"20737365",
00000755 => x"6c756166",
00000756 => x"00000074",
00000757 => x"726f7453",
00000758 => x"64612065",
00000759 => x"73657264",
00000760 => x"696d2073",
00000761 => x"696c6173",
00000762 => x"64656e67",
00000763 => x"00000000",
00000764 => x"726f7453",
00000765 => x"63612065",
00000766 => x"73736563",
00000767 => x"75616620",
00000768 => x"0000746c",
00000769 => x"69766e45",
00000770 => x"6d6e6f72",
00000771 => x"20746e65",
00000772 => x"6c6c6163",
00000773 => x"6f726620",
00000774 => x"2d55206d",
00000775 => x"65646f6d",
00000776 => x"00000000",
00000777 => x"69766e45",
00000778 => x"6d6e6f72",
00000779 => x"20746e65",
00000780 => x"6c6c6163",
00000781 => x"6f726620",
00000782 => x"2d4d206d",
00000783 => x"65646f6d",
00000784 => x"00000000",
00000785 => x"6863614d",
00000786 => x"20656e69",
00000787 => x"74666f73",
00000788 => x"65726177",
00000789 => x"746e6920",
00000790 => x"75727265",
00000791 => x"00007470",
00000792 => x"6863614d",
00000793 => x"20656e69",
00000794 => x"656d6974",
00000795 => x"6e692072",
00000796 => x"72726574",
00000797 => x"00747075",
00000798 => x"6863614d",
00000799 => x"20656e69",
00000800 => x"65747865",
00000801 => x"6c616e72",
00000802 => x"746e6920",
00000803 => x"75727265",
00000804 => x"00007470",
00000805 => x"74736146",
00000806 => x"746e6920",
00000807 => x"75727265",
00000808 => x"00207470",
00000809 => x"6e6b6e55",
00000810 => x"206e776f",
00000811 => x"70617274",
00000812 => x"75616320",
00000813 => x"203a6573",
00000814 => x"00000000",
00000815 => x"49545b20",
00000816 => x"554f454d",
00000817 => x"52455f54",
00000818 => x"00005d52",
00000819 => x"45445b20",
00000820 => x"45434956",
00000821 => x"5252455f",
00000822 => x"0000005d",
00000823 => x"4d505b20",
00000824 => x"52455f50",
00000825 => x"00005d52",
00000826 => x"50204020",
00000827 => x"00003d43",
00000828 => x"544d202c",
00000829 => x"3d4c4156",
00000830 => x"00000000",
00000831 => x"522f3c20",
00000832 => x"0a3e4554",
00000833 => x"00000000",
00000834 => x"0000058c",
00000835 => x"0000059c",
00000836 => x"000005c4",
00000837 => x"000005d0",
00000838 => x"000005dc",
00000839 => x"000005e8",
00000840 => x"000005f4",
00000841 => x"00000600",
00000842 => x"0000060c",
00000843 => x"000004f8",
00000844 => x"000004f8",
00000845 => x"00000618",
00000846 => x"33323130",
00000847 => x"37363534",
00000848 => x"42413938",
00000849 => x"46454443"
00000645 => x"00008293",
00000646 => x"f91ff0ef",
00000647 => x"40a00533",
00000648 => x"00028067",
00000649 => x"00008293",
00000650 => x"0005ca63",
00000651 => x"00054c63",
00000652 => x"f79ff0ef",
00000653 => x"00058513",
00000654 => x"00028067",
00000655 => x"40b005b3",
00000656 => x"fe0558e3",
00000657 => x"40a00533",
00000658 => x"f61ff0ef",
00000659 => x"40b00533",
00000660 => x"00028067",
00000661 => x"6f727245",
00000662 => x"4e202172",
00000663 => x"5047206f",
00000664 => x"75204f49",
00000665 => x"2074696e",
00000666 => x"746e7973",
00000667 => x"69736568",
00000668 => x"2164657a",
00000669 => x"0000000a",
00000670 => x"6e696c42",
00000671 => x"676e696b",
00000672 => x"44454c20",
00000673 => x"6d656420",
00000674 => x"7270206f",
00000675 => x"6172676f",
00000676 => x"00000a6d",
00000677 => x"000002cc",
00000678 => x"00000320",
00000679 => x"0000032c",
00000680 => x"00000334",
00000681 => x"0000033c",
00000682 => x"00000344",
00000683 => x"0000034c",
00000684 => x"00000354",
00000685 => x"0000035c",
00000686 => x"00000280",
00000687 => x"00000280",
00000688 => x"00000364",
00000689 => x"0000036c",
00000690 => x"00000280",
00000691 => x"00000280",
00000692 => x"00000280",
00000693 => x"00000374",
00000694 => x"00000280",
00000695 => x"00000280",
00000696 => x"00000280",
00000697 => x"0000037c",
00000698 => x"00000280",
00000699 => x"00000280",
00000700 => x"00000280",
00000701 => x"00000280",
00000702 => x"00000384",
00000703 => x"0000038c",
00000704 => x"00000394",
00000705 => x"0000039c",
00000706 => x"000003a4",
00000707 => x"000003ac",
00000708 => x"000003b4",
00000709 => x"000003bc",
00000710 => x"000003c4",
00000711 => x"000003cc",
00000712 => x"000003d4",
00000713 => x"000003dc",
00000714 => x"000003e4",
00000715 => x"000003ec",
00000716 => x"000003f4",
00000717 => x"000003fc",
00000718 => x"00007830",
00000719 => x"4554523c",
00000720 => x"0000203e",
00000721 => x"74736e49",
00000722 => x"74637572",
00000723 => x"206e6f69",
00000724 => x"72646461",
00000725 => x"20737365",
00000726 => x"6173696d",
00000727 => x"6e67696c",
00000728 => x"00006465",
00000729 => x"74736e49",
00000730 => x"74637572",
00000731 => x"206e6f69",
00000732 => x"65636361",
00000733 => x"66207373",
00000734 => x"746c7561",
00000735 => x"00000000",
00000736 => x"656c6c49",
00000737 => x"206c6167",
00000738 => x"74736e69",
00000739 => x"74637572",
00000740 => x"006e6f69",
00000741 => x"61657242",
00000742 => x"696f706b",
00000743 => x"0000746e",
00000744 => x"64616f4c",
00000745 => x"64646120",
00000746 => x"73736572",
00000747 => x"73696d20",
00000748 => x"67696c61",
00000749 => x"0064656e",
00000750 => x"64616f4c",
00000751 => x"63636120",
00000752 => x"20737365",
00000753 => x"6c756166",
00000754 => x"00000074",
00000755 => x"726f7453",
00000756 => x"64612065",
00000757 => x"73657264",
00000758 => x"696d2073",
00000759 => x"696c6173",
00000760 => x"64656e67",
00000761 => x"00000000",
00000762 => x"726f7453",
00000763 => x"63612065",
00000764 => x"73736563",
00000765 => x"75616620",
00000766 => x"0000746c",
00000767 => x"69766e45",
00000768 => x"6d6e6f72",
00000769 => x"20746e65",
00000770 => x"6c6c6163",
00000771 => x"6f726620",
00000772 => x"2d55206d",
00000773 => x"65646f6d",
00000774 => x"00000000",
00000775 => x"69766e45",
00000776 => x"6d6e6f72",
00000777 => x"20746e65",
00000778 => x"6c6c6163",
00000779 => x"6f726620",
00000780 => x"2d4d206d",
00000781 => x"65646f6d",
00000782 => x"00000000",
00000783 => x"6863614d",
00000784 => x"20656e69",
00000785 => x"74666f73",
00000786 => x"65726177",
00000787 => x"746e6920",
00000788 => x"75727265",
00000789 => x"00007470",
00000790 => x"6863614d",
00000791 => x"20656e69",
00000792 => x"656d6974",
00000793 => x"6e692072",
00000794 => x"72726574",
00000795 => x"00747075",
00000796 => x"6863614d",
00000797 => x"20656e69",
00000798 => x"65747865",
00000799 => x"6c616e72",
00000800 => x"746e6920",
00000801 => x"75727265",
00000802 => x"00007470",
00000803 => x"74736146",
00000804 => x"746e6920",
00000805 => x"75727265",
00000806 => x"00207470",
00000807 => x"6e6b6e55",
00000808 => x"206e776f",
00000809 => x"70617274",
00000810 => x"75616320",
00000811 => x"203a6573",
00000812 => x"00000000",
00000813 => x"49545b20",
00000814 => x"554f454d",
00000815 => x"52455f54",
00000816 => x"00005d52",
00000817 => x"45445b20",
00000818 => x"45434956",
00000819 => x"5252455f",
00000820 => x"0000005d",
00000821 => x"4d505b20",
00000822 => x"52455f50",
00000823 => x"00005d52",
00000824 => x"50204020",
00000825 => x"00003d43",
00000826 => x"544d202c",
00000827 => x"3d4c4156",
00000828 => x"00000000",
00000829 => x"522f3c20",
00000830 => x"0a3e4554",
00000831 => x"00000000",
00000832 => x"00000584",
00000833 => x"00000594",
00000834 => x"000005bc",
00000835 => x"000005c8",
00000836 => x"000005d4",
00000837 => x"000005e0",
00000838 => x"000005ec",
00000839 => x"000005f8",
00000840 => x"00000604",
00000841 => x"000004f0",
00000842 => x"000004f0",
00000843 => x"00000610",
00000844 => x"33323130",
00000845 => x"37363534",
00000846 => x"42413938",
00000847 => x"46454443"
);
 
end neorv32_application_image;
/rtl/core/neorv32_bootloader_image.vhd
1,6 → 1,6
-- The NEORV32 RISC-V Processor, https://github.com/stnolting/neorv32
-- Auto-generated memory init file (for BOOTLOADER) from source file <bootloader/main.bin>
-- Size: 3924 bytes
-- Size: 3916 bytes
 
library ieee;
use ieee.std_logic_1164.all;
17,14 → 17,14
00000003 => x"80010197",
00000004 => x"7f418193",
00000005 => x"00000517",
00000006 => x"0d450513",
00000006 => x"0cc50513",
00000007 => x"30551073",
00000008 => x"34151073",
00000009 => x"30001073",
00000010 => x"30401073",
00000011 => x"30601073",
00000012 => x"ffa00593",
00000013 => x"32059073",
00000011 => x"34401073",
00000012 => x"32001073",
00000013 => x"30601073",
00000014 => x"b0001073",
00000015 => x"b8001073",
00000016 => x"b0201073",
34,964 → 34,962
00000020 => x"00000293",
00000021 => x"00000313",
00000022 => x"00000393",
00000023 => x"00000713",
00000024 => x"00000793",
00000025 => x"00010417",
00000026 => x"d9c40413",
00000027 => x"00010497",
00000028 => x"f9448493",
00000029 => x"00042023",
00000030 => x"00440413",
00000031 => x"fe941ce3",
00000032 => x"80010597",
00000033 => x"f8058593",
00000034 => x"80818613",
00000035 => x"00c5d863",
00000036 => x"00058023",
00000037 => x"00158593",
00000038 => x"ff5ff06f",
00000039 => x"00001597",
00000040 => x"eb858593",
00000041 => x"80010617",
00000042 => x"f5c60613",
00000043 => x"80010697",
00000044 => x"f5468693",
00000045 => x"00d65c63",
00000046 => x"00058703",
00000047 => x"00e60023",
00000048 => x"00158593",
00000049 => x"00160613",
00000050 => x"fedff06f",
00000051 => x"00000513",
00000052 => x"00000593",
00000053 => x"060000ef",
00000054 => x"34051073",
00000055 => x"30047073",
00000056 => x"10500073",
00000057 => x"ffdff06f",
00000058 => x"ff810113",
00000059 => x"00812023",
00000060 => x"00912223",
00000061 => x"34202473",
00000062 => x"02044663",
00000063 => x"34102473",
00000064 => x"00041483",
00000065 => x"0034f493",
00000066 => x"00240413",
00000067 => x"34141073",
00000068 => x"00300413",
00000069 => x"00941863",
00000070 => x"34102473",
00000071 => x"00240413",
00000072 => x"34141073",
00000073 => x"00012403",
00000074 => x"00412483",
00000075 => x"00810113",
00000076 => x"30200073",
00000077 => x"fb010113",
00000078 => x"04912223",
00000079 => x"800004b7",
00000080 => x"00048793",
00000081 => x"04112623",
00000082 => x"04812423",
00000083 => x"05212023",
00000084 => x"03312e23",
00000085 => x"03412c23",
00000086 => x"03512a23",
00000087 => x"03612823",
00000088 => x"03712623",
00000089 => x"03812423",
00000090 => x"03912223",
00000091 => x"03a12023",
00000092 => x"01b12e23",
00000093 => x"0007a023",
00000094 => x"800007b7",
00000095 => x"0007a223",
00000096 => x"ffff07b7",
00000097 => x"77078793",
00000098 => x"30579073",
00000099 => x"000017b7",
00000100 => x"fa002423",
00000101 => x"90078793",
00000102 => x"faf02423",
00000103 => x"fe802783",
00000104 => x"00010737",
00000105 => x"00048493",
00000106 => x"00e7f7b3",
00000107 => x"00078863",
00000108 => x"00100793",
00000109 => x"fcf02423",
00000110 => x"fc002623",
00000111 => x"fa002023",
00000112 => x"fe002683",
00000113 => x"000097b7",
00000114 => x"ffff7637",
00000115 => x"00000713",
00000116 => x"5ff78793",
00000117 => x"a0060613",
00000118 => x"1ed7e463",
00000119 => x"000016b7",
00000120 => x"00000793",
00000121 => x"ffe68693",
00000122 => x"1ee6e663",
00000123 => x"fff70713",
00000124 => x"01879793",
00000023 => x"00010417",
00000024 => x"da440413",
00000025 => x"00010497",
00000026 => x"f9c48493",
00000027 => x"00042023",
00000028 => x"00440413",
00000029 => x"fe941ce3",
00000030 => x"00001597",
00000031 => x"ed458593",
00000032 => x"80010617",
00000033 => x"f8060613",
00000034 => x"80010697",
00000035 => x"f7868693",
00000036 => x"00d65c63",
00000037 => x"00058703",
00000038 => x"00e60023",
00000039 => x"00158593",
00000040 => x"00160613",
00000041 => x"fedff06f",
00000042 => x"80010717",
00000043 => x"f5870713",
00000044 => x"80818793",
00000045 => x"00f75863",
00000046 => x"00070023",
00000047 => x"00170713",
00000048 => x"ff5ff06f",
00000049 => x"00000513",
00000050 => x"00000593",
00000051 => x"060000ef",
00000052 => x"34051073",
00000053 => x"30047073",
00000054 => x"10500073",
00000055 => x"ff9ff06f",
00000056 => x"ff810113",
00000057 => x"00812023",
00000058 => x"00912223",
00000059 => x"34202473",
00000060 => x"02044663",
00000061 => x"34102473",
00000062 => x"00041483",
00000063 => x"0034f493",
00000064 => x"00240413",
00000065 => x"34141073",
00000066 => x"00300413",
00000067 => x"00941863",
00000068 => x"34102473",
00000069 => x"00240413",
00000070 => x"34141073",
00000071 => x"00012403",
00000072 => x"00412483",
00000073 => x"00810113",
00000074 => x"30200073",
00000075 => x"fb010113",
00000076 => x"04912223",
00000077 => x"800004b7",
00000078 => x"00048793",
00000079 => x"04112623",
00000080 => x"04812423",
00000081 => x"05212023",
00000082 => x"03312e23",
00000083 => x"03412c23",
00000084 => x"03512a23",
00000085 => x"03612823",
00000086 => x"03712623",
00000087 => x"03812423",
00000088 => x"03912223",
00000089 => x"03a12023",
00000090 => x"01b12e23",
00000091 => x"0007a023",
00000092 => x"800007b7",
00000093 => x"0007a223",
00000094 => x"ffff07b7",
00000095 => x"76878793",
00000096 => x"30579073",
00000097 => x"000017b7",
00000098 => x"fa002423",
00000099 => x"90078793",
00000100 => x"faf02423",
00000101 => x"fe802783",
00000102 => x"00010737",
00000103 => x"00048493",
00000104 => x"00e7f7b3",
00000105 => x"00078863",
00000106 => x"00100793",
00000107 => x"fcf02423",
00000108 => x"fc002623",
00000109 => x"fa002023",
00000110 => x"fe002683",
00000111 => x"000097b7",
00000112 => x"ffff7637",
00000113 => x"00000713",
00000114 => x"5ff78793",
00000115 => x"a0060613",
00000116 => x"1ed7e463",
00000117 => x"000016b7",
00000118 => x"00000793",
00000119 => x"ffe68693",
00000120 => x"1ee6e663",
00000121 => x"fff70713",
00000122 => x"01879793",
00000123 => x"00e7e7b3",
00000124 => x"10000737",
00000125 => x"00e7e7b3",
00000126 => x"10000737",
00000127 => x"00e7e7b3",
00000128 => x"faf02023",
00000129 => x"fe802783",
00000130 => x"00020737",
00000131 => x"00e7f7b3",
00000132 => x"02078463",
00000133 => x"fe002783",
00000134 => x"fff00713",
00000135 => x"f8e02c23",
00000136 => x"0027d793",
00000137 => x"f8002e23",
00000138 => x"f8f02c23",
00000139 => x"08000793",
00000140 => x"30479073",
00000141 => x"30046073",
00000142 => x"ffff1537",
00000143 => x"d2c50513",
00000144 => x"3b8000ef",
00000145 => x"f1302573",
00000146 => x"4b8000ef",
00000147 => x"ffff1537",
00000148 => x"d6450513",
00000149 => x"3a4000ef",
00000150 => x"fe002503",
00000151 => x"4a4000ef",
00000152 => x"ffff1537",
00000153 => x"d6c50513",
00000154 => x"390000ef",
00000155 => x"30102573",
00000156 => x"490000ef",
00000157 => x"ffff1537",
00000158 => x"d7450513",
00000159 => x"37c000ef",
00000160 => x"fc002573",
00000161 => x"47c000ef",
00000162 => x"ffff1537",
00000163 => x"d7850513",
00000164 => x"368000ef",
00000165 => x"fe802503",
00000166 => x"ffff1437",
00000167 => x"464000ef",
00000168 => x"ffff1537",
00000169 => x"d8050513",
00000170 => x"350000ef",
00000171 => x"ff802503",
00000172 => x"450000ef",
00000173 => x"d8840513",
00000174 => x"340000ef",
00000175 => x"ff002503",
00000176 => x"440000ef",
00000177 => x"ffff1537",
00000178 => x"d9450513",
00000179 => x"32c000ef",
00000180 => x"ffc02503",
00000181 => x"42c000ef",
00000182 => x"d8840513",
00000183 => x"31c000ef",
00000184 => x"ff402503",
00000185 => x"41c000ef",
00000186 => x"fe802783",
00000187 => x"00020737",
00000188 => x"00e7f7b3",
00000189 => x"04078c63",
00000190 => x"ffff1537",
00000191 => x"d9c50513",
00000192 => x"2f8000ef",
00000193 => x"f9402683",
00000194 => x"f9002703",
00000195 => x"f9402783",
00000196 => x"fef69ae3",
00000197 => x"fe002783",
00000198 => x"000405b7",
00000199 => x"00379793",
00000200 => x"00e78733",
00000201 => x"00f737b3",
00000202 => x"00d787b3",
00000203 => x"fe802683",
00000204 => x"00b6f6b3",
00000205 => x"0c068263",
00000206 => x"fa402683",
00000207 => x"0a06de63",
00000208 => x"ffff1537",
00000209 => x"dc850513",
00000210 => x"2b0000ef",
00000211 => x"ffff1937",
00000212 => x"dd890513",
00000213 => x"2a4000ef",
00000214 => x"ffff1a37",
00000215 => x"ffff1ab7",
00000216 => x"ffff1b37",
00000217 => x"ffff1bb7",
00000218 => x"ffff1c37",
00000219 => x"ffff1cb7",
00000220 => x"ffff1d37",
00000221 => x"e3ca0513",
00000222 => x"280000ef",
00000223 => x"fa402403",
00000224 => x"fe045ee3",
00000225 => x"0ff47413",
00000226 => x"00040513",
00000227 => x"254000ef",
00000228 => x"dd4a8513",
00000229 => x"264000ef",
00000230 => x"00010737",
00000231 => x"fa002783",
00000232 => x"fe07cee3",
00000233 => x"00e7f7b3",
00000234 => x"fe078ae3",
00000235 => x"07200793",
00000236 => x"06f41e63",
00000237 => x"ffff02b7",
00000238 => x"00028067",
00000239 => x"fb9ff06f",
00000240 => x"00170713",
00000241 => x"01071713",
00000242 => x"00c686b3",
00000243 => x"01075713",
00000244 => x"e09ff06f",
00000245 => x"ffe78613",
00000246 => x"0fd67613",
00000247 => x"00061a63",
00000248 => x"00375713",
00000249 => x"00178793",
00000250 => x"0ff7f793",
00000251 => x"dfdff06f",
00000252 => x"00175713",
00000253 => x"ff1ff06f",
00000254 => x"f9402683",
00000255 => x"f9002603",
00000256 => x"f9402503",
00000257 => x"fea69ae3",
00000258 => x"f2f6e2e3",
00000259 => x"00d79463",
00000260 => x"f0e66ee3",
00000261 => x"00100513",
00000262 => x"6a4000ef",
00000263 => x"ffff1537",
00000264 => x"dd450513",
00000265 => x"1d4000ef",
00000266 => x"228000ef",
00000267 => x"06800793",
00000268 => x"dd890513",
00000269 => x"02f40263",
00000270 => x"07500793",
00000271 => x"00000513",
00000272 => x"16f40663",
00000273 => x"07300793",
00000274 => x"14f41c63",
00000275 => x"0004a403",
00000276 => x"00041863",
00000277 => x"e44b8513",
00000278 => x"1a0000ef",
00000279 => x"f19ff06f",
00000280 => x"e60c0513",
00000281 => x"194000ef",
00000282 => x"00040513",
00000283 => x"294000ef",
00000284 => x"e68c8513",
00000285 => x"184000ef",
00000286 => x"08000537",
00000287 => x"284000ef",
00000288 => x"e80d0513",
00000289 => x"174000ef",
00000290 => x"fa402d83",
00000291 => x"fe0ddee3",
00000292 => x"0ffdfd93",
00000293 => x"000d8513",
00000294 => x"148000ef",
00000295 => x"07900793",
00000296 => x"ecfd9ae3",
00000297 => x"468000ef",
00000298 => x"00051663",
00000299 => x"00300513",
00000300 => x"1d8000ef",
00000301 => x"ffff1537",
00000302 => x"e8c50513",
00000303 => x"01045d93",
00000304 => x"138000ef",
00000305 => x"001d8d93",
00000306 => x"080009b7",
00000307 => x"fff00693",
00000308 => x"fffd8d93",
00000309 => x"06dd9063",
00000310 => x"4788d5b7",
00000311 => x"afe58593",
00000126 => x"faf02023",
00000127 => x"fe802783",
00000128 => x"00020737",
00000129 => x"00e7f7b3",
00000130 => x"02078463",
00000131 => x"fe002783",
00000132 => x"fff00713",
00000133 => x"f8e02c23",
00000134 => x"0027d793",
00000135 => x"f8002e23",
00000136 => x"f8f02c23",
00000137 => x"08000793",
00000138 => x"30479073",
00000139 => x"30046073",
00000140 => x"ffff1537",
00000141 => x"d2450513",
00000142 => x"3b8000ef",
00000143 => x"f1302573",
00000144 => x"4b8000ef",
00000145 => x"ffff1537",
00000146 => x"d5c50513",
00000147 => x"3a4000ef",
00000148 => x"fe002503",
00000149 => x"4a4000ef",
00000150 => x"ffff1537",
00000151 => x"d6450513",
00000152 => x"390000ef",
00000153 => x"30102573",
00000154 => x"490000ef",
00000155 => x"ffff1537",
00000156 => x"d6c50513",
00000157 => x"37c000ef",
00000158 => x"fc002573",
00000159 => x"47c000ef",
00000160 => x"ffff1537",
00000161 => x"d7050513",
00000162 => x"368000ef",
00000163 => x"fe802503",
00000164 => x"ffff1437",
00000165 => x"464000ef",
00000166 => x"ffff1537",
00000167 => x"d7850513",
00000168 => x"350000ef",
00000169 => x"ff802503",
00000170 => x"450000ef",
00000171 => x"d8040513",
00000172 => x"340000ef",
00000173 => x"ff002503",
00000174 => x"440000ef",
00000175 => x"ffff1537",
00000176 => x"d8c50513",
00000177 => x"32c000ef",
00000178 => x"ffc02503",
00000179 => x"42c000ef",
00000180 => x"d8040513",
00000181 => x"31c000ef",
00000182 => x"ff402503",
00000183 => x"41c000ef",
00000184 => x"fe802783",
00000185 => x"00020737",
00000186 => x"00e7f7b3",
00000187 => x"04078c63",
00000188 => x"ffff1537",
00000189 => x"d9450513",
00000190 => x"2f8000ef",
00000191 => x"f9402683",
00000192 => x"f9002703",
00000193 => x"f9402783",
00000194 => x"fef69ae3",
00000195 => x"fe002783",
00000196 => x"000405b7",
00000197 => x"00379793",
00000198 => x"00e78733",
00000199 => x"00f737b3",
00000200 => x"00d787b3",
00000201 => x"fe802683",
00000202 => x"00b6f6b3",
00000203 => x"0c068263",
00000204 => x"fa402683",
00000205 => x"0a06de63",
00000206 => x"ffff1537",
00000207 => x"dc050513",
00000208 => x"2b0000ef",
00000209 => x"ffff1937",
00000210 => x"dd090513",
00000211 => x"2a4000ef",
00000212 => x"ffff1a37",
00000213 => x"ffff1ab7",
00000214 => x"ffff1b37",
00000215 => x"ffff1bb7",
00000216 => x"ffff1c37",
00000217 => x"ffff1cb7",
00000218 => x"ffff1d37",
00000219 => x"e34a0513",
00000220 => x"280000ef",
00000221 => x"fa402403",
00000222 => x"fe045ee3",
00000223 => x"0ff47413",
00000224 => x"00040513",
00000225 => x"254000ef",
00000226 => x"dcca8513",
00000227 => x"264000ef",
00000228 => x"00010737",
00000229 => x"fa002783",
00000230 => x"fe07cee3",
00000231 => x"00e7f7b3",
00000232 => x"fe078ae3",
00000233 => x"07200793",
00000234 => x"06f41e63",
00000235 => x"ffff02b7",
00000236 => x"00028067",
00000237 => x"fb9ff06f",
00000238 => x"00170713",
00000239 => x"01071713",
00000240 => x"00c686b3",
00000241 => x"01075713",
00000242 => x"e09ff06f",
00000243 => x"ffe78613",
00000244 => x"0fd67613",
00000245 => x"00061a63",
00000246 => x"00375713",
00000247 => x"00178793",
00000248 => x"0ff7f793",
00000249 => x"dfdff06f",
00000250 => x"00175713",
00000251 => x"ff1ff06f",
00000252 => x"f9402683",
00000253 => x"f9002603",
00000254 => x"f9402503",
00000255 => x"fea69ae3",
00000256 => x"f2f6e2e3",
00000257 => x"00d79463",
00000258 => x"f0e66ee3",
00000259 => x"00100513",
00000260 => x"6a4000ef",
00000261 => x"ffff1537",
00000262 => x"dcc50513",
00000263 => x"1d4000ef",
00000264 => x"228000ef",
00000265 => x"06800793",
00000266 => x"dd090513",
00000267 => x"02f40263",
00000268 => x"07500793",
00000269 => x"00000513",
00000270 => x"16f40663",
00000271 => x"07300793",
00000272 => x"14f41c63",
00000273 => x"0004a403",
00000274 => x"00041863",
00000275 => x"e3cb8513",
00000276 => x"1a0000ef",
00000277 => x"f19ff06f",
00000278 => x"e58c0513",
00000279 => x"194000ef",
00000280 => x"00040513",
00000281 => x"294000ef",
00000282 => x"e60c8513",
00000283 => x"184000ef",
00000284 => x"08000537",
00000285 => x"284000ef",
00000286 => x"e78d0513",
00000287 => x"174000ef",
00000288 => x"fa402d83",
00000289 => x"fe0ddee3",
00000290 => x"0ffdfd93",
00000291 => x"000d8513",
00000292 => x"148000ef",
00000293 => x"07900793",
00000294 => x"ecfd9ae3",
00000295 => x"468000ef",
00000296 => x"00051663",
00000297 => x"00300513",
00000298 => x"1d8000ef",
00000299 => x"ffff1537",
00000300 => x"e8450513",
00000301 => x"01045d93",
00000302 => x"138000ef",
00000303 => x"001d8d93",
00000304 => x"080009b7",
00000305 => x"fff00693",
00000306 => x"fffd8d93",
00000307 => x"06dd9063",
00000308 => x"4788d5b7",
00000309 => x"afe58593",
00000310 => x"08000537",
00000311 => x"718000ef",
00000312 => x"08000537",
00000313 => x"718000ef",
00000314 => x"08000537",
00000315 => x"00040593",
00000316 => x"00450513",
00000317 => x"708000ef",
00000318 => x"ff002603",
00000319 => x"08000737",
00000320 => x"ffc47413",
00000321 => x"00000d93",
00000322 => x"00000793",
00000323 => x"00c70813",
00000324 => x"010d8533",
00000325 => x"00cd86b3",
00000326 => x"05b41c63",
00000327 => x"00870513",
00000328 => x"40f005b3",
00000329 => x"6d8000ef",
00000330 => x"ffff1537",
00000331 => x"d2850513",
00000332 => x"f29ff06f",
00000333 => x"468000ef",
00000334 => x"fa802703",
00000335 => x"0d800513",
00000336 => x"00176713",
00000337 => x"fae02423",
00000338 => x"3b0000ef",
00000339 => x"00098513",
00000340 => x"48c000ef",
00000341 => x"fa802703",
00000342 => x"ffe77713",
00000343 => x"fae02423",
00000344 => x"3f8000ef",
00000345 => x"00010637",
00000346 => x"00c989b3",
00000347 => x"f61ff06f",
00000348 => x"0006a583",
00000349 => x"00c12623",
00000350 => x"004d8d93",
00000351 => x"00b787b3",
00000352 => x"00f12423",
00000353 => x"678000ef",
00000354 => x"080007b7",
00000355 => x"00c78813",
00000356 => x"00c12603",
00000357 => x"00812783",
00000358 => x"08000737",
00000359 => x"f75ff06f",
00000360 => x"06c00793",
00000361 => x"00f41863",
00000362 => x"00100513",
00000363 => x"510000ef",
00000364 => x"dc5ff06f",
00000365 => x"06500793",
00000366 => x"00f41863",
00000367 => x"0004a783",
00000368 => x"e8078ae3",
00000369 => x"e65ff06f",
00000370 => x"03f00793",
00000371 => x"e9cb0513",
00000372 => x"e8f404e3",
00000373 => x"ffff17b7",
00000374 => x"ed878513",
00000375 => x"e7dff06f",
00000376 => x"00040737",
00000377 => x"fa002783",
00000378 => x"00e7f7b3",
00000379 => x"fe079ce3",
00000380 => x"faa02223",
00000381 => x"00008067",
00000382 => x"ff010113",
00000383 => x"00812423",
00000384 => x"01212023",
00000385 => x"00112623",
00000386 => x"00912223",
00000387 => x"00050413",
00000388 => x"00a00913",
00000389 => x"00044483",
00000390 => x"00140413",
00000391 => x"00049e63",
00000392 => x"00c12083",
00000393 => x"00812403",
00000394 => x"00412483",
00000395 => x"00012903",
00000396 => x"01010113",
00000397 => x"00008067",
00000398 => x"01249663",
00000399 => x"00d00513",
00000400 => x"fa1ff0ef",
00000401 => x"00048513",
00000402 => x"f99ff0ef",
00000403 => x"fc9ff06f",
00000404 => x"ff010113",
00000405 => x"00112623",
00000406 => x"30047073",
00000407 => x"ffff1537",
00000408 => x"c8c50513",
00000409 => x"f95ff0ef",
00000410 => x"00010737",
00000411 => x"fa002783",
00000412 => x"fe07cee3",
00000413 => x"00e7f7b3",
00000414 => x"fe078ae3",
00000415 => x"ff002783",
00000416 => x"00078067",
00000417 => x"0000006f",
00000418 => x"ff010113",
00000419 => x"00812423",
00000420 => x"00050413",
00000421 => x"ffff1537",
00000422 => x"c9c50513",
00000423 => x"00112623",
00000424 => x"f59ff0ef",
00000425 => x"03040513",
00000426 => x"0ff57513",
00000427 => x"f35ff0ef",
00000428 => x"03a00513",
00000429 => x"f2dff0ef",
00000430 => x"02000513",
00000431 => x"f25ff0ef",
00000432 => x"00141793",
00000433 => x"008787b3",
00000434 => x"ffff1537",
00000435 => x"00379793",
00000436 => x"ee450513",
00000437 => x"00f50533",
00000438 => x"f21ff0ef",
00000439 => x"30047073",
00000440 => x"fe802783",
00000441 => x"00010737",
00000442 => x"00e7f7b3",
00000443 => x"00078863",
00000444 => x"00100793",
00000445 => x"fcf02423",
00000446 => x"fc002623",
00000447 => x"0000006f",
00000448 => x"fe010113",
00000449 => x"01212823",
00000450 => x"00050913",
00000451 => x"ffff1537",
00000452 => x"00912a23",
00000453 => x"ca850513",
00000454 => x"ffff14b7",
00000455 => x"00812c23",
00000456 => x"01312623",
00000457 => x"00112e23",
00000458 => x"01c00413",
00000459 => x"ecdff0ef",
00000460 => x"f4448493",
00000461 => x"ffc00993",
00000462 => x"008957b3",
00000463 => x"00f7f793",
00000464 => x"00f487b3",
00000465 => x"0007c503",
00000466 => x"ffc40413",
00000467 => x"e95ff0ef",
00000468 => x"ff3414e3",
00000469 => x"01c12083",
00000470 => x"01812403",
00000471 => x"01412483",
00000472 => x"01012903",
00000473 => x"00c12983",
00000474 => x"02010113",
00000475 => x"00008067",
00000476 => x"fb010113",
00000477 => x"04112623",
00000478 => x"04512423",
00000479 => x"04612223",
00000480 => x"04712023",
00000481 => x"02812e23",
00000482 => x"02912c23",
00000483 => x"02a12a23",
00000484 => x"02b12823",
00000485 => x"02c12623",
00000486 => x"02d12423",
00000487 => x"02e12223",
00000488 => x"02f12023",
00000489 => x"01012e23",
00000490 => x"01112c23",
00000491 => x"01c12a23",
00000492 => x"01d12823",
00000493 => x"01e12623",
00000494 => x"01f12423",
00000495 => x"342024f3",
00000496 => x"800007b7",
00000497 => x"00778793",
00000498 => x"0af49663",
00000499 => x"fe802783",
00000500 => x"00010737",
00000501 => x"00e7f7b3",
00000502 => x"00078863",
00000503 => x"fc802783",
00000504 => x"0017c793",
00000505 => x"fcf02423",
00000506 => x"fe802783",
00000507 => x"00020737",
00000508 => x"00e7f7b3",
00000509 => x"02078863",
00000510 => x"f9802703",
00000511 => x"f9c02683",
00000512 => x"fe002783",
00000513 => x"0027d793",
00000514 => x"00e78733",
00000515 => x"00f737b3",
00000516 => x"00d787b3",
00000517 => x"fff00693",
00000518 => x"f8d02c23",
00000519 => x"f8f02e23",
00000520 => x"f8e02c23",
00000521 => x"03c12403",
00000522 => x"04c12083",
00000523 => x"04812283",
00000524 => x"04412303",
00000525 => x"04012383",
00000526 => x"03812483",
00000527 => x"03412503",
00000528 => x"03012583",
00000529 => x"02c12603",
00000530 => x"02812683",
00000531 => x"02412703",
00000532 => x"02012783",
00000533 => x"01c12803",
00000534 => x"01812883",
00000535 => x"01412e03",
00000536 => x"01012e83",
00000537 => x"00c12f03",
00000538 => x"00812f83",
00000539 => x"05010113",
00000540 => x"30200073",
00000541 => x"00700793",
00000542 => x"00f49c63",
00000543 => x"800007b7",
00000544 => x"0047a783",
00000545 => x"00078663",
00000546 => x"00100513",
00000547 => x"dfdff0ef",
00000548 => x"34102473",
00000549 => x"fe802783",
00000550 => x"00040737",
00000551 => x"00e7f7b3",
00000552 => x"04078663",
00000553 => x"ffff1537",
00000554 => x"cac50513",
00000555 => x"d4dff0ef",
00000556 => x"00048513",
00000557 => x"e4dff0ef",
00000558 => x"ffff1537",
00000559 => x"cd450513",
00000560 => x"d39ff0ef",
00000561 => x"00040513",
00000562 => x"e39ff0ef",
00000563 => x"ffff1537",
00000564 => x"cdc50513",
00000565 => x"d25ff0ef",
00000566 => x"34302573",
00000567 => x"e25ff0ef",
00000568 => x"ffff1537",
00000569 => x"ce450513",
00000570 => x"d11ff0ef",
00000571 => x"00440413",
00000572 => x"34141073",
00000573 => x"f31ff06f",
00000574 => x"faa02623",
00000575 => x"fa802783",
00000576 => x"fe07cee3",
00000577 => x"fac02503",
00000578 => x"00008067",
00000579 => x"ff010113",
00000580 => x"00812423",
00000581 => x"fa800413",
00000582 => x"00042783",
00000583 => x"00112623",
00000584 => x"09e00513",
00000585 => x"0017e793",
00000586 => x"00f42023",
00000587 => x"fcdff0ef",
00000588 => x"00000513",
00000589 => x"fc5ff0ef",
00000590 => x"00042783",
00000591 => x"00c12083",
00000592 => x"0ff57513",
00000593 => x"ffe7f793",
00000594 => x"00f42023",
00000595 => x"00812403",
00000596 => x"01010113",
00000597 => x"00008067",
00000598 => x"ff010113",
00000599 => x"00112623",
00000600 => x"fa802783",
00000601 => x"00500513",
00000602 => x"0017e793",
00000603 => x"faf02423",
00000604 => x"f89ff0ef",
00000605 => x"00000513",
00000606 => x"f81ff0ef",
00000607 => x"fa802783",
00000608 => x"00157513",
00000609 => x"ffe7f793",
00000610 => x"faf02423",
00000611 => x"fc051ae3",
00000612 => x"00c12083",
00000613 => x"01010113",
00000614 => x"00008067",
00000615 => x"ff010113",
00000616 => x"00812423",
00000617 => x"fa800413",
00000618 => x"00042783",
00000619 => x"00112623",
00000620 => x"00600513",
00000621 => x"0017e793",
00000622 => x"00f42023",
00000623 => x"f3dff0ef",
00000624 => x"00042783",
00000625 => x"00c12083",
00000626 => x"ffe7f793",
00000627 => x"00f42023",
00000628 => x"00812403",
00000629 => x"01010113",
00000630 => x"00008067",
00000631 => x"ff010113",
00000632 => x"00812423",
00000633 => x"00050413",
00000634 => x"01055513",
00000635 => x"0ff57513",
00000636 => x"00112623",
00000637 => x"f05ff0ef",
00000638 => x"00845513",
00000639 => x"0ff57513",
00000640 => x"ef9ff0ef",
00000641 => x"0ff47513",
00000642 => x"00812403",
00000643 => x"00c12083",
00000644 => x"01010113",
00000645 => x"ee5ff06f",
00000646 => x"fd010113",
00000647 => x"02812423",
00000648 => x"02912223",
00000649 => x"03212023",
00000650 => x"01312e23",
00000651 => x"02112623",
00000652 => x"00050993",
00000653 => x"00058493",
00000654 => x"00c10913",
00000655 => x"00358413",
00000656 => x"04099263",
00000657 => x"fa402783",
00000658 => x"fe07dee3",
00000659 => x"00f90023",
00000660 => x"00190913",
00000661 => x"fff40793",
00000662 => x"02849263",
00000663 => x"02c12083",
00000664 => x"02812403",
00000665 => x"00c12503",
00000666 => x"02412483",
00000667 => x"02012903",
00000668 => x"01c12983",
00000669 => x"03010113",
00000670 => x"00008067",
00000671 => x"00078413",
00000672 => x"fc1ff06f",
00000673 => x"fa802783",
00000674 => x"00300513",
00000675 => x"0017e793",
00000676 => x"faf02423",
00000677 => x"e65ff0ef",
00000678 => x"00040513",
00000679 => x"f41ff0ef",
00000680 => x"00000513",
00000681 => x"e55ff0ef",
00000682 => x"fa802783",
00000683 => x"ffe7f793",
00000684 => x"faf02423",
00000685 => x"00a90023",
00000686 => x"f99ff06f",
00000687 => x"fd010113",
00000688 => x"01412c23",
00000689 => x"80000a37",
00000690 => x"02812423",
00000691 => x"004a0793",
00000692 => x"02112623",
00000693 => x"02912223",
00000694 => x"03212023",
00000695 => x"01312e23",
00000696 => x"01512a23",
00000697 => x"01612823",
00000698 => x"01712623",
00000699 => x"01812423",
00000700 => x"00100713",
00000701 => x"00e7a023",
00000702 => x"00050413",
00000703 => x"004a0a13",
00000704 => x"02051863",
00000705 => x"ffff1537",
00000706 => x"cfc50513",
00000707 => x"aedff0ef",
00000708 => x"080005b7",
00000709 => x"00040513",
00000710 => x"f01ff0ef",
00000711 => x"4788d7b7",
00000712 => x"afe78793",
00000713 => x"02f50463",
00000714 => x"00000513",
00000715 => x"01c0006f",
00000716 => x"ffff1537",
00000717 => x"d1c50513",
00000718 => x"ac1ff0ef",
00000719 => x"dd1ff0ef",
00000720 => x"fc0518e3",
00000721 => x"00300513",
00000722 => x"b41ff0ef",
00000723 => x"080009b7",
00000724 => x"00498593",
00000725 => x"00040513",
00000726 => x"ec1ff0ef",
00000727 => x"00050a93",
00000728 => x"00898593",
00000729 => x"00040513",
00000730 => x"eb1ff0ef",
00000731 => x"ff002c03",
00000732 => x"00050b13",
00000733 => x"ffcafb93",
00000734 => x"00000913",
00000735 => x"00000493",
00000736 => x"00c98993",
00000737 => x"013905b3",
00000738 => x"05791c63",
00000739 => x"016484b3",
00000740 => x"00200513",
00000741 => x"fa049ae3",
00000742 => x"ffff1537",
00000743 => x"d2850513",
00000744 => x"a59ff0ef",
00000745 => x"02c12083",
00000746 => x"02812403",
00000747 => x"800007b7",
00000748 => x"0157a023",
00000749 => x"000a2023",
00000750 => x"02412483",
00000751 => x"02012903",
00000752 => x"01c12983",
00000753 => x"01812a03",
00000754 => x"01412a83",
00000755 => x"01012b03",
00000756 => x"00c12b83",
00000757 => x"00812c03",
00000758 => x"03010113",
00000759 => x"00008067",
00000760 => x"00040513",
00000761 => x"e35ff0ef",
00000762 => x"012c07b3",
00000763 => x"00a484b3",
00000764 => x"00a7a023",
00000765 => x"00490913",
00000766 => x"f8dff06f",
00000767 => x"fd010113",
00000768 => x"02812423",
00000769 => x"02912223",
00000770 => x"03212023",
00000771 => x"02112623",
00000772 => x"01312e23",
00000773 => x"00050413",
00000774 => x"00b12623",
00000775 => x"00c10913",
00000776 => x"00350493",
00000777 => x"00094983",
00000778 => x"d75ff0ef",
00000779 => x"fa802783",
00000780 => x"00200513",
00000781 => x"00190913",
00000782 => x"0017e793",
00000783 => x"faf02423",
00000784 => x"cb9ff0ef",
00000785 => x"00048513",
00000786 => x"d95ff0ef",
00000787 => x"00098513",
00000788 => x"ca9ff0ef",
00000789 => x"fa802783",
00000790 => x"ffe7f793",
00000791 => x"faf02423",
00000792 => x"cf9ff0ef",
00000793 => x"00048793",
00000794 => x"fff48493",
00000795 => x"faf41ce3",
00000796 => x"02c12083",
00000797 => x"02812403",
00000798 => x"02412483",
00000799 => x"02012903",
00000800 => x"01c12983",
00000801 => x"03010113",
00000802 => x"00008067",
00000803 => x"746f6f42",
00000804 => x"2e676e69",
00000805 => x"0a0a2e2e",
00000806 => x"00000000",
00000807 => x"52450a07",
00000808 => x"5f524f52",
00000809 => x"00000000",
00000810 => x"00007830",
00000811 => x"52455b0a",
00000812 => x"20524f52",
00000813 => x"6e55202d",
00000814 => x"65707865",
00000815 => x"64657463",
00000816 => x"63786520",
00000817 => x"69747065",
00000818 => x"20216e6f",
00000819 => x"7561636d",
00000820 => x"003d6573",
00000821 => x"70656d20",
00000822 => x"00003d63",
00000823 => x"76746d20",
00000824 => x"003d6c61",
00000825 => x"7274205d",
00000826 => x"676e6979",
00000827 => x"206f7420",
00000828 => x"75736572",
00000829 => x"2e2e656d",
00000830 => x"00000a2e",
00000831 => x"69617741",
00000832 => x"676e6974",
00000833 => x"6f656e20",
00000834 => x"32337672",
00000835 => x"6578655f",
00000836 => x"6e69622e",
00000837 => x"202e2e2e",
00000838 => x"00000000",
00000839 => x"64616f4c",
00000840 => x"2e676e69",
00000841 => x"00202e2e",
00000842 => x"00004b4f",
00000843 => x"3c0a0a0a",
00000844 => x"454e203c",
00000845 => x"3356524f",
00000846 => x"6f422032",
00000847 => x"6f6c746f",
00000848 => x"72656461",
00000849 => x"0a3e3e20",
00000850 => x"444c420a",
00000851 => x"46203a56",
00000852 => x"31206265",
00000853 => x"30322036",
00000854 => x"480a3232",
00000855 => x"203a5657",
00000856 => x"00000020",
00000857 => x"4b4c430a",
00000313 => x"00040593",
00000314 => x"00450513",
00000315 => x"708000ef",
00000316 => x"ff002603",
00000317 => x"08000737",
00000318 => x"ffc47413",
00000319 => x"00000d93",
00000320 => x"00000793",
00000321 => x"00c70813",
00000322 => x"010d8533",
00000323 => x"00cd86b3",
00000324 => x"05b41c63",
00000325 => x"00870513",
00000326 => x"40f005b3",
00000327 => x"6d8000ef",
00000328 => x"ffff1537",
00000329 => x"d2050513",
00000330 => x"f29ff06f",
00000331 => x"468000ef",
00000332 => x"fa802703",
00000333 => x"0d800513",
00000334 => x"00176713",
00000335 => x"fae02423",
00000336 => x"3b0000ef",
00000337 => x"00098513",
00000338 => x"48c000ef",
00000339 => x"fa802703",
00000340 => x"ffe77713",
00000341 => x"fae02423",
00000342 => x"3f8000ef",
00000343 => x"00010637",
00000344 => x"00c989b3",
00000345 => x"f61ff06f",
00000346 => x"0006a583",
00000347 => x"00c12623",
00000348 => x"004d8d93",
00000349 => x"00b787b3",
00000350 => x"00f12423",
00000351 => x"678000ef",
00000352 => x"080007b7",
00000353 => x"00c78813",
00000354 => x"00c12603",
00000355 => x"00812783",
00000356 => x"08000737",
00000357 => x"f75ff06f",
00000358 => x"06c00793",
00000359 => x"00f41863",
00000360 => x"00100513",
00000361 => x"510000ef",
00000362 => x"dc5ff06f",
00000363 => x"06500793",
00000364 => x"00f41863",
00000365 => x"0004a783",
00000366 => x"e8078ae3",
00000367 => x"e65ff06f",
00000368 => x"03f00793",
00000369 => x"e94b0513",
00000370 => x"e8f404e3",
00000371 => x"ffff17b7",
00000372 => x"ed078513",
00000373 => x"e7dff06f",
00000374 => x"00040737",
00000375 => x"fa002783",
00000376 => x"00e7f7b3",
00000377 => x"fe079ce3",
00000378 => x"faa02223",
00000379 => x"00008067",
00000380 => x"ff010113",
00000381 => x"00812423",
00000382 => x"01212023",
00000383 => x"00112623",
00000384 => x"00912223",
00000385 => x"00050413",
00000386 => x"00a00913",
00000387 => x"00044483",
00000388 => x"00140413",
00000389 => x"00049e63",
00000390 => x"00c12083",
00000391 => x"00812403",
00000392 => x"00412483",
00000393 => x"00012903",
00000394 => x"01010113",
00000395 => x"00008067",
00000396 => x"01249663",
00000397 => x"00d00513",
00000398 => x"fa1ff0ef",
00000399 => x"00048513",
00000400 => x"f99ff0ef",
00000401 => x"fc9ff06f",
00000402 => x"ff010113",
00000403 => x"00112623",
00000404 => x"30047073",
00000405 => x"ffff1537",
00000406 => x"c8450513",
00000407 => x"f95ff0ef",
00000408 => x"00010737",
00000409 => x"fa002783",
00000410 => x"fe07cee3",
00000411 => x"00e7f7b3",
00000412 => x"fe078ae3",
00000413 => x"ff002783",
00000414 => x"00078067",
00000415 => x"0000006f",
00000416 => x"ff010113",
00000417 => x"00812423",
00000418 => x"00050413",
00000419 => x"ffff1537",
00000420 => x"c9450513",
00000421 => x"00112623",
00000422 => x"f59ff0ef",
00000423 => x"03040513",
00000424 => x"0ff57513",
00000425 => x"f35ff0ef",
00000426 => x"03a00513",
00000427 => x"f2dff0ef",
00000428 => x"02000513",
00000429 => x"f25ff0ef",
00000430 => x"00141793",
00000431 => x"008787b3",
00000432 => x"ffff1537",
00000433 => x"00379793",
00000434 => x"edc50513",
00000435 => x"00f50533",
00000436 => x"f21ff0ef",
00000437 => x"30047073",
00000438 => x"fe802783",
00000439 => x"00010737",
00000440 => x"00e7f7b3",
00000441 => x"00078863",
00000442 => x"00100793",
00000443 => x"fcf02423",
00000444 => x"fc002623",
00000445 => x"0000006f",
00000446 => x"fe010113",
00000447 => x"01212823",
00000448 => x"00050913",
00000449 => x"ffff1537",
00000450 => x"00912a23",
00000451 => x"ca050513",
00000452 => x"ffff14b7",
00000453 => x"00812c23",
00000454 => x"01312623",
00000455 => x"00112e23",
00000456 => x"01c00413",
00000457 => x"ecdff0ef",
00000458 => x"f3c48493",
00000459 => x"ffc00993",
00000460 => x"008957b3",
00000461 => x"00f7f793",
00000462 => x"00f487b3",
00000463 => x"0007c503",
00000464 => x"ffc40413",
00000465 => x"e95ff0ef",
00000466 => x"ff3414e3",
00000467 => x"01c12083",
00000468 => x"01812403",
00000469 => x"01412483",
00000470 => x"01012903",
00000471 => x"00c12983",
00000472 => x"02010113",
00000473 => x"00008067",
00000474 => x"fb010113",
00000475 => x"04112623",
00000476 => x"04512423",
00000477 => x"04612223",
00000478 => x"04712023",
00000479 => x"02812e23",
00000480 => x"02912c23",
00000481 => x"02a12a23",
00000482 => x"02b12823",
00000483 => x"02c12623",
00000484 => x"02d12423",
00000485 => x"02e12223",
00000486 => x"02f12023",
00000487 => x"01012e23",
00000488 => x"01112c23",
00000489 => x"01c12a23",
00000490 => x"01d12823",
00000491 => x"01e12623",
00000492 => x"01f12423",
00000493 => x"342024f3",
00000494 => x"800007b7",
00000495 => x"00778793",
00000496 => x"0af49663",
00000497 => x"fe802783",
00000498 => x"00010737",
00000499 => x"00e7f7b3",
00000500 => x"00078863",
00000501 => x"fc802783",
00000502 => x"0017c793",
00000503 => x"fcf02423",
00000504 => x"fe802783",
00000505 => x"00020737",
00000506 => x"00e7f7b3",
00000507 => x"02078863",
00000508 => x"f9802703",
00000509 => x"f9c02683",
00000510 => x"fe002783",
00000511 => x"0027d793",
00000512 => x"00e78733",
00000513 => x"00f737b3",
00000514 => x"00d787b3",
00000515 => x"fff00693",
00000516 => x"f8d02c23",
00000517 => x"f8f02e23",
00000518 => x"f8e02c23",
00000519 => x"03c12403",
00000520 => x"04c12083",
00000521 => x"04812283",
00000522 => x"04412303",
00000523 => x"04012383",
00000524 => x"03812483",
00000525 => x"03412503",
00000526 => x"03012583",
00000527 => x"02c12603",
00000528 => x"02812683",
00000529 => x"02412703",
00000530 => x"02012783",
00000531 => x"01c12803",
00000532 => x"01812883",
00000533 => x"01412e03",
00000534 => x"01012e83",
00000535 => x"00c12f03",
00000536 => x"00812f83",
00000537 => x"05010113",
00000538 => x"30200073",
00000539 => x"00700793",
00000540 => x"00f49c63",
00000541 => x"800007b7",
00000542 => x"0047a783",
00000543 => x"00078663",
00000544 => x"00100513",
00000545 => x"dfdff0ef",
00000546 => x"34102473",
00000547 => x"fe802783",
00000548 => x"00040737",
00000549 => x"00e7f7b3",
00000550 => x"04078663",
00000551 => x"ffff1537",
00000552 => x"ca450513",
00000553 => x"d4dff0ef",
00000554 => x"00048513",
00000555 => x"e4dff0ef",
00000556 => x"ffff1537",
00000557 => x"ccc50513",
00000558 => x"d39ff0ef",
00000559 => x"00040513",
00000560 => x"e39ff0ef",
00000561 => x"ffff1537",
00000562 => x"cd450513",
00000563 => x"d25ff0ef",
00000564 => x"34302573",
00000565 => x"e25ff0ef",
00000566 => x"ffff1537",
00000567 => x"cdc50513",
00000568 => x"d11ff0ef",
00000569 => x"00440413",
00000570 => x"34141073",
00000571 => x"f31ff06f",
00000572 => x"faa02623",
00000573 => x"fa802783",
00000574 => x"fe07cee3",
00000575 => x"fac02503",
00000576 => x"00008067",
00000577 => x"ff010113",
00000578 => x"00812423",
00000579 => x"fa800413",
00000580 => x"00042783",
00000581 => x"00112623",
00000582 => x"09e00513",
00000583 => x"0017e793",
00000584 => x"00f42023",
00000585 => x"fcdff0ef",
00000586 => x"00000513",
00000587 => x"fc5ff0ef",
00000588 => x"00042783",
00000589 => x"00c12083",
00000590 => x"0ff57513",
00000591 => x"ffe7f793",
00000592 => x"00f42023",
00000593 => x"00812403",
00000594 => x"01010113",
00000595 => x"00008067",
00000596 => x"ff010113",
00000597 => x"00112623",
00000598 => x"fa802783",
00000599 => x"00500513",
00000600 => x"0017e793",
00000601 => x"faf02423",
00000602 => x"f89ff0ef",
00000603 => x"00000513",
00000604 => x"f81ff0ef",
00000605 => x"fa802783",
00000606 => x"00157513",
00000607 => x"ffe7f793",
00000608 => x"faf02423",
00000609 => x"fc051ae3",
00000610 => x"00c12083",
00000611 => x"01010113",
00000612 => x"00008067",
00000613 => x"ff010113",
00000614 => x"00812423",
00000615 => x"fa800413",
00000616 => x"00042783",
00000617 => x"00112623",
00000618 => x"00600513",
00000619 => x"0017e793",
00000620 => x"00f42023",
00000621 => x"f3dff0ef",
00000622 => x"00042783",
00000623 => x"00c12083",
00000624 => x"ffe7f793",
00000625 => x"00f42023",
00000626 => x"00812403",
00000627 => x"01010113",
00000628 => x"00008067",
00000629 => x"ff010113",
00000630 => x"00812423",
00000631 => x"00050413",
00000632 => x"01055513",
00000633 => x"0ff57513",
00000634 => x"00112623",
00000635 => x"f05ff0ef",
00000636 => x"00845513",
00000637 => x"0ff57513",
00000638 => x"ef9ff0ef",
00000639 => x"0ff47513",
00000640 => x"00812403",
00000641 => x"00c12083",
00000642 => x"01010113",
00000643 => x"ee5ff06f",
00000644 => x"fd010113",
00000645 => x"02812423",
00000646 => x"02912223",
00000647 => x"03212023",
00000648 => x"01312e23",
00000649 => x"02112623",
00000650 => x"00050993",
00000651 => x"00058493",
00000652 => x"00c10913",
00000653 => x"00358413",
00000654 => x"04099263",
00000655 => x"fa402783",
00000656 => x"fe07dee3",
00000657 => x"00f90023",
00000658 => x"00190913",
00000659 => x"fff40793",
00000660 => x"02849263",
00000661 => x"02c12083",
00000662 => x"02812403",
00000663 => x"00c12503",
00000664 => x"02412483",
00000665 => x"02012903",
00000666 => x"01c12983",
00000667 => x"03010113",
00000668 => x"00008067",
00000669 => x"00078413",
00000670 => x"fc1ff06f",
00000671 => x"fa802783",
00000672 => x"00300513",
00000673 => x"0017e793",
00000674 => x"faf02423",
00000675 => x"e65ff0ef",
00000676 => x"00040513",
00000677 => x"f41ff0ef",
00000678 => x"00000513",
00000679 => x"e55ff0ef",
00000680 => x"fa802783",
00000681 => x"ffe7f793",
00000682 => x"faf02423",
00000683 => x"00a90023",
00000684 => x"f99ff06f",
00000685 => x"fd010113",
00000686 => x"01412c23",
00000687 => x"80000a37",
00000688 => x"02812423",
00000689 => x"004a0793",
00000690 => x"02112623",
00000691 => x"02912223",
00000692 => x"03212023",
00000693 => x"01312e23",
00000694 => x"01512a23",
00000695 => x"01612823",
00000696 => x"01712623",
00000697 => x"01812423",
00000698 => x"00100713",
00000699 => x"00e7a023",
00000700 => x"00050413",
00000701 => x"004a0a13",
00000702 => x"02051863",
00000703 => x"ffff1537",
00000704 => x"cf450513",
00000705 => x"aedff0ef",
00000706 => x"080005b7",
00000707 => x"00040513",
00000708 => x"f01ff0ef",
00000709 => x"4788d7b7",
00000710 => x"afe78793",
00000711 => x"02f50463",
00000712 => x"00000513",
00000713 => x"01c0006f",
00000714 => x"ffff1537",
00000715 => x"d1450513",
00000716 => x"ac1ff0ef",
00000717 => x"dd1ff0ef",
00000718 => x"fc0518e3",
00000719 => x"00300513",
00000720 => x"b41ff0ef",
00000721 => x"080009b7",
00000722 => x"00498593",
00000723 => x"00040513",
00000724 => x"ec1ff0ef",
00000725 => x"00050a93",
00000726 => x"00898593",
00000727 => x"00040513",
00000728 => x"eb1ff0ef",
00000729 => x"ff002c03",
00000730 => x"00050b13",
00000731 => x"ffcafb93",
00000732 => x"00000913",
00000733 => x"00000493",
00000734 => x"00c98993",
00000735 => x"013905b3",
00000736 => x"05791c63",
00000737 => x"016484b3",
00000738 => x"00200513",
00000739 => x"fa049ae3",
00000740 => x"ffff1537",
00000741 => x"d2050513",
00000742 => x"a59ff0ef",
00000743 => x"02c12083",
00000744 => x"02812403",
00000745 => x"800007b7",
00000746 => x"0157a023",
00000747 => x"000a2023",
00000748 => x"02412483",
00000749 => x"02012903",
00000750 => x"01c12983",
00000751 => x"01812a03",
00000752 => x"01412a83",
00000753 => x"01012b03",
00000754 => x"00c12b83",
00000755 => x"00812c03",
00000756 => x"03010113",
00000757 => x"00008067",
00000758 => x"00040513",
00000759 => x"e35ff0ef",
00000760 => x"012c07b3",
00000761 => x"00a484b3",
00000762 => x"00a7a023",
00000763 => x"00490913",
00000764 => x"f8dff06f",
00000765 => x"fd010113",
00000766 => x"02812423",
00000767 => x"02912223",
00000768 => x"03212023",
00000769 => x"02112623",
00000770 => x"01312e23",
00000771 => x"00050413",
00000772 => x"00b12623",
00000773 => x"00c10913",
00000774 => x"00350493",
00000775 => x"00094983",
00000776 => x"d75ff0ef",
00000777 => x"fa802783",
00000778 => x"00200513",
00000779 => x"00190913",
00000780 => x"0017e793",
00000781 => x"faf02423",
00000782 => x"cb9ff0ef",
00000783 => x"00048513",
00000784 => x"d95ff0ef",
00000785 => x"00098513",
00000786 => x"ca9ff0ef",
00000787 => x"fa802783",
00000788 => x"ffe7f793",
00000789 => x"faf02423",
00000790 => x"cf9ff0ef",
00000791 => x"00048793",
00000792 => x"fff48493",
00000793 => x"faf41ce3",
00000794 => x"02c12083",
00000795 => x"02812403",
00000796 => x"02412483",
00000797 => x"02012903",
00000798 => x"01c12983",
00000799 => x"03010113",
00000800 => x"00008067",
00000801 => x"746f6f42",
00000802 => x"2e676e69",
00000803 => x"0a0a2e2e",
00000804 => x"00000000",
00000805 => x"52450a07",
00000806 => x"5f524f52",
00000807 => x"00000000",
00000808 => x"00007830",
00000809 => x"52455b0a",
00000810 => x"20524f52",
00000811 => x"6e55202d",
00000812 => x"65707865",
00000813 => x"64657463",
00000814 => x"63786520",
00000815 => x"69747065",
00000816 => x"20216e6f",
00000817 => x"7561636d",
00000818 => x"003d6573",
00000819 => x"70656d20",
00000820 => x"00003d63",
00000821 => x"76746d20",
00000822 => x"003d6c61",
00000823 => x"7274205d",
00000824 => x"676e6979",
00000825 => x"206f7420",
00000826 => x"75736572",
00000827 => x"2e2e656d",
00000828 => x"00000a2e",
00000829 => x"69617741",
00000830 => x"676e6974",
00000831 => x"6f656e20",
00000832 => x"32337672",
00000833 => x"6578655f",
00000834 => x"6e69622e",
00000835 => x"202e2e2e",
00000836 => x"00000000",
00000837 => x"64616f4c",
00000838 => x"2e676e69",
00000839 => x"00202e2e",
00000840 => x"00004b4f",
00000841 => x"3c0a0a0a",
00000842 => x"454e203c",
00000843 => x"3356524f",
00000844 => x"6f422032",
00000845 => x"6f6c746f",
00000846 => x"72656461",
00000847 => x"0a3e3e20",
00000848 => x"444c420a",
00000849 => x"46203a56",
00000850 => x"32206265",
00000851 => x"30322034",
00000852 => x"480a3232",
00000853 => x"203a5657",
00000854 => x"00000020",
00000855 => x"4b4c430a",
00000856 => x"0020203a",
00000857 => x"4153490a",
00000858 => x"0020203a",
00000859 => x"4153490a",
00000860 => x"0020203a",
00000861 => x"00202b20",
00000862 => x"434f530a",
00000863 => x"0020203a",
00000864 => x"454d490a",
00000865 => x"00203a4d",
00000866 => x"74796220",
00000867 => x"40207365",
00000868 => x"00000000",
00000869 => x"454d440a",
00000870 => x"00203a4d",
00000871 => x"75410a0a",
00000872 => x"6f626f74",
00000873 => x"6920746f",
00000874 => x"7338206e",
00000875 => x"7250202e",
00000876 => x"20737365",
00000877 => x"20796e61",
00000878 => x"2079656b",
00000879 => x"61206f74",
00000880 => x"74726f62",
00000881 => x"00000a2e",
00000882 => x"726f6241",
00000883 => x"2e646574",
00000884 => x"00000a0a",
00000885 => x"0000000a",
00000886 => x"69617641",
00000887 => x"6c62616c",
00000888 => x"4d432065",
00000889 => x"0a3a7344",
00000890 => x"203a6820",
00000891 => x"706c6548",
00000892 => x"3a72200a",
00000893 => x"73655220",
00000894 => x"74726174",
00000895 => x"3a75200a",
00000896 => x"6c705520",
00000897 => x"0a64616f",
00000898 => x"203a7320",
00000899 => x"726f7453",
00000900 => x"6f742065",
00000901 => x"616c6620",
00000902 => x"200a6873",
00000903 => x"4c203a6c",
00000904 => x"2064616f",
00000905 => x"6d6f7266",
00000906 => x"616c6620",
00000907 => x"200a6873",
00000908 => x"45203a65",
00000909 => x"75636578",
00000910 => x"00006574",
00000911 => x"444d430a",
00000912 => x"00203e3a",
00000913 => x"65206f4e",
00000914 => x"75636578",
00000915 => x"6c626174",
00000916 => x"76612065",
00000917 => x"616c6961",
00000918 => x"2e656c62",
00000919 => x"00000000",
00000920 => x"74697257",
00000921 => x"00002065",
00000922 => x"74796220",
00000923 => x"74207365",
00000924 => x"5053206f",
00000925 => x"6c662049",
00000926 => x"20687361",
00000927 => x"00783040",
00000928 => x"7928203f",
00000929 => x"20296e2f",
00000930 => x"00000000",
00000931 => x"616c460a",
00000932 => x"6e696873",
00000933 => x"2e2e2e67",
00000934 => x"00000020",
00000935 => x"20296328",
00000936 => x"53207962",
00000937 => x"68706574",
00000938 => x"4e206e61",
00000939 => x"69746c6f",
00000940 => x"680a676e",
00000941 => x"73707474",
00000942 => x"672f2f3a",
00000943 => x"75687469",
00000944 => x"6f632e62",
00000945 => x"74732f6d",
00000946 => x"746c6f6e",
00000947 => x"2f676e69",
00000948 => x"726f656e",
00000949 => x"00323376",
00000950 => x"61766e49",
00000951 => x"2064696c",
00000952 => x"00444d43",
00000953 => x"20657865",
00000954 => x"6e676973",
00000955 => x"72757461",
00000956 => x"61662065",
00000957 => x"00006c69",
00000958 => x"00000000",
00000959 => x"65637865",
00000960 => x"6e696465",
00000961 => x"4d492067",
00000962 => x"63204d45",
00000963 => x"63617061",
00000964 => x"00797469",
00000965 => x"63656863",
00000966 => x"6d75736b",
00000967 => x"69616620",
00000968 => x"0000006c",
00000969 => x"00000000",
00000970 => x"00000000",
00000971 => x"20495053",
00000972 => x"73616c66",
00000973 => x"63612068",
00000974 => x"73736563",
00000975 => x"69616620",
00000976 => x"0064656c",
00000977 => x"33323130",
00000978 => x"37363534",
00000979 => x"62613938",
00000980 => x"66656463"
00000859 => x"00202b20",
00000860 => x"434f530a",
00000861 => x"0020203a",
00000862 => x"454d490a",
00000863 => x"00203a4d",
00000864 => x"74796220",
00000865 => x"40207365",
00000866 => x"00000000",
00000867 => x"454d440a",
00000868 => x"00203a4d",
00000869 => x"75410a0a",
00000870 => x"6f626f74",
00000871 => x"6920746f",
00000872 => x"7338206e",
00000873 => x"7250202e",
00000874 => x"20737365",
00000875 => x"20796e61",
00000876 => x"2079656b",
00000877 => x"61206f74",
00000878 => x"74726f62",
00000879 => x"00000a2e",
00000880 => x"726f6241",
00000881 => x"2e646574",
00000882 => x"00000a0a",
00000883 => x"0000000a",
00000884 => x"69617641",
00000885 => x"6c62616c",
00000886 => x"4d432065",
00000887 => x"0a3a7344",
00000888 => x"203a6820",
00000889 => x"706c6548",
00000890 => x"3a72200a",
00000891 => x"73655220",
00000892 => x"74726174",
00000893 => x"3a75200a",
00000894 => x"6c705520",
00000895 => x"0a64616f",
00000896 => x"203a7320",
00000897 => x"726f7453",
00000898 => x"6f742065",
00000899 => x"616c6620",
00000900 => x"200a6873",
00000901 => x"4c203a6c",
00000902 => x"2064616f",
00000903 => x"6d6f7266",
00000904 => x"616c6620",
00000905 => x"200a6873",
00000906 => x"45203a65",
00000907 => x"75636578",
00000908 => x"00006574",
00000909 => x"444d430a",
00000910 => x"00203e3a",
00000911 => x"65206f4e",
00000912 => x"75636578",
00000913 => x"6c626174",
00000914 => x"76612065",
00000915 => x"616c6961",
00000916 => x"2e656c62",
00000917 => x"00000000",
00000918 => x"74697257",
00000919 => x"00002065",
00000920 => x"74796220",
00000921 => x"74207365",
00000922 => x"5053206f",
00000923 => x"6c662049",
00000924 => x"20687361",
00000925 => x"00783040",
00000926 => x"7928203f",
00000927 => x"20296e2f",
00000928 => x"00000000",
00000929 => x"616c460a",
00000930 => x"6e696873",
00000931 => x"2e2e2e67",
00000932 => x"00000020",
00000933 => x"20296328",
00000934 => x"53207962",
00000935 => x"68706574",
00000936 => x"4e206e61",
00000937 => x"69746c6f",
00000938 => x"680a676e",
00000939 => x"73707474",
00000940 => x"672f2f3a",
00000941 => x"75687469",
00000942 => x"6f632e62",
00000943 => x"74732f6d",
00000944 => x"746c6f6e",
00000945 => x"2f676e69",
00000946 => x"726f656e",
00000947 => x"00323376",
00000948 => x"61766e49",
00000949 => x"2064696c",
00000950 => x"00444d43",
00000951 => x"20657865",
00000952 => x"6e676973",
00000953 => x"72757461",
00000954 => x"61662065",
00000955 => x"00006c69",
00000956 => x"00000000",
00000957 => x"65637865",
00000958 => x"6e696465",
00000959 => x"4d492067",
00000960 => x"63204d45",
00000961 => x"63617061",
00000962 => x"00797469",
00000963 => x"63656863",
00000964 => x"6d75736b",
00000965 => x"69616620",
00000966 => x"0000006c",
00000967 => x"00000000",
00000968 => x"00000000",
00000969 => x"20495053",
00000970 => x"73616c66",
00000971 => x"63612068",
00000972 => x"73736563",
00000973 => x"69616620",
00000974 => x"0064656c",
00000975 => x"33323130",
00000976 => x"37363534",
00000977 => x"62613938",
00000978 => x"66656463"
);
 
end neorv32_bootloader_image;
/rtl/core/neorv32_bus_keeper.vhd
74,11 → 74,8
constant lo_abb_c : natural := index_size_f(buskeeper_size_c); -- low address boundary bit
 
-- Control register --
constant ctrl_err_type_c : natural := 0; -- r/-: error type LSB: 0=device error, 1=access timeout
constant ctrl_nul_check_en_c : natural := 16; -- r/w: enable NULL address check
constant ctrl_err_flag_c : natural := 31; -- r/c: bus error encountered, sticky; cleared by writing zero
--
signal ctrl_null_check_en : std_ulogic;
constant ctrl_err_type_c : natural := 0; -- r/-: error type LSB: 0=device error, 1=access timeout
constant ctrl_err_flag_c : natural := 31; -- r/c: bus error encountered, sticky; cleared by writing zero
 
-- error codes --
constant err_device_c : std_ulogic := '0'; -- device access error
88,9 → 85,6
signal err_flag : std_ulogic;
signal err_type : std_ulogic;
 
-- NULL address check --
signal null_check : std_ulogic;
 
-- access control --
signal acc_en : std_ulogic; -- module access enable
signal wren : std_ulogic; -- word write enable
124,26 → 118,19
rw_access: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
ack_o <= '-';
data_o <= (others => '-');
ctrl_null_check_en <= '0'; -- required
err_flag <= '0'; -- required
err_type <= '0';
ack_o <= '-';
data_o <= (others => '-');
err_flag <= '0'; -- required
err_type <= '0';
elsif rising_edge(clk_i) then
-- bus handshake --
ack_o <= wren or rden;
 
-- write access --
if (wren = '1') then
ctrl_null_check_en <= data_i(ctrl_nul_check_en_c);
end if;
 
-- read access --
data_o <= (others => '0');
if (rden = '1') then
data_o(ctrl_err_type_c) <= err_type;
data_o(ctrl_nul_check_en_c) <= ctrl_null_check_en;
data_o(ctrl_err_flag_c) <= err_flag;
data_o(ctrl_err_type_c) <= err_type;
data_o(ctrl_err_flag_c) <= err_flag;
end if;
--
if (control.bus_err = '1') then -- sticky error flag
176,14 → 163,11
control.timeout <= std_ulogic_vector(to_unsigned(max_proc_int_response_time_c, index_size_f(max_proc_int_response_time_c)+1));
if (bus_rden_i = '1') or (bus_wren_i = '1') then
control.pending <= '1';
if (null_check = '1') then -- invalid access to NULL address
control.bus_err <= '1';
end if;
end if;
-- access monitor: PENDING --
else
control.timeout <= std_ulogic_vector(unsigned(control.timeout) - 1); -- countdown timer
if (bus_err_i = '1') or (control.bus_err = '1') then -- error termination by bus system
if (bus_err_i = '1') then -- error termination by bus system
control.err_type <= err_device_c; -- device error
control.bus_err <= '1';
control.pending <= '0';
201,9 → 185,6
end if;
end process keeper_control;
 
-- NULL address check --
null_check <= '1' when (ctrl_null_check_en = '1') and (or_reduce_f(addr_i) = '0') else '0';
 
-- signal bus error to CPU --
err_o <= control.bus_err;
 
/rtl/core/neorv32_busswitch.vhd
1,7 → 1,7
-- #################################################################################################
-- # << NEORV32 - Bus Switch >> #
-- # ********************************************************************************************* #
-- # Allows to access a single peripheral bus ("p_bus") by two controller buses. Controller port A #
-- # Allows to access a single peripheral bus ("p_bus") by two controller ports. Controller port A #
-- # ("ca_bus") has priority over controller port B ("cb_bus"). #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
99,7 → 99,7
signal p_bus_we, p_bus_re : std_ulogic;
 
-- access arbiter --
type arbiter_state_t is (IDLE, BUSY, RETIRE, BUSY_SWITCHED, RETIRE_SWITCHED);
type arbiter_state_t is (IDLE, A_BUSY, A_RETIRE, B_BUSY, B_RETIRE);
type arbiter_t is record
state : arbiter_state_t;
state_nxt : arbiter_state_t;
111,39 → 111,27
 
begin
 
-- Access Buffer --------------------------------------------------------------------------
-- Access Arbiter -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
access_buffer: process(rstn_i, clk_i)
arbiter_sync: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
arbiter.state <= IDLE;
ca_rd_req_buf <= '0';
ca_wr_req_buf <= '0';
cb_rd_req_buf <= '0';
cb_wr_req_buf <= '0';
elsif rising_edge(clk_i) then
 
-- arbiter --
arbiter.state <= arbiter.state_nxt;
-- controller A requests --
if (ca_rd_req_buf = '0') and (ca_wr_req_buf = '0') then -- idle
ca_rd_req_buf <= ca_bus_re_i;
ca_wr_req_buf <= ca_bus_we_i;
elsif (ca_bus_err = '1') or -- error termination
(ca_bus_ack = '1') then -- normal termination
ca_rd_req_buf <= '0';
ca_wr_req_buf <= '0';
end if;
 
ca_rd_req_buf <= (ca_rd_req_buf or ca_bus_re_i) and (not (ca_bus_err or ca_bus_ack));
ca_wr_req_buf <= (ca_wr_req_buf or ca_bus_we_i) and (not (ca_bus_err or ca_bus_ack)) and (not bool_to_ulogic_f(PORT_CA_READ_ONLY));
-- controller B requests --
if (cb_rd_req_buf = '0') and (cb_wr_req_buf = '0') then
cb_rd_req_buf <= cb_bus_re_i;
cb_wr_req_buf <= cb_bus_we_i;
elsif (cb_bus_err = '1') or -- error termination
(cb_bus_ack = '1') then -- normal termination
cb_rd_req_buf <= '0';
cb_wr_req_buf <= '0';
end if;
 
cb_rd_req_buf <= (cb_rd_req_buf or cb_bus_re_i) and (not (cb_bus_err or cb_bus_ack));
cb_wr_req_buf <= (cb_wr_req_buf or cb_bus_we_i) and (not (cb_bus_err or cb_bus_ack)) and (not bool_to_ulogic_f(PORT_CB_READ_ONLY));
end if;
end process access_buffer;
end process arbiter_sync;
 
-- any current requests? --
ca_req_current <= (ca_bus_re_i or ca_bus_we_i) when (PORT_CA_READ_ONLY = false) else ca_bus_re_i;
154,20 → 142,8
cb_req_buffered <= (cb_rd_req_buf or cb_wr_req_buf) when (PORT_CB_READ_ONLY = false) else cb_rd_req_buf;
 
 
-- Access Arbiter Sync --------------------------------------------------------------------
-- Bus Arbiter ----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
arbiter_sync: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
arbiter.state <= IDLE;
elsif rising_edge(clk_i) then
arbiter.state <= arbiter.state_nxt;
end if;
end process arbiter_sync;
 
 
-- Peripheral Bus Arbiter -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
arbiter_comb: process(arbiter, ca_req_current, cb_req_current, ca_req_buffered, cb_req_buffered,
ca_rd_req_buf, ca_wr_req_buf, cb_rd_req_buf, cb_wr_req_buf, p_bus_ack_i, p_bus_err_i)
begin
180,64 → 156,53
-- state machine --
case arbiter.state is
 
when IDLE => -- Controller a has full bus access
when IDLE => -- port A or B access
-- ------------------------------------------------------------
p_bus_src_o <= '0'; -- access from port A
if (ca_req_current = '1') then -- current request?
arbiter.bus_sel <= '0';
arbiter.state_nxt <= BUSY;
elsif (ca_req_buffered = '1') then -- buffered request?
arbiter.bus_sel <= '0';
arbiter.state_nxt <= RETIRE;
elsif (cb_req_current = '1') then -- current request from controller b?
arbiter.bus_sel <= '1';
arbiter.state_nxt <= BUSY_SWITCHED;
elsif (cb_req_buffered = '1') then -- buffered request from controller b?
arbiter.bus_sel <= '1';
arbiter.state_nxt <= RETIRE_SWITCHED;
if (ca_req_current = '1') then -- current request from controller A?
arbiter.bus_sel <= '0'; -- access from port A
arbiter.state_nxt <= A_BUSY;
elsif (ca_req_buffered = '1') then -- buffered request from controller A?
arbiter.bus_sel <= '0'; -- access from port A
arbiter.state_nxt <= A_RETIRE;
elsif (cb_req_current = '1') then -- buffered request from controller B?
arbiter.bus_sel <= '1'; -- access from port B
arbiter.state_nxt <= B_BUSY;
elsif (cb_req_buffered = '1') then -- current request from controller B?
arbiter.bus_sel <= '1'; -- access from port B
arbiter.state_nxt <= B_RETIRE;
end if;
 
when BUSY => -- transaction in progress
when A_BUSY => -- port A pending access
-- ------------------------------------------------------------
p_bus_src_o <= '0'; -- access from port A
arbiter.bus_sel <= '0';
if (p_bus_err_i = '1') or -- error termination
(p_bus_ack_i = '1') then -- normal termination
arbiter.bus_sel <= '0'; -- access from port A
if (p_bus_err_i = '1') or (p_bus_ack_i = '1') then -- termination
arbiter.state_nxt <= IDLE;
end if;
 
when RETIRE => -- retire pending access
when A_RETIRE => -- port A trigger buffered access
-- ------------------------------------------------------------
p_bus_src_o <= '0'; -- access from port A
arbiter.bus_sel <= '0';
if (PORT_CA_READ_ONLY = false) then
arbiter.we_trig <= ca_wr_req_buf;
end if;
arbiter.bus_sel <= '0'; -- access from port A
arbiter.we_trig <= ca_wr_req_buf;
arbiter.re_trig <= ca_rd_req_buf;
arbiter.state_nxt <= BUSY;
arbiter.state_nxt <= A_BUSY;
 
when BUSY_SWITCHED => -- switched transaction in progress
when B_BUSY => -- port B pending access
-- ------------------------------------------------------------
p_bus_src_o <= '1'; -- access from port B
arbiter.bus_sel <= '1';
if (p_bus_err_i = '1') or -- error termination
(p_bus_ack_i = '1') then -- normal termination
arbiter.bus_sel <= '1'; -- access from port B
if (p_bus_err_i = '1') or (p_bus_ack_i = '1') then -- termination
if (ca_req_buffered = '1') or (ca_req_current = '1') then -- any request from A?
arbiter.state_nxt <= RETIRE;
arbiter.state_nxt <= A_RETIRE;
else
arbiter.state_nxt <= IDLE;
end if;
end if;
 
when RETIRE_SWITCHED => -- retire pending switched access
when B_RETIRE => -- port B trigger buffered access
-- ------------------------------------------------------------
p_bus_src_o <= '1'; -- access from port B
arbiter.bus_sel <= '1';
if (PORT_CB_READ_ONLY = false) then
arbiter.we_trig <= cb_wr_req_buf;
end if;
arbiter.bus_sel <= '1'; -- access from port B
arbiter.we_trig <= cb_wr_req_buf;
arbiter.re_trig <= cb_rd_req_buf;
arbiter.state_nxt <= BUSY_SWITCHED;
arbiter.state_nxt <= B_BUSY;
 
end case;
end process arbiter_comb;
246,9 → 211,11
-- Peripheral Bus Switch ------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
p_bus_addr_o <= ca_bus_addr_i when (arbiter.bus_sel = '0') else cb_bus_addr_i;
p_bus_wdata_o <= cb_bus_wdata_i when (PORT_CA_READ_ONLY = true) else ca_bus_wdata_i when (PORT_CB_READ_ONLY = true) else
p_bus_wdata_o <= cb_bus_wdata_i when (PORT_CA_READ_ONLY = true) else
ca_bus_wdata_i when (PORT_CB_READ_ONLY = true) else
ca_bus_wdata_i when (arbiter.bus_sel = '0') else cb_bus_wdata_i;
p_bus_ben_o <= cb_bus_ben_i when (PORT_CA_READ_ONLY = true) else ca_bus_ben_i when (PORT_CB_READ_ONLY = true) else
p_bus_ben_o <= cb_bus_ben_i when (PORT_CA_READ_ONLY = true) else
ca_bus_ben_i when (PORT_CB_READ_ONLY = true) else
ca_bus_ben_i when (arbiter.bus_sel = '0') else cb_bus_ben_i;
p_bus_we <= ca_bus_we_i when (arbiter.bus_sel = '0') else cb_bus_we_i;
p_bus_re <= ca_bus_re_i when (arbiter.bus_sel = '0') else cb_bus_re_i;
255,6 → 222,7
p_bus_we_o <= (p_bus_we or arbiter.we_trig);
p_bus_re_o <= (p_bus_re or arbiter.re_trig);
p_bus_lock_o <= ca_bus_lock_i or cb_bus_lock_i;
p_bus_src_o <= arbiter.bus_sel;
 
ca_bus_rdata_o <= p_bus_rdata_i;
cb_bus_rdata_o <= p_bus_rdata_i;
/rtl/core/neorv32_cfs.vhd
76,7 → 76,9
 
architecture neorv32_cfs_rtl of neorv32_cfs is
 
-- IO space: module base address (DO NOT MODIFY!) --
-- IO space: module base address --
-- WARNING: Do not modify the CFS base address or the CFS' occupied address
-- space as this might cause access collisions with other processor modules.
constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit
constant lo_abb_c : natural := index_size_f(cfs_size_c); -- low address boundary bit
 
95,24 → 97,20
 
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- This logic is required to handle the CPU accesses.
-- DO NOT MODIFY this unless you really know what you are doing.
-- This logic is required to handle the CPU accesses - DO NOT MODIFY!
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = cfs_base_c(hi_abb_c downto lo_abb_c)) else '0';
addr <= cfs_base_c(31 downto lo_abb_c) & addr_i(lo_abb_c-1 downto 2) & "00"; -- word aligned
wren <= acc_en and wren_i; -- write accesses always write a full 32-bit word
wren <= acc_en and wren_i; -- only full-word write accesses are supported
rden <= acc_en and rden_i; -- read accesses always return a full 32-bit word
 
-- NOTE: Do not modify the CFS base address or the CFS' occupied address space as this might cause access
-- collisions with other modules.
 
 
-- CFS Generics ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- In it's default version the CFS provides three configuration generics:
-- CFS_IN_SIZE - configures the size (in bits) of the CFS input conduit cfs_in_i
-- CFS_OUT_SIZE - configures the size (in bits) of the CFS output conduit cfs_out_o
-- CFS_CONFIG - is a blank 32-bit generic. It is intended as a "generic conduit" to propagate
-- custom configuration flags from the top entity down to this module.
-- > CFS_IN_SIZE - configures the size (in bits) of the CFS input conduit cfs_in_i
-- > CFS_OUT_SIZE - configures the size (in bits) of the CFS output conduit cfs_out_o
-- > CFS_CONFIG - is a blank 32-bit generic. It is intended as a "generic conduit" to propagate
-- custom configuration flags from the top entity down to this module.
 
 
-- CFS IOs --------------------------------------------------------------------------------
141,26 → 139,26
-- clkgen_i is always synchronous to the main system clock (clk_i).
--
-- The following clock dividers are available:
-- + clkgen_i(clk_div2_c) -> MAIN_CLK/2
-- + clkgen_i(clk_div4_c) -> MAIN_CLK/4
-- + clkgen_i(clk_div8_c) -> MAIN_CLK/8
-- + clkgen_i(clk_div64_c) -> MAIN_CLK/64
-- + clkgen_i(clk_div128_c) -> MAIN_CLK/128
-- + clkgen_i(clk_div1024_c) -> MAIN_CLK/1024
-- + clkgen_i(clk_div2048_c) -> MAIN_CLK/2048
-- + clkgen_i(clk_div4096_c) -> MAIN_CLK/4096
-- > clkgen_i(clk_div2_c) -> MAIN_CLK/2
-- > clkgen_i(clk_div4_c) -> MAIN_CLK/4
-- > clkgen_i(clk_div8_c) -> MAIN_CLK/8
-- > clkgen_i(clk_div64_c) -> MAIN_CLK/64
-- > clkgen_i(clk_div128_c) -> MAIN_CLK/128
-- > clkgen_i(clk_div1024_c) -> MAIN_CLK/1024
-- > clkgen_i(clk_div2048_c) -> MAIN_CLK/2048
-- > clkgen_i(clk_div4096_c) -> MAIN_CLK/4096
--
-- For instance, if you want to drive a clock process at MAIN_CLK/8 clock speed you can use the following construct:
--
-- if (rstn_i = '0') then -- async and low-active reset (if required at all)
-- ...
-- elsif rising_edge(clk_i) then -- always use the main clock for all clock processes!
-- elsif rising_edge(clk_i) then -- always use the main clock for all clock processes
-- if (clkgen_i(clk_div8_c) = '1') then -- the div8 "clock" is actually a clock enable
-- ...
-- end if;
-- end if;
--
-- The clkgen_i input clocks are available when at least one IO/peripheral device (for example the UART) requires the clocks
-- The clkgen_i input clocks are available when at least one IO/peripheral device (for example UART0) requires the clocks
-- generated by the clock generator. The CFS can enable the clock generator by itself by setting the clkgen_en_o signal high.
-- The CFS cannot ensure to deactivate the clock generator by setting the clkgen_en_o signal low as other peripherals might
-- still keep the generator activated. Make sure to deactivate the CFS's clkgen_en_o if no clocks are required in here to
181,55 → 179,57
 
-- Read/Write Access ----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- Here we are reading/writing from/to the interface registers of the module. Please note that the peripheral/IO modules
-- of the NEORV32 can only be written in full word mode (32-bit). Any other write accesses (half-word or byte) will raise
-- a store bus access fault exception.
-- Here we are reading/writing from/to the interface registers of the module and generate the CPU access handshake (bus response).
--
-- The CFS provides up to 32 memory-mapped 32-bit interface register. For instance, these could be used to provide a
-- The CFS provides up to 32 memory-mapped 32-bit interface registers. For instance, these could be used to provide a
-- <control register> for global control of the unit, a <data register> for reading/writing from/to a data FIFO, a
-- <command register> for issuing commands and a <status register> for status information.
--
-- Following the interface protocol, each read or write access has to be acknowledged in the following cycle using the ack_o
-- signal (or even later if the module needs additional time; exceeding the maximum ACK latency will raise a bus exception).
-- If no ACK is generated at all, the bus access will time out and cause a bus access fault exception.
-- signal (or even later if the module needs additional time). If no ACK is generated at all, the bus access will time out
-- and cause a bus access fault exception.
--
-- This module also provides an optional ERROR signal to indicate a faulty access operation (for example when accessing an
-- unused, read-only or "locked" CFS register address). This signal may only be set when the module is actually accessed
-- and is asserted INSTEAD of the ACK signal. Setting the ERR signal will raise a bus access exception that can be handled
-- by the application software.
-- and is set INSTEAD of the ACK signal. Setting the ERR signal will raise a bus access exception with a "Device Error" qualifier
-- that can be handled by the application software.
 
err_o <= '0'; -- Tie to zero if not explicitly used.
 
-- Host access: Read and write access to the interface registers + bus transfer acknowledge. This example only implements
-- four physical r/w register (the four lowest CFS registers). The remaining addresses of the CFS are not associated with
-- any physical registers - any access to those is simply ignored but still acknowledged.
 
-- Host access example: Read and write access to the interface registers + bus transfer acknowledge. This example only
-- implements four physical r/w register (the four lowest CFS registers). The remaining addresses of the CFS are not associated
-- with any physical registers - any access to those is simply ignored but still acknowledged. Only full-word write accesses are
-- supported (and acknowledged) by this example. Sub-word write access will not alter any CFS register state and will cause
-- a "bus store access" exception (with a "Device Timeout" qualifier as not ACK is generated in that case).
 
host_access: process(clk_i)
begin
if rising_edge(clk_i) then -- synchronous interface for read and write accesses
-- transfer/access acknowledge --
ack_o <= rden or wren; -- default: required for the CPU to check the CFS is answering a bus read OR write request;
-- all r/w accesses (to any cfs_reg) will succeed
-- default: required for the CPU to check the CFS is answering a bus read OR write request;
-- all read and write accesses (to any cfs_reg, even if there is no according physical register implemented) will succeed.
ack_o <= rden or wren;
 
-- write access --
if (wren = '1') then
if (wren = '1') then -- full-word write access, high for one cycle if there is an actual write access
if (addr = cfs_reg0_addr_c) then -- make sure to use the internal "addr" signal for the read/write interface
cfs_reg_wr(0) <= data_i; -- physical register, for example: control register
cfs_reg_wr(0) <= data_i; -- some physical register, for example: control register
end if;
if (addr = cfs_reg1_addr_c) then
cfs_reg_wr(1) <= data_i; -- physical register, for example: data in/out fifo
cfs_reg_wr(1) <= data_i; -- some physical register, for example: data in/out fifo
end if;
if (addr = cfs_reg2_addr_c) then
cfs_reg_wr(2) <= data_i; -- physical register, for example: command fifo
cfs_reg_wr(2) <= data_i; -- some physical register, for example: command fifo
end if;
if (addr = cfs_reg3_addr_c) then
cfs_reg_wr(3) <= data_i; -- physical register, for example: status register
cfs_reg_wr(3) <= data_i; -- some physical register, for example: status register
end if;
end if;
 
-- read access --
data_o <= (others => '0'); -- the output has to be zero if there is no actual read access
if (rden = '1') then -- the read access is always a full 32-bit word wide
data_o <= (others => '0'); -- the output HAS TO BE ZERO if there is no actual read access
if (rden = '1') then -- the read access is always 32-bit wide, high for one cycle if there is an actual read access
case addr is -- make sure to use the internal 'addr' signal for the read/write interface
when cfs_reg0_addr_c => data_o <= cfs_reg_rd(0);
when cfs_reg1_addr_c => data_o <= cfs_reg_rd(1);
247,14 → 247,12
 
-- This is where the actual functionality can be implemented.
-- The logic below is just a very simple example that transforms data
-- from an inpout register into data in an output register.
cfs_core_logic: process(cfs_reg_wr)
begin
cfs_reg_rd(0) <= bin_to_gray_f(cfs_reg_wr(0)); -- convert binary to gray code
cfs_reg_rd(1) <= gray_to_bin_f(cfs_reg_wr(1)); -- convert gray to binary code
cfs_reg_rd(2) <= bit_rev_f(cfs_reg_wr(2)); -- bit reversal
cfs_reg_rd(3) <= bswap32_f(cfs_reg_wr(3)); -- byte swap (endianness conversion)
end process cfs_core_logic;
-- from an input register into data in an output register.
 
cfs_reg_rd(0) <= bin_to_gray_f(cfs_reg_wr(0)); -- convert binary to gray code
cfs_reg_rd(1) <= gray_to_bin_f(cfs_reg_wr(1)); -- convert gray to binary code
cfs_reg_rd(2) <= bit_rev_f(cfs_reg_wr(2)); -- bit reversal
cfs_reg_rd(3) <= bswap32_f(cfs_reg_wr(3)); -- byte swap (endianness conversion)
 
 
end neorv32_cfs_rtl;
/rtl/core/neorv32_cpu.vhd
85,8 → 85,8
CPU_CNT_WIDTH : natural; -- total width of CPU cycle and instret counters (0..64)
CPU_IPB_ENTRIES : natural; -- entries is instruction prefetch buffer, has to be a power of 2
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS : natural; -- number of regions (0..64)
PMP_MIN_GRANULARITY : natural; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
PMP_NUM_REGIONS : natural; -- number of regions (0..16)
PMP_MIN_GRANULARITY : natural; -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS : natural; -- number of implemented HPM counters (0..29)
HPM_CNT_WIDTH : natural -- total size of HPM counters (0..64)
108,7 → 108,7
i_bus_ack_i : in std_ulogic; -- bus transfer acknowledge
i_bus_err_i : in std_ulogic; -- bus transfer error
i_bus_fence_o : out std_ulogic; -- executed FENCEI operation
i_bus_priv_o : out std_ulogic_vector(1 downto 0); -- privilege level
i_bus_priv_o : out std_ulogic; -- privilege level
-- data bus interface --
d_bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
d_bus_rdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
120,7 → 120,7
d_bus_ack_i : in std_ulogic; -- bus transfer acknowledge
d_bus_err_i : in std_ulogic; -- bus transfer error
d_bus_fence_o : out std_ulogic; -- executed FENCE operation
d_bus_priv_o : out std_ulogic_vector(1 downto 0); -- privilege level
d_bus_priv_o : out std_ulogic; -- privilege level
-- system time input from MTIME --
time_i : in std_ulogic_vector(63 downto 0); -- current system time
-- interrupts (risc-v compliant) --
185,7 → 185,7
cond_sel_string_f(CPU_EXTENSION_RISCV_Zfinx, "_Zfinx", "") &
cond_sel_string_f(CPU_EXTENSION_RISCV_Zmmul, "_Zmmul", "") &
cond_sel_string_f(CPU_EXTENSION_RISCV_Zxcfu, "_Zxcfu", "") &
cond_sel_string_f(CPU_EXTENSION_RISCV_DEBUG, "_DEBUG", "") &
cond_sel_string_f(CPU_EXTENSION_RISCV_DEBUG, "_DebugMode", "") &
""
severity note;
 
213,11 → 213,10
-- Instruction prefetch buffer size --
assert not (is_power_of_two_f(CPU_IPB_ENTRIES) = false) report "NEORV32 CPU CONFIG ERROR! Number of entries in instruction prefetch buffer <CPU_IPB_ENTRIES> has to be a power of two." severity error;
 
-- PMP regions check --
assert not (PMP_NUM_REGIONS > 64) report "NEORV32 CPU CONFIG ERROR! Number of PMP regions <PMP_NUM_REGIONS> out of valid range (0..64)." severity error;
-- PMP granularity --
-- PMP check --
assert not (PMP_NUM_REGIONS > 16) report "NEORV32 CPU CONFIG ERROR! Number of PMP regions <PMP_NUM_REGIONS> out of valid range (0..16)." severity error;
assert not ((is_power_of_two_f(PMP_MIN_GRANULARITY) = false) and (PMP_NUM_REGIONS > 0)) report "NEORV32 CPU CONFIG ERROR! <PMP_MIN_GRANULARITY> has to be a power of two." severity error;
assert not ((PMP_MIN_GRANULARITY < 8) and (PMP_NUM_REGIONS > 0)) report "NEORV32 CPU CONFIG ERROR! <PMP_MIN_GRANULARITY> has to be >= 8 bytes." severity error;
assert not ((PMP_MIN_GRANULARITY < 4) and (PMP_NUM_REGIONS > 0)) report "NEORV32 CPU CONFIG ERROR! <PMP_MIN_GRANULARITY> has to be >= 4 bytes." severity error;
assert not ((CPU_EXTENSION_RISCV_Zicsr = false) and (PMP_NUM_REGIONS > 0)) report "NEORV32 CPU CONFIG ERROR! Physical memory protection (PMP) requires <CPU_EXTENSION_RISCV_Zicsr> extension to be enabled." severity error;
 
-- HPM counters check --
271,8 → 270,8
CPU_CNT_WIDTH => CPU_CNT_WIDTH, -- total width of CPU cycle and instret counters (0..64)
CPU_IPB_ENTRIES => CPU_IPB_ENTRIES, -- entries is instruction prefetch buffer, has to be a power of 2
-- Physical memory protection (PMP) --
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..64)
PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..16)
PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS => HPM_NUM_CNTS, -- number of implemented HPM counters (0..29)
HPM_CNT_WIDTH => HPM_CNT_WIDTH -- total size of HPM counters
341,8 → 340,10
clk_i => clk_i, -- global clock, rising edge
ctrl_i => ctrl, -- main control bus
-- data input --
alu_i => alu_res, -- ALU result
mem_i => mem_rdata, -- memory read data
alu_i => alu_res, -- ALU result
csr_i => csr_rdata, -- CSR read data
pc2_i => next_pc, -- next PC
-- data output --
rs1_o => rs1, -- operand 1
rs2_o => rs2 -- operand 2
372,9 → 373,7
rs1_i => rs1, -- rf source 1
rs2_i => rs2, -- rf source 2
pc_i => curr_pc, -- current PC
pc2_i => next_pc, -- next PC
imm_i => imm, -- immediate
csr_i => csr_rdata, -- CSR read data
-- data output --
cmp_o => comparator, -- comparator status
res_o => alu_res, -- ALU result
392,8 → 391,8
CPU_EXTENSION_RISCV_A => CPU_EXTENSION_RISCV_A, -- implement atomic extension?
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension?
-- Physical memory protection (PMP) --
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..64)
PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..16)
PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
)
port map (
-- global control --
447,8 → 446,8
);
 
-- current privilege level --
i_bus_priv_o <= ctrl(ctrl_priv_lvl_msb_c downto ctrl_priv_lvl_lsb_c);
d_bus_priv_o <= ctrl(ctrl_priv_lvl_msb_c downto ctrl_priv_lvl_lsb_c);
i_bus_priv_o <= ctrl(ctrl_priv_mode_c);
d_bus_priv_o <= ctrl(ctrl_priv_mode_c);
 
 
end neorv32_cpu_rtl;
/rtl/core/neorv32_cpu_alu.vhd
62,9 → 62,7
rs1_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 1
rs2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 2
pc_i : in std_ulogic_vector(data_width_c-1 downto 0); -- current PC
pc2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- next PC
imm_i : in std_ulogic_vector(data_width_c-1 downto 0); -- immediate
csr_i : in std_ulogic_vector(data_width_c-1 downto 0); -- CSR read data
-- data output --
cmp_o : out std_ulogic_vector(1 downto 0); -- comparator status
res_o : out std_ulogic_vector(data_width_c-1 downto 0); -- ALU result
87,20 → 85,11
 
-- results --
signal addsub_res : std_ulogic_vector(data_width_c downto 0);
signal alu_res : std_ulogic_vector(data_width_c-1 downto 0);
signal cp_res : std_ulogic_vector(data_width_c-1 downto 0);
 
-- co-processor arbiter and interface --
type cp_ctrl_t is record
cmd : std_ulogic;
cmd_ff : std_ulogic;
start : std_ulogic;
end record;
signal cp_ctrl : cp_ctrl_t;
 
-- co-processor interface --
type cp_data_if_t is array (0 to 7) of std_ulogic_vector(data_width_c-1 downto 0);
signal cp_result : cp_data_if_t; -- co-processor result
signal cp_result : cp_data_if_t; -- co-processor i result
signal cp_start : std_ulogic_vector(7 downto 0); -- trigger co-processor i
signal cp_valid : std_ulogic_vector(7 downto 0); -- co-processor i done
 
152,76 → 141,42
 
-- ALU Operation Select -------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
alu_core: process(ctrl_i, addsub_res, rs1_i, opb)
alu_core: process(ctrl_i, addsub_res, cp_res, rs1_i, opb)
begin
case ctrl_i(ctrl_alu_op2_c downto ctrl_alu_op0_c) is
when alu_op_add_c => alu_res <= addsub_res(data_width_c-1 downto 0); -- (default)
when alu_op_sub_c => alu_res <= addsub_res(data_width_c-1 downto 0);
-- when alu_op_mova_c => alu_res <= rs1_i; -- FIXME
when alu_op_slt_c => alu_res <= (others => '0'); alu_res(0) <= addsub_res(addsub_res'left); -- => carry/borrow
when alu_op_movb_c => alu_res <= opb;
when alu_op_xor_c => alu_res <= rs1_i xor opb; -- only rs1 required for logic ops (opa would also contain pc)
when alu_op_or_c => alu_res <= rs1_i or opb;
when alu_op_and_c => alu_res <= rs1_i and opb;
when others => alu_res <= addsub_res(data_width_c-1 downto 0);
when alu_op_add_c => res_o <= addsub_res(data_width_c-1 downto 0); -- default
when alu_op_sub_c => res_o <= addsub_res(data_width_c-1 downto 0);
when alu_op_cp_c => res_o <= cp_res;
when alu_op_slt_c => res_o <= (others => '0'); res_o(0) <= addsub_res(addsub_res'left); -- carry/borrow
when alu_op_movb_c => res_o <= opb;
when alu_op_xor_c => res_o <= rs1_i xor opb; -- only rs1 required for logic ops (opa would also contain pc)
when alu_op_or_c => res_o <= rs1_i or opb;
when alu_op_and_c => res_o <= rs1_i and opb;
when others => res_o <= addsub_res(data_width_c-1 downto 0);
end case;
end process alu_core;
 
-- ALU Function Select --------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
alu_function_mux: process(ctrl_i, alu_res, pc2_i, csr_i, cp_res)
begin
case ctrl_i(ctrl_alu_func1_c downto ctrl_alu_func0_c) is
when alu_func_core_c => res_o <= alu_res; -- (default)
when alu_func_nxpc_c => res_o <= pc2_i;
when alu_func_csrr_c => res_o <= csr_i;
when alu_func_copro_c => res_o <= cp_res;
when others => res_o <= alu_res; -- undefined
end case;
end process alu_function_mux;
 
 
-- **************************************************************************************************************************
-- CPU Co-Processors
-- ALU Co-Processors
-- **************************************************************************************************************************
 
-- Co-Processor Interface --
-- Co-processor "valid" signal has to be asserted (for one cycle) one cycle before asserting output data
-- Co-processor "output data" has to be always zero unless co-processor was explicitly triggered
 
-- Co-Processor Arbiter -------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
cp_arbiter: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
cp_ctrl.cmd_ff <= '0';
elsif rising_edge(clk_i) then
cp_ctrl.cmd_ff <= cp_ctrl.cmd;
end if;
end process cp_arbiter;
 
-- is co-processor operation? --
cp_ctrl.cmd <= '1' when (ctrl_i(ctrl_alu_func1_c downto ctrl_alu_func0_c) = alu_func_copro_c) else '0';
cp_ctrl.start <= '1' when (cp_ctrl.cmd = '1') and (cp_ctrl.cmd_ff = '0') else '0';
 
-- co-processor select / start trigger --
cp_start(0) <= '1' when (cp_ctrl.start = '1') and (ctrl_i(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) = "000") else '0';
cp_start(1) <= '1' when (cp_ctrl.start = '1') and (ctrl_i(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) = "001") else '0';
cp_start(2) <= '1' when (cp_ctrl.start = '1') and (ctrl_i(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) = "010") else '0';
cp_start(3) <= '1' when (cp_ctrl.start = '1') and (ctrl_i(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) = "011") else '0';
cp_start(4) <= '1' when (cp_ctrl.start = '1') and (ctrl_i(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) = "100") else '0';
cp_start(5) <= '1' when (cp_ctrl.start = '1') and (ctrl_i(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) = "101") else '0';
cp_start(6) <= '1' when (cp_ctrl.start = '1') and (ctrl_i(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) = "110") else '0';
cp_start(7) <= '1' when (cp_ctrl.start = '1') and (ctrl_i(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) = "111") else '0';
-- > "cp_start" is high for one cycle to trigger operation of the according co-processor
cp_start(7 downto 0) <= ctrl_i(ctrl_cp_trig7_c downto ctrl_cp_trig0_c);
 
-- co-processor operation done? --
idone_o <= or_reduce_f(cp_valid);
-- > "cp_valid" signal has to be set (for one cycle) one cycle before output data (cp_result) is valid
idone_o <= cp_valid(0) or cp_valid(1) or cp_valid(2) or cp_valid(3) or
cp_valid(4) or cp_valid(5) or cp_valid(6) or cp_valid(7);
 
-- co-processor result - only the *actually selected* co-processor may output data != 0 --
cp_res <= cp_result(0) or cp_result(1) or cp_result(2) or cp_result(3) or cp_result(4) or cp_result(5) or cp_result(6) or cp_result(7);
-- co-processor result --
-- > "cp_result" data has to be always zero unless co-processor was actually triggered
cp_res <= cp_result(0) or cp_result(1) or cp_result(2) or cp_result(3) or
cp_result(4) or cp_result(5) or cp_result(6) or cp_result(7);
 
 
-- Co-Processor 0: Shifter (CPU Core ISA) --------------------------------------------------
-- Co-Processor 0: Shifter Unit (CPU Base ISA) --------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_cp_shifter_inst: neorv32_cpu_cp_shifter
generic map (
242,7 → 197,7
);
 
 
-- Co-Processor 1: Integer Multiplication/Division ('M' Extension) ------------------------
-- Co-Processor 1: Integer Multiplication/Division Unit ('M' Extension) -------------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_cp_muldiv_inst_true:
if (CPU_EXTENSION_RISCV_M = true) or (CPU_EXTENSION_RISCV_Zmmul = true) generate
/rtl/core/neorv32_cpu_bus.vhd
46,8 → 46,8
CPU_EXTENSION_RISCV_A : boolean; -- implement atomic extension?
CPU_EXTENSION_RISCV_C : boolean; -- implement compressed extension?
-- Physical memory protection (PMP) --
PMP_NUM_REGIONS : natural; -- number of regions (0..64)
PMP_MIN_GRANULARITY : natural -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
PMP_NUM_REGIONS : natural; -- number of regions (0..16)
PMP_MIN_GRANULARITY : natural -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
);
port (
-- global control --
105,13 → 105,10
 
-- PMP modes --
constant pmp_off_mode_c : std_ulogic_vector(1 downto 0) := "00"; -- null region (disabled)
--constant pmp_tor_mode_c : std_ulogic_vector(1 downto 0) := "01"; -- top of range
constant pmp_tor_mode_c : std_ulogic_vector(1 downto 0) := "01"; -- top of range
--constant pmp_na4_mode_c : std_ulogic_vector(1 downto 0) := "10"; -- naturally aligned four-byte region
constant pmp_napot_mode_c : std_ulogic_vector(1 downto 0) := "11"; -- naturally aligned power-of-two region (>= 8 bytes)
--constant pmp_napot_mode_c : std_ulogic_vector(1 downto 0) := "11"; -- naturally aligned power-of-two region (>= 8 bytes)
 
-- PMP granularity --
constant pmp_g_c : natural := index_size_f(PMP_MIN_GRANULARITY);
 
-- PMP configuration register bits --
constant pmp_cfg_r_c : natural := 0; -- read permit
constant pmp_cfg_w_c : natural := 1; -- write permit
121,6 → 118,9
--
constant pmp_cfg_l_c : natural := 7; -- locked entry
 
-- PMP minimal granularity --
constant pmp_lsb_c : natural := index_size_f(PMP_MIN_GRANULARITY);
 
-- data interface registers --
signal mar, mdo, mdi : std_ulogic_vector(data_width_c-1 downto 0);
 
147,17 → 147,12
signal exclusive_lock_status : std_ulogic_vector(data_width_c-1 downto 0); -- read data
 
-- physical memory protection --
type pmp_addr_t is array (0 to PMP_NUM_REGIONS-1) of std_ulogic_vector(data_width_c-1 downto 0);
type pmp_t is record
addr_mask : pmp_addr_t;
region_base : pmp_addr_t; -- region config base address
region_i_addr : pmp_addr_t; -- masked instruction access base address for comparator
region_d_addr : pmp_addr_t; -- masked data access base address for comparator
i_match : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region match for instruction interface
d_match : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region match for data interface
if_fault : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region access fault for fetch operation
ld_fault : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region access fault for load operation
st_fault : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region access fault for store operation
i_match : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region match for instruction interface
d_match : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region match for data interface
if_fault : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region access fault for fetch operation
ld_fault : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region access fault for load operation
st_fault : std_ulogic_vector(PMP_NUM_REGIONS-1 downto 0); -- region access fault for store operation
end record;
signal pmp : pmp_t;
 
196,28 → 191,7
-- address read-back for exception controller --
mar_o <= mar;
 
-- alignment check --
misaligned_d_check: process(mar, ctrl_i)
begin
case ctrl_i(ctrl_bus_size_msb_c downto ctrl_bus_size_lsb_c) is -- data size
when "00" => -- byte
d_misaligned <= '0';
when "01" => -- half-word
if (mar(0) /= '0') then
d_misaligned <= '1';
else
d_misaligned <= '0';
end if;
when others => -- word
if (mar(1 downto 0) /= "00") then
d_misaligned <= '1';
else
d_misaligned <= '0';
end if;
end case;
end process misaligned_d_check;
 
 
-- Data Interface: Write Data -------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
mem_do_reg: process(rstn_i, clk_i)
304,6 → 278,7
 
-- Data Access Arbiter --------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- controlled by pipeline BACK-end --
data_access_arbiter: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
316,12 → 291,14
if (d_arbiter.wr_req = '0') and (d_arbiter.rd_req = '0') then -- idle
d_arbiter.wr_req <= ctrl_i(ctrl_bus_wr_c);
d_arbiter.rd_req <= ctrl_i(ctrl_bus_rd_c);
d_arbiter.err_align <= d_misaligned;
d_arbiter.err_align <= '0';
d_arbiter.err_bus <= '0';
else -- in progress
d_arbiter.err_align <= (d_arbiter.err_align or d_misaligned) and (not ctrl_i(ctrl_bus_derr_ack_c));
d_arbiter.err_bus <= (d_arbiter.err_bus or d_bus_err_i or (st_pmp_fault and d_arbiter.wr_req) or (ld_pmp_fault and d_arbiter.rd_req)) and (not ctrl_i(ctrl_bus_derr_ack_c));
if ((d_bus_ack_i = '1') and (d_bus_err_i = '0')) or (ctrl_i(ctrl_bus_derr_ack_c) = '1') then -- wait for normal termination / CPU abort
else -- in progress, accumulate error
d_arbiter.err_align <= d_arbiter.err_align or d_misaligned;
d_arbiter.err_bus <= d_arbiter.err_bus or d_bus_err_i or (st_pmp_fault and d_arbiter.wr_req) or (ld_pmp_fault and d_arbiter.rd_req);
if (d_bus_ack_i = '1') or (ctrl_i(ctrl_trap_c) = '1') then -- wait for ACK or TRAP
-- > do not abort directly when an error has been detected - wait until the trap environment
-- > has started (ctrl_i(ctrl_trap_c)) to make sure the error signals are evaluated BEFORE d_wait_o clears
d_arbiter.wr_req <= '0';
d_arbiter.rd_req <= '0';
end if;
349,6 → 326,27
d_bus_fence_o <= ctrl_i(ctrl_bus_fence_c);
d_bus_rdata <= d_bus_rdata_i;
 
-- check data access address alignment --
misaligned_d_check: process(mar, ctrl_i)
begin
case ctrl_i(ctrl_bus_size_msb_c downto ctrl_bus_size_lsb_c) is -- data size
when "00" => -- byte
d_misaligned <= '0';
when "01" => -- half-word
if (mar(0) /= '0') then
d_misaligned <= '1';
else
d_misaligned <= '0';
end if;
when others => -- word
if (mar(1 downto 0) /= "00") then
d_misaligned <= '1';
else
d_misaligned <= '0';
end if;
end case;
end process misaligned_d_check;
 
-- additional register stage for control signals if using PMP_NUM_REGIONS > pmp_num_regions_critical_c --
pmp_dbus_buffer: process(rstn_i, clk_i)
begin
395,6 → 393,7
 
-- Instruction Fetch Arbiter --------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- controlled by pipeline FRONT-end --
ifetch_arbiter: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
405,12 → 404,12
-- instruction fetch request --
if (i_arbiter.rd_req = '0') then -- idle
i_arbiter.rd_req <= ctrl_i(ctrl_bus_if_c);
i_arbiter.err_align <= i_misaligned;
i_arbiter.err_align <= '0';
i_arbiter.err_bus <= '0';
else -- in progress
i_arbiter.err_align <= (i_arbiter.err_align or i_misaligned) and (not ctrl_i(ctrl_bus_ierr_ack_c));
i_arbiter.err_bus <= (i_arbiter.err_bus or i_bus_err_i or if_pmp_fault) and (not ctrl_i(ctrl_bus_ierr_ack_c));
if ((i_bus_ack_i = '1') and (i_bus_err_i = '0')) or (ctrl_i(ctrl_bus_ierr_ack_c) = '1') then -- wait for normal termination / CPU abort
else -- in progress, accumulate errors
i_arbiter.err_align <= i_arbiter.err_align or i_misaligned;
i_arbiter.err_bus <= i_arbiter.err_bus or i_bus_err_i or if_pmp_fault;
if (i_bus_ack_i = '1') or (i_arbiter.err_align = '1') or (i_arbiter.err_bus = '1') then -- wait for ACK or ERROR
i_arbiter.rd_req <= '0';
end if;
end if;
453,53 → 452,39
 
-- Physical Memory Protection (PMP) -------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- compute address masks (ITERATIVE!!!) --
pmp_masks: process(rstn_i, clk_i)
-- check access address region --
pmp_check_address: process(pmp_addr_i, fetch_pc_i, mar)
begin
if (rstn_i = '0') then
pmp.addr_mask <= (others => (others => def_rst_val_c));
elsif rising_edge(clk_i) then -- address mask computation (not the actual address check!) has a latency of max +32 cycles
for r in 0 to PMP_NUM_REGIONS-1 loop -- iterate over all regions
pmp.addr_mask(r) <= (others => '0');
for i in pmp_g_c to data_width_c-1 loop
pmp.addr_mask(r)(i) <= pmp.addr_mask(r)(i-1) or (not pmp_addr_i(r)(i-1));
end loop; -- i
end loop; -- r
end if;
end process pmp_masks;
for i in 0 to PMP_NUM_REGIONS-1 loop -- iterate over all regions
if (i = 0) then -- use ZERO as bottom boundary and current entry as top boundary for first entry
pmp.i_match(i) <= bool_to_ulogic_f(unsigned(fetch_pc_i(data_width_c-1 downto pmp_lsb_c)) < unsigned(pmp_addr_i(0)(data_width_c-1 downto pmp_lsb_c)));
pmp.d_match(i) <= bool_to_ulogic_f(unsigned(mar(data_width_c-1 downto pmp_lsb_c)) < unsigned(pmp_addr_i(0)(data_width_c-1 downto pmp_lsb_c)));
else -- use previous entry as bottom boundary and current entry as top boundary
pmp.i_match(i) <= bool_to_ulogic_f((unsigned(pmp_addr_i(i-1)(data_width_c-1 downto pmp_lsb_c)) <= unsigned(fetch_pc_i(data_width_c-1 downto pmp_lsb_c))) and
(unsigned(fetch_pc_i(data_width_c-1 downto pmp_lsb_c)) < unsigned(pmp_addr_i(i)(data_width_c-1 downto pmp_lsb_c))));
pmp.d_match(i) <= bool_to_ulogic_f((unsigned(pmp_addr_i(i-1)(data_width_c-1 downto pmp_lsb_c)) <= unsigned(mar(data_width_c-1 downto pmp_lsb_c))) and
(unsigned(mar(data_width_c-1 downto pmp_lsb_c)) < unsigned(pmp_addr_i(i)(data_width_c-1 downto pmp_lsb_c))));
end if;
end loop; -- i
end process pmp_check_address;
 
 
-- address access check --
pmp_address_check:
for r in 0 to PMP_NUM_REGIONS-1 generate -- iterate over all regions
pmp.region_i_addr(r) <= fetch_pc_i and pmp.addr_mask(r);
pmp.region_d_addr(r) <= mar and pmp.addr_mask(r);
pmp.region_base(r) <= pmp_addr_i(r)(data_width_c+1 downto 2) and pmp.addr_mask(r);
--
pmp.i_match(r) <= '1' when (pmp.region_i_addr(r)(data_width_c-1 downto pmp_g_c) = pmp.region_base(r)(data_width_c-1 downto pmp_g_c)) else '0';
pmp.d_match(r) <= '1' when (pmp.region_d_addr(r)(data_width_c-1 downto pmp_g_c) = pmp.region_base(r)(data_width_c-1 downto pmp_g_c)) else '0';
end generate; -- r
 
 
-- check access type and region's permissions --
-- check access type and permissions --
pmp_check_permission: process(pmp, pmp_ctrl_i, ctrl_i)
begin
for r in 0 to PMP_NUM_REGIONS-1 loop -- iterate over all regions
if ((ctrl_i(ctrl_priv_lvl_msb_c downto ctrl_priv_lvl_lsb_c) = priv_mode_u_c) or (pmp_ctrl_i(r)(pmp_cfg_l_c) = '1')) and -- user privilege level or locked pmp entry -> enforce permissions also for machine mode
(pmp_ctrl_i(r)(pmp_cfg_ah_c downto pmp_cfg_al_c) /= pmp_off_mode_c) and -- active entry
pmp.if_fault <= (others => '0');
pmp.ld_fault <= (others => '0');
pmp.st_fault <= (others => '0');
for i in 0 to PMP_NUM_REGIONS-1 loop -- iterate over all regions
if ((ctrl_i(ctrl_priv_mode_c) = priv_mode_u_c) or (pmp_ctrl_i(i)(pmp_cfg_l_c) = '1')) and -- enforce if USER-mode or LOCKED
(pmp_ctrl_i(i)(pmp_cfg_ah_c downto pmp_cfg_al_c) = pmp_tor_mode_c) and -- active entry
(ctrl_i(ctrl_debug_running_c) = '0') then -- disable PMP checks when in debug mode
pmp.if_fault(r) <= pmp.i_match(r) and (not pmp_ctrl_i(r)(pmp_cfg_x_c)); -- fetch access match no execute permission
pmp.ld_fault(r) <= pmp.d_match(r) and (not pmp_ctrl_i(r)(pmp_cfg_r_c)); -- load access match no read permission
pmp.st_fault(r) <= pmp.d_match(r) and (not pmp_ctrl_i(r)(pmp_cfg_w_c)); -- store access match no write permission
else
pmp.if_fault(r) <= '0';
pmp.ld_fault(r) <= '0';
pmp.st_fault(r) <= '0';
pmp.if_fault(i) <= pmp.i_match(i) and (not pmp_ctrl_i(i)(pmp_cfg_x_c)); -- fetch access match no execute permission
pmp.ld_fault(i) <= pmp.d_match(i) and (not pmp_ctrl_i(i)(pmp_cfg_r_c)); -- load access match no read permission
pmp.st_fault(i) <= pmp.d_match(i) and (not pmp_ctrl_i(i)(pmp_cfg_w_c)); -- store access match no write permission
end if;
end loop; -- r
end loop; -- i
end process pmp_check_permission;
 
 
-- final PMP access fault signals --
if_pmp_fault <= or_reduce_f(pmp.if_fault) when (PMP_NUM_REGIONS > 0) else '0';
ld_pmp_fault <= or_reduce_f(pmp.ld_fault) when (PMP_NUM_REGIONS > 0) else '0';
/rtl/core/neorv32_cpu_control.vhd
10,6 → 10,11
-- # + CSR module: Read/write access to control and status registers #
-- # + Debug module: CPU debug mode handling (on-chip debugger) #
-- # + Trigger module: Hardware-assisted breakpoints (on-chip debugger) #
-- # #
-- # NOTE: If <dedicated_reset_c> = true then <def_rst_val_c> evaluates to '-'. Registers that #
-- # reset to <def_rst_val_c> do NOT actually have a real reset by default and have to be #
-- # explicitly initialized by software! This is only used for "uncritical" registers. Many #
-- # of them will be initialized by the default crt0 start-up code. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
76,8 → 81,8
CPU_CNT_WIDTH : natural; -- total width of CPU cycle and instret counters (0..64)
CPU_IPB_ENTRIES : natural; -- entries is instruction prefetch buffer, has to be a power of 2
-- Physical memory protection (PMP) --
PMP_NUM_REGIONS : natural; -- number of regions (0..64)
PMP_MIN_GRANULARITY : natural; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
PMP_NUM_REGIONS : natural; -- number of regions (0..16)
PMP_MIN_GRANULARITY : natural; -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS : natural; -- number of implemented HPM counters (0..29)
HPM_CNT_WIDTH : natural -- total size of HPM counters (0..64)
150,7 → 155,7
pc : std_ulogic_vector(data_width_c-1 downto 0);
pc_nxt : std_ulogic_vector(data_width_c-1 downto 0);
reset : std_ulogic;
bus_err_ack : std_ulogic;
bus_ir : std_ulogic;
end record;
signal fetch_engine : fetch_engine_t;
 
192,22 → 197,20
 
-- instruction decoding helper logic --
type decode_aux_t is record
is_a_lr : std_ulogic;
is_a_sc : std_ulogic;
is_f_op : std_ulogic;
sys_env_cmd : std_ulogic_vector(11 downto 0);
is_m_mul : std_ulogic;
is_m_div : std_ulogic;
is_b_imm : std_ulogic;
is_b_reg : std_ulogic;
rs1_zero : std_ulogic;
rs2_zero : std_ulogic;
rd_zero : std_ulogic;
is_a_lr : std_ulogic;
is_a_sc : std_ulogic;
is_f_op : std_ulogic;
is_m_mul : std_ulogic;
is_m_div : std_ulogic;
is_b_imm : std_ulogic;
is_b_reg : std_ulogic;
rs1_zero : std_ulogic;
rd_zero : std_ulogic;
end record;
signal decode_aux : decode_aux_t;
 
-- instruction execution engine --
type execute_engine_state_t is (SYS_WAIT, DISPATCH, TRAP_ENTER, TRAP_EXIT, TRAP_EXECUTE, EXECUTE, ALU_WAIT,
type execute_engine_state_t is (DISPATCH, TRAP_ENTER, TRAP_EXIT, TRAP_EXECUTE, EXECUTE, ALU_WAIT,
BRANCH, LOADSTORE_0, LOADSTORE_1, LOADSTORE_2, SYS_ENV, CSR_ACCESS);
type execute_engine_t is record
state : execute_engine_state_t;
229,7 → 232,7
pc_we : std_ulogic; -- PC update enabled
next_pc : std_ulogic_vector(data_width_c-1 downto 0); -- next PC, corresponding to next instruction to be executed
next_pc_inc : std_ulogic_vector(data_width_c-1 downto 0); -- increment to get next PC
last_pc : std_ulogic_vector(data_width_c-1 downto 0); -- PC of last executed instruction
pc_last : std_ulogic_vector(data_width_c-1 downto 0); -- PC of last executed instruction
--
sleep : std_ulogic; -- CPU in sleep mode
sleep_nxt : std_ulogic;
240,11 → 243,10
 
-- trap controller --
type trap_ctrl_t is record
exc_buf : std_ulogic_vector(exception_width_c-1 downto 0);
exc_buf : std_ulogic_vector(exc_width_c-1 downto 0);
exc_fire : std_ulogic; -- set if there is a valid source in the exception buffer
irq_buf : std_ulogic_vector(interrupt_width_c-1 downto 0);
irq_buf : std_ulogic_vector(irq_width_c-1 downto 0);
irq_fire : std_ulogic; -- set if there is a valid source in the interrupt buffer
exc_clr : std_ulogic; -- clear all buffered exceptions
cause : std_ulogic_vector(6 downto 0); -- trap ID for mcause CSR
cause_nxt : std_ulogic_vector(6 downto 0);
db_irq_fire : std_ulogic; -- set if there is a valid IRQ source in the "enter debug mode" trap buffer
265,18 → 267,15
-- CPU main control bus --
signal ctrl_nxt, ctrl : std_ulogic_vector(ctrl_width_c-1 downto 0);
 
-- fast instruction fetch access --
signal bus_fast_ir : std_ulogic;
 
-- RISC-V control and status registers (CSRs) --
type pmp_ctrl_t is array (0 to PMP_NUM_REGIONS-1) of std_ulogic_vector(7 downto 0);
type pmp_addr_t is array (0 to PMP_NUM_REGIONS-1) of std_ulogic_vector(data_width_c-1 downto 0);
type pmp_ctrl_rd_t is array (0 to 63) of std_ulogic_vector(7 downto 0);
type pmpcfg_t is array (0 to 15) of std_ulogic_vector(7 downto 0);
type pmpaddr_t is array (0 to PMP_NUM_REGIONS-1) of std_ulogic_vector(data_width_c-3 downto index_size_f(PMP_MIN_GRANULARITY)-2);
type mhpmevent_t is array (0 to HPM_NUM_CNTS-1) of std_ulogic_vector(hpmcnt_event_size_c-1 downto 0);
type mhpmcnt_t is array (0 to HPM_NUM_CNTS-1) of std_ulogic_vector(31 downto 0);
type mhpmcnt_nxt_t is array (0 to HPM_NUM_CNTS-1) of std_ulogic_vector(32 downto 0);
type mhpmevent_rd_t is array (0 to 28) of std_ulogic_vector(data_width_c-1 downto 0);
type mhpmcnt_t is array (0 to HPM_NUM_CNTS-1) of std_ulogic_vector(data_width_c-1 downto 0);
type mhpmcnt_nxt_t is array (0 to HPM_NUM_CNTS-1) of std_ulogic_vector(data_width_c downto 0);
type mhpmcnt_ovfl_t is array (0 to HPM_NUM_CNTS-1) of std_ulogic_vector(0 downto 0);
type mhpmcnt_rd_t is array (0 to 29) of std_ulogic_vector(31 downto 0);
type mhpmcnt_rd_t is array (0 to 29) of std_ulogic_vector(data_width_c-1 downto 0);
type csr_t is record
addr : std_ulogic_vector(11 downto 0); -- csr address
we : std_ulogic; -- csr write enable
286,7 → 285,8
--
mstatus_mie : std_ulogic; -- mstatus.MIE: global IRQ enable (R/W)
mstatus_mpie : std_ulogic; -- mstatus.MPIE: previous global IRQ enable (R/W)
mstatus_mpp : std_ulogic_vector(1 downto 0); -- mstatus.MPP: machine previous privilege mode
mstatus_mpp : std_ulogic; -- mstatus.MPP: machine previous privilege mode
mstatus_tw : std_ulogic; -- mstatus.TW: do not allow user mode to execute WFI instruction when set
--
mie_msie : std_ulogic; -- mie.MSIE: machine software interrupt enable (R/W)
mie_meie : std_ulogic; -- mie.MEIE: machine external interrupt enable (R/W)
293,7 → 293,7
mie_mtie : std_ulogic; -- mie.MEIE: machine timer interrupt enable (R/W)
mie_firqe : std_ulogic_vector(15 downto 0); -- mie.firq*e: fast interrupt enabled (R/W)
--
mip_clr : std_ulogic_vector(15 downto 0); -- clear pending FIRQ
mip_firq_nclr : std_ulogic_vector(15 downto 0); -- clear pending FIRQ (active-low)
--
mcounteren_cy : std_ulogic; -- mcounteren.cy: allow cycle[h] access from user-mode
mcounteren_tm : std_ulogic; -- mcounteren.tm: allow time[h] access from user-mode
303,10 → 303,8
mcountinhibit_ir : std_ulogic; -- mcounterinhibit.ir: enable auto-increment for [m]instret[h]
mcountinhibit_hpm : std_ulogic_vector(HPM_NUM_CNTS-1 downto 0); -- mcounterinhibit.hpm3: enable auto-increment for mhpmcounterx[h]
--
privilege : std_ulogic_vector(1 downto 0); -- hart's current privilege mode
privilege_rd : std_ulogic_vector(1 downto 0); -- hart's current privilege mode (effective)
priv_m_mode : std_ulogic; -- CPU in M-mode
priv_u_mode : std_ulogic; -- CPU in u-mode
privilege : std_ulogic; -- current privilege mode
privilege_eff : std_ulogic; -- current *effective* privilege mode
--
mepc : std_ulogic_vector(data_width_c-1 downto 0); -- mepc: machine exception pc (R/W)
mcause : std_ulogic_vector(5 downto 0); -- mcause: machine trap cause (R/W)
314,17 → 312,18
mtval : std_ulogic_vector(data_width_c-1 downto 0); -- mtval: machine bad address or instruction (R/W)
--
mhpmevent : mhpmevent_t; -- mhpmevent*: machine performance-monitoring event selector (R/W)
mhpmevent_rd : mhpmevent_rd_t; -- read data
--
mscratch : std_ulogic_vector(data_width_c-1 downto 0); -- mscratch: scratch register (R/W)
--
mcycle : std_ulogic_vector(31 downto 0); -- mcycle (R/W)
mcycle_nxt : std_ulogic_vector(32 downto 0);
mcycle : std_ulogic_vector(data_width_c-1 downto 0); -- mcycle (R/W)
mcycle_nxt : std_ulogic_vector(data_width_c downto 0);
mcycle_ovfl : std_ulogic_vector(00 downto 0); -- counter low-to-high-word overflow
mcycleh : std_ulogic_vector(31 downto 0); -- mcycleh (R/W)
minstret : std_ulogic_vector(31 downto 0); -- minstret (R/W)
minstret_nxt : std_ulogic_vector(32 downto 0);
mcycleh : std_ulogic_vector(data_width_c-1 downto 0); -- mcycleh (R/W)
minstret : std_ulogic_vector(data_width_c-1 downto 0); -- minstret (R/W)
minstret_nxt : std_ulogic_vector(data_width_c downto 0);
minstret_ovfl : std_ulogic_vector(00 downto 0); -- counter low-to-high-word overflow
minstreth : std_ulogic_vector(31 downto 0); -- minstreth (R/W)
minstreth : std_ulogic_vector(data_width_c-1 downto 0); -- minstreth (R/W)
--
mhpmcounter : mhpmcnt_t; -- mhpmcounter* (R/W), plus carry bit
mhpmcounter_nxt : mhpmcnt_nxt_t;
333,9 → 332,8
mhpmcounter_rd : mhpmcnt_rd_t; -- mhpmcounter* (R/W): actual read data
mhpmcounterh_rd : mhpmcnt_rd_t; -- mhpmcounter*h (R/W): actual read data
--
pmpcfg : pmp_ctrl_t; -- physical memory protection - configuration registers
pmpcfg_rd : pmp_ctrl_rd_t; -- physical memory protection - actual read data
pmpaddr : pmp_addr_t; -- physical memory protection - address registers
pmpcfg : pmpcfg_t; -- physical memory protection - configuration registers
pmpaddr : pmpaddr_t; -- physical memory protection - address registers (bits 33:2 of PHYSICAL address)
--
frm : std_ulogic_vector(02 downto 0); -- frm (R/W): FPU rounding mode
fflags : std_ulogic_vector(04 downto 0); -- fflags (R/W): FPU exception flags
343,7 → 341,7
dcsr_ebreakm : std_ulogic; -- dcsr.ebreakm (R/W): behavior of ebreak instruction on m-mode
dcsr_ebreaku : std_ulogic; -- dcsr.ebreaku (R/W): behavior of ebreak instruction on u-mode
dcsr_step : std_ulogic; -- dcsr.step (R/W): single-step mode
dcsr_prv : std_ulogic_vector(01 downto 0); -- dcsr.prv (R/W): current privilege level when entering debug mode
dcsr_prv : std_ulogic; -- dcsr.prv (R/W): current privilege level when entering debug mode
dcsr_cause : std_ulogic_vector(02 downto 0); -- dcsr.cause (R/-): why was debug mode entered
dcsr_rd : std_ulogic_vector(data_width_c-1 downto 0); -- dcsr (R/(W)): debug mode control and status register
dpc : std_ulogic_vector(data_width_c-1 downto 0); -- dpc (R/W): debug mode program counter
409,11 → 407,7
fetch_engine.state <= fetch_engine.state_nxt;
fetch_engine.state_prev <= fetch_engine.state;
fetch_engine.restart <= fetch_engine.restart_nxt or fetch_engine.reset;
if (fetch_engine.restart = '1') and (fetch_engine.state = IFETCH_REQUEST) then -- only update PC if no fetch request is pending
fetch_engine.pc <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- initialize with "real" application PC
else
fetch_engine.pc <= fetch_engine.pc_nxt;
end if;
fetch_engine.pc <= fetch_engine.pc_nxt;
end if;
end process fetch_engine_fsm_sync;
 
426,22 → 420,22
fetch_engine_fsm_comb: process(fetch_engine, execute_engine, ipb, instr_i, bus_i_wait_i, be_instr_i, ma_instr_i)
begin
-- arbiter defaults --
bus_fast_ir <= '0';
fetch_engine.bus_ir <= '0';
fetch_engine.state_nxt <= fetch_engine.state;
fetch_engine.pc_nxt <= fetch_engine.pc;
fetch_engine.bus_err_ack <= '0';
fetch_engine.restart_nxt <= fetch_engine.restart;
 
-- instruction prefetch buffer defaults --
ipb.we <= '0';
ipb.wdata <= be_instr_i & ma_instr_i & instr_i(31 downto 0); -- store exception info and instruction word
ipb.clear <= fetch_engine.restart; -- clear instruction buffer while being reset
 
-- state machine --
if (fetch_engine.state = IFETCH_REQUEST) then -- IFETCH_REQUEST: request new 32-bit-aligned instruction word
-- ------------------------------------------------------------
if (ipb.free = '1') and (fetch_engine.restart = '0') then -- free entry in buffer AND no reset request?
bus_fast_ir <= '1'; -- fast instruction fetch request
if (fetch_engine.restart = '1') then -- reset request
fetch_engine.pc_nxt <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- initialize with "real" application PC
elsif (ipb.free = '1') then -- free entry in buffer
fetch_engine.bus_ir <= '1'; -- instruction fetch request
fetch_engine.state_nxt <= IFETCH_ISSUE;
end if;
fetch_engine.restart_nxt <= '0';
448,7 → 442,6
 
else -- IFETCH_ISSUE: store instruction data to prefetch buffer
-- ------------------------------------------------------------
fetch_engine.bus_err_ack <= be_instr_i or ma_instr_i; -- ACK bus/alignment errors
if (bus_i_wait_i = '0') or (be_instr_i = '1') or (ma_instr_i = '1') then -- wait for bus response
fetch_engine.pc_nxt <= std_ulogic_vector(unsigned(fetch_engine.pc) + 4);
ipb.we <= not fetch_engine.restart; -- write to IPB if not being reset
458,7 → 451,10
end if;
end process fetch_engine_fsm_comb;
 
-- clear instruction prefetch buffer while being reset --
ipb.clear <= fetch_engine.restart or fetch_engine.reset;
 
 
-- ****************************************************************************************************************************
-- Instruction Prefetch Buffer
-- ****************************************************************************************************************************
535,7 → 531,6
-- instruction issue interface defaults --
cmd_issue.valid <= '0';
 
 
-- construct instruction data --
-- cmd_issue.data = <illegal_compressed_instruction> & <bus_error & alignment_error> & <is_compressed_instrucion> & <32-bit_instruction_word>
if (issue_engine.align = '0') or (CPU_EXTENSION_RISCV_C = false) then -- 32-bit aligned
552,13 → 547,11
end if;
end if;
 
 
-- store high half-word - we might need it for an unaligned uncompressed instruction --
if (execute_engine.state = DISPATCH) and (ipb.avail = '1') and (CPU_EXTENSION_RISCV_C = true) then
issue_engine.buf_nxt <= ipb.rdata(33 downto 32) & ipb.rdata(31 downto 16);
end if;
 
 
-- state machine --
if (ipb.avail = '1') then -- instruction data available?
 
600,6 → 593,9
neorv32_cpu_decompressor_inst_true:
if (CPU_EXTENSION_RISCV_C = true) generate
neorv32_cpu_decompressor_inst: neorv32_cpu_decompressor
generic map (
FPU_ENABLE => CPU_EXTENSION_RISCV_Zfinx -- floating-point instruction enabled
)
port map (
-- instruction input --
ci_instr16_i => ci_instr16, -- compressed instruction input
622,13 → 618,11
 
-- Immediate Generator --------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
imm_gen: process(rstn_i, clk_i)
imm_gen: process(clk_i)
variable opcode_v : std_ulogic_vector(6 downto 0);
begin
if (rstn_i = '0') then
imm_o <= (others => def_rst_val_c);
elsif rising_edge(clk_i) then
-- default: I-immediate: ALU-immediate, loads, jump-and-link with registers
if rising_edge(clk_i) then
-- default: I-immediate: ALU-immediate, loads, jump-and-link with register
imm_o(31 downto 11) <= (others => execute_engine.i_reg(31)); -- sign extension
imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
imm_o(04 downto 01) <= execute_engine.i_reg(24 downto 21);
693,18 → 687,18
execute_engine_fsm_sync: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
-- no dedicated RESET required --
execute_engine.state_prev <= SYS_WAIT; -- actual reset value is not relevant
-- no dedicated reset required --
execute_engine.state_prev <= DISPATCH; -- actual reset value is not relevant
execute_engine.i_reg <= (others => def_rst_val_c);
execute_engine.is_ci <= def_rst_val_c;
execute_engine.is_ici <= def_rst_val_c;
execute_engine.last_pc <= (others => def_rst_val_c);
execute_engine.i_reg_last <= (others => def_rst_val_c);
execute_engine.next_pc <= (others => def_rst_val_c);
ctrl <= (others => def_rst_val_c);
-- registers that DO require a specific reset state --
-- registers that DO require a specific RESET state --
execute_engine.pc <= CPU_BOOT_ADDR(data_width_c-1 downto 2) & "00"; -- 32-bit aligned!
execute_engine.state <= SYS_WAIT;
execute_engine.pc_last <= CPU_BOOT_ADDR(data_width_c-1 downto 2) & "00";
execute_engine.state <= DISPATCH;
execute_engine.sleep <= '0';
execute_engine.branched <= '1'; -- reset is a branch from "somewhere"
ctrl(ctrl_bus_rd_c) <= '0';
719,6 → 713,7
end if;
end if;
 
-- execute engine arbiter --
execute_engine.state <= execute_engine.state_nxt;
execute_engine.state_prev <= execute_engine.state;
execute_engine.sleep <= execute_engine.sleep_nxt;
729,7 → 724,7
 
-- PC & IR of "last executed" instruction for trap handling --
if (execute_engine.state = EXECUTE) then
execute_engine.last_pc <= execute_engine.pc;
execute_engine.pc_last <= execute_engine.pc;
execute_engine.i_reg_last <= execute_engine.i_reg;
end if;
 
736,16 → 731,12
-- next PC logic --
case execute_engine.state is
when TRAP_ENTER => -- ENTERING trap environment
if (CPU_EXTENSION_RISCV_DEBUG = false) then -- normal trapping
if (trap_ctrl.cause(5) = '1') and (CPU_EXTENSION_RISCV_DEBUG = true) then -- trap cause: debug mode (re-)entry
execute_engine.next_pc <= CPU_DEBUG_ADDR; -- debug mode enter; start at "parking loop" <normal_entry>
elsif (debug_ctrl.running = '1') and (CPU_EXTENSION_RISCV_DEBUG = true) then -- any other exception INSIDE debug mode
execute_engine.next_pc <= std_ulogic_vector(unsigned(CPU_DEBUG_ADDR) + 4); -- start at "parking loop" <exception_entry>
else -- normal trapping
execute_engine.next_pc <= csr.mtvec(data_width_c-1 downto 1) & '0'; -- trap enter
else -- DEBUG MODE enabled
if (trap_ctrl.cause(5) = '1') then -- trap cause: debug mode (re-)entry
execute_engine.next_pc <= CPU_DEBUG_ADDR; -- debug mode enter; start at "parking loop" <normal_entry>
elsif (debug_ctrl.running = '1') then -- any other exception INSIDE debug mode
execute_engine.next_pc <= std_ulogic_vector(unsigned(CPU_DEBUG_ADDR) + 4); -- execute at "parking loop" <exception_entry>
else -- normal trapping
execute_engine.next_pc <= csr.mtvec(data_width_c-1 downto 1) & '0'; -- trap enter
end if;
end if;
when TRAP_EXIT => -- LEAVING trap environment
if (CPU_EXTENSION_RISCV_DEBUG = false) or (debug_ctrl.running = '0') then -- normal end of trap
759,7 → 750,7
NULL;
end case;
 
-- main control bus --
-- main control bus buffer --
ctrl <= ctrl_nxt;
end if;
end process execute_engine_fsm_sync;
766,11 → 757,12
 
 
-- PC increment for next linear instruction (+2 for compressed instr., +4 otherwise) --
execute_engine.next_pc_inc <= x"00000004" when ((execute_engine.is_ci = '0') or (CPU_EXTENSION_RISCV_C = false)) else x"00000002";
execute_engine.next_pc_inc(data_width_c-1 downto 4) <= (others => '0');
execute_engine.next_pc_inc(3 downto 0) <= x"4" when ((execute_engine.is_ci = '0') or (CPU_EXTENSION_RISCV_C = false)) else x"2";
 
-- PC output --
curr_pc_o <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- current PC for ALU ops
next_pc_o <= execute_engine.next_pc(data_width_c-1 downto 1) & '0'; -- next PC for ALU ops
curr_pc_o <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- current PC
next_pc_o <= execute_engine.next_pc(data_width_c-1 downto 1) & '0'; -- next PC
 
-- CSR access address --
csr.addr <= execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c);
778,25 → 770,22
 
-- CPU Control Bus Output -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
ctrl_output: process(ctrl, fetch_engine, trap_ctrl, bus_fast_ir, execute_engine, csr, debug_ctrl)
ctrl_output: process(ctrl, fetch_engine, trap_ctrl, execute_engine, csr, debug_ctrl)
begin
-- signals from execute engine --
ctrl_o <= ctrl;
-- prevent commits if illegal instruction --
ctrl_o(ctrl_rf_wb_en_c) <= ctrl(ctrl_rf_wb_en_c) and (not trap_ctrl.exc_buf(exception_iillegal_c));
ctrl_o(ctrl_bus_rd_c) <= ctrl(ctrl_bus_rd_c) and (not trap_ctrl.exc_buf(exception_iillegal_c));
ctrl_o(ctrl_bus_wr_c) <= ctrl(ctrl_bus_wr_c) and (not trap_ctrl.exc_buf(exception_iillegal_c));
-- current privilege level --
ctrl_o(ctrl_priv_lvl_msb_c downto ctrl_priv_lvl_lsb_c) <= csr.privilege_rd;
ctrl_o(ctrl_rf_wb_en_c) <= ctrl(ctrl_rf_wb_en_c) and (not trap_ctrl.exc_buf(exc_iillegal_c));
ctrl_o(ctrl_bus_rd_c) <= ctrl(ctrl_bus_rd_c) and (not trap_ctrl.exc_buf(exc_iillegal_c));
ctrl_o(ctrl_bus_wr_c) <= ctrl(ctrl_bus_wr_c) and (not trap_ctrl.exc_buf(exc_iillegal_c));
-- current effective privilege level --
ctrl_o(ctrl_priv_mode_c) <= csr.privilege_eff;
-- register addresses --
ctrl_o(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c) <= execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c);
ctrl_o(ctrl_rf_rs2_adr4_c downto ctrl_rf_rs2_adr0_c) <= execute_engine.i_reg(instr_rs2_msb_c downto instr_rs2_lsb_c);
ctrl_o(ctrl_rf_rd_adr4_c downto ctrl_rf_rd_adr0_c) <= execute_engine.i_reg(instr_rd_msb_c downto instr_rd_lsb_c);
-- instruction fetch request --
ctrl_o(ctrl_bus_if_c) <= bus_fast_ir;
-- bus error control --
ctrl_o(ctrl_bus_ierr_ack_c) <= fetch_engine.bus_err_ack; -- instruction fetch bus access error ACK
ctrl_o(ctrl_bus_derr_ack_c) <= trap_ctrl.env_start_ack; -- data access bus error access ACK
ctrl_o(ctrl_bus_if_c) <= fetch_engine.bus_ir;
-- memory access size / sign --
ctrl_o(ctrl_bus_unsigned_c) <= execute_engine.i_reg(instr_funct3_msb_c); -- unsigned LOAD (LBU, LHU)
ctrl_o(ctrl_bus_size_msb_c downto ctrl_bus_size_lsb_c) <= execute_engine.i_reg(instr_funct3_lsb_c+1 downto instr_funct3_lsb_c); -- mem transfer size
819,7 → 808,6
-- Decoding Helper Logic ------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
decode_helper: process(execute_engine)
variable sys_env_cmd_mask_v : std_ulogic_vector(11 downto 0);
begin
-- defaults --
decode_aux.is_a_lr <= '0';
830,7 → 818,6
decode_aux.is_b_imm <= '0';
decode_aux.is_b_reg <= '0';
decode_aux.rs1_zero <= '0';
decode_aux.rs2_zero <= '0';
decode_aux.rd_zero <= '0';
 
-- is atomic load-reservate/store-conditional? --
841,79 → 828,81
 
-- is BITMANIP instruction? --
-- pretty complex as we have to extract this from the ALU/ALUI instruction space --
-- immediate operation --
if ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0110000") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001") and
(
(execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00000") or -- CLZ
(execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00001") or -- CTZ
(execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00010") or -- CPOP
(execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00100") or -- SEXT.B
(execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00101") -- SEXT.H
)
) or
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0110000") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101")) or -- RORI
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0010100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101") and (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00111")) or -- ORCB
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0110100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101")) or -- REV8
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0100100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- BCLRI
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0100100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101")) or -- BEXTI
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0110100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- BINVI
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0010100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) then -- BSETI
decode_aux.is_b_imm <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B); -- BITMANIP implemented at all?
if (CPU_EXTENSION_RISCV_B = true) then -- BITMANIP implemented at all?
-- immediate operation --
if ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0110000") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001") and
(
(execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00000") or -- CLZ
(execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00001") or -- CTZ
(execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00010") or -- CPOP
(execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00100") or -- SEXT.B
(execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00101") -- SEXT.H
)
) or
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0110000") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101")) or -- RORI
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0010100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101") and (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00111")) or -- ORCB
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0110100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101")) or -- REV8
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0100100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- BCLRI
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0100100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101")) or -- BEXTI
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0110100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- BINVI
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0010100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) then -- BSETI
decode_aux.is_b_imm <= '1';
end if;
-- register operation --
if ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0110000") and (execute_engine.i_reg(instr_funct3_msb_c-1 downto instr_funct3_lsb_c) = "01")) or -- ROR / ROL
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000101") and (execute_engine.i_reg(instr_funct3_msb_c) = '1')) or -- MIN[U] / MAX[U]
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "100")) or -- ZEXTH
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0100100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- BCLR
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0100100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101")) or -- BEXT
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0110100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- BINV
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0010100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- BSET
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000101") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- CLMUL
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000101") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "011")) or -- CLMULH
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000101") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "010")) or -- CLMULR
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0100000") and
(
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "111") or -- ANDN
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "110") or -- ORN
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "100") -- XORN
)
) or
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0010000") and
(
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "010") or -- SH1ADD
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "100") or -- SH2ADD
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "110") -- SH3ADD
)
) then
decode_aux.is_b_reg <= '1';
end if;
end if;
-- register operation --
if ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0110000") and (execute_engine.i_reg(instr_funct3_msb_c-1 downto instr_funct3_lsb_c) = "01")) or -- ROR / ROL
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000101") and (execute_engine.i_reg(instr_funct3_msb_c) = '1')) or -- MIN[U] / MAX[U]
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "100")) or -- ZEXTH
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0100100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- BCLR
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0100100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101")) or -- BEXT
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0110100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- BINV
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0010100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- BSET
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000101") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- CLMUL
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000101") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "011")) or -- CLMULH
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000101") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "010")) or -- CLMULR
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0100000") and
(
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "111") or -- ANDN
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "110") or -- ORN
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "100") -- XORN
)
) or
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0010000") and
(
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "010") or -- SH1ADD
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "100") or -- SH2ADD
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "110") -- SH3ADD
)
) then
decode_aux.is_b_reg <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B); -- BITMANIP implemented at all?
end if;
 
-- floating-point operations (Zfinx) --
if ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+3) = "0000")) or -- FADD.S / FSUB.S
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00010")) or -- FMUL.S
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "11100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- FCLASS.S
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00100") and (execute_engine.i_reg(instr_funct3_msb_c) = '0')) or -- FSGNJ[N/X].S
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00101") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_msb_c-1) = "00")) or -- FMIN.S / FMAX.S
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "10100") and (execute_engine.i_reg(instr_funct3_msb_c) = '0')) or -- FEQ.S / FLT.S / FLE.S
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "11010") and (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c+1) = "0000")) or -- FCVT.S.W*
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "11000") and (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c+1) = "0000")) then -- FCVT.W*.S
decode_aux.is_f_op <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zfinx); -- FPU implemented at all?
if (CPU_EXTENSION_RISCV_Zfinx = true) then -- FPU implemented at all?
if ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+3) = "0000")) or -- FADD.S / FSUB.S
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00010")) or -- FMUL.S
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "11100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- FCLASS.S
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00100") and (execute_engine.i_reg(instr_funct3_msb_c) = '0')) or -- FSGNJ[N/X].S
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00101") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_msb_c-1) = "00")) or -- FMIN.S / FMAX.S
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "10100") and (execute_engine.i_reg(instr_funct3_msb_c) = '0')) or -- FEQ.S / FLT.S / FLE.S
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "11010") and (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c+1) = "0000")) or -- FCVT.S.W*
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "11000") and (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c+1) = "0000")) then -- FCVT.W*.S
decode_aux.is_f_op <= '1';
end if;
end if;
 
-- system/environment instructions --
sys_env_cmd_mask_v := funct12_ecall_c or funct12_ebreak_c or funct12_mret_c or funct12_wfi_c or funct12_dret_c; -- sum-up set bits
decode_aux.sys_env_cmd <= execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) and sys_env_cmd_mask_v; -- set unused bits to always-zero
 
-- integer MUL (M/Zmmul) / DIV (M) operation --
if (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5)) and
(execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then
decode_aux.is_m_mul <= (not execute_engine.i_reg(instr_funct3_msb_c)) and (bool_to_ulogic_f(CPU_EXTENSION_RISCV_M) or bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zmmul));
decode_aux.is_m_div <= execute_engine.i_reg(instr_funct3_msb_c) and bool_to_ulogic_f(CPU_EXTENSION_RISCV_M);
if (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5)) and (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then
if ((CPU_EXTENSION_RISCV_M = true) or (CPU_EXTENSION_RISCV_Zmmul = true)) and (execute_engine.i_reg(instr_funct3_msb_c) = '0') then
decode_aux.is_m_mul <= '1';
end if;
if (CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_funct3_msb_c) = '1') then
decode_aux.is_m_div <= '1';
end if;
end if;
 
-- register address checks --
-- register/uimm5 checks --
decode_aux.rs1_zero <= not or_reduce_f(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c));
decode_aux.rs2_zero <= not or_reduce_f(execute_engine.i_reg(instr_rs2_msb_c downto instr_rs2_lsb_c));
decode_aux.rd_zero <= not or_reduce_f(execute_engine.i_reg(instr_rd_msb_c downto instr_rd_lsb_c));
end process decode_helper;
 
956,9 → 945,8
 
-- CONTROL DEFAULTS --
ctrl_nxt <= (others => '0'); -- default: all off
-- ALU main control --
ctrl_nxt(ctrl_alu_op2_c downto ctrl_alu_op0_c) <= alu_op_add_c; -- default ALU operation: ADD
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_core_c; -- default ALU operation: ADD
ctrl_nxt(ctrl_alu_op2_c downto ctrl_alu_op0_c) <= alu_op_add_c; -- default ALU operation: ADD
ctrl_nxt(ctrl_rf_mux1_c downto ctrl_rf_mux0_c) <= rf_mux_alu_c; -- default RF input: ALU
-- ALU sign control --
if (execute_engine.i_reg(instr_opcode_lsb_c+4) = '1') then -- ALU ops
ctrl_nxt(ctrl_alu_unsigned_c) <= execute_engine.i_reg(instr_funct3_lsb_c+0); -- unsigned ALU operation? (SLTIU, SLTU)
966,17 → 954,12
ctrl_nxt(ctrl_alu_unsigned_c) <= execute_engine.i_reg(instr_funct3_lsb_c+1); -- unsigned branches? (BLTU, BGEU)
end if;
-- atomic store-conditional instruction (evaluate lock status) --
ctrl_nxt(ctrl_bus_ch_lock_c) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_A) and decode_aux.is_a_sc;
ctrl_nxt(ctrl_bus_ch_lock_c) <= decode_aux.is_a_sc;
 
 
-- state machine --
case execute_engine.state is
 
when SYS_WAIT => -- System delay cycle (to let side effects kick in)
-- ------------------------------------------------------------
execute_engine.state_nxt <= DISPATCH;
 
 
when DISPATCH => -- Get new command from instruction issue engine
-- ------------------------------------------------------------
-- PC update --
990,7 → 973,9
execute_engine.branched_nxt <= '0';
execute_engine.pc_we <= not execute_engine.branched; -- update PC with linear next_pc if there was no actual branch
-- IR update - exceptions --
trap_ctrl.instr_ma <= cmd_issue.data(33) and (not bool_to_ulogic_f(CPU_EXTENSION_RISCV_C)); -- misaligned instruction fetch address, if C disabled
if (CPU_EXTENSION_RISCV_C = false) then
trap_ctrl.instr_ma <= cmd_issue.data(33); -- misaligned instruction fetch address, if C disabled
end if;
trap_ctrl.instr_be <= cmd_issue.data(34); -- bus access fault during instruction fetch
execute_engine.is_ici_nxt <= cmd_issue.data(35); -- invalid decompressed instruction
-- any reason to go to trap state? --
1006,7 → 991,7
end if;
 
 
when TRAP_ENTER => -- Start trap environment - get xTVEC, stay here for sleep mode
when TRAP_ENTER => -- Start trap environment - get trap vector (depc or epc), stay here for sleep mode
-- ------------------------------------------------------------
if (trap_ctrl.env_start = '1') then -- trap triggered?
trap_ctrl.env_start_ack <= '1';
1026,7 → 1011,7
fetch_engine.reset <= '1';
execute_engine.pc_we <= '1';
execute_engine.sleep_nxt <= '0'; -- disable sleep mode
execute_engine.state_nxt <= SYS_WAIT;
execute_engine.state_nxt <= DISPATCH;
 
 
when EXECUTE => -- Decode and execute instruction (control has to be here for exactly 1 cycle in any case!)
1059,27 → 1044,23
-- co-processor MULDIV operation (multi-cycle) --
if ((CPU_EXTENSION_RISCV_M = true) and ((decode_aux.is_m_mul = '1') or (decode_aux.is_m_div = '1'))) or -- MUL/DIV
((CPU_EXTENSION_RISCV_Zmmul = true) and (decode_aux.is_m_mul = '1')) then -- MUL
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_muldiv_c; -- use MULDIV CP
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_copro_c;
execute_engine.state_nxt <= ALU_WAIT;
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_muldiv_c; -- trigger MULDIV CP
execute_engine.state_nxt <= ALU_WAIT;
-- co-processor BIT-MANIPULATION operation (multi-cycle) --
elsif (CPU_EXTENSION_RISCV_B = true) and
(((execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5)) and (decode_aux.is_b_reg = '1')) or -- register operation
((execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alui_c(5)) and (decode_aux.is_b_imm = '1'))) then -- immediate operation
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_bitmanip_c; -- use BITMANIP CP
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_copro_c;
execute_engine.state_nxt <= ALU_WAIT;
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_bitmanip_c; -- trigger BITMANIP CP
execute_engine.state_nxt <= ALU_WAIT;
-- co-processor SHIFT operation (multi-cycle) --
elsif (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) then
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_shifter_c; -- use SHIFTER CP (only relevant for shift operations)
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_copro_c;
execute_engine.state_nxt <= ALU_WAIT;
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_shifter_c; -- trigger SHIFTER CP
execute_engine.state_nxt <= ALU_WAIT;
-- ALU CORE operation (single-cycle) --
else
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_core_c;
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
execute_engine.state_nxt <= DISPATCH;
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
execute_engine.state_nxt <= DISPATCH;
end if;
 
 
1118,13 → 1099,13
-- ------------------------------------------------------------
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fence_c) then -- FENCE
ctrl_nxt(ctrl_bus_fence_c) <= '1';
execute_engine.state_nxt <= SYS_WAIT;
execute_engine.state_nxt <= DISPATCH;
elsif (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fencei_c) and (CPU_EXTENSION_RISCV_Zifencei = true) then -- FENCE.I
ctrl_nxt(ctrl_bus_fencei_c) <= '1';
execute_engine.branched_nxt <= '1'; -- this is an actual branch
execute_engine.state_nxt <= TRAP_EXECUTE; -- use TRAP_EXECUTE to "modify" PC (PC <= PC)
else -- illegal fence instruction
execute_engine.state_nxt <= SYS_WAIT;
execute_engine.state_nxt <= DISPATCH;
end if;
 
 
1132,10 → 1113,9
-- ------------------------------------------------------------
if (CPU_EXTENSION_RISCV_Zfinx = true) then
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_fpu_c; -- trigger FPU CP
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_copro_c;
execute_engine.state_nxt <= ALU_WAIT;
else
execute_engine.state_nxt <= SYS_WAIT;
execute_engine.state_nxt <= DISPATCH;
end if;
 
 
1143,14 → 1123,13
-- ------------------------------------------------------------
if (CPU_EXTENSION_RISCV_Zxcfu = true) then
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_cfu_c; -- trigger CFU CP
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_copro_c;
execute_engine.state_nxt <= ALU_WAIT;
else
execute_engine.state_nxt <= SYS_WAIT;
execute_engine.state_nxt <= DISPATCH;
end if;
 
 
when others => -- system/csr access OR illegal opcode - nothing bad (= no commits) will happen here if there is an illegal opcode
when others => -- system/csr access OR illegal opcode
-- ------------------------------------------------------------
if (CPU_EXTENSION_RISCV_Zicsr = true) then
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_env_c) then -- system/environment
1159,58 → 1138,58
execute_engine.state_nxt <= CSR_ACCESS;
end if;
else
execute_engine.state_nxt <= SYS_WAIT;
execute_engine.state_nxt <= DISPATCH;
end if;
 
end case;
 
 
when SYS_ENV => -- system environment operation - no action if illegal instruction
when SYS_ENV => -- system environment operation
-- ------------------------------------------------------------
execute_engine.state_nxt <= SYS_WAIT; -- default
if (trap_ctrl.exc_buf(exception_iillegal_c) = '0') then -- no illegal instruction
case decode_aux.sys_env_cmd is -- use a simplified input here (with hardwired zeros)
when funct12_ecall_c => trap_ctrl.env_call <= '1'; -- ECALL
when funct12_ebreak_c => trap_ctrl.break_point <= '1'; -- EBREAK
when funct12_mret_c => execute_engine.state_nxt <= TRAP_EXIT; -- MRET
when funct12_dret_c => -- DRET
if (CPU_EXTENSION_RISCV_DEBUG = true) then
execute_engine.state_nxt <= TRAP_EXIT;
debug_ctrl.dret <= '1';
else
NULL; -- executed as NOP (and raise illegal instruction exception)
end if;
when funct12_wfi_c => -- WFI
if (CPU_EXTENSION_RISCV_DEBUG = true) and ((debug_ctrl.running = '1') or (csr.dcsr_step = '1')) then -- NOP when in debug-mode or during single-stepping
NULL; -- executed as NOP
else
execute_engine.sleep_nxt <= '1'; -- go to sleep mode
end if;
when others => NULL; -- undefined, execute as NOP
end case;
-- MRET / DRET --
if (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_mret_c) then
execute_engine.state_nxt <= TRAP_EXIT; -- mret
elsif (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_dret_c) and
(CPU_EXTENSION_RISCV_DEBUG = true) then
debug_ctrl.dret <= '1';
execute_engine.state_nxt <= TRAP_EXIT; -- dret
else
execute_engine.state_nxt <= DISPATCH; -- default
end if;
-- ECALL / EBREAK --
if ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c+1) = funct12_ecall_c(11 downto 1))) then
if (execute_engine.i_reg(instr_funct12_lsb_c) = funct12_ecall_c(0)) then
trap_ctrl.env_call <= '1'; -- ecall
else
trap_ctrl.break_point <= '1'; -- ebreak
end if;
end if;
-- WFI --
if (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_wfi_c) and
((CPU_EXTENSION_RISCV_DEBUG = false) or ((debug_ctrl.running = '0') and (csr.dcsr_step = '0'))) then
execute_engine.sleep_nxt <= '1'; -- not executed (NOP) when in debug-mode or during single-stepping
end if;
 
 
when CSR_ACCESS => -- read & write status and control register (CSR) - no read/write if illegal instruction
-- ------------------------------------------------------------
-- CSR write access --
-- CSR write access [invalid CSR instructions are already checked by the illegal instruction logic] --
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) then -- CSRRW(I)
csr.we_nxt <= '1'; -- always write CSR
else -- CSRRS(I) / CSRRC(I) [invalid CSR instructions are already checked by the illegal instruction logic]
csr.we_nxt <= not decode_aux.rs1_zero; -- write CSR if rs1/imm is not zero
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) or -- CSRRW(I); always write CSR
(decode_aux.rs1_zero = '0') then -- CSRRS(I) / CSRRC(I): write CSR if rs1/imm5 is NOT zero
csr.we_nxt <= '1';
end if;
-- register file write back --
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_csrr_c;
ctrl_nxt(ctrl_rf_mux1_c downto ctrl_rf_mux0_c) <= rf_mux_csr_c;
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
execute_engine.state_nxt <= DISPATCH;
 
 
when ALU_WAIT => -- wait for multi-cycle ALU operation (co-processor) to finish
when ALU_WAIT => -- wait for multi-cycle ALU operation (ALU co-processor) to finish
-- ------------------------------------------------------------
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_copro_c;
ctrl_nxt(ctrl_alu_op2_c downto ctrl_alu_op0_c) <= alu_op_cp_c;
-- wait for completion or abort on illegal instruction exception (the co-processor will also terminate operations)
if (alu_idone_i = '1') or (trap_ctrl.exc_buf(exception_iillegal_c) = '1') then
if (alu_idone_i = '1') or (trap_ctrl.exc_buf(exc_iillegal_c) = '1') then
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back (won't happen in case of an illegal instruction)
execute_engine.state_nxt <= DISPATCH;
end if;
1219,7 → 1198,7
when BRANCH => -- update PC for taken branches and jumps
-- ------------------------------------------------------------
-- get and store return address (only relevant for jump-and-link operations) --
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_nxpc_c; -- next PC
ctrl_nxt(ctrl_rf_mux1_c downto ctrl_rf_mux0_c) <= rf_mux_npc_c; -- next PC
ctrl_nxt(ctrl_rf_wb_en_c) <= execute_engine.i_reg(instr_opcode_lsb_c+2); -- valid RF write-back? (is jump-and-link?)
-- destination address --
execute_engine.pc_mux_sel <= '1'; -- PC <= alu.add = branch/jump destination
1228,10 → 1207,8
execute_engine.pc_we <= '1'; -- update PC
execute_engine.branched_nxt <= '1'; -- this is an actual branch
fetch_engine.reset <= '1'; -- trigger new instruction fetch from modified PC
execute_engine.state_nxt <= SYS_WAIT;
else
execute_engine.state_nxt <= DISPATCH;
end if;
execute_engine.state_nxt <= DISPATCH;
 
 
when LOADSTORE_0 => -- trigger memory request
1258,7 → 1235,7
when LOADSTORE_2 => -- wait for bus transaction to finish
-- ------------------------------------------------------------
ctrl_nxt(ctrl_bus_mi_we_c) <= '1'; -- keep writing input data to MDI (only relevant for load (and SC.W) operations)
ctrl_nxt(ctrl_rf_in_mux_c) <= '1'; -- RF input = memory input (only relevant for LOADs)
ctrl_nxt(ctrl_rf_mux1_c downto ctrl_rf_mux0_c) <= rf_mux_mem_c; -- memory read data
-- wait for memory response --
if (trap_ctrl.env_start = '1') and (trap_ctrl.cause(6 downto 5) = "00") then -- abort if SYNC EXCEPTION (from bus or illegal cmd) / no IRQs and NOT DEBUG-MODE-related
execute_engine.state_nxt <= DISPATCH;
1279,7 → 1256,7
 
when others => -- undefined
-- ------------------------------------------------------------
execute_engine.state_nxt <= SYS_WAIT;
execute_engine.state_nxt <= DISPATCH;
 
end case;
end process execute_engine_fsm_comb;
1293,19 → 1270,18
-- -------------------------------------------------------------------------------------------
csr_access_check: process(execute_engine.i_reg, decode_aux, csr, debug_ctrl)
variable csr_wacc_v : std_ulogic; -- actual CSR write
-- variable csr_racc_v : std_ulogic; -- actual CSR read
begin
-- is this CSR instruction really going to write to a CSR? --
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) then
csr_wacc_v := '1'; -- always write CSR
-- csr_racc_v := or_reduce_f(execute_engine.i_reg(instr_rd_msb_c downto instr_rd_lsb_c)); -- read if rd != 0
else -- clear/set
csr_wacc_v := not decode_aux.rs1_zero; -- write if rs1/uimm5 != 0
-- csr_racc_v := '1'; -- always read CSR
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or -- always write CSR
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) or -- always write CSR
(decode_aux.rs1_zero = '0') then -- clear/set: write CSR if rs1/imm5 is NOT zero
csr_wacc_v := '1';
else
csr_wacc_v := '0';
end if;
 
-- check CSR access --
csr_acc_valid <= '0'; -- default: invalid access
case csr.addr is
 
-- floating-point CSRs --
1317,30 → 1293,23
csr_mcycle_c | csr_mcycleh_c | csr_minstret_c | csr_minstreth_c | csr_mcountinhibit_c =>
-- NOTE: MISA and MTVAL are read-only in the NEORV32 but we do not cause an exception here for compatibility.
-- Machine-level code should read-back those CSRs after writing them to realize they are read-only.
csr_acc_valid <= csr.priv_m_mode; -- M-mode only
csr_acc_valid <= csr.privilege_eff; -- M-mode only
 
-- machine information registers & NEORV32-specific registers, read-only --
when csr_mvendorid_c | csr_marchid_c | csr_mimpid_c | csr_mhartid_c | csr_mconfigptr_c | csr_mxisa_c =>
csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only
csr_acc_valid <= (not csr_wacc_v) and csr.privilege_eff; -- M-mode only, read-only
 
-- user-mode registers --
when csr_mcounteren_c | csr_menvcfg_c | csr_menvcfgh_c =>
csr_acc_valid <= csr.priv_m_mode and bool_to_ulogic_f(CPU_EXTENSION_RISCV_U);
csr_acc_valid <= csr.privilege_eff and bool_to_ulogic_f(CPU_EXTENSION_RISCV_U);
 
-- physical memory protection (PMP) --
when csr_pmpaddr0_c | csr_pmpaddr1_c | csr_pmpaddr2_c | csr_pmpaddr3_c | csr_pmpaddr4_c | csr_pmpaddr5_c | csr_pmpaddr6_c | csr_pmpaddr7_c | -- address
csr_pmpaddr8_c | csr_pmpaddr9_c | csr_pmpaddr10_c | csr_pmpaddr11_c | csr_pmpaddr12_c | csr_pmpaddr13_c | csr_pmpaddr14_c | csr_pmpaddr15_c |
csr_pmpaddr16_c | csr_pmpaddr17_c | csr_pmpaddr18_c | csr_pmpaddr19_c | csr_pmpaddr20_c | csr_pmpaddr21_c | csr_pmpaddr22_c | csr_pmpaddr23_c |
csr_pmpaddr24_c | csr_pmpaddr25_c | csr_pmpaddr26_c | csr_pmpaddr27_c | csr_pmpaddr28_c | csr_pmpaddr29_c | csr_pmpaddr30_c | csr_pmpaddr31_c |
csr_pmpaddr32_c | csr_pmpaddr33_c | csr_pmpaddr34_c | csr_pmpaddr35_c | csr_pmpaddr36_c | csr_pmpaddr37_c | csr_pmpaddr38_c | csr_pmpaddr39_c |
csr_pmpaddr40_c | csr_pmpaddr41_c | csr_pmpaddr42_c | csr_pmpaddr43_c | csr_pmpaddr44_c | csr_pmpaddr45_c | csr_pmpaddr46_c | csr_pmpaddr47_c |
csr_pmpaddr48_c | csr_pmpaddr49_c | csr_pmpaddr50_c | csr_pmpaddr51_c | csr_pmpaddr52_c | csr_pmpaddr53_c | csr_pmpaddr54_c | csr_pmpaddr55_c |
csr_pmpaddr56_c | csr_pmpaddr57_c | csr_pmpaddr58_c | csr_pmpaddr59_c | csr_pmpaddr60_c | csr_pmpaddr61_c | csr_pmpaddr62_c | csr_pmpaddr63_c |
csr_pmpcfg0_c | csr_pmpcfg1_c | csr_pmpcfg2_c | csr_pmpcfg3_c | csr_pmpcfg4_c | csr_pmpcfg5_c | csr_pmpcfg6_c | csr_pmpcfg7_c | -- configuration
csr_pmpcfg8_c | csr_pmpcfg9_c | csr_pmpcfg10_c | csr_pmpcfg11_c | csr_pmpcfg12_c | csr_pmpcfg13_c | csr_pmpcfg14_c | csr_pmpcfg15_c =>
csr_acc_valid <= csr.priv_m_mode and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS > 0)); -- M-mode only
csr_pmpcfg0_c | csr_pmpcfg1_c | csr_pmpcfg2_c | csr_pmpcfg3_c => -- configuration
csr_acc_valid <= csr.privilege_eff and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS > 0)); -- M-mode only
 
-- hardware performance monitors (HPM) --
-- machine hardware performance monitors (MHPM) --
when csr_mhpmcounter3_c | csr_mhpmcounter4_c | csr_mhpmcounter5_c | csr_mhpmcounter6_c | csr_mhpmcounter7_c | csr_mhpmcounter8_c | -- counter LOW
csr_mhpmcounter9_c | csr_mhpmcounter10_c | csr_mhpmcounter11_c | csr_mhpmcounter12_c | csr_mhpmcounter13_c | csr_mhpmcounter14_c |
csr_mhpmcounter15_c | csr_mhpmcounter16_c | csr_mhpmcounter17_c | csr_mhpmcounter18_c | csr_mhpmcounter19_c | csr_mhpmcounter20_c |
1356,14 → 1325,27
csr_mhpmevent15_c | csr_mhpmevent16_c | csr_mhpmevent17_c | csr_mhpmevent18_c | csr_mhpmevent19_c | csr_mhpmevent20_c |
csr_mhpmevent21_c | csr_mhpmevent22_c | csr_mhpmevent23_c | csr_mhpmevent24_c | csr_mhpmevent25_c | csr_mhpmevent26_c |
csr_mhpmevent27_c | csr_mhpmevent28_c | csr_mhpmevent29_c | csr_mhpmevent30_c | csr_mhpmevent31_c =>
csr_acc_valid <= csr.priv_m_mode and bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zihpm); -- M-mode only
csr_acc_valid <= csr.privilege_eff and bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zihpm); -- M-mode only
 
-- -- user hardware performance monitors (HPM) --
-- when csr_hpmcounter3_c | csr_hpmcounter4_c | csr_hpmcounter5_c | csr_hpmcounter6_c | csr_hpmcounter7_c | csr_hpmcounter8_c | -- counter LOW
-- csr_hpmcounter9_c | csr_hpmcounter10_c | csr_hpmcounter11_c | csr_hpmcounter12_c | csr_hpmcounter13_c | csr_hpmcounter14_c |
-- csr_hpmcounter15_c | csr_hpmcounter16_c | csr_hpmcounter17_c | csr_hpmcounter18_c | csr_hpmcounter19_c | csr_hpmcounter20_c |
-- csr_hpmcounter21_c | csr_hpmcounter22_c | csr_hpmcounter23_c | csr_hpmcounter24_c | csr_hpmcounter25_c | csr_hpmcounter26_c |
-- csr_hpmcounter27_c | csr_hpmcounter28_c | csr_hpmcounter29_c | csr_hpmcounter30_c | csr_hpmcounter31_c |
-- csr_hpmcounter3h_c | csr_hpmcounter4h_c | csr_hpmcounter5h_c | csr_hpmcounter6h_c | csr_hpmcounter7h_c | csr_hpmcounter8h_c | -- counter HIGH
-- csr_hpmcounter9h_c | csr_hpmcounter10h_c | csr_hpmcounter11h_c | csr_hpmcounter12h_c | csr_hpmcounter13h_c | csr_hpmcounter14h_c |
-- csr_hpmcounter15h_c | csr_hpmcounter16h_c | csr_hpmcounter17h_c | csr_hpmcounter18h_c | csr_hpmcounter19h_c | csr_hpmcounter20h_c |
-- csr_hpmcounter21h_c | csr_hpmcounter22h_c | csr_hpmcounter23h_c | csr_hpmcounter24h_c | csr_hpmcounter25h_c | csr_hpmcounter26h_c |
-- csr_hpmcounter27h_c | csr_hpmcounter28h_c | csr_hpmcounter29h_c | csr_hpmcounter30h_c | csr_hpmcounter31h_c =>
-- csr_acc_valid <= '0'; -- >>> NOT IMPLEMENTED <<<
 
-- user-level counters/timers (read-only) --
when csr_cycle_c | csr_cycleh_c | csr_instret_c | csr_instreth_c | csr_time_c | csr_timeh_c =>
when csr_cycle_c | csr_cycleh_c | csr_time_c | csr_timeh_c | csr_instret_c | csr_instreth_c =>
case csr.addr(1 downto 0) is
when "00" => csr_acc_valid <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicntr) and (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_cy); -- cyle[h]: M-mode, U-mode if authorized, implemented at all, read-only
when "01" => csr_acc_valid <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicntr) and (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_tm); -- time[h]: M-mode, U-mode if authorized, implemented at all, read-only
when "10" => csr_acc_valid <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicntr) and (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_ir); -- instret[h]: M-mode, U-mode if authorized, implemented at all read-only
when "00" => csr_acc_valid <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicntr) and (not csr_wacc_v) and (csr.privilege_eff or csr.mcounteren_cy); -- cyle[h]: M-mode, U-mode if authorized, implemented at all, read-only
when "01" => csr_acc_valid <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicntr) and (not csr_wacc_v) and (csr.privilege_eff or csr.mcounteren_tm); -- time[h]: M-mode, U-mode if authorized, implemented at all, read-only
when "10" => csr_acc_valid <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicntr) and (not csr_wacc_v) and (csr.privilege_eff or csr.mcounteren_ir); -- instret[h]: M-mode, U-mode if authorized, implemented at all read-only
when others => csr_acc_valid <= '0';
end case;
 
1373,8 → 1355,8
 
-- trigger module CSRs --
when csr_tselect_c | csr_tdata1_c | csr_tdata2_c | csr_tdata3_c | csr_tinfo_c | csr_tcontrol_c | csr_mcontext_c | csr_scontext_c =>
-- access in debug-mode or M-mode (M-mode: writes are ignored as DMODE is hardwired to 1)
csr_acc_valid <= (debug_ctrl.running or csr.priv_m_mode) and bool_to_ulogic_f(CPU_EXTENSION_RISCV_DEBUG);
-- access in debug-mode or M-mode (M-mode: writes to tdata* are ignored as DMODE is hardwired to 1)
csr_acc_valid <= (debug_ctrl.running or csr.privilege_eff) and bool_to_ulogic_f(CPU_EXTENSION_RISCV_DEBUG);
 
-- undefined / not implemented --
when others =>
1388,234 → 1370,230
illegal_instruction_check: process(execute_engine, decode_aux, csr, csr_acc_valid, debug_ctrl)
variable opcode_v : std_ulogic_vector(6 downto 0);
begin
-- illegal instructions are checked in the EXECUTE state
-- the execute engine should not commit any illegal instruction
if (execute_engine.state = EXECUTE) then
-- defaults --
illegal_instruction <= '0';
illegal_register <= '0';
-- defaults --
illegal_instruction <= '0';
illegal_register <= '0';
 
-- check opcode for rv32 --
if (execute_engine.i_reg(instr_opcode_lsb_c+1 downto instr_opcode_lsb_c) = "11") then
illegal_opcode_lsbs <= '0';
else
illegal_opcode_lsbs <= '1';
end if;
-- check opcode for rv32 --
if (execute_engine.i_reg(instr_opcode_lsb_c+1 downto instr_opcode_lsb_c) = "11") then
illegal_opcode_lsbs <= '0';
else
illegal_opcode_lsbs <= '1';
end if;
 
-- check for illegal compressed instruction --
if (CPU_EXTENSION_RISCV_C = true) then
illegal_compressed <= execute_engine.is_ici;
else
illegal_compressed <= '0';
end if;
-- check for illegal compressed instruction --
if (CPU_EXTENSION_RISCV_C = true) then
illegal_compressed <= execute_engine.is_ici;
else
illegal_compressed <= '0';
end if;
 
-- check instructions --
opcode_v := execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c+2) & "11"; -- save some bits here, LSBs are always 11 for rv32
case opcode_v is
-- check instructions --
opcode_v := execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c+2) & "11"; -- save some bits here, LSBs are always 11 for rv32
case opcode_v is
 
when opcode_lui_c | opcode_auipc_c | opcode_jal_c => -- check sufficient LUI, UIPC, JAL (only check actual OPCODE)
-- ------------------------------------------------------------
when opcode_lui_c | opcode_auipc_c | opcode_jal_c => -- check sufficient LUI, UIPC, JAL (only check actual OPCODE)
-- ------------------------------------------------------------
illegal_instruction <= '0';
-- illegal E-CPU register? --
illegal_register <= execute_engine.i_reg(instr_rd_msb_c);
 
when opcode_alu_c => -- check ALU.funct3 & ALU.funct7
-- ------------------------------------------------------------
if (((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_subadd_c) or (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c)) and
(execute_engine.i_reg(instr_funct7_msb_c-2 downto instr_funct7_lsb_c) = "00000") and (execute_engine.i_reg(instr_funct7_msb_c) = '0')) or
(((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_slt_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sltu_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_xor_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_or_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_and_c)) and
(execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000000")) then -- valid base ALUI instruction?
illegal_instruction <= '0';
-- illegal E-CPU register? --
illegal_register <= execute_engine.i_reg(instr_rd_msb_c);
elsif ((CPU_EXTENSION_RISCV_M = true) or (CPU_EXTENSION_RISCV_Zmmul = false)) and (decode_aux.is_m_mul = '1') then -- valid MUL instruction?
illegal_instruction <= '0';
elsif (CPU_EXTENSION_RISCV_M = true) and (decode_aux.is_m_div = '1') then -- valid DIV instruction?
illegal_instruction <= '0';
elsif (CPU_EXTENSION_RISCV_B = true) and (decode_aux.is_b_reg = '1') then -- valid BITMANIP instruction?
illegal_instruction <= '0';
else
illegal_instruction <= '1';
end if;
-- illegal E-CPU register? --
illegal_register <= execute_engine.i_reg(instr_rd_msb_c) or execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rs2_msb_c);
 
when opcode_alu_c => -- check ALU.funct3 & ALU.funct7
-- ------------------------------------------------------------
if (((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_subadd_c) or (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c)) and
(execute_engine.i_reg(instr_funct7_msb_c-2 downto instr_funct7_lsb_c) = "00000") and (execute_engine.i_reg(instr_funct7_msb_c) = '0')) or
(((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_slt_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sltu_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_xor_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_or_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_and_c)) and
(execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000000")) then -- valid base ALUI instruction?
illegal_instruction <= '0';
elsif ((CPU_EXTENSION_RISCV_M = true) or (CPU_EXTENSION_RISCV_Zmmul = false)) and (decode_aux.is_m_mul = '1') then -- valid MUL instruction?
illegal_instruction <= '0';
elsif (CPU_EXTENSION_RISCV_M = true) and (decode_aux.is_m_div = '1') then -- valid DIV instruction?
illegal_instruction <= '0';
elsif (CPU_EXTENSION_RISCV_B = true) and (decode_aux.is_b_reg = '1') then -- valid BITMANIP instruction?
illegal_instruction <= '0';
else
illegal_instruction <= '1';
end if;
-- illegal E-CPU register? --
illegal_register <= execute_engine.i_reg(instr_rd_msb_c) or execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rs2_msb_c);
when opcode_alui_c => -- check ALUI.funct7
-- ------------------------------------------------------------
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_subadd_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_slt_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sltu_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_xor_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_or_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_and_c) or
((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) and -- shift logical left
(execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000000")) or
((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) and -- shift right
((execute_engine.i_reg(instr_funct7_msb_c-2 downto instr_funct7_lsb_c) = "00000") and (execute_engine.i_reg(instr_funct7_msb_c) = '0'))) then -- valid base ALUI instruction?
illegal_instruction <= '0';
elsif (CPU_EXTENSION_RISCV_B = true) and (decode_aux.is_b_imm = '1') then -- valid BITMANIP immediate instruction?
illegal_instruction <= '0';
else
illegal_instruction <= '1';
end if;
-- illegal E-CPU register? --
illegal_register <= execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rd_msb_c);
 
when opcode_alui_c => -- check ALUI.funct7
-- ------------------------------------------------------------
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_subadd_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_slt_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sltu_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_xor_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_or_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_and_c) or
((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) and -- shift logical left
(execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000000")) or
((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) and -- shift right
((execute_engine.i_reg(instr_funct7_msb_c-2 downto instr_funct7_lsb_c) = "00000") and (execute_engine.i_reg(instr_funct7_msb_c) = '0'))) then -- valid base ALUI instruction?
illegal_instruction <= '0';
elsif (CPU_EXTENSION_RISCV_B = true) and (decode_aux.is_b_imm = '1') then -- valid BITMANIP immediate instruction?
illegal_instruction <= '0';
else
illegal_instruction <= '1';
end if;
-- illegal E-CPU register? --
illegal_register <= execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rd_msb_c);
when opcode_load_c => -- check LOAD.funct3
-- ------------------------------------------------------------
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lb_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lh_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lw_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lbu_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lhu_c) then
illegal_instruction <= '0';
else
illegal_instruction <= '1';
end if;
-- illegal E-CPU register? --
illegal_register <= execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rd_msb_c);
 
when opcode_load_c => -- check LOAD.funct3
-- ------------------------------------------------------------
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lb_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lh_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lw_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lbu_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lhu_c) then
illegal_instruction <= '0';
else
illegal_instruction <= '1';
end if;
-- illegal E-CPU register? --
illegal_register <= execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rd_msb_c);
when opcode_store_c => -- check STORE.funct3
-- ------------------------------------------------------------
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sb_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sh_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sw_c) then
illegal_instruction <= '0';
else
illegal_instruction <= '1';
end if;
-- illegal E-CPU register? --
illegal_register <= execute_engine.i_reg(instr_rs2_msb_c) or execute_engine.i_reg(instr_rs1_msb_c);
 
when opcode_store_c => -- check STORE.funct3
-- ------------------------------------------------------------
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sb_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sh_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sw_c) then
when opcode_atomic_c => -- atomic instructions
-- ------------------------------------------------------------
if (CPU_EXTENSION_RISCV_A = true) then
if (execute_engine.i_reg(instr_funct5_msb_c downto instr_funct5_lsb_c) = "00010") then -- LR
illegal_instruction <= '0';
else
illegal_instruction <= '1';
end if;
-- illegal E-CPU register? --
illegal_register <= execute_engine.i_reg(instr_rs2_msb_c) or execute_engine.i_reg(instr_rs1_msb_c);
 
when opcode_atomic_c => -- atomic instructions
-- ------------------------------------------------------------
if (CPU_EXTENSION_RISCV_A = true) then
if (execute_engine.i_reg(instr_funct5_msb_c downto instr_funct5_lsb_c) = "00010") then -- LR
illegal_instruction <= '0';
-- illegal E-CPU register? --
illegal_register <= execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rd_msb_c);
elsif (execute_engine.i_reg(instr_funct5_msb_c downto instr_funct5_lsb_c) = "00011") then -- SC
illegal_instruction <= '0';
-- illegal E-CPU register? --
illegal_register <= execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rs2_msb_c) or execute_engine.i_reg(instr_rd_msb_c);
else
illegal_instruction <= '1';
end if;
else
illegal_instruction <= '1';
end if;
 
when opcode_branch_c => -- check BRANCH.funct3
-- ------------------------------------------------------------
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_beq_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bne_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_blt_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bge_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bltu_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bgeu_c) then
-- illegal E-CPU register? --
illegal_register <= execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rd_msb_c);
elsif (execute_engine.i_reg(instr_funct5_msb_c downto instr_funct5_lsb_c) = "00011") then -- SC
illegal_instruction <= '0';
-- illegal E-CPU register? --
illegal_register <= execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rs2_msb_c) or execute_engine.i_reg(instr_rd_msb_c);
else
illegal_instruction <= '1';
end if;
-- illegal E-CPU register? --
illegal_register <= execute_engine.i_reg(instr_rs2_msb_c) or execute_engine.i_reg(instr_rs1_msb_c);
else
illegal_instruction <= '1';
end if;
 
when opcode_jalr_c => -- check JALR.funct3
-- ------------------------------------------------------------
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "000") then
illegal_instruction <= '0';
else
illegal_instruction <= '1';
end if;
-- illegal E-CPU register? --
illegal_register <= execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rd_msb_c);
when opcode_branch_c => -- check BRANCH.funct3
-- ------------------------------------------------------------
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_beq_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bne_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_blt_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bge_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bltu_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bgeu_c) then
illegal_instruction <= '0';
else
illegal_instruction <= '1';
end if;
-- illegal E-CPU register? --
illegal_register <= execute_engine.i_reg(instr_rs2_msb_c) or execute_engine.i_reg(instr_rs1_msb_c);
 
when opcode_fence_c => -- check FENCE.funct3
-- ------------------------------------------------------------
if ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fencei_c) and (CPU_EXTENSION_RISCV_Zifencei = true)) or -- FENCE.I
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fence_c) then -- FENCE
illegal_instruction <= '0';
else
illegal_instruction <= '1';
end if;
-- NOTE: ignore all remaining bit fields here
when opcode_jalr_c => -- check JALR.funct3
-- ------------------------------------------------------------
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "000") then
illegal_instruction <= '0';
else
illegal_instruction <= '1';
end if;
-- illegal E-CPU register? --
illegal_register <= execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rd_msb_c);
 
when opcode_syscsr_c => -- check system instructions
-- ------------------------------------------------------------
-- CSR access --
if ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrs_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrc_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrsi_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrci_c)) and
(csr_acc_valid = '1') then -- valid CSR access?
illegal_instruction <= '0';
-- illegal E-CPU register? --
if (execute_engine.i_reg(instr_funct3_msb_c) = '0') then -- reg-reg CSR
illegal_register <= execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rd_msb_c);
else -- reg-imm CSR
illegal_register <= execute_engine.i_reg(instr_rd_msb_c);
end if;
-- system: ecall, ebreak, mret, wfi, dret --
elsif (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "000") and
(decode_aux.rs1_zero = '1') and (decode_aux.rd_zero = '1') and
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_ecall_c) or -- ECALL
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_ebreak_c) or -- EBREAK
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_mret_c) and (csr.priv_m_mode = '1')) or -- MRET (only allowed in M-mode)
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_dret_c) and (CPU_EXTENSION_RISCV_DEBUG = true) and (debug_ctrl.running = '1')) or -- DRET (only allowed in D-mode)
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_wfi_c)) then -- WFI (always allowed to execute)
illegal_instruction <= '0';
else
illegal_instruction <= '1';
end if;
when opcode_fence_c => -- check FENCE.funct3
-- ------------------------------------------------------------
if ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fencei_c) and (CPU_EXTENSION_RISCV_Zifencei = true)) or -- FENCE.I
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fence_c) then -- FENCE
illegal_instruction <= '0';
else
illegal_instruction <= '1';
end if;
-- NOTE: ignore all remaining bit fields here
 
when opcode_fop_c => -- floating point operations - single/dual operands
-- ------------------------------------------------------------
if (CPU_EXTENSION_RISCV_Zfinx = true) and -- F extension implemented
(execute_engine.i_reg(instr_funct7_lsb_c+1 downto instr_funct7_lsb_c) = float_single_c) and -- single-precision operations only
(decode_aux.is_f_op = '1') then -- is correct/supported floating-point instruction
illegal_instruction <= '0';
else
illegal_instruction <= '1';
end if;
when opcode_syscsr_c => -- check system instructions
-- ------------------------------------------------------------
-- CSR access --
if ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrs_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrc_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrsi_c) or
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrci_c)) and
(csr_acc_valid = '1') then -- valid CSR access?
illegal_instruction <= '0';
-- illegal E-CPU register? --
-- FIXME: rs2 is not checked!
illegal_register <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zfinx) and (execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rd_msb_c));
 
when opcode_cust0_c => -- CFU: custom instructions
-- ------------------------------------------------------------
if (CPU_EXTENSION_RISCV_Zxcfu = true) then -- CFU extension implemented
illegal_instruction <= '0';
else
illegal_instruction <= '1';
if (execute_engine.i_reg(instr_funct3_msb_c) = '0') then -- reg-reg CSR
illegal_register <= execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rd_msb_c);
else -- reg-imm CSR
illegal_register <= execute_engine.i_reg(instr_rd_msb_c);
end if;
-- illegal E-CPU register? --
illegal_register <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zxcfu) and (execute_engine.i_reg(instr_rs2_msb_c) or execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rd_msb_c));
-- system: ecall, ebreak, mret, wfi, dret --
-- > WFI is always allowed to execute in M-mode; in U-mode it is allowed to execute if mstatus.TW = 0
elsif (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "000") and
(decode_aux.rs1_zero = '1') and (decode_aux.rd_zero = '1') and
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_ecall_c) or -- ECALL
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_ebreak_c) or -- EBREAK
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_mret_c) and (csr.privilege = priv_mode_m_c)) or -- MRET (only allowed in ACTUAL M-mode)
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_dret_c) and (CPU_EXTENSION_RISCV_DEBUG = true) and (debug_ctrl.running = '1')) or -- DRET (only allowed in D-mode)
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_wfi_c) and ((csr.privilege = priv_mode_m_c) or (csr.mstatus_tw = '0')))) then -- WFI
illegal_instruction <= '0';
else
illegal_instruction <= '1';
end if;
 
when others => -- undefined instruction -> illegal!
-- ------------------------------------------------------------
when opcode_fop_c => -- floating point operations - single/dual operands
-- ------------------------------------------------------------
if (CPU_EXTENSION_RISCV_Zfinx = true) and -- F extension implemented
(execute_engine.i_reg(instr_funct7_lsb_c+1 downto instr_funct7_lsb_c) = float_single_c) and -- single-precision operations only
(decode_aux.is_f_op = '1') then -- is correct/supported floating-point instruction
illegal_instruction <= '0';
else
illegal_instruction <= '1';
end if;
-- illegal E-CPU register? --
-- FIXME: rs2 is not checked!
illegal_register <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zfinx) and (execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rd_msb_c));
 
end case;
else
illegal_opcode_lsbs <= '0';
illegal_compressed <= '0';
illegal_instruction <= '0';
illegal_register <= '0';
end if;
when opcode_cust0_c => -- CFU: custom instructions
-- ------------------------------------------------------------
if (CPU_EXTENSION_RISCV_Zxcfu = true) then -- CFU extension implemented
illegal_instruction <= '0';
else
illegal_instruction <= '1';
end if;
-- illegal E-CPU register? --
illegal_register <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zxcfu) and (execute_engine.i_reg(instr_rs2_msb_c) or execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rd_msb_c));
 
when others => -- undefined instruction -> illegal!
-- ------------------------------------------------------------
illegal_instruction <= '1';
 
end case;
end process illegal_instruction_check;
 
-- any illegal condition? --
trap_ctrl.instr_il <= illegal_opcode_lsbs or -- illegal opcode MSB bits
illegal_instruction or -- illegal instruction format/layout
(bool_to_ulogic_f(CPU_EXTENSION_RISCV_E) and illegal_register) or -- illegal register access in E extension
illegal_compressed; -- illegal compressed instruction
 
-- Illegal Operation Check ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- check in EXECUTE state: any illegal condition? --
trap_ctrl.instr_il <= (illegal_opcode_lsbs or -- illegal opcode LSB bits - not rv32
illegal_instruction or -- illegal instruction
(bool_to_ulogic_f(CPU_EXTENSION_RISCV_E) and illegal_register) or -- illegal register access in E extension
illegal_compressed) -- illegal compressed instruction
when (execute_engine.state = EXECUTE) else '0';
 
 
-- ****************************************************************************************************************************
-- Exception and Interrupt (= Traps) Control
-- ****************************************************************************************************************************
1628,63 → 1606,61
if (rstn_i = '0') then
trap_ctrl.exc_buf <= (others => '0');
trap_ctrl.irq_buf <= (others => '0');
trap_ctrl.exc_clr <= '0';
trap_ctrl.env_start <= '0';
trap_ctrl.cause <= (others => '0');
elsif rising_edge(clk_i) then
if (CPU_EXTENSION_RISCV_Zicsr = true) then
-- > clear all queued exception triggers when starting the trap handling environment (trap_ctrl.env_start = 1)
 
-- exception queue: misaligned load/store/instruction address --
trap_ctrl.exc_buf(exception_lalign_c) <= (trap_ctrl.exc_buf(exception_lalign_c) or ma_load_i) and (not trap_ctrl.exc_clr);
trap_ctrl.exc_buf(exception_salign_c) <= (trap_ctrl.exc_buf(exception_salign_c) or ma_store_i) and (not trap_ctrl.exc_clr);
trap_ctrl.exc_buf(exception_ialign_c) <= (trap_ctrl.exc_buf(exception_ialign_c) or trap_ctrl.instr_ma) and (not trap_ctrl.exc_clr);
trap_ctrl.exc_buf(exc_lalign_c) <= (trap_ctrl.exc_buf(exc_lalign_c) or ma_load_i) and (not trap_ctrl.env_start);
trap_ctrl.exc_buf(exc_salign_c) <= (trap_ctrl.exc_buf(exc_salign_c) or ma_store_i) and (not trap_ctrl.env_start);
trap_ctrl.exc_buf(exc_ialign_c) <= (trap_ctrl.exc_buf(exc_ialign_c) or trap_ctrl.instr_ma) and (not trap_ctrl.env_start);
 
-- exception queue: load/store/instruction bus access error --
trap_ctrl.exc_buf(exception_laccess_c) <= (trap_ctrl.exc_buf(exception_laccess_c) or be_load_i) and (not trap_ctrl.exc_clr);
trap_ctrl.exc_buf(exception_saccess_c) <= (trap_ctrl.exc_buf(exception_saccess_c) or be_store_i) and (not trap_ctrl.exc_clr);
trap_ctrl.exc_buf(exception_iaccess_c) <= (trap_ctrl.exc_buf(exception_iaccess_c) or trap_ctrl.instr_be) and (not trap_ctrl.exc_clr);
trap_ctrl.exc_buf(exc_laccess_c) <= (trap_ctrl.exc_buf(exc_laccess_c) or be_load_i) and (not trap_ctrl.env_start);
trap_ctrl.exc_buf(exc_saccess_c) <= (trap_ctrl.exc_buf(exc_saccess_c) or be_store_i) and (not trap_ctrl.env_start);
trap_ctrl.exc_buf(exc_iaccess_c) <= (trap_ctrl.exc_buf(exc_iaccess_c) or trap_ctrl.instr_be) and (not trap_ctrl.env_start);
 
-- exception queue: illegal instruction / environment calls --
trap_ctrl.exc_buf(exception_m_envcall_c) <= (trap_ctrl.exc_buf(exception_m_envcall_c) or (trap_ctrl.env_call and csr.priv_m_mode)) and (not trap_ctrl.exc_clr);
trap_ctrl.exc_buf(exception_u_envcall_c) <= (trap_ctrl.exc_buf(exception_u_envcall_c) or (trap_ctrl.env_call and csr.priv_u_mode)) and (not trap_ctrl.exc_clr);
trap_ctrl.exc_buf(exception_iillegal_c) <= (trap_ctrl.exc_buf(exception_iillegal_c) or trap_ctrl.instr_il) and (not trap_ctrl.exc_clr);
trap_ctrl.exc_buf(exc_m_envcall_c) <= (trap_ctrl.exc_buf(exc_m_envcall_c) or (trap_ctrl.env_call and ( csr.privilege))) and (not trap_ctrl.env_start);
trap_ctrl.exc_buf(exc_u_envcall_c) <= (trap_ctrl.exc_buf(exc_u_envcall_c) or (trap_ctrl.env_call and (not csr.privilege))) and (not trap_ctrl.env_start);
trap_ctrl.exc_buf(exc_iillegal_c) <= (trap_ctrl.exc_buf(exc_iillegal_c) or trap_ctrl.instr_il) and (not trap_ctrl.env_start);
 
-- exception queue: break point --
if (CPU_EXTENSION_RISCV_DEBUG = true) then
trap_ctrl.exc_buf(exception_break_c) <= (not trap_ctrl.exc_clr) and (trap_ctrl.exc_buf(exception_break_c) or
(trap_ctrl.break_point and csr.priv_m_mode and (not csr.dcsr_ebreakm) and (not debug_ctrl.running)) or -- break to machine-trap-handler when in machine mode on "ebreak"
(trap_ctrl.break_point and csr.priv_u_mode and (not csr.dcsr_ebreaku) and (not debug_ctrl.running))); -- break to machine-trap-handler when in user mode on "ebreak"
trap_ctrl.exc_buf(exc_break_c) <= (not trap_ctrl.env_start) and (trap_ctrl.exc_buf(exc_break_c) or
(trap_ctrl.break_point and ( csr.privilege) and (not csr.dcsr_ebreakm) and (not debug_ctrl.running)) or -- break to machine-trap-handler when in machine mode on "ebreak"
(trap_ctrl.break_point and (not csr.privilege) and (not csr.dcsr_ebreaku) and (not debug_ctrl.running))); -- break to machine-trap-handler when in user mode on "ebreak"
else
trap_ctrl.exc_buf(exception_break_c) <= (trap_ctrl.exc_buf(exception_break_c) or trap_ctrl.break_point) and (not trap_ctrl.exc_clr);
trap_ctrl.exc_buf(exc_break_c) <= (trap_ctrl.exc_buf(exc_break_c) or trap_ctrl.break_point) and (not trap_ctrl.env_start);
end if;
 
-- exception queue / interrupt buffer: enter debug mode --
trap_ctrl.exc_buf(exception_db_break_c) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_DEBUG) and (trap_ctrl.exc_buf(exception_db_break_c) or debug_ctrl.trig_break) and (not trap_ctrl.exc_clr);
trap_ctrl.exc_buf(exception_db_hw_c) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_DEBUG) and (trap_ctrl.exc_buf(exception_db_hw_c) or debug_ctrl.trig_hw) and (not trap_ctrl.exc_clr);
trap_ctrl.irq_buf(interrupt_db_halt_c) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_DEBUG) and debug_ctrl.trig_halt;
trap_ctrl.irq_buf(interrupt_db_step_c) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_DEBUG) and debug_ctrl.trig_step;
if (CPU_EXTENSION_RISCV_DEBUG = true) then
trap_ctrl.exc_buf(exc_db_break_c) <= (trap_ctrl.exc_buf(exc_db_break_c) or debug_ctrl.trig_break) and (not trap_ctrl.env_start);
trap_ctrl.exc_buf(exc_db_hw_c) <= (trap_ctrl.exc_buf(exc_db_hw_c) or debug_ctrl.trig_hw) and (not trap_ctrl.env_start);
trap_ctrl.irq_buf(irq_db_halt_c) <= debug_ctrl.trig_halt;
trap_ctrl.irq_buf(irq_db_step_c) <= debug_ctrl.trig_step;
end if;
 
-- interrupt buffer: machine software/external/timer interrupt --
trap_ctrl.irq_buf(interrupt_msw_irq_c) <= csr.mie_msie and msw_irq_i;
trap_ctrl.irq_buf(interrupt_mext_irq_c) <= csr.mie_meie and mext_irq_i;
trap_ctrl.irq_buf(interrupt_mtime_irq_c) <= csr.mie_mtie and mtime_irq_i;
trap_ctrl.irq_buf(irq_msw_irq_c) <= csr.mie_msie and msw_irq_i;
trap_ctrl.irq_buf(irq_mext_irq_c) <= csr.mie_meie and mext_irq_i;
trap_ctrl.irq_buf(irq_mtime_irq_c) <= csr.mie_mtie and mtime_irq_i;
 
-- interrupt *queue*: NEORV32-specific fast interrupts (FIRQ) - require manual ACK/clear --
trap_ctrl.irq_buf(interrupt_firq_15_c downto interrupt_firq_0_c) <= (trap_ctrl.irq_buf(interrupt_firq_15_c downto interrupt_firq_0_c) or (csr.mie_firqe and firq_i)) and (not csr.mip_clr);
trap_ctrl.irq_buf(irq_firq_15_c downto irq_firq_0_c) <= (trap_ctrl.irq_buf(irq_firq_15_c downto irq_firq_0_c) or (csr.mie_firqe and firq_i)) and csr.mip_firq_nclr;
 
-- trap environment control --
if (trap_ctrl.env_start = '0') then -- no started trap handler
if (trap_ctrl.exc_fire = '1') or ((trap_ctrl.irq_fire = '1') and -- exception triggered!
((execute_engine.state = EXECUTE) or (execute_engine.state = TRAP_ENTER))) then -- fire IRQs in EXECUTE or TRAP state only to continue execution even on permanent IRQ
trap_ctrl.cause <= trap_ctrl.cause_nxt; -- capture source ID for program (for mcause csr)
trap_ctrl.exc_clr <= '1'; -- clear exceptions (no ack mask: these have highest priority and are always evaluated first!)
trap_ctrl.cause <= trap_ctrl.cause_nxt; -- capture trap ID for mcause csr
trap_ctrl.env_start <= '1'; -- now execute engine can start trap handler
end if;
else -- trap waiting to get started
if (trap_ctrl.env_start_ack = '1') then -- start of trap handler acknowledged by execution engine
trap_ctrl.exc_clr <= '0';
trap_ctrl.env_start <= '0';
end if;
elsif (trap_ctrl.env_start_ack = '1') then -- start of trap handler acknowledged by execute engine
trap_ctrl.env_start <= '0';
end if;
end if;
end if;
1691,12 → 1667,12
end process trap_controller;
 
-- any exception/interrupt? --
trap_ctrl.exc_fire <= or_reduce_f(trap_ctrl.exc_buf); -- exceptions/faults CANNOT be masked
trap_ctrl.exc_fire <= or_reduce_f(trap_ctrl.exc_buf); -- sync. exceptions CANNOT be masked
trap_ctrl.irq_fire <= (or_reduce_f(trap_ctrl.irq_buf) and csr.mstatus_mie and trap_ctrl.db_irq_en) or trap_ctrl.db_irq_fire; -- interrupts CAN be masked (but not the DEBUG halt IRQ)
 
-- debug mode (entry) interrupts --
trap_ctrl.db_irq_en <= '0' when (CPU_EXTENSION_RISCV_DEBUG = true) and ((debug_ctrl.running = '1') or (csr.dcsr_step = '1')) else '1'; -- no interrupts when IN debug mode or IN single-step mode
trap_ctrl.db_irq_fire <= (trap_ctrl.irq_buf(interrupt_db_step_c) or trap_ctrl.irq_buf(interrupt_db_halt_c)) when (CPU_EXTENSION_RISCV_DEBUG = true) else '0'; -- "NMI" for debug mode entry
trap_ctrl.db_irq_fire <= (trap_ctrl.irq_buf(irq_db_step_c) or trap_ctrl.irq_buf(irq_db_halt_c)) when (CPU_EXTENSION_RISCV_DEBUG = true) else '0'; -- "NMI" for debug mode entry
 
 
-- Trap Priority Encoder ------------------------------------------------------------------
1710,45 → 1686,45
-- ----------------------------------------------------------------------------------------
 
-- exception: 0.0 instruction address misaligned --
if (trap_ctrl.exc_buf(exception_ialign_c) = '1') then
if (trap_ctrl.exc_buf(exc_ialign_c) = '1') then
trap_ctrl.cause_nxt <= trap_ima_c;
 
-- exception: 0.1 instruction access fault --
elsif (trap_ctrl.exc_buf(exception_iaccess_c) = '1') then
elsif (trap_ctrl.exc_buf(exc_iaccess_c) = '1') then
trap_ctrl.cause_nxt <= trap_iba_c;
 
-- exception: 0.2 illegal instruction --
elsif (trap_ctrl.exc_buf(exception_iillegal_c) = '1') then
elsif (trap_ctrl.exc_buf(exc_iillegal_c) = '1') then
trap_ctrl.cause_nxt <= trap_iil_c;
 
 
-- exception: 0.11 environment call from M-mode --
elsif (trap_ctrl.exc_buf(exception_m_envcall_c) = '1') then
elsif (trap_ctrl.exc_buf(exc_m_envcall_c) = '1') then
trap_ctrl.cause_nxt <= trap_menv_c;
 
-- exception: 0.8 environment call from U-mode --
elsif (trap_ctrl.exc_buf(exception_u_envcall_c) = '1') then
elsif (trap_ctrl.exc_buf(exc_u_envcall_c) = '1') then
trap_ctrl.cause_nxt <= trap_uenv_c;
 
-- exception: 0.3 breakpoint --
elsif (trap_ctrl.exc_buf(exception_break_c) = '1') then
elsif (trap_ctrl.exc_buf(exc_break_c) = '1') then
trap_ctrl.cause_nxt <= trap_brk_c;
 
 
-- exception: 0.6 store address misaligned -
elsif (trap_ctrl.exc_buf(exception_salign_c) = '1') then
elsif (trap_ctrl.exc_buf(exc_salign_c) = '1') then
trap_ctrl.cause_nxt <= trap_sma_c;
 
-- exception: 0.4 load address misaligned --
elsif (trap_ctrl.exc_buf(exception_lalign_c) = '1') then
elsif (trap_ctrl.exc_buf(exc_lalign_c) = '1') then
trap_ctrl.cause_nxt <= trap_lma_c;
 
-- exception: 0.7 store access fault --
elsif (trap_ctrl.exc_buf(exception_saccess_c) = '1') then
elsif (trap_ctrl.exc_buf(exc_saccess_c) = '1') then
trap_ctrl.cause_nxt <= trap_sbe_c;
 
-- exception: 0.5 load access fault --
elsif (trap_ctrl.exc_buf(exception_laccess_c) = '1') then
elsif (trap_ctrl.exc_buf(exc_laccess_c) = '1') then
trap_ctrl.cause_nxt <= trap_lbe_c;
 
-- ----------------------------------------------------------------------------------------
1758,19 → 1734,21
-- ----------------------------------------------------------------------------------------
 
-- hardware trigger (sync) --
elsif (trap_ctrl.exc_buf(exception_db_hw_c) = '1') then
elsif (trap_ctrl.exc_buf(exc_db_hw_c) = '1') then
trap_ctrl.cause_nxt <= trap_db_hw_c;
 
-- break instruction (sync) --
elsif (trap_ctrl.exc_buf(exception_db_break_c) = '1') then
elsif (trap_ctrl.exc_buf(exc_db_break_c) = '1') then
trap_ctrl.cause_nxt <= trap_db_break_c;
 
-- async. exceptions / interrupts
 
-- external halt request (async) --
elsif (trap_ctrl.irq_buf(interrupt_db_halt_c) = '1') then
elsif (trap_ctrl.irq_buf(irq_db_halt_c) = '1') then
trap_ctrl.cause_nxt <= trap_db_halt_c;
 
-- single stepping (async) --
elsif (trap_ctrl.irq_buf(interrupt_db_step_c) = '1') then
elsif (trap_ctrl.irq_buf(irq_db_step_c) = '1') then
trap_ctrl.cause_nxt <= trap_db_step_c;
 
-- ----------------------------------------------------------------------------------------
1778,67 → 1756,67
-- ----------------------------------------------------------------------------------------
 
-- interrupt: 1.16 fast interrupt channel 0 --
elsif (trap_ctrl.irq_buf(interrupt_firq_0_c) = '1') then
elsif (trap_ctrl.irq_buf(irq_firq_0_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq0_c;
 
-- interrupt: 1.17 fast interrupt channel 1 --
elsif (trap_ctrl.irq_buf(interrupt_firq_1_c) = '1') then
elsif (trap_ctrl.irq_buf(irq_firq_1_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq1_c;
 
-- interrupt: 1.18 fast interrupt channel 2 --
elsif (trap_ctrl.irq_buf(interrupt_firq_2_c) = '1') then
elsif (trap_ctrl.irq_buf(irq_firq_2_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq2_c;
 
-- interrupt: 1.19 fast interrupt channel 3 --
elsif (trap_ctrl.irq_buf(interrupt_firq_3_c) = '1') then
elsif (trap_ctrl.irq_buf(irq_firq_3_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq3_c;
 
-- interrupt: 1.20 fast interrupt channel 4 --
elsif (trap_ctrl.irq_buf(interrupt_firq_4_c) = '1') then
elsif (trap_ctrl.irq_buf(irq_firq_4_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq4_c;
 
-- interrupt: 1.21 fast interrupt channel 5 --
elsif (trap_ctrl.irq_buf(interrupt_firq_5_c) = '1') then
elsif (trap_ctrl.irq_buf(irq_firq_5_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq5_c;
 
-- interrupt: 1.22 fast interrupt channel 6 --
elsif (trap_ctrl.irq_buf(interrupt_firq_6_c) = '1') then
elsif (trap_ctrl.irq_buf(irq_firq_6_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq6_c;
 
-- interrupt: 1.23 fast interrupt channel 7 --
elsif (trap_ctrl.irq_buf(interrupt_firq_7_c) = '1') then
elsif (trap_ctrl.irq_buf(irq_firq_7_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq7_c;
 
-- interrupt: 1.24 fast interrupt channel 8 --
elsif (trap_ctrl.irq_buf(interrupt_firq_8_c) = '1') then
elsif (trap_ctrl.irq_buf(irq_firq_8_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq8_c;
 
-- interrupt: 1.25 fast interrupt channel 9 --
elsif (trap_ctrl.irq_buf(interrupt_firq_9_c) = '1') then
elsif (trap_ctrl.irq_buf(irq_firq_9_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq9_c;
 
-- interrupt: 1.26 fast interrupt channel 10 --
elsif (trap_ctrl.irq_buf(interrupt_firq_10_c) = '1') then
elsif (trap_ctrl.irq_buf(irq_firq_10_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq10_c;
 
-- interrupt: 1.27 fast interrupt channel 11 --
elsif (trap_ctrl.irq_buf(interrupt_firq_11_c) = '1') then
elsif (trap_ctrl.irq_buf(irq_firq_11_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq11_c;
 
-- interrupt: 1.28 fast interrupt channel 12 --
elsif (trap_ctrl.irq_buf(interrupt_firq_12_c) = '1') then
elsif (trap_ctrl.irq_buf(irq_firq_12_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq12_c;
 
-- interrupt: 1.29 fast interrupt channel 13 --
elsif (trap_ctrl.irq_buf(interrupt_firq_13_c) = '1') then
elsif (trap_ctrl.irq_buf(irq_firq_13_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq13_c;
 
-- interrupt: 1.30 fast interrupt channel 14 --
elsif (trap_ctrl.irq_buf(interrupt_firq_14_c) = '1') then
elsif (trap_ctrl.irq_buf(irq_firq_14_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq14_c;
 
-- interrupt: 1.31 fast interrupt channel 15 --
elsif (trap_ctrl.irq_buf(interrupt_firq_15_c) = '1') then
elsif (trap_ctrl.irq_buf(irq_firq_15_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq15_c;
 
-- ----------------------------------------------------------------------------------------
1845,16 → 1823,16
-- standard RISC-V interrupts (*asynchronous* exceptions)
-- ----------------------------------------------------------------------------------------
 
-- interrupt: 1.11 machine external interrupt --
elsif (trap_ctrl.irq_buf(interrupt_mext_irq_c) = '1') then
-- interrupt: 1.11 machine external interrupt (MEI) --
elsif (trap_ctrl.irq_buf(irq_mext_irq_c) = '1') then
trap_ctrl.cause_nxt <= trap_mei_c;
 
-- interrupt: 1.3 machine SW interrupt --
elsif (trap_ctrl.irq_buf(interrupt_msw_irq_c) = '1') then
-- interrupt: 1.3 machine SW interrupt (MSI) --
elsif (trap_ctrl.irq_buf(irq_msw_irq_c) = '1') then
trap_ctrl.cause_nxt <= trap_msi_c;
 
-- interrupt: 1.7 machine timer interrupt --
else--if (trap_ctrl.irq_buf(interrupt_mtime_irq_c) = '1') then -- last condition, so NO IF required
-- interrupt: 1.7 machine timer interrupt (MTI) --
else--if (trap_ctrl.irq_buf(irq_mtime_irq_c) = '1') then -- last condition, so NO IF required
trap_ctrl.cause_nxt <= trap_mti_c;
 
end if;
1890,15 → 1868,13
csr_write_access: process(rstn_i, clk_i)
variable cause_v : std_ulogic_vector(6 downto 0);
begin
-- NOTE: If <dedicated_reset_c> = true then <def_rst_val_c> evaluates to '-'. Registers that reset to <def_rst_val_c>
-- do NOT actually have a real reset by default and have to be explicitly initialized by software!
-- see: https://forums.xilinx.com/t5/General-Technical-Discussion/quot-Don-t-care-quot-reset-value/td-p/412845
if (rstn_i = '0') then
csr.we <= '0';
--
csr.mstatus_mie <= '0';
csr.mstatus_mpie <= '0';
csr.mstatus_mpp <= (others => '0');
csr.mstatus_mpp <= '0';
csr.mstatus_tw <= '0';
csr.privilege <= priv_mode_m_c; -- start in MACHINE mode
csr.mie_msie <= def_rst_val_c;
csr.mie_meie <= def_rst_val_c;
1909,7 → 1885,7
csr.mepc <= (others => def_rst_val_c);
csr.mcause <= (others => def_rst_val_c);
csr.mtval <= (others => def_rst_val_c);
csr.mip_clr <= (others => def_rst_val_c);
csr.mip_firq_nclr <= (others => def_rst_val_c);
--
csr.pmpcfg <= (others => (others => '0'));
csr.pmpaddr <= (others => (others => def_rst_val_c));
1930,7 → 1906,7
csr.dcsr_ebreakm <= '0';
csr.dcsr_ebreaku <= '0';
csr.dcsr_step <= '0';
csr.dcsr_prv <= (others => def_rst_val_c);
csr.dcsr_prv <= priv_mode_m_c;
csr.dcsr_cause <= (others => def_rst_val_c);
csr.dpc <= (others => def_rst_val_c);
csr.dscratch0 <= (others => def_rst_val_c);
1943,13 → 1919,13
csr.we <= csr.we_nxt;
 
-- defaults --
csr.mip_clr <= (others => '0');
csr.mip_firq_nclr <= (others => '1'); -- active low
 
if (CPU_EXTENSION_RISCV_Zicsr = true) then
-- --------------------------------------------------------------------------------
-- CSR access by application software
-- --------------------------------------------------------------------------------
if (csr.we = '1') and (trap_ctrl.exc_buf(exception_iillegal_c) = '0') then -- manual write access and not illegal instruction
if (csr.we = '1') and (trap_ctrl.exc_buf(exc_iillegal_c) = '0') then -- manual write access and not illegal instruction
 
-- user floating-point CSRs --
-- --------------------------------------------------------------------
1974,18 → 1950,16
csr.mstatus_mie <= csr.wdata(03);
csr.mstatus_mpie <= csr.wdata(07);
if (CPU_EXTENSION_RISCV_U = true) then -- user mode implemented
csr.mstatus_mpp(0) <= csr.wdata(11) or csr.wdata(12);
csr.mstatus_mpp(1) <= csr.wdata(11) or csr.wdata(12);
csr.mstatus_mpp <= csr.wdata(11) or csr.wdata(12); -- everything /= U will fall back to M
csr.mstatus_tw <= csr.wdata(21);
end if;
end if;
-- R/W: mie - machine interrupt enable register --
if (csr.addr(2 downto 0) = csr_mie_c(2 downto 0)) then
csr.mie_msie <= csr.wdata(03); -- machine SW IRQ enable
csr.mie_mtie <= csr.wdata(07); -- machine TIMER IRQ enable
csr.mie_meie <= csr.wdata(11); -- machine EXT IRQ enable
for i in 0 to 15 loop -- fast interrupt channels 0..15
csr.mie_firqe(i) <= csr.wdata(16+i);
end loop; -- i
csr.mie_msie <= csr.wdata(03); -- machine SW IRQ enable
csr.mie_mtie <= csr.wdata(07); -- machine TIMER IRQ enable
csr.mie_meie <= csr.wdata(11); -- machine EXT IRQ enable
csr.mie_firqe <= csr.wdata(31 downto 16); -- fast interrupt channels 0..15
end if;
-- R/W: mtvec - machine trap-handler base address (for ALL exceptions) --
if (csr.addr(2 downto 0) = csr_mtvec_c(2 downto 0)) then
2019,7 → 1993,7
end if;
-- R/W: mip - machine interrupt pending --
if (csr.addr(3 downto 0) = csr_mip_c(3 downto 0)) then
csr.mip_clr <= csr.wdata(31 downto 16);
csr.mip_firq_nclr <= csr.wdata(31 downto 16); -- set low to clear according bit (FIRQs only)
end if;
end if;
 
2026,21 → 2000,23
-- physical memory protection: R/W: pmpcfg* - PMP configuration registers --
-- --------------------------------------------------------------------
if (PMP_NUM_REGIONS > 0) then
if (csr.addr(11 downto 4) = csr_class_pmpcfg_c) then -- pmp configuration CSR class
for i in 0 to PMP_NUM_REGIONS-1 loop
if (csr.addr(3 downto 0) = std_ulogic_vector(to_unsigned(i, 4))) then
if (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpcfg access
csr.pmpcfg(i)(0) <= csr.wdata((i mod 4)*8+0); -- R (rights.read)
csr.pmpcfg(i)(1) <= csr.wdata((i mod 4)*8+1); -- W (rights.write)
csr.pmpcfg(i)(2) <= csr.wdata((i mod 4)*8+2); -- X (rights.execute)
csr.pmpcfg(i)(3) <= csr.wdata((i mod 4)*8+3) and csr.wdata((i mod 4)*8+4); -- A_L
csr.pmpcfg(i)(4) <= csr.wdata((i mod 4)*8+3) and csr.wdata((i mod 4)*8+4); -- A_H - NAPOT/OFF only
csr.pmpcfg(i)(5) <= '0'; -- reserved
csr.pmpcfg(i)(6) <= '0'; -- reserved
csr.pmpcfg(i)(7) <= csr.wdata((i mod 4)*8+7); -- L (locked / rights also enforced in m-mode)
end if;
if (csr.addr(11 downto 2) = csr_class_pmpcfg_c) then -- pmp configuration CSR class
for i in 0 to 3 loop -- 3 pmpcfg CSRs
if (csr.addr(1 downto 0) = std_ulogic_vector(to_unsigned(i, 2))) then
for j in 0 to 3 loop -- 4 entries per CSR
if (csr.pmpcfg(i*4+j)(7) = '0') then -- unlocked pmpcfg entry
csr.pmpcfg(i*4+j)(0) <= csr.wdata(j*8+0); -- R - read
csr.pmpcfg(i*4+j)(1) <= csr.wdata(j*8+1); -- W - write
csr.pmpcfg(i*4+j)(2) <= csr.wdata(j*8+2); -- X - execute
csr.pmpcfg(i*4+j)(3) <= csr.wdata(j*8+3); -- A_L - mode low [TOR-mode only!]
csr.pmpcfg(i*4+j)(4) <= '0'; -- A_H - mode high [TOR-mode only!]
csr.pmpcfg(i*4+j)(5) <= '0'; -- reserved
csr.pmpcfg(i*4+j)(6) <= '0'; -- reserved
csr.pmpcfg(i*4+j)(7) <= csr.wdata(j*8+7); -- L (locked / also enforce in machine-mode)
end if;
end loop; -- j (entry)
end if;
end loop; -- i (PMP regions)
end loop; -- i (pmpcfg CSR)
end if;
end if;
 
2047,12 → 2023,10
-- physical memory protection: R/W: pmpaddr* - PMP address registers --
-- --------------------------------------------------------------------
if (PMP_NUM_REGIONS > 0) then
if (csr.addr(11 downto 4) = csr_pmpaddr0_c(11 downto 4)) or (csr.addr(11 downto 4) = csr_pmpaddr16_c(11 downto 4)) or
(csr.addr(11 downto 4) = csr_pmpaddr32_c(11 downto 4)) or (csr.addr(11 downto 4) = csr_pmpaddr48_c(11 downto 4)) then
if (csr.addr(11 downto 4) = csr_class_pmpaddr_c) then
for i in 0 to PMP_NUM_REGIONS-1 loop
if (csr.addr(6 downto 0) = std_ulogic_vector(unsigned(csr_pmpaddr0_c(6 downto 0)) + i)) and (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpaddr access
csr.pmpaddr(i) <= csr.wdata;
csr.pmpaddr(i)(index_size_f(PMP_MIN_GRANULARITY)-4 downto 0) <= (others => '1');
if (csr.addr(3 downto 0) = std_ulogic_vector(to_unsigned(i, 4))) and (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpaddr access
csr.pmpaddr(i) <= csr.wdata(data_width_c-3 downto index_size_f(PMP_MIN_GRANULARITY)-2);
end if;
end loop; -- i (PMP regions)
end if;
2065,7 → 2039,7
if (csr.addr(4 downto 0) = csr_mcountinhibit_c(4 downto 0)) then
csr.mcountinhibit_cy <= csr.wdata(0); -- enable auto-increment of [m]cycle[h] counter
csr.mcountinhibit_ir <= csr.wdata(2); -- enable auto-increment of [m]instret[h] counter
if (HPM_NUM_CNTS > 0) then -- any HPMs available?
if (HPM_NUM_CNTS > 0) and (CPU_EXTENSION_RISCV_Zihpm = true) then -- any HPMs available?
csr.mcountinhibit_hpm <= csr.wdata(csr.mcountinhibit_hpm'left+3 downto 3); -- enable auto-increment of [m]hpmcounter*[h] counter
end if;
end if;
2090,10 → 2064,7
csr.dcsr_step <= csr.wdata(2);
if (CPU_EXTENSION_RISCV_U = true) then -- user mode implemented
csr.dcsr_ebreaku <= csr.wdata(12);
csr.dcsr_prv(0) <= csr.wdata(1) or csr.wdata(0);
csr.dcsr_prv(1) <= csr.wdata(1) or csr.wdata(0);
else -- only machine mode is available
csr.dcsr_prv <= priv_mode_m_c;
csr.dcsr_prv <= csr.wdata(1) or csr.wdata(0); -- everything /= U will fall back to M
end if;
end if;
-- R/W: dpc - debug mode program counter --
2130,18 → 2101,21
-- --------------------------------------------------------------------------------
else
 
-- floating-point (FPU) exception flags --
-- --------------------------------------------------------------------
if (CPU_EXTENSION_RISCV_Zfinx = true) and (trap_ctrl.exc_buf(exception_iillegal_c) = '0') then -- no illegal instruction
-- floating-point (FPU) exception flags
-- --------------------------------------------------------------------
if (CPU_EXTENSION_RISCV_Zfinx = true) and (trap_ctrl.exc_buf(exc_iillegal_c) = '0') then -- no illegal instruction
csr.fflags <= csr.fflags or fpu_flags_i; -- accumulate flags ("accrued exception flags")
end if;
 
-- TRAP ENTER: write machine trap cause, PC and trap value register --
-- --------------------------------------------------------------------
-- TRAP ENTER: write machine trap cause, PC and trap value register
-- --------------------------------------------------------------------
if (trap_ctrl.env_start_ack = '1') then -- trap handler starting?
 
if (CPU_EXTENSION_RISCV_DEBUG = false) or ((trap_ctrl.cause(5) = '0') and -- update mtval/mepc/mcause only when NOT ENTRY debug mode exception
(debug_ctrl.running = '0')) then -- and NOT IN debug mode
-- normal trap entry: write mcause, mepc and mtval --
-- --------------------------------------------------------------------
if (CPU_EXTENSION_RISCV_DEBUG = false) or ((trap_ctrl.cause(5) = '0') and (debug_ctrl.running = '0')) then
 
-- trap cause ID code --
csr.mcause(csr.mcause'left) <= trap_ctrl.cause(trap_ctrl.cause'left); -- 1: interrupt, 0: exception
2151,7 → 2125,7
if (trap_ctrl.cause(trap_ctrl.cause'left) = '1') then -- for INTERRUPTS (async source)
csr.mepc <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- this is the CURRENT pc = interrupted instruction
else -- for sync. EXCEPTIONS (sync source)
csr.mepc <= execute_engine.last_pc(data_width_c-1 downto 1) & '0'; -- this is the LAST pc = last executed instruction
csr.mepc <= execute_engine.pc_last(data_width_c-1 downto 1) & '0'; -- this is the LAST pc = last executed instruction
end if;
 
-- trap value --
2161,7 → 2135,7
when trap_ima_c | trap_iba_c => -- misaligned instruction address OR instruction access error
csr.mtval <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- address of faulting instruction
when trap_brk_c => -- breakpoint
csr.mtval <= execute_engine.last_pc(data_width_c-1 downto 1) & '0'; -- address of breakpoint instruction
csr.mtval <= execute_engine.pc_last(data_width_c-1 downto 1) & '0'; -- address of breakpoint instruction
when trap_lma_c | trap_lbe_c | trap_sma_c | trap_sbe_c => -- misaligned load/store address OR load/store access error
csr.mtval <= mar_i; -- faulting data access address
when trap_iil_c => -- illegal instruction
2174,10 → 2148,11
 
-- DEBUG MODE (trap) enter: write dpc and dcsr --
-- --------------------------------------------------------------------
if (CPU_EXTENSION_RISCV_DEBUG = true) and (trap_ctrl.cause(5) = '1') and (debug_ctrl.running = '0') then -- debug mode entry exception
if (CPU_EXTENSION_RISCV_DEBUG = true) and (trap_ctrl.cause(5) = '1') and (debug_ctrl.running = '0') then
 
-- trap cause ID code --
csr.dcsr_cause <= trap_ctrl.cause(2 downto 0); -- why did we enter debug mode?
 
-- current privilege mode when debug mode was entered --
csr.dcsr_prv <= csr.privilege;
 
2185,7 → 2160,7
if (trap_ctrl.cause(trap_ctrl.cause'left) = '1') then -- for INTERRUPTS (async source)
csr.dpc <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- this is the CURRENT pc = interrupted instruction
else -- for sync. EXCEPTIONS (sync source)
csr.dpc <= execute_engine.last_pc(data_width_c-1 downto 1) & '0'; -- this is the LAST pc = last executed instruction
csr.dpc <= execute_engine.pc_last(data_width_c-1 downto 1) & '0'; -- this is the LAST pc = last executed instruction
end if;
 
end if;
2192,33 → 2167,33
 
end if;
 
-- mstatus: context switch --
-- --------------------------------------------------------------------
-- ENTER: trap handling starting?
-- mstatus: context switch
-- --------------------------------------------------------------------
-- ENTER: trap handler starting
if (trap_ctrl.env_start_ack = '1') then -- trap handler starting?
 
if (CPU_EXTENSION_RISCV_DEBUG = false) or -- normal trapping (debug mode NOT implemented)
((debug_ctrl.running = '0') and (trap_ctrl.cause(5) = '0')) then -- not IN debug mode and not ENTERING debug mode
csr.mstatus_mie <= '0'; -- disable interrupts
csr.mstatus_mpie <= csr.mstatus_mie; -- buffer previous mie state
if (CPU_EXTENSION_RISCV_U = true) then -- implement user mode
if (CPU_EXTENSION_RISCV_U = true) then -- user mode implemented
csr.privilege <= priv_mode_m_c; -- execute trap in machine mode
csr.mstatus_mpp <= csr.privilege; -- buffer previous privilege mode
csr.mstatus_mpp <= csr.privilege; -- backup previous privilege mode
end if;
end if;
 
-- EXIT: return from exception
-- EXIT: return from trap
elsif (trap_ctrl.env_end = '1') then
if (CPU_EXTENSION_RISCV_DEBUG = true) and (debug_ctrl.running = '1') then -- return from debug mode
if (CPU_EXTENSION_RISCV_U = true) then -- implement user mode
if (CPU_EXTENSION_RISCV_U = true) then -- user mode implemented
csr.privilege <= csr.dcsr_prv;
end if;
else -- return from "normal trap"
csr.mstatus_mie <= csr.mstatus_mpie; -- restore global IRQ enable flag
csr.mstatus_mpie <= '1';
if (CPU_EXTENSION_RISCV_U = true) then -- implement user mode
if (CPU_EXTENSION_RISCV_U = true) then -- user mode implemented
csr.privilege <= csr.mstatus_mpp; -- go back to previous privilege mode
csr.mstatus_mpp <= (others => '0');
csr.mstatus_mpp <= '0'; -- MRET has to clear mstatus.MPP
end if;
end if;
end if;
2225,98 → 2200,326
 
end if; -- /hardware csr access
end if;
end if;
end process csr_write_access;
 
-- --------------------------------------------------------------------------------
-- override write access for disabled functions
-- --------------------------------------------------------------------------------
-- effective privilege mode is M when in debug mode --
csr.privilege_eff <= priv_mode_m_c when (CPU_EXTENSION_RISCV_DEBUG = true) and (debug_ctrl.running = '1') else csr.privilege;
 
-- user mode disabled --
if (CPU_EXTENSION_RISCV_U = false) then
csr.privilege <= priv_mode_m_c;
csr.mstatus_mpp <= priv_mode_m_c;
csr.mcounteren_cy <= '0';
csr.mcounteren_tm <= '0';
csr.mcounteren_ir <= '0';
csr.dcsr_ebreaku <= '0';
csr.dcsr_prv <= priv_mode_m_c;
end if;
-- PMP output to bus unit --
pmp_output:
for i in 0 to PMP_NUM_REGIONS-1 generate
pmp_addr_o(i)(data_width_c-1 downto index_size_f(PMP_MIN_GRANULARITY)) <= csr.pmpaddr(i); -- physical address
pmp_ctrl_o(i) <= csr.pmpcfg(i);
end generate;
 
-- pmp disabled --
if (PMP_NUM_REGIONS = 0) then
csr.pmpcfg <= (others => (others => '0'));
csr.pmpaddr <= (others => (others => '1'));
end if;
 
-- hpms disabled --
if (HPM_NUM_CNTS = 0) then
csr.mhpmevent <= (others => (others => '0'));
csr.mcountinhibit_hpm <= (others => '0');
end if;
-- Control and Status Registers - Read Access ---------------------------------------------
-- -------------------------------------------------------------------------------------------
csr_read_access: process(rstn_i, clk_i)
variable csr_addr_v : std_ulogic_vector(11 downto 0);
begin
if rising_edge(clk_i) then
csr.rdata <= (others => '0'); -- default output, unimplemented CSRs are hardwired to zero
if (CPU_EXTENSION_RISCV_Zicsr = true) then
csr_addr_v(11 downto 10) := csr.addr(11 downto 10);
csr_addr_v(09 downto 08) := (others => csr.addr(8)); -- !!! WARNING: MACHINE (11) and USER (00) CSRs ONLY !!!
csr_addr_v(07 downto 00) := csr.addr(07 downto 00);
case csr_addr_v is
 
-- cpu counters disabled --
if (CPU_CNT_WIDTH = 0) then
csr.mcounteren_cy <= '0';
csr.mcounteren_ir <= '0';
csr.mcountinhibit_cy <= '0';
csr.mcountinhibit_ir <= '0';
end if;
-- floating-point CSRs --
-- --------------------------------------------------------------------
when csr_fflags_c => -- fflags (r/w): floating-point (FPU) exception flags
if (CPU_EXTENSION_RISCV_Zfinx) then csr.rdata(4 downto 0) <= csr.fflags; else NULL; end if;
when csr_frm_c => -- frm (r/w): floating-point (FPU) rounding mode
if (CPU_EXTENSION_RISCV_Zfinx) then csr.rdata(2 downto 0) <= csr.frm; else NULL; end if;
when csr_fcsr_c => -- fcsr (r/w): floating-point (FPU) control/status (frm + fflags)
if (CPU_EXTENSION_RISCV_Zfinx) then csr.rdata(7 downto 0) <= csr.frm & csr.fflags; else NULL; end if;
 
-- floating-point extension disabled --
if (CPU_EXTENSION_RISCV_Zfinx = false) then
csr.fflags <= (others => '0');
csr.frm <= (others => '0');
end if;
-- machine trap setup --
-- --------------------------------------------------------------------
when csr_mstatus_c => -- mstatus (r/w): machine status register
csr.rdata(03) <= csr.mstatus_mie; -- MIE
csr.rdata(07) <= csr.mstatus_mpie; -- MPIE
csr.rdata(12 downto 11) <= (others => csr.mstatus_mpp); -- MPP: machine previous privilege mode
csr.rdata(21) <= csr.mstatus_tw and bool_to_ulogic_f(CPU_EXTENSION_RISCV_U); -- TW
-- when csr_mstatush_c => -- mstatush (r/w): machine status register - high, implemented but always zero
-- csr.rdata <= (others => '0');
when csr_misa_c => -- misa (r/-): ISA and extensions
csr.rdata(00) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_A); -- A CPU extension
csr.rdata(01) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B); -- B CPU extension
csr.rdata(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C); -- C CPU extension
csr.rdata(04) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- E CPU extension
csr.rdata(08) <= not bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- I CPU extension (if not E)
csr.rdata(12) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_M); -- M CPU extension
csr.rdata(20) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_U); -- U CPU extension
csr.rdata(23) <= '1'; -- X CPU extension (non-standard extensions / NEORV32-specific)
csr.rdata(30) <= '1'; -- 32-bit architecture (MXL lo)
csr.rdata(31) <= '0'; -- 32-bit architecture (MXL hi)
when csr_mie_c => -- mie (r/w): machine interrupt-enable register
csr.rdata(03) <= csr.mie_msie; -- machine software IRQ enable
csr.rdata(07) <= csr.mie_mtie; -- machine timer IRQ enable
csr.rdata(11) <= csr.mie_meie; -- machine external IRQ enable
csr.rdata(31 downto 16) <= csr.mie_firqe;
when csr_mtvec_c => -- mtvec (r/w): machine trap-handler base address (for ALL exceptions)
csr.rdata <= csr.mtvec(data_width_c-1 downto 2) & "00"; -- mtvec.MODE=0
when csr_mcounteren_c => -- mcounteren (r/w): machine counter enable register, hardwired to zero if user mode is not implemented
csr.rdata(0) <= csr.mcounteren_cy and bool_to_ulogic_f(CPU_EXTENSION_RISCV_U); -- enable user-level access to cycle[h]
csr.rdata(1) <= csr.mcounteren_tm and bool_to_ulogic_f(CPU_EXTENSION_RISCV_U); -- enable user-level access to time[h]
csr.rdata(2) <= csr.mcounteren_ir and bool_to_ulogic_f(CPU_EXTENSION_RISCV_U); -- enable user-level access to instret[h]
 
-- debug mode disabled --
if (CPU_EXTENSION_RISCV_DEBUG = false) then
csr.dcsr_ebreakm <= '0';
csr.dcsr_ebreaku <= '0';
csr.dcsr_step <= '0';
csr.dcsr_cause <= (others => '0');
csr.dpc <= (others => '0');
csr.dscratch0 <= (others => '0');
end if;
-- machine trap handling --
-- --------------------------------------------------------------------
when csr_mscratch_c => -- mscratch (r/w): machine scratch register
csr.rdata <= csr.mscratch;
when csr_mepc_c => -- mepc (r/w): machine exception program counter
csr.rdata <= csr.mepc(data_width_c-1 downto 1) & '0';
when csr_mcause_c => -- mcause (r/w): machine trap cause
csr.rdata(31) <= csr.mcause(csr.mcause'left);
csr.rdata(csr.mcause'left-1 downto 0) <= csr.mcause(csr.mcause'left-1 downto 0);
when csr_mtval_c => -- mtval (r/-): machine bad address or instruction
csr.rdata <= csr.mtval;
when csr_mip_c => -- mip (r/w): machine interrupt pending
csr.rdata(03) <= trap_ctrl.irq_buf(irq_msw_irq_c);
csr.rdata(07) <= trap_ctrl.irq_buf(irq_mtime_irq_c);
csr.rdata(11) <= trap_ctrl.irq_buf(irq_mext_irq_c);
csr.rdata(31 downto 16) <= trap_ctrl.irq_buf(irq_firq_15_c downto irq_firq_0_c);
 
-- trigger module disabled --
if (CPU_EXTENSION_RISCV_DEBUG = false) then
csr.tdata1_exe <= '0';
csr.tdata2 <= (others => '0');
end if;
-- physical memory protection - configuration (r/w) --
-- --------------------------------------------------------------------
when csr_pmpcfg0_c =>
if (PMP_NUM_REGIONS > 0) then
if (PMP_NUM_REGIONS > 00) then csr.rdata(07 downto 00) <= csr.pmpcfg(00); end if;
if (PMP_NUM_REGIONS > 01) then csr.rdata(15 downto 08) <= csr.pmpcfg(01); end if;
if (PMP_NUM_REGIONS > 02) then csr.rdata(23 downto 16) <= csr.pmpcfg(02); end if;
if (PMP_NUM_REGIONS > 03) then csr.rdata(31 downto 24) <= csr.pmpcfg(03); end if;
else NULL; end if;
when csr_pmpcfg1_c =>
if (PMP_NUM_REGIONS > 4) then
if (PMP_NUM_REGIONS > 04) then csr.rdata(07 downto 00) <= csr.pmpcfg(04); end if;
if (PMP_NUM_REGIONS > 05) then csr.rdata(15 downto 08) <= csr.pmpcfg(05); end if;
if (PMP_NUM_REGIONS > 06) then csr.rdata(23 downto 16) <= csr.pmpcfg(06); end if;
if (PMP_NUM_REGIONS > 07) then csr.rdata(31 downto 24) <= csr.pmpcfg(07); end if;
else NULL; end if;
when csr_pmpcfg2_c =>
if (PMP_NUM_REGIONS > 8) then
if (PMP_NUM_REGIONS > 08) then csr.rdata(07 downto 00) <= csr.pmpcfg(08); end if;
if (PMP_NUM_REGIONS > 09) then csr.rdata(15 downto 08) <= csr.pmpcfg(09); end if;
if (PMP_NUM_REGIONS > 10) then csr.rdata(23 downto 16) <= csr.pmpcfg(10); end if;
if (PMP_NUM_REGIONS > 11) then csr.rdata(31 downto 24) <= csr.pmpcfg(11); end if;
else NULL; end if;
when csr_pmpcfg3_c =>
if (PMP_NUM_REGIONS > 12) then
if (PMP_NUM_REGIONS > 12) then csr.rdata(07 downto 00) <= csr.pmpcfg(12); end if;
if (PMP_NUM_REGIONS > 13) then csr.rdata(15 downto 08) <= csr.pmpcfg(13); end if;
if (PMP_NUM_REGIONS > 14) then csr.rdata(23 downto 16) <= csr.pmpcfg(14); end if;
if (PMP_NUM_REGIONS > 15) then csr.rdata(31 downto 24) <= csr.pmpcfg(15); end if;
else NULL; end if;
 
end if;
end process csr_write_access;
-- physical memory protection - addresses (r/w) --
-- --------------------------------------------------------------------
when csr_pmpaddr0_c => if (PMP_NUM_REGIONS > 00) then csr.rdata(data_width_c-3 downto index_size_f(PMP_MIN_GRANULARITY)-2) <= csr.pmpaddr(00); else NULL; end if;
when csr_pmpaddr1_c => if (PMP_NUM_REGIONS > 01) then csr.rdata(data_width_c-3 downto index_size_f(PMP_MIN_GRANULARITY)-2) <= csr.pmpaddr(01); else NULL; end if;
when csr_pmpaddr2_c => if (PMP_NUM_REGIONS > 02) then csr.rdata(data_width_c-3 downto index_size_f(PMP_MIN_GRANULARITY)-2) <= csr.pmpaddr(02); else NULL; end if;
when csr_pmpaddr3_c => if (PMP_NUM_REGIONS > 03) then csr.rdata(data_width_c-3 downto index_size_f(PMP_MIN_GRANULARITY)-2) <= csr.pmpaddr(03); else NULL; end if;
when csr_pmpaddr4_c => if (PMP_NUM_REGIONS > 04) then csr.rdata(data_width_c-3 downto index_size_f(PMP_MIN_GRANULARITY)-2) <= csr.pmpaddr(04); else NULL; end if;
when csr_pmpaddr5_c => if (PMP_NUM_REGIONS > 05) then csr.rdata(data_width_c-3 downto index_size_f(PMP_MIN_GRANULARITY)-2) <= csr.pmpaddr(05); else NULL; end if;
when csr_pmpaddr6_c => if (PMP_NUM_REGIONS > 06) then csr.rdata(data_width_c-3 downto index_size_f(PMP_MIN_GRANULARITY)-2) <= csr.pmpaddr(06); else NULL; end if;
when csr_pmpaddr7_c => if (PMP_NUM_REGIONS > 07) then csr.rdata(data_width_c-3 downto index_size_f(PMP_MIN_GRANULARITY)-2) <= csr.pmpaddr(07); else NULL; end if;
when csr_pmpaddr8_c => if (PMP_NUM_REGIONS > 08) then csr.rdata(data_width_c-3 downto index_size_f(PMP_MIN_GRANULARITY)-2) <= csr.pmpaddr(08); else NULL; end if;
when csr_pmpaddr9_c => if (PMP_NUM_REGIONS > 09) then csr.rdata(data_width_c-3 downto index_size_f(PMP_MIN_GRANULARITY)-2) <= csr.pmpaddr(09); else NULL; end if;
when csr_pmpaddr10_c => if (PMP_NUM_REGIONS > 10) then csr.rdata(data_width_c-3 downto index_size_f(PMP_MIN_GRANULARITY)-2) <= csr.pmpaddr(10); else NULL; end if;
when csr_pmpaddr11_c => if (PMP_NUM_REGIONS > 11) then csr.rdata(data_width_c-3 downto index_size_f(PMP_MIN_GRANULARITY)-2) <= csr.pmpaddr(11); else NULL; end if;
when csr_pmpaddr12_c => if (PMP_NUM_REGIONS > 12) then csr.rdata(data_width_c-3 downto index_size_f(PMP_MIN_GRANULARITY)-2) <= csr.pmpaddr(12); else NULL; end if;
when csr_pmpaddr13_c => if (PMP_NUM_REGIONS > 13) then csr.rdata(data_width_c-3 downto index_size_f(PMP_MIN_GRANULARITY)-2) <= csr.pmpaddr(13); else NULL; end if;
when csr_pmpaddr14_c => if (PMP_NUM_REGIONS > 14) then csr.rdata(data_width_c-3 downto index_size_f(PMP_MIN_GRANULARITY)-2) <= csr.pmpaddr(14); else NULL; end if;
when csr_pmpaddr15_c => if (PMP_NUM_REGIONS > 15) then csr.rdata(data_width_c-3 downto index_size_f(PMP_MIN_GRANULARITY)-2) <= csr.pmpaddr(15); else NULL; end if;
 
-- decode current privilege mode --
csr.privilege_rd <= priv_mode_m_c when (CPU_EXTENSION_RISCV_DEBUG = true) and (debug_ctrl.running = '1') else csr.privilege; -- effective privilege mode ("machine" when in debug mode)
csr.priv_m_mode <= '1' when (csr.privilege_rd = priv_mode_m_c) else '0';
csr.priv_u_mode <= '1' when (csr.privilege_rd = priv_mode_u_c) and (CPU_EXTENSION_RISCV_U = true) else '0';
-- machine counter setup --
-- --------------------------------------------------------------------
when csr_mcountinhibit_c => -- mcountinhibit (r/w): machine counter-inhibit register
csr.rdata(0) <= csr.mcountinhibit_cy; -- enable auto-increment of [m]cycle[h] counter
csr.rdata(2) <= csr.mcountinhibit_ir; -- enable auto-increment of [m]instret[h] counter
if (HPM_NUM_CNTS > 0) and (CPU_EXTENSION_RISCV_Zihpm = true) then -- any HPMs available?
csr.rdata(csr.mcountinhibit_hpm'left+3 downto 3) <= csr.mcountinhibit_hpm; -- enable auto-increment of [m]hpmcounterx[h] counter
end if;
 
-- PMP configuration output to bus unit --
pmp_output: process(csr)
begin
pmp_addr_o <= (others => (others => '0'));
pmp_ctrl_o <= (others => (others => '0'));
if (PMP_NUM_REGIONS /= 0) then
for i in 0 to PMP_NUM_REGIONS-1 loop
pmp_addr_o(i) <= csr.pmpaddr(i) & "11";
pmp_addr_o(i)(index_size_f(PMP_MIN_GRANULARITY)-4 downto 0) <= (others => '1');
pmp_ctrl_o(i) <= csr.pmpcfg(i);
end loop; -- i
end if;
end process pmp_output;
-- machine performance-monitoring event selector (r/w) --
-- --------------------------------------------------------------------
when csr_mhpmevent3_c => if (HPM_NUM_CNTS > 00) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(00); else NULL; end if;
when csr_mhpmevent4_c => if (HPM_NUM_CNTS > 01) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(01); else NULL; end if;
when csr_mhpmevent5_c => if (HPM_NUM_CNTS > 02) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(02); else NULL; end if;
when csr_mhpmevent6_c => if (HPM_NUM_CNTS > 03) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(03); else NULL; end if;
when csr_mhpmevent7_c => if (HPM_NUM_CNTS > 04) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(04); else NULL; end if;
when csr_mhpmevent8_c => if (HPM_NUM_CNTS > 05) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(05); else NULL; end if;
when csr_mhpmevent9_c => if (HPM_NUM_CNTS > 06) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(06); else NULL; end if;
when csr_mhpmevent10_c => if (HPM_NUM_CNTS > 07) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(07); else NULL; end if;
when csr_mhpmevent11_c => if (HPM_NUM_CNTS > 08) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(08); else NULL; end if;
when csr_mhpmevent12_c => if (HPM_NUM_CNTS > 09) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(09); else NULL; end if;
when csr_mhpmevent13_c => if (HPM_NUM_CNTS > 10) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(10); else NULL; end if;
when csr_mhpmevent14_c => if (HPM_NUM_CNTS > 11) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(11); else NULL; end if;
when csr_mhpmevent15_c => if (HPM_NUM_CNTS > 12) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(12); else NULL; end if;
when csr_mhpmevent16_c => if (HPM_NUM_CNTS > 13) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(13); else NULL; end if;
when csr_mhpmevent17_c => if (HPM_NUM_CNTS > 14) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(14); else NULL; end if;
when csr_mhpmevent18_c => if (HPM_NUM_CNTS > 15) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(15); else NULL; end if;
when csr_mhpmevent19_c => if (HPM_NUM_CNTS > 16) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(16); else NULL; end if;
when csr_mhpmevent20_c => if (HPM_NUM_CNTS > 17) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(17); else NULL; end if;
when csr_mhpmevent21_c => if (HPM_NUM_CNTS > 18) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(18); else NULL; end if;
when csr_mhpmevent22_c => if (HPM_NUM_CNTS > 19) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(19); else NULL; end if;
when csr_mhpmevent23_c => if (HPM_NUM_CNTS > 20) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(20); else NULL; end if;
when csr_mhpmevent24_c => if (HPM_NUM_CNTS > 21) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(21); else NULL; end if;
when csr_mhpmevent25_c => if (HPM_NUM_CNTS > 22) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(22); else NULL; end if;
when csr_mhpmevent26_c => if (HPM_NUM_CNTS > 23) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(23); else NULL; end if;
when csr_mhpmevent27_c => if (HPM_NUM_CNTS > 24) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(24); else NULL; end if;
when csr_mhpmevent28_c => if (HPM_NUM_CNTS > 25) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(25); else NULL; end if;
when csr_mhpmevent29_c => if (HPM_NUM_CNTS > 26) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(26); else NULL; end if;
when csr_mhpmevent30_c => if (HPM_NUM_CNTS > 27) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(27); else NULL; end if;
when csr_mhpmevent31_c => if (HPM_NUM_CNTS > 28) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmevent_rd(28); else NULL; end if;
 
-- PMP config read dummy --
pmp_rd_dummy: process(csr)
begin
csr.pmpcfg_rd <= (others => (others => '0'));
if (PMP_NUM_REGIONS /= 0) then
for i in 0 to PMP_NUM_REGIONS-1 loop
csr.pmpcfg_rd(i) <= csr.pmpcfg(i);
end loop; -- i
-- counters and timers --
-- --------------------------------------------------------------------
when csr_cycle_c | csr_mcycle_c => -- [m]cycle (r/w): Cycle counter LOW
if (cpu_cnt_lo_width_c > 0) and (CPU_EXTENSION_RISCV_Zicntr) then csr.rdata(cpu_cnt_lo_width_c-1 downto 0) <= csr.mcycle(cpu_cnt_lo_width_c-1 downto 0); else NULL; end if;
when csr_cycleh_c | csr_mcycleh_c => -- [m]cycleh (r/w): Cycle counter HIGH
if (cpu_cnt_hi_width_c > 0) and (CPU_EXTENSION_RISCV_Zicntr) then csr.rdata(cpu_cnt_hi_width_c-1 downto 0) <= csr.mcycleh(cpu_cnt_hi_width_c-1 downto 0); else NULL; end if;
 
when csr_instret_c | csr_minstret_c => -- [m]instret (r/w): Instructions-retired counter LOW
if (cpu_cnt_lo_width_c > 0) and (CPU_EXTENSION_RISCV_Zicntr) then csr.rdata(cpu_cnt_lo_width_c-1 downto 0) <= csr.minstret(cpu_cnt_lo_width_c-1 downto 0); else NULL; end if;
when csr_instreth_c | csr_minstreth_c => -- [m]instreth (r/w): Instructions-retired counter HIGH
if (cpu_cnt_hi_width_c > 0) and (CPU_EXTENSION_RISCV_Zicntr) then csr.rdata(cpu_cnt_hi_width_c-1 downto 0) <= csr.minstreth(cpu_cnt_hi_width_c-1 downto 0); else NULL; end if;
 
when csr_time_c => -- time (r/-): System time LOW (from MTIME unit)
if (CPU_EXTENSION_RISCV_Zicntr) then csr.rdata <= time_i(31 downto 00); else NULL; end if;
when csr_timeh_c => -- timeh (r/-): System time HIGH (from MTIME unit)
if (CPU_EXTENSION_RISCV_Zicntr) then csr.rdata <= time_i(63 downto 32); else NULL; end if;
 
-- hardware performance counters --
-- --------------------------------------------------------------------
-- low word (r/w) --
when csr_mhpmcounter3_c | csr_hpmcounter3_c => if (HPM_NUM_CNTS > 00) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(00); else NULL; end if;
when csr_mhpmcounter4_c | csr_hpmcounter4_c => if (HPM_NUM_CNTS > 01) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(01); else NULL; end if;
when csr_mhpmcounter5_c | csr_hpmcounter5_c => if (HPM_NUM_CNTS > 02) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(02); else NULL; end if;
when csr_mhpmcounter6_c | csr_hpmcounter6_c => if (HPM_NUM_CNTS > 03) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(03); else NULL; end if;
when csr_mhpmcounter7_c | csr_hpmcounter7_c => if (HPM_NUM_CNTS > 04) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(04); else NULL; end if;
when csr_mhpmcounter8_c | csr_hpmcounter8_c => if (HPM_NUM_CNTS > 05) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(05); else NULL; end if;
when csr_mhpmcounter9_c | csr_hpmcounter9_c => if (HPM_NUM_CNTS > 06) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(06); else NULL; end if;
when csr_mhpmcounter10_c | csr_hpmcounter10_c => if (HPM_NUM_CNTS > 07) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(07); else NULL; end if;
when csr_mhpmcounter11_c | csr_hpmcounter11_c => if (HPM_NUM_CNTS > 08) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(08); else NULL; end if;
when csr_mhpmcounter12_c | csr_hpmcounter12_c => if (HPM_NUM_CNTS > 09) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(09); else NULL; end if;
when csr_mhpmcounter13_c | csr_hpmcounter13_c => if (HPM_NUM_CNTS > 10) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(10); else NULL; end if;
when csr_mhpmcounter14_c | csr_hpmcounter14_c => if (HPM_NUM_CNTS > 11) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(11); else NULL; end if;
when csr_mhpmcounter15_c | csr_hpmcounter15_c => if (HPM_NUM_CNTS > 12) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(12); else NULL; end if;
when csr_mhpmcounter16_c | csr_hpmcounter16_c => if (HPM_NUM_CNTS > 13) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(13); else NULL; end if;
when csr_mhpmcounter17_c | csr_hpmcounter17_c => if (HPM_NUM_CNTS > 14) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(14); else NULL; end if;
when csr_mhpmcounter18_c | csr_hpmcounter18_c => if (HPM_NUM_CNTS > 15) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(15); else NULL; end if;
when csr_mhpmcounter19_c | csr_hpmcounter19_c => if (HPM_NUM_CNTS > 16) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(16); else NULL; end if;
when csr_mhpmcounter20_c | csr_hpmcounter20_c => if (HPM_NUM_CNTS > 17) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(17); else NULL; end if;
when csr_mhpmcounter21_c | csr_hpmcounter21_c => if (HPM_NUM_CNTS > 18) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(18); else NULL; end if;
when csr_mhpmcounter22_c | csr_hpmcounter22_c => if (HPM_NUM_CNTS > 19) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(19); else NULL; end if;
when csr_mhpmcounter23_c | csr_hpmcounter23_c => if (HPM_NUM_CNTS > 20) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(20); else NULL; end if;
when csr_mhpmcounter24_c | csr_hpmcounter24_c => if (HPM_NUM_CNTS > 21) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(21); else NULL; end if;
when csr_mhpmcounter25_c | csr_hpmcounter25_c => if (HPM_NUM_CNTS > 22) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(22); else NULL; end if;
when csr_mhpmcounter26_c | csr_hpmcounter26_c => if (HPM_NUM_CNTS > 23) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(23); else NULL; end if;
when csr_mhpmcounter27_c | csr_hpmcounter27_c => if (HPM_NUM_CNTS > 24) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(24); else NULL; end if;
when csr_mhpmcounter28_c | csr_hpmcounter28_c => if (HPM_NUM_CNTS > 25) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(25); else NULL; end if;
when csr_mhpmcounter29_c | csr_hpmcounter29_c => if (HPM_NUM_CNTS > 26) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(26); else NULL; end if;
when csr_mhpmcounter30_c | csr_hpmcounter30_c => if (HPM_NUM_CNTS > 27) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(27); else NULL; end if;
when csr_mhpmcounter31_c | csr_hpmcounter31_c => if (HPM_NUM_CNTS > 28) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounter_rd(28); else NULL; end if;
-- high word (r/w) --
when csr_mhpmcounter3h_c | csr_hpmcounter3h_c => if (HPM_NUM_CNTS > 00) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(00); else NULL; end if;
when csr_mhpmcounter4h_c | csr_hpmcounter4h_c => if (HPM_NUM_CNTS > 01) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(01); else NULL; end if;
when csr_mhpmcounter5h_c | csr_hpmcounter5h_c => if (HPM_NUM_CNTS > 02) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(02); else NULL; end if;
when csr_mhpmcounter6h_c | csr_hpmcounter6h_c => if (HPM_NUM_CNTS > 03) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(03); else NULL; end if;
when csr_mhpmcounter7h_c | csr_hpmcounter7h_c => if (HPM_NUM_CNTS > 04) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(04); else NULL; end if;
when csr_mhpmcounter8h_c | csr_hpmcounter8h_c => if (HPM_NUM_CNTS > 05) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(05); else NULL; end if;
when csr_mhpmcounter9h_c | csr_hpmcounter9h_c => if (HPM_NUM_CNTS > 06) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(06); else NULL; end if;
when csr_mhpmcounter10h_c | csr_hpmcounter10h_c => if (HPM_NUM_CNTS > 07) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(07); else NULL; end if;
when csr_mhpmcounter11h_c | csr_hpmcounter11h_c => if (HPM_NUM_CNTS > 08) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(08); else NULL; end if;
when csr_mhpmcounter12h_c | csr_hpmcounter12h_c => if (HPM_NUM_CNTS > 09) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(09); else NULL; end if;
when csr_mhpmcounter13h_c | csr_hpmcounter13h_c => if (HPM_NUM_CNTS > 10) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(10); else NULL; end if;
when csr_mhpmcounter14h_c | csr_hpmcounter14h_c => if (HPM_NUM_CNTS > 11) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(11); else NULL; end if;
when csr_mhpmcounter15h_c | csr_hpmcounter15h_c => if (HPM_NUM_CNTS > 12) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(12); else NULL; end if;
when csr_mhpmcounter16h_c | csr_hpmcounter16h_c => if (HPM_NUM_CNTS > 13) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(13); else NULL; end if;
when csr_mhpmcounter17h_c | csr_hpmcounter17h_c => if (HPM_NUM_CNTS > 14) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(14); else NULL; end if;
when csr_mhpmcounter18h_c | csr_hpmcounter18h_c => if (HPM_NUM_CNTS > 15) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(15); else NULL; end if;
when csr_mhpmcounter19h_c | csr_hpmcounter19h_c => if (HPM_NUM_CNTS > 16) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(16); else NULL; end if;
when csr_mhpmcounter20h_c | csr_hpmcounter20h_c => if (HPM_NUM_CNTS > 17) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(17); else NULL; end if;
when csr_mhpmcounter21h_c | csr_hpmcounter21h_c => if (HPM_NUM_CNTS > 18) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(18); else NULL; end if;
when csr_mhpmcounter22h_c | csr_hpmcounter22h_c => if (HPM_NUM_CNTS > 19) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(19); else NULL; end if;
when csr_mhpmcounter23h_c | csr_hpmcounter23h_c => if (HPM_NUM_CNTS > 20) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(20); else NULL; end if;
when csr_mhpmcounter24h_c | csr_hpmcounter24h_c => if (HPM_NUM_CNTS > 21) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(21); else NULL; end if;
when csr_mhpmcounter25h_c | csr_hpmcounter25h_c => if (HPM_NUM_CNTS > 22) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(22); else NULL; end if;
when csr_mhpmcounter26h_c | csr_hpmcounter26h_c => if (HPM_NUM_CNTS > 23) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(23); else NULL; end if;
when csr_mhpmcounter27h_c | csr_hpmcounter27h_c => if (HPM_NUM_CNTS > 24) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(24); else NULL; end if;
when csr_mhpmcounter28h_c | csr_hpmcounter28h_c => if (HPM_NUM_CNTS > 25) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(25); else NULL; end if;
when csr_mhpmcounter29h_c | csr_hpmcounter29h_c => if (HPM_NUM_CNTS > 26) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(26); else NULL; end if;
when csr_mhpmcounter30h_c | csr_hpmcounter30h_c => if (HPM_NUM_CNTS > 27) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(27); else NULL; end if;
when csr_mhpmcounter31h_c | csr_hpmcounter31h_c => if (HPM_NUM_CNTS > 28) and (CPU_EXTENSION_RISCV_Zihpm) then csr.rdata <= csr.mhpmcounterh_rd(28); else NULL; end if;
 
-- machine information registers --
-- --------------------------------------------------------------------
-- when csr_mvendorid_c => csr.rdata <= (others => '0'); -- mvendorid (r/-): vendor ID, implemented but always zero
when csr_marchid_c => csr.rdata(4 downto 0) <= "10011"; -- marchid (r/-): arch ID - official RISC-V open-source arch ID
when csr_mimpid_c => csr.rdata <= hw_version_c; -- mimpid (r/-): implementation ID -- NEORV32 hardware version
when csr_mhartid_c => csr.rdata <= std_ulogic_vector(to_unsigned(HW_THREAD_ID, 32)); -- mhartid (r/-): hardware thread ID
-- when csr_mconfigptr_c => csr.rdata <= (others => '0'); -- mconfigptr (r/-): machine configuration pointer register, implemented but always zero
 
-- debug mode CSRs --
-- --------------------------------------------------------------------
when csr_dcsr_c => if (CPU_EXTENSION_RISCV_DEBUG) then csr.rdata <= csr.dcsr_rd; else NULL; end if; -- dcsr (r/w): debug mode control and status
when csr_dpc_c => if (CPU_EXTENSION_RISCV_DEBUG) then csr.rdata <= csr.dpc; else NULL; end if; -- dpc (r/w): debug mode program counter
when csr_dscratch0_c => if (CPU_EXTENSION_RISCV_DEBUG) then csr.rdata <= csr.dscratch0; else NULL; end if; -- dscratch0 (r/w): debug mode scratch register 0
 
-- trigger module CSRs --
-- --------------------------------------------------------------------
-- when csr_tselect_c => if (CPU_EXTENSION_RISCV_DEBUG) then csr.rdata <= (others => '0'); else NULL; end if; -- tselect (r/w): always zero = only 1 trigger available
when csr_tdata1_c => if (CPU_EXTENSION_RISCV_DEBUG) then csr.rdata <= csr.tdata1_rd; else NULL; end if; -- tdata1 (r/w): match control
when csr_tdata2_c => if (CPU_EXTENSION_RISCV_DEBUG) then csr.rdata <= csr.tdata2; else NULL; end if; -- tdata2 (r/w): address-compare
-- when csr_tdata3_c => if (CPU_EXTENSION_RISCV_DEBUG) then csr.rdata <= (others => '0'); else NULL; end if; -- tdata3 (r/w): implemented but always zero
when csr_tinfo_c => if (CPU_EXTENSION_RISCV_DEBUG) then csr.rdata <= x"00000004"; else NULL; end if; -- tinfo (r/w): address-match trigger only
-- when csr_tcontrol_c => if (CPU_EXTENSION_RISCV_DEBUG) then csr.rdata <= (others => '0'); else NULL; end if; -- tcontrol (r/w): implemented but always zero
-- when csr_mcontext_c => if (CPU_EXTENSION_RISCV_DEBUG) then csr.rdata <= (others => '0'); else NULL; end if; -- mcontext (r/w): implemented but always zero
-- when csr_scontext_c => if (CPU_EXTENSION_RISCV_DEBUG) then csr.rdata <= (others => '0'); else NULL; end if; -- scontext (r/w): implemented but always zero
 
-- NEORV32-specific (RISC-V "custom") read-only CSRs --
-- --------------------------------------------------------------------
-- machine extended ISA extensions information --
when csr_mxisa_c =>
-- ISA extended (sub-)extensions --
csr.rdata(00) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicsr); -- Zicsr: privileged architecture (!!!)
csr.rdata(01) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zifencei); -- Zifencei: instruction stream sync.
csr.rdata(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zmmul); -- Zmmul: mul/div
csr.rdata(03) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zxcfu); -- Zxcfu: custom RISC-V instructions
csr.rdata(04) <= '0'; -- reserved
csr.rdata(05) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zfinx); -- Zfinx: FPU using x registers, "F-alternative"
csr.rdata(06) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicntr) and
bool_to_ulogic_f(boolean(CPU_CNT_WIDTH /= 64)); -- Zxscnt: reduced-size CPU counters (from Zicntr)
csr.rdata(07) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicntr); -- Zicntr: base instructions, cycle and time CSRs
csr.rdata(08) <= bool_to_ulogic_f(boolean(PMP_NUM_REGIONS > 0)); -- PMP: physical memory protection (Zspmp)
csr.rdata(09) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zihpm); -- Zihpm: hardware performance monitors
csr.rdata(10) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_DEBUG); -- RISC-V debug mode
-- tuning options --
csr.rdata(30) <= bool_to_ulogic_f(FAST_MUL_EN); -- DSP-based multiplication (M extensions only)
csr.rdata(31) <= bool_to_ulogic_f(FAST_SHIFT_EN); -- parallel logic for shifts (barrel shifters)
 
-- undefined/unavailable --
-- --------------------------------------------------------------------
when others =>
NULL; -- not implemented, read as zero
 
end case;
end if;
end if;
end process pmp_rd_dummy;
end process csr_read_access;
 
-- CSR read data output --
csr_rdata_o <= csr.rdata;
 
-- ****************************************************************************************************************************
-- CPU Counters / HPMs (CSRs)
-- ****************************************************************************************************************************
 
-- Control and Status Registers - Counters ------------------------------------------------
-- -------------------------------------------------------------------------------------------
csr_counters: process(rstn_i, clk_i)
2343,8 → 2546,8
csr.mcycle(cpu_cnt_lo_width_c-1 downto 0) <= csr.mcycle_nxt(cpu_cnt_lo_width_c-1 downto 0);
end if;
else
csr.mcycle <= (others => '-');
csr.mcycle_ovfl(0) <= '-';
csr.mcycle_ovfl <= (others => '-');
csr.mcycle <= (others => '-');
end if;
 
-- [m]cycleh --
2368,8 → 2571,8
csr.minstret(cpu_cnt_lo_width_c-1 downto 0) <= csr.minstret_nxt(cpu_cnt_lo_width_c-1 downto 0);
end if;
else
csr.minstret <= (others => '-');
csr.minstret_ovfl(0) <= '-';
csr.minstret_ovfl <= (others => '-');
csr.minstret <= (others => '-');
end if;
 
-- [m]instreth --
2396,8 → 2599,8
csr.mhpmcounter(i)(hpm_cnt_lo_width_c-1 downto 0) <= csr.mhpmcounter_nxt(i)(hpm_cnt_lo_width_c-1 downto 0);
end if;
else
csr.mhpmcounter(i) <= (others => '-');
csr.mhpmcounter_ovfl(i)(0) <= '-';
csr.mhpmcounter_ovfl(i) <= (others => '-');
csr.mhpmcounter(i) <= (others => '-');
end if;
 
-- [m]hpmcounter*h --
2416,7 → 2619,6
end if;
end process csr_counters;
 
 
-- mcycle & minstret increment LOW --
csr.mcycle_nxt <= std_ulogic_vector(unsigned('0' & csr.mcycle) + 1);
csr.minstret_nxt <= std_ulogic_vector(unsigned('0' & csr.minstret) + 1);
2431,10 → 2633,12
-- hpm counter read --
hpm_rd_dummy: process(csr)
begin
csr.mhpmevent_rd <= (others => (others => '0'));
csr.mhpmcounter_rd <= (others => (others => '0'));
csr.mhpmcounterh_rd <= (others => (others => '0'));
if (HPM_NUM_CNTS /= 0) and (CPU_EXTENSION_RISCV_Zihpm = true) then
for i in 0 to HPM_NUM_CNTS-1 loop
csr.mhpmevent_rd(i)(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(i);
if (hpm_cnt_lo_width_c > 0) then
csr.mhpmcounter_rd(i)(hpm_cnt_lo_width_c-1 downto 0) <= csr.mhpmcounter(i)(hpm_cnt_lo_width_c-1 downto 0);
end if;
2448,11 → 2652,9
 
-- Hardware Performance Monitor - Counter Event Control -----------------------------------
-- -------------------------------------------------------------------------------------------
hpmcnt_ctrl: process(rstn_i, clk_i)
hpmcnt_ctrl: process(clk_i)
begin
if (rstn_i = '0') then
hpmcnt_trigger <= (others => def_rst_val_c);
elsif rising_edge(clk_i) then
if rising_edge(clk_i) then
-- enable selected triggers by ANDing actual events and according CSR configuration bits --
-- OR everything to see if counter should increment --
hpmcnt_trigger <= (others => '0'); -- default
2488,350 → 2690,6
cnt_event(hpmcnt_event_illegal_c) <= '1' when (trap_ctrl.env_start_ack = '1') and (trap_ctrl.cause = trap_iil_c) else '0'; -- illegal operation
 
 
-- Control and Status Registers - Read Access ---------------------------------------------
-- -------------------------------------------------------------------------------------------
csr_read_access: process(rstn_i, clk_i)
variable csr_addr_v : std_ulogic_vector(11 downto 0);
begin
if rising_edge(clk_i) then
csr.rdata <= (others => '0'); -- default output, unimplemented CSRs are hardwired to zero
if (CPU_EXTENSION_RISCV_Zicsr = true) then
csr_addr_v(11 downto 10) := csr.addr(11 downto 10);
csr_addr_v(09 downto 08) := (others => csr.addr(8)); -- !!! WARNING: MACHINE (11) and USER (00) registers ONLY !!!
csr_addr_v(07 downto 00) := csr.addr(07 downto 00);
case csr_addr_v is
 
-- floating-point CSRs --
-- --------------------------------------------------------------------
when csr_fflags_c => -- fflags (r/w): floating-point (FPU) exception flags
if (CPU_EXTENSION_RISCV_Zfinx = true) then csr.rdata(4 downto 0) <= csr.fflags; else NULL; end if;
when csr_frm_c => -- frm (r/w): floating-point (FPU) rounding mode
if (CPU_EXTENSION_RISCV_Zfinx = true) then csr.rdata(2 downto 0) <= csr.frm; else NULL; end if;
when csr_fcsr_c => -- fcsr (r/w): floating-point (FPU) control/status (frm + fflags)
if (CPU_EXTENSION_RISCV_Zfinx = true) then csr.rdata(7 downto 5) <= csr.frm; csr.rdata(4 downto 0) <= csr.fflags; else NULL; end if;
 
-- machine trap setup --
-- --------------------------------------------------------------------
when csr_mstatus_c => -- mstatus (r/w): machine status register
csr.rdata(03) <= csr.mstatus_mie; -- MIE
csr.rdata(07) <= csr.mstatus_mpie; -- MPIE
csr.rdata(11) <= csr.mstatus_mpp(0); -- MPP: machine previous privilege mode low
csr.rdata(12) <= csr.mstatus_mpp(1); -- MPP: machine previous privilege mode high
when csr_misa_c => -- misa (r/-): ISA and extensions
csr.rdata(00) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_A); -- A CPU extension
csr.rdata(01) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B); -- B CPU extension
csr.rdata(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C); -- C CPU extension
csr.rdata(04) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- E CPU extension
csr.rdata(08) <= not bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- I CPU extension (if not E)
csr.rdata(12) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_M); -- M CPU extension
csr.rdata(20) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_U); -- U CPU extension
csr.rdata(23) <= '1'; -- X CPU extension (non-std extensions)
csr.rdata(30) <= '1'; -- 32-bit architecture (MXL lo)
csr.rdata(31) <= '0'; -- 32-bit architecture (MXL hi)
when csr_mie_c => -- mie (r/w): machine interrupt-enable register
csr.rdata(03) <= csr.mie_msie; -- machine software IRQ enable
csr.rdata(07) <= csr.mie_mtie; -- machine timer IRQ enable
csr.rdata(11) <= csr.mie_meie; -- machine external IRQ enable
for i in 0 to 15 loop -- fast interrupt channels 0..15 enable
csr.rdata(16+i) <= csr.mie_firqe(i);
end loop; -- i
when csr_mtvec_c => -- mtvec (r/w): machine trap-handler base address (for ALL exceptions)
csr.rdata <= csr.mtvec(data_width_c-1 downto 2) & "00"; -- mtvec.MODE=0
when csr_mcounteren_c => -- mcounteren (r/w): machine counter enable register
if (CPU_EXTENSION_RISCV_U = false) then -- this CSR is hardwired to zero if user mode is not implemented
NULL;
else
csr.rdata(0) <= csr.mcounteren_cy; -- enable user-level access to cycle[h]
csr.rdata(1) <= csr.mcounteren_tm; -- enable user-level access to time[h]
csr.rdata(2) <= csr.mcounteren_ir; -- enable user-level access to instret[h]
end if;
 
-- machine trap handling --
-- --------------------------------------------------------------------
when csr_mscratch_c => -- mscratch (r/w): machine scratch register
csr.rdata <= csr.mscratch;
when csr_mepc_c => -- mepc (r/w): machine exception program counter
csr.rdata <= csr.mepc(data_width_c-1 downto 1) & '0';
when csr_mcause_c => -- mcause (r/w): machine trap cause
csr.rdata(31) <= csr.mcause(csr.mcause'left);
csr.rdata(csr.mcause'left-1 downto 0) <= csr.mcause(csr.mcause'left-1 downto 0);
when csr_mtval_c => -- mtval (r/-): machine bad address or instruction
csr.rdata <= csr.mtval;
when csr_mip_c => -- mip (r/w): machine interrupt pending
csr.rdata(03) <= trap_ctrl.irq_buf(interrupt_msw_irq_c);
csr.rdata(07) <= trap_ctrl.irq_buf(interrupt_mtime_irq_c);
csr.rdata(11) <= trap_ctrl.irq_buf(interrupt_mext_irq_c);
for i in 0 to 15 loop -- fast interrupt channels 0..15 pending
csr.rdata(16+i) <= trap_ctrl.irq_buf(interrupt_firq_0_c+i);
end loop; -- i
 
-- physical memory protection - configuration (r/w) --
-- --------------------------------------------------------------------
when csr_pmpcfg0_c => if (PMP_NUM_REGIONS > 00) then csr.rdata <= csr.pmpcfg_rd(03) & csr.pmpcfg_rd(02) & csr.pmpcfg_rd(01) & csr.pmpcfg_rd(00); else NULL; end if;
when csr_pmpcfg1_c => if (PMP_NUM_REGIONS > 03) then csr.rdata <= csr.pmpcfg_rd(07) & csr.pmpcfg_rd(06) & csr.pmpcfg_rd(05) & csr.pmpcfg_rd(04); else NULL; end if;
when csr_pmpcfg2_c => if (PMP_NUM_REGIONS > 07) then csr.rdata <= csr.pmpcfg_rd(11) & csr.pmpcfg_rd(10) & csr.pmpcfg_rd(09) & csr.pmpcfg_rd(08); else NULL; end if;
when csr_pmpcfg3_c => if (PMP_NUM_REGIONS > 11) then csr.rdata <= csr.pmpcfg_rd(15) & csr.pmpcfg_rd(14) & csr.pmpcfg_rd(13) & csr.pmpcfg_rd(12); else NULL; end if;
when csr_pmpcfg4_c => if (PMP_NUM_REGIONS > 15) then csr.rdata <= csr.pmpcfg_rd(19) & csr.pmpcfg_rd(18) & csr.pmpcfg_rd(17) & csr.pmpcfg_rd(16); else NULL; end if;
when csr_pmpcfg5_c => if (PMP_NUM_REGIONS > 19) then csr.rdata <= csr.pmpcfg_rd(23) & csr.pmpcfg_rd(22) & csr.pmpcfg_rd(21) & csr.pmpcfg_rd(20); else NULL; end if;
when csr_pmpcfg6_c => if (PMP_NUM_REGIONS > 23) then csr.rdata <= csr.pmpcfg_rd(27) & csr.pmpcfg_rd(26) & csr.pmpcfg_rd(25) & csr.pmpcfg_rd(24); else NULL; end if;
when csr_pmpcfg7_c => if (PMP_NUM_REGIONS > 27) then csr.rdata <= csr.pmpcfg_rd(31) & csr.pmpcfg_rd(30) & csr.pmpcfg_rd(29) & csr.pmpcfg_rd(28); else NULL; end if;
when csr_pmpcfg8_c => if (PMP_NUM_REGIONS > 31) then csr.rdata <= csr.pmpcfg_rd(35) & csr.pmpcfg_rd(34) & csr.pmpcfg_rd(33) & csr.pmpcfg_rd(32); else NULL; end if;
when csr_pmpcfg9_c => if (PMP_NUM_REGIONS > 35) then csr.rdata <= csr.pmpcfg_rd(39) & csr.pmpcfg_rd(38) & csr.pmpcfg_rd(37) & csr.pmpcfg_rd(36); else NULL; end if;
when csr_pmpcfg10_c => if (PMP_NUM_REGIONS > 39) then csr.rdata <= csr.pmpcfg_rd(43) & csr.pmpcfg_rd(42) & csr.pmpcfg_rd(41) & csr.pmpcfg_rd(40); else NULL; end if;
when csr_pmpcfg11_c => if (PMP_NUM_REGIONS > 43) then csr.rdata <= csr.pmpcfg_rd(47) & csr.pmpcfg_rd(46) & csr.pmpcfg_rd(45) & csr.pmpcfg_rd(44); else NULL; end if;
when csr_pmpcfg12_c => if (PMP_NUM_REGIONS > 47) then csr.rdata <= csr.pmpcfg_rd(51) & csr.pmpcfg_rd(50) & csr.pmpcfg_rd(49) & csr.pmpcfg_rd(48); else NULL; end if;
when csr_pmpcfg13_c => if (PMP_NUM_REGIONS > 51) then csr.rdata <= csr.pmpcfg_rd(55) & csr.pmpcfg_rd(54) & csr.pmpcfg_rd(53) & csr.pmpcfg_rd(52); else NULL; end if;
when csr_pmpcfg14_c => if (PMP_NUM_REGIONS > 55) then csr.rdata <= csr.pmpcfg_rd(59) & csr.pmpcfg_rd(58) & csr.pmpcfg_rd(57) & csr.pmpcfg_rd(56); else NULL; end if;
when csr_pmpcfg15_c => if (PMP_NUM_REGIONS > 59) then csr.rdata <= csr.pmpcfg_rd(63) & csr.pmpcfg_rd(62) & csr.pmpcfg_rd(61) & csr.pmpcfg_rd(60); else NULL; end if;
 
-- physical memory protection - addresses (r/w) --
-- --------------------------------------------------------------------
when csr_pmpaddr0_c => if (PMP_NUM_REGIONS > 00) then csr.rdata <= csr.pmpaddr(00); else NULL; end if;
when csr_pmpaddr1_c => if (PMP_NUM_REGIONS > 01) then csr.rdata <= csr.pmpaddr(01); else NULL; end if;
when csr_pmpaddr2_c => if (PMP_NUM_REGIONS > 02) then csr.rdata <= csr.pmpaddr(02); else NULL; end if;
when csr_pmpaddr3_c => if (PMP_NUM_REGIONS > 03) then csr.rdata <= csr.pmpaddr(03); else NULL; end if;
when csr_pmpaddr4_c => if (PMP_NUM_REGIONS > 04) then csr.rdata <= csr.pmpaddr(04); else NULL; end if;
when csr_pmpaddr5_c => if (PMP_NUM_REGIONS > 05) then csr.rdata <= csr.pmpaddr(05); else NULL; end if;
when csr_pmpaddr6_c => if (PMP_NUM_REGIONS > 06) then csr.rdata <= csr.pmpaddr(06); else NULL; end if;
when csr_pmpaddr7_c => if (PMP_NUM_REGIONS > 07) then csr.rdata <= csr.pmpaddr(07); else NULL; end if;
when csr_pmpaddr8_c => if (PMP_NUM_REGIONS > 08) then csr.rdata <= csr.pmpaddr(08); else NULL; end if;
when csr_pmpaddr9_c => if (PMP_NUM_REGIONS > 09) then csr.rdata <= csr.pmpaddr(09); else NULL; end if;
when csr_pmpaddr10_c => if (PMP_NUM_REGIONS > 10) then csr.rdata <= csr.pmpaddr(10); else NULL; end if;
when csr_pmpaddr11_c => if (PMP_NUM_REGIONS > 11) then csr.rdata <= csr.pmpaddr(11); else NULL; end if;
when csr_pmpaddr12_c => if (PMP_NUM_REGIONS > 12) then csr.rdata <= csr.pmpaddr(12); else NULL; end if;
when csr_pmpaddr13_c => if (PMP_NUM_REGIONS > 13) then csr.rdata <= csr.pmpaddr(13); else NULL; end if;
when csr_pmpaddr14_c => if (PMP_NUM_REGIONS > 14) then csr.rdata <= csr.pmpaddr(14); else NULL; end if;
when csr_pmpaddr15_c => if (PMP_NUM_REGIONS > 15) then csr.rdata <= csr.pmpaddr(15); else NULL; end if;
when csr_pmpaddr16_c => if (PMP_NUM_REGIONS > 16) then csr.rdata <= csr.pmpaddr(16); else NULL; end if;
when csr_pmpaddr17_c => if (PMP_NUM_REGIONS > 17) then csr.rdata <= csr.pmpaddr(17); else NULL; end if;
when csr_pmpaddr18_c => if (PMP_NUM_REGIONS > 18) then csr.rdata <= csr.pmpaddr(18); else NULL; end if;
when csr_pmpaddr19_c => if (PMP_NUM_REGIONS > 19) then csr.rdata <= csr.pmpaddr(19); else NULL; end if;
when csr_pmpaddr20_c => if (PMP_NUM_REGIONS > 20) then csr.rdata <= csr.pmpaddr(20); else NULL; end if;
when csr_pmpaddr21_c => if (PMP_NUM_REGIONS > 21) then csr.rdata <= csr.pmpaddr(21); else NULL; end if;
when csr_pmpaddr22_c => if (PMP_NUM_REGIONS > 22) then csr.rdata <= csr.pmpaddr(22); else NULL; end if;
when csr_pmpaddr23_c => if (PMP_NUM_REGIONS > 23) then csr.rdata <= csr.pmpaddr(23); else NULL; end if;
when csr_pmpaddr24_c => if (PMP_NUM_REGIONS > 24) then csr.rdata <= csr.pmpaddr(24); else NULL; end if;
when csr_pmpaddr25_c => if (PMP_NUM_REGIONS > 25) then csr.rdata <= csr.pmpaddr(25); else NULL; end if;
when csr_pmpaddr26_c => if (PMP_NUM_REGIONS > 26) then csr.rdata <= csr.pmpaddr(26); else NULL; end if;
when csr_pmpaddr27_c => if (PMP_NUM_REGIONS > 27) then csr.rdata <= csr.pmpaddr(27); else NULL; end if;
when csr_pmpaddr28_c => if (PMP_NUM_REGIONS > 28) then csr.rdata <= csr.pmpaddr(28); else NULL; end if;
when csr_pmpaddr29_c => if (PMP_NUM_REGIONS > 29) then csr.rdata <= csr.pmpaddr(29); else NULL; end if;
when csr_pmpaddr30_c => if (PMP_NUM_REGIONS > 30) then csr.rdata <= csr.pmpaddr(30); else NULL; end if;
when csr_pmpaddr31_c => if (PMP_NUM_REGIONS > 31) then csr.rdata <= csr.pmpaddr(31); else NULL; end if;
when csr_pmpaddr32_c => if (PMP_NUM_REGIONS > 32) then csr.rdata <= csr.pmpaddr(32); else NULL; end if;
when csr_pmpaddr33_c => if (PMP_NUM_REGIONS > 33) then csr.rdata <= csr.pmpaddr(33); else NULL; end if;
when csr_pmpaddr34_c => if (PMP_NUM_REGIONS > 34) then csr.rdata <= csr.pmpaddr(34); else NULL; end if;
when csr_pmpaddr35_c => if (PMP_NUM_REGIONS > 35) then csr.rdata <= csr.pmpaddr(35); else NULL; end if;
when csr_pmpaddr36_c => if (PMP_NUM_REGIONS > 36) then csr.rdata <= csr.pmpaddr(36); else NULL; end if;
when csr_pmpaddr37_c => if (PMP_NUM_REGIONS > 37) then csr.rdata <= csr.pmpaddr(37); else NULL; end if;
when csr_pmpaddr38_c => if (PMP_NUM_REGIONS > 38) then csr.rdata <= csr.pmpaddr(38); else NULL; end if;
when csr_pmpaddr39_c => if (PMP_NUM_REGIONS > 39) then csr.rdata <= csr.pmpaddr(39); else NULL; end if;
when csr_pmpaddr40_c => if (PMP_NUM_REGIONS > 40) then csr.rdata <= csr.pmpaddr(40); else NULL; end if;
when csr_pmpaddr41_c => if (PMP_NUM_REGIONS > 41) then csr.rdata <= csr.pmpaddr(41); else NULL; end if;
when csr_pmpaddr42_c => if (PMP_NUM_REGIONS > 42) then csr.rdata <= csr.pmpaddr(42); else NULL; end if;
when csr_pmpaddr43_c => if (PMP_NUM_REGIONS > 43) then csr.rdata <= csr.pmpaddr(43); else NULL; end if;
when csr_pmpaddr44_c => if (PMP_NUM_REGIONS > 44) then csr.rdata <= csr.pmpaddr(44); else NULL; end if;
when csr_pmpaddr45_c => if (PMP_NUM_REGIONS > 45) then csr.rdata <= csr.pmpaddr(45); else NULL; end if;
when csr_pmpaddr46_c => if (PMP_NUM_REGIONS > 46) then csr.rdata <= csr.pmpaddr(46); else NULL; end if;
when csr_pmpaddr47_c => if (PMP_NUM_REGIONS > 47) then csr.rdata <= csr.pmpaddr(47); else NULL; end if;
when csr_pmpaddr48_c => if (PMP_NUM_REGIONS > 48) then csr.rdata <= csr.pmpaddr(48); else NULL; end if;
when csr_pmpaddr49_c => if (PMP_NUM_REGIONS > 49) then csr.rdata <= csr.pmpaddr(49); else NULL; end if;
when csr_pmpaddr50_c => if (PMP_NUM_REGIONS > 50) then csr.rdata <= csr.pmpaddr(50); else NULL; end if;
when csr_pmpaddr51_c => if (PMP_NUM_REGIONS > 51) then csr.rdata <= csr.pmpaddr(51); else NULL; end if;
when csr_pmpaddr52_c => if (PMP_NUM_REGIONS > 52) then csr.rdata <= csr.pmpaddr(52); else NULL; end if;
when csr_pmpaddr53_c => if (PMP_NUM_REGIONS > 53) then csr.rdata <= csr.pmpaddr(53); else NULL; end if;
when csr_pmpaddr54_c => if (PMP_NUM_REGIONS > 54) then csr.rdata <= csr.pmpaddr(54); else NULL; end if;
when csr_pmpaddr55_c => if (PMP_NUM_REGIONS > 55) then csr.rdata <= csr.pmpaddr(55); else NULL; end if;
when csr_pmpaddr56_c => if (PMP_NUM_REGIONS > 56) then csr.rdata <= csr.pmpaddr(56); else NULL; end if;
when csr_pmpaddr57_c => if (PMP_NUM_REGIONS > 57) then csr.rdata <= csr.pmpaddr(57); else NULL; end if;
when csr_pmpaddr58_c => if (PMP_NUM_REGIONS > 58) then csr.rdata <= csr.pmpaddr(58); else NULL; end if;
when csr_pmpaddr59_c => if (PMP_NUM_REGIONS > 59) then csr.rdata <= csr.pmpaddr(59); else NULL; end if;
when csr_pmpaddr60_c => if (PMP_NUM_REGIONS > 60) then csr.rdata <= csr.pmpaddr(60); else NULL; end if;
when csr_pmpaddr61_c => if (PMP_NUM_REGIONS > 61) then csr.rdata <= csr.pmpaddr(61); else NULL; end if;
when csr_pmpaddr62_c => if (PMP_NUM_REGIONS > 62) then csr.rdata <= csr.pmpaddr(62); else NULL; end if;
when csr_pmpaddr63_c => if (PMP_NUM_REGIONS > 63) then csr.rdata <= csr.pmpaddr(63); else NULL; end if;
 
-- machine counter setup --
-- --------------------------------------------------------------------
when csr_mcountinhibit_c => -- mcountinhibit (r/w): machine counter-inhibit register
csr.rdata(0) <= csr.mcountinhibit_cy; -- enable auto-increment of [m]cycle[h] counter
csr.rdata(2) <= csr.mcountinhibit_ir; -- enable auto-increment of [m]instret[h] counter
if (HPM_NUM_CNTS > 0) then -- any HPMs available?
csr.rdata(csr.mcountinhibit_hpm'left+3 downto 3) <= csr.mcountinhibit_hpm; -- enable auto-increment of [m]hpmcounterx[h] counter
end if;
 
-- machine performance-monitoring event selector (r/w) --
-- --------------------------------------------------------------------
when csr_mhpmevent3_c => if (HPM_NUM_CNTS > 00) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(00); else NULL; end if;
when csr_mhpmevent4_c => if (HPM_NUM_CNTS > 01) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(01); else NULL; end if;
when csr_mhpmevent5_c => if (HPM_NUM_CNTS > 02) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(02); else NULL; end if;
when csr_mhpmevent6_c => if (HPM_NUM_CNTS > 03) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(03); else NULL; end if;
when csr_mhpmevent7_c => if (HPM_NUM_CNTS > 04) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(04); else NULL; end if;
when csr_mhpmevent8_c => if (HPM_NUM_CNTS > 05) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(05); else NULL; end if;
when csr_mhpmevent9_c => if (HPM_NUM_CNTS > 06) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(06); else NULL; end if;
when csr_mhpmevent10_c => if (HPM_NUM_CNTS > 07) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(07); else NULL; end if;
when csr_mhpmevent11_c => if (HPM_NUM_CNTS > 08) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(08); else NULL; end if;
when csr_mhpmevent12_c => if (HPM_NUM_CNTS > 09) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(09); else NULL; end if;
when csr_mhpmevent13_c => if (HPM_NUM_CNTS > 10) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(10); else NULL; end if;
when csr_mhpmevent14_c => if (HPM_NUM_CNTS > 11) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(11); else NULL; end if;
when csr_mhpmevent15_c => if (HPM_NUM_CNTS > 12) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(12); else NULL; end if;
when csr_mhpmevent16_c => if (HPM_NUM_CNTS > 13) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(13); else NULL; end if;
when csr_mhpmevent17_c => if (HPM_NUM_CNTS > 14) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(14); else NULL; end if;
when csr_mhpmevent18_c => if (HPM_NUM_CNTS > 15) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(15); else NULL; end if;
when csr_mhpmevent19_c => if (HPM_NUM_CNTS > 16) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(16); else NULL; end if;
when csr_mhpmevent20_c => if (HPM_NUM_CNTS > 17) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(17); else NULL; end if;
when csr_mhpmevent21_c => if (HPM_NUM_CNTS > 18) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(18); else NULL; end if;
when csr_mhpmevent22_c => if (HPM_NUM_CNTS > 19) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(19); else NULL; end if;
when csr_mhpmevent23_c => if (HPM_NUM_CNTS > 20) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(20); else NULL; end if;
when csr_mhpmevent24_c => if (HPM_NUM_CNTS > 21) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(21); else NULL; end if;
when csr_mhpmevent25_c => if (HPM_NUM_CNTS > 22) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(22); else NULL; end if;
when csr_mhpmevent26_c => if (HPM_NUM_CNTS > 23) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(23); else NULL; end if;
when csr_mhpmevent27_c => if (HPM_NUM_CNTS > 24) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(24); else NULL; end if;
when csr_mhpmevent28_c => if (HPM_NUM_CNTS > 25) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(25); else NULL; end if;
when csr_mhpmevent29_c => if (HPM_NUM_CNTS > 26) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(26); else NULL; end if;
when csr_mhpmevent30_c => if (HPM_NUM_CNTS > 27) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(27); else NULL; end if;
when csr_mhpmevent31_c => if (HPM_NUM_CNTS > 28) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata(hpmcnt_event_size_c-1 downto 0) <= csr.mhpmevent(28); else NULL; end if;
 
-- counters and timers --
-- --------------------------------------------------------------------
when csr_cycle_c | csr_mcycle_c => -- [m]cycle (r/w): Cycle counter LOW
if (cpu_cnt_lo_width_c > 0) and (CPU_EXTENSION_RISCV_Zicntr = true) then csr.rdata(cpu_cnt_lo_width_c-1 downto 0) <= csr.mcycle(cpu_cnt_lo_width_c-1 downto 0); else NULL; end if;
when csr_cycleh_c | csr_mcycleh_c => -- [m]cycleh (r/w): Cycle counter HIGH
if (cpu_cnt_hi_width_c > 0) and (CPU_EXTENSION_RISCV_Zicntr = true) then csr.rdata(cpu_cnt_hi_width_c-1 downto 0) <= csr.mcycleh(cpu_cnt_hi_width_c-1 downto 0); else NULL; end if;
 
when csr_instret_c | csr_minstret_c => -- [m]instret (r/w): Instructions-retired counter LOW
if (cpu_cnt_lo_width_c > 0) and (CPU_EXTENSION_RISCV_Zicntr = true) then csr.rdata(cpu_cnt_lo_width_c-1 downto 0) <= csr.minstret(cpu_cnt_lo_width_c-1 downto 0); else NULL; end if;
when csr_instreth_c | csr_minstreth_c => -- [m]instreth (r/w): Instructions-retired counter HIGH
if (cpu_cnt_hi_width_c > 0) and (CPU_EXTENSION_RISCV_Zicntr = true) then csr.rdata(cpu_cnt_hi_width_c-1 downto 0) <= csr.minstreth(cpu_cnt_hi_width_c-1 downto 0); else NULL; end if;
 
when csr_time_c => -- time (r/-): System time LOW (from MTIME unit)
if (CPU_EXTENSION_RISCV_Zicntr = true) then csr.rdata <= time_i(31 downto 00); else NULL; end if;
when csr_timeh_c => -- timeh (r/-): System time HIGH (from MTIME unit)
if (CPU_EXTENSION_RISCV_Zicntr = true) then csr.rdata <= time_i(63 downto 32); else NULL; end if;
 
-- hardware performance counters --
-- --------------------------------------------------------------------
-- low word (r/w) --
when csr_mhpmcounter3_c => if (HPM_NUM_CNTS > 00) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(00); else NULL; end if;
when csr_mhpmcounter4_c => if (HPM_NUM_CNTS > 01) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(01); else NULL; end if;
when csr_mhpmcounter5_c => if (HPM_NUM_CNTS > 02) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(02); else NULL; end if;
when csr_mhpmcounter6_c => if (HPM_NUM_CNTS > 03) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(03); else NULL; end if;
when csr_mhpmcounter7_c => if (HPM_NUM_CNTS > 04) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(04); else NULL; end if;
when csr_mhpmcounter8_c => if (HPM_NUM_CNTS > 05) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(05); else NULL; end if;
when csr_mhpmcounter9_c => if (HPM_NUM_CNTS > 06) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(06); else NULL; end if;
when csr_mhpmcounter10_c => if (HPM_NUM_CNTS > 07) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(07); else NULL; end if;
when csr_mhpmcounter11_c => if (HPM_NUM_CNTS > 08) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(08); else NULL; end if;
when csr_mhpmcounter12_c => if (HPM_NUM_CNTS > 09) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(09); else NULL; end if;
when csr_mhpmcounter13_c => if (HPM_NUM_CNTS > 10) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(10); else NULL; end if;
when csr_mhpmcounter14_c => if (HPM_NUM_CNTS > 11) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(11); else NULL; end if;
when csr_mhpmcounter15_c => if (HPM_NUM_CNTS > 12) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(12); else NULL; end if;
when csr_mhpmcounter16_c => if (HPM_NUM_CNTS > 13) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(13); else NULL; end if;
when csr_mhpmcounter17_c => if (HPM_NUM_CNTS > 14) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(14); else NULL; end if;
when csr_mhpmcounter18_c => if (HPM_NUM_CNTS > 15) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(15); else NULL; end if;
when csr_mhpmcounter19_c => if (HPM_NUM_CNTS > 16) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(16); else NULL; end if;
when csr_mhpmcounter20_c => if (HPM_NUM_CNTS > 17) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(17); else NULL; end if;
when csr_mhpmcounter21_c => if (HPM_NUM_CNTS > 18) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(18); else NULL; end if;
when csr_mhpmcounter22_c => if (HPM_NUM_CNTS > 19) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(19); else NULL; end if;
when csr_mhpmcounter23_c => if (HPM_NUM_CNTS > 20) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(20); else NULL; end if;
when csr_mhpmcounter24_c => if (HPM_NUM_CNTS > 21) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(21); else NULL; end if;
when csr_mhpmcounter25_c => if (HPM_NUM_CNTS > 22) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(22); else NULL; end if;
when csr_mhpmcounter26_c => if (HPM_NUM_CNTS > 23) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(23); else NULL; end if;
when csr_mhpmcounter27_c => if (HPM_NUM_CNTS > 24) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(24); else NULL; end if;
when csr_mhpmcounter28_c => if (HPM_NUM_CNTS > 25) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(25); else NULL; end if;
when csr_mhpmcounter29_c => if (HPM_NUM_CNTS > 26) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(26); else NULL; end if;
when csr_mhpmcounter30_c => if (HPM_NUM_CNTS > 27) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(27); else NULL; end if;
when csr_mhpmcounter31_c => if (HPM_NUM_CNTS > 28) and (CPU_EXTENSION_RISCV_Zihpm = true) then csr.rdata <= csr.mhpmcounter_rd(28); else NULL; end if;
-- high word (r/w) --
when csr_mhpmcounter3h_c => if (HPM_NUM_CNTS > 00) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(00); else NULL; end if;
when csr_mhpmcounter4h_c => if (HPM_NUM_CNTS > 01) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(01); else NULL; end if;
when csr_mhpmcounter5h_c => if (HPM_NUM_CNTS > 02) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(02); else NULL; end if;
when csr_mhpmcounter6h_c => if (HPM_NUM_CNTS > 03) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(03); else NULL; end if;
when csr_mhpmcounter7h_c => if (HPM_NUM_CNTS > 04) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(04); else NULL; end if;
when csr_mhpmcounter8h_c => if (HPM_NUM_CNTS > 05) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(05); else NULL; end if;
when csr_mhpmcounter9h_c => if (HPM_NUM_CNTS > 06) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(06); else NULL; end if;
when csr_mhpmcounter10h_c => if (HPM_NUM_CNTS > 07) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(07); else NULL; end if;
when csr_mhpmcounter11h_c => if (HPM_NUM_CNTS > 08) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(08); else NULL; end if;
when csr_mhpmcounter12h_c => if (HPM_NUM_CNTS > 09) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(09); else NULL; end if;
when csr_mhpmcounter13h_c => if (HPM_NUM_CNTS > 10) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(10); else NULL; end if;
when csr_mhpmcounter14h_c => if (HPM_NUM_CNTS > 11) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(11); else NULL; end if;
when csr_mhpmcounter15h_c => if (HPM_NUM_CNTS > 12) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(12); else NULL; end if;
when csr_mhpmcounter16h_c => if (HPM_NUM_CNTS > 13) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(13); else NULL; end if;
when csr_mhpmcounter17h_c => if (HPM_NUM_CNTS > 14) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(14); else NULL; end if;
when csr_mhpmcounter18h_c => if (HPM_NUM_CNTS > 15) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(15); else NULL; end if;
when csr_mhpmcounter19h_c => if (HPM_NUM_CNTS > 16) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(16); else NULL; end if;
when csr_mhpmcounter20h_c => if (HPM_NUM_CNTS > 17) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(17); else NULL; end if;
when csr_mhpmcounter21h_c => if (HPM_NUM_CNTS > 18) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(18); else NULL; end if;
when csr_mhpmcounter22h_c => if (HPM_NUM_CNTS > 19) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(19); else NULL; end if;
when csr_mhpmcounter23h_c => if (HPM_NUM_CNTS > 20) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(20); else NULL; end if;
when csr_mhpmcounter24h_c => if (HPM_NUM_CNTS > 21) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(21); else NULL; end if;
when csr_mhpmcounter25h_c => if (HPM_NUM_CNTS > 22) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(22); else NULL; end if;
when csr_mhpmcounter26h_c => if (HPM_NUM_CNTS > 23) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(23); else NULL; end if;
when csr_mhpmcounter27h_c => if (HPM_NUM_CNTS > 24) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(24); else NULL; end if;
when csr_mhpmcounter28h_c => if (HPM_NUM_CNTS > 25) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(25); else NULL; end if;
when csr_mhpmcounter29h_c => if (HPM_NUM_CNTS > 26) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(26); else NULL; end if;
when csr_mhpmcounter30h_c => if (HPM_NUM_CNTS > 27) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(27); else NULL; end if;
when csr_mhpmcounter31h_c => if (HPM_NUM_CNTS > 28) and (CPU_EXTENSION_RISCV_Zihpm = true) and (hpm_cnt_hi_width_c > 0) then csr.rdata <= csr.mhpmcounterh_rd(28); else NULL; end if;
 
-- machine information registers --
-- --------------------------------------------------------------------
-- when csr_mvendorid_c => NULL; -- mvendorid (r/-): vendor ID, implemented but always zero
when csr_marchid_c => csr.rdata(4 downto 0) <= "10011"; -- marchid (r/-): arch ID - official RISC-V open-source arch ID
when csr_mimpid_c => csr.rdata <= hw_version_c; -- mimpid (r/-): implementation ID -- NEORV32 hardware version
when csr_mhartid_c => csr.rdata <= std_ulogic_vector(to_unsigned(HW_THREAD_ID, 32)); -- mhartid (r/-): hardware thread ID
-- when csr_mconfigptr_c => NULL; -- mconfigptr (r/-): machine configuration pointer register, implemented but always zero
 
-- debug mode CSRs --
-- --------------------------------------------------------------------
when csr_dcsr_c => if (CPU_EXTENSION_RISCV_DEBUG = true) then csr.rdata <= csr.dcsr_rd; else NULL; end if; -- dcsr (r/w): debug mode control and status
when csr_dpc_c => if (CPU_EXTENSION_RISCV_DEBUG = true) then csr.rdata <= csr.dpc; else NULL; end if; -- dpc (r/w): debug mode program counter
when csr_dscratch0_c => if (CPU_EXTENSION_RISCV_DEBUG = true) then csr.rdata <= csr.dscratch0; else NULL; end if; -- dscratch0 (r/w): debug mode scratch register 0
 
-- trigger module CSRs --
-- --------------------------------------------------------------------
-- when csr_tselect_c => if (CPU_EXTENSION_RISCV_DEBUG = true) then csr.rdata <= (others => '0'); else NULL; end if; -- tselect (r/w): always zero = only 1 trigger available
when csr_tdata1_c => if (CPU_EXTENSION_RISCV_DEBUG = true) then csr.rdata <= csr.tdata1_rd; else NULL; end if; -- tdata1 (r/w): match control
when csr_tdata2_c => if (CPU_EXTENSION_RISCV_DEBUG = true) then csr.rdata <= csr.tdata2; else NULL; end if; -- tdata2 (r/w): address-compare
-- when csr_tdata3_c => if (CPU_EXTENSION_RISCV_DEBUG = true) then csr.rdata <= (others => '0'); else NULL; end if; -- tdata3 (r/w): implemented but always zero
when csr_tinfo_c => if (CPU_EXTENSION_RISCV_DEBUG = true) then csr.rdata <= x"00000004"; else NULL; end if; -- tinfo (r/w): address-match trigger only
-- when csr_tcontrol_c => if (CPU_EXTENSION_RISCV_DEBUG = true) then csr.rdata <= (others => '0'); else NULL; end if; -- tcontrol (r/w): implemented but always zero
-- when csr_mcontext_c => if (CPU_EXTENSION_RISCV_DEBUG = true) then csr.rdata <= (others => '0'); else NULL; end if; -- mcontext (r/w): implemented but always zero
-- when csr_scontext_c => if (CPU_EXTENSION_RISCV_DEBUG = true) then csr.rdata <= (others => '0'); else NULL; end if; -- scontext (r/w): implemented but always zero
 
-- NEORV32-specific (RISC-V "custom") read-only CSRs --
-- --------------------------------------------------------------------
-- machine extended ISA extensions information --
when csr_mxisa_c =>
-- ISA (sub-)extensions --
csr.rdata(00) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicsr); -- Zicsr: privileged architecture (!!!)
csr.rdata(01) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zifencei); -- Zifencei: instruction stream sync.
csr.rdata(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zmmul); -- Zmmul: mul/div
csr.rdata(03) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zxcfu); -- Zxcfu: custom RISC-V instructions
csr.rdata(04) <= '0'; -- reserved
csr.rdata(05) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zfinx); -- Zfinx: FPU using x registers, "F-alternative"
csr.rdata(06) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicntr) and
bool_to_ulogic_f(boolean(CPU_CNT_WIDTH /= 64)); -- Zxscnt: reduced-size CPU counters (from Zicntr)
csr.rdata(07) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicntr); -- Zicntr: base instructions, cycle and time CSRs
csr.rdata(08) <= bool_to_ulogic_f(boolean(PMP_NUM_REGIONS > 0)); -- PMP: physical memory protection (Zspmp)
csr.rdata(09) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zihpm); -- Zihpm: hardware performance monitors
csr.rdata(10) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_DEBUG); -- RISC-V debug mode
-- ISA options --
csr.rdata(30) <= bool_to_ulogic_f(FAST_MUL_EN); -- DSP-based multiplication (M extensions only)
csr.rdata(31) <= bool_to_ulogic_f(FAST_SHIFT_EN); -- parallel logic for shifts (barrel shifters)
 
-- undefined/unavailable --
-- --------------------------------------------------------------------
when others =>
NULL; -- not implemented, read as zero
 
end case;
end if;
end if;
end process csr_read_access;
 
-- CSR read data output --
csr_rdata_o <= csr.rdata;
 
 
-- ****************************************************************************************************************************
-- CPU Debug Mode (Part of the On-Chip Debugger)
-- ****************************************************************************************************************************
2893,8 → 2751,8
-- entry debug mode triggers --
debug_ctrl.trig_hw <= hw_trigger_fire and (not debug_ctrl.running); -- enter debug mode by HW trigger module request
debug_ctrl.trig_break <= trap_ctrl.break_point and (debug_ctrl.running or -- re-enter debug mode
(csr.priv_m_mode and csr.dcsr_ebreakm and (not debug_ctrl.running)) or -- enabled goto-debug-mode in machine mode on "ebreak"
(csr.priv_u_mode and csr.dcsr_ebreaku and (not debug_ctrl.running))); -- enabled goto-debug-mode in user mode on "ebreak"
(( csr.privilege) and csr.dcsr_ebreakm) or -- enabled goto-debug-mode in machine mode on "ebreak"
((not csr.privilege) and csr.dcsr_ebreaku)); -- enabled goto-debug-mode in user mode on "ebreak"
debug_ctrl.trig_halt <= debug_ctrl.ext_halt_req and (not debug_ctrl.running); -- external halt request (if not halted already)
debug_ctrl.trig_step <= csr.dcsr_step and (not debug_ctrl.running); -- single-step mode (trigger when NOT CURRENTLY in debug mode)
 
2915,7 → 2773,7
csr.dcsr_rd(04) <= '0'; -- mprven: mstatus.mprv is ignored in debug mode
csr.dcsr_rd(03) <= '0'; -- nmip: no pending non-maskable interrupt
csr.dcsr_rd(02) <= csr.dcsr_step; -- step: single-step mode
csr.dcsr_rd(01 downto 00) <= csr.dcsr_prv; -- prv: privilege mode when debug mode was entered
csr.dcsr_rd(01 downto 00) <= (others => csr.dcsr_prv); -- prv: privilege mode when debug mode was entered
 
 
-- ****************************************************************************************************************************
/rtl/core/neorv32_cpu_cp_cfu.vhd
77,9 → 77,12
 
begin
 
-- ****************************************************************************************************************************
-- This controller is required to handle the CPU/pipeline interface. Do not modify!
-- ****************************************************************************************************************************
 
-- CFU Controller -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- This controller is required to handle the CPU/pipeline interface. Do not modify!
cfu_control: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
109,18 → 112,20
 
 
-- ****************************************************************************************************************************
-- Actual CFU user logic - Add your custom logic below
-- Actual CFU user logic - ADD YOUR CUSTOM LOGIC BELOW
-- ****************************************************************************************************************************
 
-- ----------------------------------------------------------------------------------------
-- CFU Instruction Format
-- ----------------------------------------------------------------------------------------
-- The CFU only supports the R2-type RISC-V instruction format. This format consists of two source registers (rs1 and rs2),
-- a destination register (rd) and two "immediate" bit-fields (funct7 and funct3). It is up to the user to decide which
-- of these fields are actually used by the CFU logic.
--
-- The user logic of the CFU has access to the following pre-defined signals:
--
-- -------------------------------------------------------------------------------------------
 
 
-- ----------------------------------------------------------------------------------------
-- Input Operands
-- -------------------------------------------------------------------------------------------
-- ----------------------------------------------------------------------------------------
-- > rs1_i (input, 32-bit): source register 1
-- > rs2_i (input, 32-bit): source register 2
-- > control.funct3 (input, 3-bit): 3-bit function select / immediate, driven by instruction word's funct3 bit field
134,26 → 139,28
-- static already at compile time. These immediates can be used to select the actual function to be executed or they
-- can be used as immediates for certain operations (like shift amounts, addresses or offsets).
--
-- [NOTE]: rs1_i and rs2_i are directly driven by the register file (block RAM). It is recommended to buffer these signals
-- using CFU-internal registers before using them for computations as the rs1 and rs2 nets need to drive a lot of logic
-- in the CPU.
-- [NOTE] rs1_i and rs2_i are directly driven by the register file (block RAM). For complex CFU designs it is recommended
-- to buffer these signals using CFU-internal registers before using them for computations as the rs1 and rs2 nets
-- need to drive a lot of logic in the CPU. Obviously, this will increase the CFU latency by one cycle.
--
-- [NOTE]: It is not possible for the CFU and it's according instruction words to cause any kind of exception. The CPU
-- control logic only verifies the custom instructions OPCODE and checks if the CFU is implemented at all. No combination
-- of funct7 and funct3 will cause an exception.
--
-- -------------------------------------------------------------------------------------------
-- Result output
-- -------------------------------------------------------------------------------------------
-- [NOTE] It is not possible for the CFU and it's according instruction words to cause any kind of exception. The CPU
-- control logic only verifies the custom instructions OPCODE and checks if the CFU is implemented at all. No
-- combinations of funct7 and funct3 will cause an exception.
 
 
-- ----------------------------------------------------------------------------------------
-- Result Output
-- ----------------------------------------------------------------------------------------
-- > control.result (output, 32-bit): processing result
--
-- When the CFU has finished computation, the data in the control.result signal will be written to the CPU's register
-- file. The destination register is addressed by the rd bit-field in the instruction. The CFU result output is
-- registered in the CFU controller (see above) so do not worry too much about increasing the CPU's critical path. ;)
--
-- -------------------------------------------------------------------------------------------
 
 
-- ----------------------------------------------------------------------------------------
-- Control
-- -------------------------------------------------------------------------------------------
-- ----------------------------------------------------------------------------------------
-- > rstn_i (input, 1-bit): asynchronous reset, low-active
-- > clk_i (input, 1-bit): main clock, triggering on rising edge
-- > start_i (input, 1-bit): operation trigger (start processing, high for one cycle)
162,9 → 169,10
-- For pure-combinatorial instructions (without internal state) a subset of those signals is sufficient; see the minimal
-- example below. If the CFU shall also include states (like memories, registers or "buffers") the start_i signal can be
-- used to trigger a new CFU operation. As soon as all internal computations have completed, the control.done signal has
-- to be set to indicate completion. This will write the result data (control.result) to the CPU register file.
-- to be set to indicate completion. This will finish CFU operation and will write the processing result (control.result)
-- to the CPU register file.
--
-- [IMPORTANT]: The control.done *has to be set at some time*, otherwise the CPU will be halted forever.
-- [NOTE] The control.done **has to be set at some time**, otherwise the CPU will get stalled forever.
 
 
-- User Logic Example ---------------------------------------------------------------------
/rtl/core/neorv32_cpu_cp_fpu.vhd
507,7 → 507,7
min_max_select: process(fpu_operands, comp_less_ff, fu_compare, ctrl_i)
variable cond_v : std_ulogic_vector(2 downto 0);
begin
-- comparison restul - check for special cases: -0 is less than +0
-- comparison result - check for special cases: -0 is less than +0
if ((fpu_operands.rs1_class(fp_class_neg_zero_c) = '1') and (fpu_operands.rs2_class(fp_class_pos_zero_c) = '1')) then
cond_v(0) := ctrl_i(ctrl_ir_funct3_0_c);
elsif ((fpu_operands.rs1_class(fp_class_pos_zero_c) = '1') and (fpu_operands.rs2_class(fp_class_neg_zero_c) = '1')) then
516,7 → 516,7
cond_v(0) := comp_less_ff xnor ctrl_i(ctrl_ir_funct3_0_c); -- min/max select
end if;
 
-- nmumber NaN check --
-- number NaN check --
cond_v(2) := fpu_operands.rs1_class(fp_class_snan_c) or fpu_operands.rs1_class(fp_class_qnan_c);
cond_v(1) := fpu_operands.rs2_class(fp_class_snan_c) or fpu_operands.rs2_class(fp_class_qnan_c);
 
/rtl/core/neorv32_cpu_cp_muldiv.vhd
1,12 → 1,11
-- #################################################################################################
-- # << NEORV32 - CPU Co-Processor: Integer Multiplier/Divider Unit (RISC-V "M" Extension) >> #
-- # ********************************************************************************************* #
-- # Multiplier and Divider unit. Implements the RISC-V M CPU extension. #
-- # Multiplier and Divider unit. Implements the RISC-V M & Zmmul CPU extensions. #
-- # #
-- # Multiplier core (signed/unsigned) uses classical serial algorithm. Unit latency: 31+3 cycles #
-- # Divider core (unsigned) uses classical serial algorithm. Unit latency: 32+4 cycles #
-- # #
-- # Multiplier core (signed/unsigned) uses classical serial algorithm. Latency = 31+3 cycles. #
-- # Multiplications can be mapped to DSP blocks (faster!) when FAST_MUL_EN = true. #
-- # Divider core (unsigned-only) uses classical serial algorithm. latency = 32+4 cycles. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
90,7 → 89,6
signal div_opy : std_ulogic_vector(data_width_c-1 downto 0);
signal rs1_is_signed : std_ulogic;
signal rs2_is_signed : std_ulogic;
signal opy_is_zero : std_ulogic;
signal div_res_corr : std_ulogic;
signal out_en : std_ulogic;
 
125,7 → 123,6
out_en <= '0';
valid_o <= '0';
div_res_corr <= def_rst_val_c;
opy_is_zero <= def_rst_val_c;
elsif rising_edge(clk_i) then
-- defaults --
start_div <= '0';
153,16 → 150,14
end if;
 
when DIV_PREPROCESS =>
-- check relevant input signs --
if (cp_op = cp_op_div_c) then -- result sign compensation for div?
div_res_corr <= rs1_i(rs1_i'left) xor rs2_i(rs2_i'left);
elsif (cp_op = cp_op_rem_c) then -- result sign compensation for rem?
-- check relevant input signs for result sign compensation --
if (cp_op = cp_op_div_c) then -- signed div operation
div_res_corr <= (rs1_i(rs1_i'left) xor rs2_i(rs2_i'left)) and or_reduce_f(rs2_i); -- different signs AND rs2 not zero
elsif (cp_op = cp_op_rem_c) then -- signed rem operation
div_res_corr <= rs1_i(rs1_i'left);
else
div_res_corr <= '0';
end if;
-- divide by zero? --
opy_is_zero <= not or_reduce_f(rs2_i); -- set if rs2 = 0
-- abs(rs2) --
if ((rs2_i(rs2_i'left) and rs2_is_signed) = '1') then -- signed division?
div_opy <= std_ulogic_vector(0 - unsigned(rs2_i)); -- make positive
169,7 → 164,6
else
div_opy <= rs2_i;
end if;
--
state <= PROCESSING;
 
when PROCESSING =>
297,23 → 291,26
div_sub <= std_ulogic_vector(unsigned('0' & remainder(30 downto 0) & quotient(31)) - unsigned('0' & div_opy));
 
-- result sign compensation --
div_sign_comp_in <= quotient when (cp_op = cp_op_div_c) else remainder;
div_sign_comp_in <= quotient when (cp_op = cp_op_div_c) or (cp_op = cp_op_divu_c) else remainder;
div_sign_comp <= std_ulogic_vector(0 - unsigned(div_sign_comp_in));
div_res <= div_sign_comp when (div_res_corr = '1') and (opy_is_zero = '0') else div_sign_comp_in;
div_res <= div_sign_comp when (div_res_corr = '1') else div_sign_comp_in;
end generate;
 
-- no divider --
divider_core_serial_none:
if (DIVISION_EN = false) generate
remainder <= (others => '0');
quotient <= (others => '0');
div_res <= (others => '0');
remainder <= (others => '0');
quotient <= (others => '0');
div_sub <= (others => '0');
div_sign_comp_in <= (others => '0');
div_sign_comp <= (others => '0');
div_res <= (others => '0');
end generate;
 
 
-- Data Output ----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
operation_result: process(out_en, cp_op_ff, mul_product, div_res, quotient, opy_is_zero, rs1_i, remainder)
operation_result: process(out_en, cp_op_ff, mul_product, div_res, div_sign_comp_in)
begin
if (out_en = '1') then
case cp_op_ff is
321,18 → 318,10
res_o <= mul_product(31 downto 00);
when cp_op_mulh_c | cp_op_mulhsu_c | cp_op_mulhu_c =>
res_o <= mul_product(63 downto 32);
when cp_op_div_c =>
when cp_op_div_c | cp_op_rem_c =>
res_o <= div_res;
when cp_op_divu_c =>
res_o <= quotient;
when cp_op_rem_c =>
if (opy_is_zero = '0') then
res_o <= div_res;
else
res_o <= rs1_i;
end if;
when others => -- cp_op_remu_c
res_o <= remainder;
when others => -- cp_op_divu_c | cp_op_remu_c
res_o <= div_sign_comp_in;
end case;
else
res_o <= (others => '0');
/rtl/core/neorv32_cpu_decompressor.vhd
3,7 → 3,7
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
-- # Copyright (c) 2022, Stephan Nolting. All rights reserved. #
-- # #
-- # Redistribution and use in source and binary forms, with or without modification, are #
-- # permitted provided that the following conditions are met: #
40,6 → 40,9
use neorv32.neorv32_package.all;
 
entity neorv32_cpu_decompressor is
generic (
FPU_ENABLE : boolean -- floating-point instruction enabled
);
port (
-- instruction input --
ci_instr16_i : in std_ulogic_vector(15 downto 0); -- compressed instruction input
133,7 → 136,9
ci_instr32_o(instr_imm12_lsb_c + 8) <= ci_instr16_i(9);
ci_instr32_o(instr_imm12_lsb_c + 9) <= ci_instr16_i(10);
--
ci_illegal_o <= not or_reduce_f(ci_instr16_i(12 downto 2)); -- 12:2 = "00000000000" is official illegal instruction
if (ci_instr16_i(12 downto 2) = "00000000000") then -- 12:2 = "00000000000" is official illegal instruction
ci_illegal_o <= '1';
end if;
 
when "010" | "011" => -- C.LW / C.FLW
-- ----------------------------------------------------------------------------------------------------------
148,7 → 153,7
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_lw_c;
ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c) <= "01" & ci_instr16_i(ci_rs1_3_msb_c downto ci_rs1_3_lsb_c); -- x8 - x15
ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= "01" & ci_instr16_i(ci_rd_3_msb_c downto ci_rd_3_lsb_c); -- x8 - x15
if (ci_instr16_i(ci_funct3_lsb_c) = '1') then -- C.FLW
if (ci_instr16_i(ci_funct3_lsb_c) = '1') and (FPU_ENABLE = false) then -- C.FLW
ci_illegal_o <= '1';
end if;
 
165,7 → 170,7
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_sw_c;
ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c) <= "01" & ci_instr16_i(ci_rs1_3_msb_c downto ci_rs1_3_lsb_c); -- x8 - x15
ci_instr32_o(instr_rs2_msb_c downto instr_rs2_lsb_c) <= "01" & ci_instr16_i(ci_rs2_3_msb_c downto ci_rs2_3_lsb_c); -- x8 - x15
if (ci_instr16_i(ci_funct3_lsb_c) = '1') then -- C.FSW
if (ci_instr16_i(ci_funct3_lsb_c) = '1') and (FPU_ENABLE = false) then -- C.FSW
ci_illegal_o <= '1';
end if;
 
252,7 → 257,6
ci_instr32_o(instr_imm12_lsb_c + 7) <= ci_instr16_i(3);
ci_instr32_o(instr_imm12_lsb_c + 8) <= ci_instr16_i(4);
ci_instr32_o(instr_imm12_lsb_c + 9) <= ci_instr16_i(12);
 
else -- C.LUI
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_lui_c;
ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= ci_instr16_i(ci_rd_5_msb_c downto ci_rd_5_lsb_c);
284,62 → 288,61
 
when "100" => -- C.SRLI, C.SRAI, C.ANDI, C.SUB, C.XOR, C.OR, C.AND, reserved
-- ----------------------------------------------------------------------------------------------------------
ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= "01" & ci_instr16_i(ci_rs1_3_msb_c downto ci_rs1_3_lsb_c);
ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c) <= "01" & ci_instr16_i(ci_rs1_3_msb_c downto ci_rs1_3_lsb_c);
ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= "01" & ci_instr16_i(ci_rs1_3_msb_c downto ci_rs1_3_lsb_c);
if (ci_instr16_i(11 downto 10) = "11") then -- register-register operation
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alu_c;
ci_instr32_o(instr_rs2_msb_c downto instr_rs2_lsb_c) <= "01" & ci_instr16_i(ci_rs2_3_msb_c downto ci_rs2_3_lsb_c);
case ci_instr16_i(6 downto 5) is
when "00" => -- C.SUB
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_subadd_c;
ci_instr32_o(instr_funct7_msb_c downto instr_funct7_lsb_c) <= "0100000";
when "01" => -- C.XOR
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_xor_c;
ci_instr32_o(instr_funct7_msb_c downto instr_funct7_lsb_c) <= "0000000";
when "10" => -- C.OR
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_or_c;
ci_instr32_o(instr_funct7_msb_c downto instr_funct7_lsb_c) <= "0000000";
when others => -- C.AND
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_and_c;
ci_instr32_o(instr_funct7_msb_c downto instr_funct7_lsb_c) <= "0000000";
end case;
else -- register-immediate operation
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alui_c;
case ci_instr16_i(11 downto 10) is
when "00" => -- C.SRLI
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_sr_c;
ci_instr32_o(instr_funct7_msb_c downto instr_funct7_lsb_c) <= "0000000";
ci_instr32_o(instr_imm12_lsb_c + 0) <= ci_instr16_i(2);
ci_instr32_o(instr_imm12_lsb_c + 1) <= ci_instr16_i(3);
ci_instr32_o(instr_imm12_lsb_c + 2) <= ci_instr16_i(4);
ci_instr32_o(instr_imm12_lsb_c + 3) <= ci_instr16_i(5);
ci_instr32_o(instr_imm12_lsb_c + 4) <= ci_instr16_i(6);
ci_illegal_o <= ci_instr16_i(12);
when "01" => -- C.SRAI
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_sr_c;
ci_instr32_o(instr_funct7_msb_c downto instr_funct7_lsb_c) <= "0100000";
ci_instr32_o(instr_imm12_lsb_c + 0) <= ci_instr16_i(2);
ci_instr32_o(instr_imm12_lsb_c + 1) <= ci_instr16_i(3);
ci_instr32_o(instr_imm12_lsb_c + 2) <= ci_instr16_i(4);
ci_instr32_o(instr_imm12_lsb_c + 3) <= ci_instr16_i(5);
ci_instr32_o(instr_imm12_lsb_c + 4) <= ci_instr16_i(6);
ci_illegal_o <= ci_instr16_i(12);
when "10" => -- C.ANDI
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_and_c;
ci_instr32_o(instr_imm12_msb_c downto instr_imm12_lsb_c) <= (others => ci_instr16_i(12)); -- sign extend
ci_instr32_o(instr_imm12_lsb_c + 0) <= ci_instr16_i(2);
ci_instr32_o(instr_imm12_lsb_c + 1) <= ci_instr16_i(3);
ci_instr32_o(instr_imm12_lsb_c + 2) <= ci_instr16_i(4);
ci_instr32_o(instr_imm12_lsb_c + 3) <= ci_instr16_i(5);
ci_instr32_o(instr_imm12_lsb_c + 4) <= ci_instr16_i(6);
ci_instr32_o(instr_imm12_lsb_c + 5) <= ci_instr16_i(12);
when others => -- register-register operation
NULL;
end case;
end if;
if (ci_instr16_i(12 downto 10) = "111") then -- reserved / undefined
ci_illegal_o <= '1';
end if;
ci_instr32_o(instr_rs2_msb_c downto instr_rs2_lsb_c) <= "01" & ci_instr16_i(ci_rs2_3_msb_c downto ci_rs2_3_lsb_c);
case ci_instr16_i(11 downto 10) is
when "00" => -- C.SRLI
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alui_c;
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_sr_c;
ci_instr32_o(instr_funct7_msb_c downto instr_funct7_lsb_c) <= "0000000";
ci_instr32_o(instr_imm12_lsb_c + 0) <= ci_instr16_i(2);
ci_instr32_o(instr_imm12_lsb_c + 1) <= ci_instr16_i(3);
ci_instr32_o(instr_imm12_lsb_c + 2) <= ci_instr16_i(4);
ci_instr32_o(instr_imm12_lsb_c + 3) <= ci_instr16_i(5);
ci_instr32_o(instr_imm12_lsb_c + 4) <= ci_instr16_i(6);
if (ci_instr16_i(12) = '1') then
ci_illegal_o <= '1';
end if;
when "01" => -- C.SRAI
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alui_c;
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_sr_c;
ci_instr32_o(instr_funct7_msb_c downto instr_funct7_lsb_c) <= "0100000";
ci_instr32_o(instr_imm12_lsb_c + 0) <= ci_instr16_i(2);
ci_instr32_o(instr_imm12_lsb_c + 1) <= ci_instr16_i(3);
ci_instr32_o(instr_imm12_lsb_c + 2) <= ci_instr16_i(4);
ci_instr32_o(instr_imm12_lsb_c + 3) <= ci_instr16_i(5);
ci_instr32_o(instr_imm12_lsb_c + 4) <= ci_instr16_i(6);
if (ci_instr16_i(12) = '1') then
ci_illegal_o <= '1';
end if;
when "10" => -- C.ANDI
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alui_c;
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_and_c;
ci_instr32_o(instr_imm12_msb_c downto instr_imm12_lsb_c) <= (others => ci_instr16_i(12)); -- sign extend
ci_instr32_o(instr_imm12_lsb_c + 0) <= ci_instr16_i(2);
ci_instr32_o(instr_imm12_lsb_c + 1) <= ci_instr16_i(3);
ci_instr32_o(instr_imm12_lsb_c + 2) <= ci_instr16_i(4);
ci_instr32_o(instr_imm12_lsb_c + 3) <= ci_instr16_i(5);
ci_instr32_o(instr_imm12_lsb_c + 4) <= ci_instr16_i(6);
ci_instr32_o(instr_imm12_lsb_c + 5) <= ci_instr16_i(12);
when others => -- "11" = register-register operation
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alu_c;
case ci_instr16_i(6 downto 5) is
when "00" => -- C.SUB
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_subadd_c;
ci_instr32_o(instr_funct7_msb_c downto instr_funct7_lsb_c) <= "0100000";
when "01" => -- C.XOR
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_xor_c;
ci_instr32_o(instr_funct7_msb_c downto instr_funct7_lsb_c) <= "0000000";
when "10" => -- C.OR
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_or_c;
ci_instr32_o(instr_funct7_msb_c downto instr_funct7_lsb_c) <= "0000000";
when others => -- C.AND
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_and_c;
ci_instr32_o(instr_funct7_msb_c downto instr_funct7_lsb_c) <= "0000000";
end case;
end case;
 
when others => -- undefined
-- ----------------------------------------------------------------------------------------------------------
363,7 → 366,9
ci_instr32_o(instr_imm12_lsb_c + 2) <= ci_instr16_i(4);
ci_instr32_o(instr_imm12_lsb_c + 3) <= ci_instr16_i(5);
ci_instr32_o(instr_imm12_lsb_c + 4) <= ci_instr16_i(6);
ci_illegal_o <= ci_instr16_i(12);
if (ci_instr16_i(12) = '1') then
ci_illegal_o <= ci_instr16_i(12);
end if;
 
when "010" | "011" => -- C.LWSP / C.FLWSP
-- ----------------------------------------------------------------------------------------------------------
379,7 → 384,7
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_lw_c;
ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c) <= "00010"; -- stack pointer
ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= ci_instr16_i(ci_rd_5_msb_c downto ci_rd_5_lsb_c);
if (ci_instr16_i(ci_funct3_lsb_c) = '1') then -- C.FLWSP
if (ci_instr16_i(ci_funct3_lsb_c) = '1') and (FPU_ENABLE = false) then -- C.FLWSP
ci_illegal_o <= '1';
end if;
 
397,7 → 402,7
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_sw_c;
ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c) <= "00010"; -- stack pointer
ci_instr32_o(instr_rs2_msb_c downto instr_rs2_lsb_c) <= ci_instr16_i(ci_rs2_5_msb_c downto ci_rs2_5_lsb_c);
if (ci_instr16_i(ci_funct3_lsb_c) = '1') then -- C.FSWSP
if (ci_instr16_i(ci_funct3_lsb_c) = '1') and (FPU_ENABLE = false) then -- C.FSWSP
ci_illegal_o <= '1';
end if;
 
/rtl/core/neorv32_cpu_regfile.vhd
4,8 → 4,8
-- # General purpose data register file. 32 entries (= 1024 bit) for normal mode (RV32I), #
-- # 16 entries (= 512 bit) for embedded mode (RV32E) when RISC-V "E" extension is enabled. #
-- # #
-- # Register zero (r0/x0) is a "normal" physical register that has to be initialized to zero by #
-- # the early boot code. Register zero is always set to zero when written. #
-- # Register zero (x0) is a "normal" physical register that should be initialized to zero by #
-- # the early boot code. However, it is always set to zero when written. #
-- # #
-- # The register file uses synchronous read accesses and a *single* (multiplexed) address port #
-- # for writing and reading rd/rs1 and a single read-only port for rs2. Therefore, the whole #
13,7 → 13,7
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
-- # Copyright (c) 2022, Stephan Nolting. All rights reserved. #
-- # #
-- # Redistribution and use in source and binary forms, with or without modification, are #
-- # permitted provided that the following conditions are met: #
58,8 → 58,10
clk_i : in std_ulogic; -- global clock, rising edge
ctrl_i : in std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
-- data input --
alu_i : in std_ulogic_vector(data_width_c-1 downto 0); -- ALU result
mem_i : in std_ulogic_vector(data_width_c-1 downto 0); -- memory read data
alu_i : in std_ulogic_vector(data_width_c-1 downto 0); -- ALU result
csr_i : in std_ulogic_vector(data_width_c-1 downto 0); -- CSR read data
pc2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- next PC
-- data output --
rs1_o : out std_ulogic_vector(data_width_c-1 downto 0); -- operand 1
rs2_o : out std_ulogic_vector(data_width_c-1 downto 0) -- operand 2
74,62 → 76,70
signal reg_file : reg_file_t;
signal reg_file_emb : reg_file_emb_t;
signal rf_wdata : std_ulogic_vector(data_width_c-1 downto 0); -- actual write-back data
signal rd_is_r0 : std_ulogic; -- writing to r0?
signal dst_addr : std_ulogic_vector(4 downto 0); -- destination address
signal rd_is_x0 : std_ulogic; -- writing to x0?
signal opa_addr : std_ulogic_vector(4 downto 0); -- rs1/dst address
signal opb_addr : std_ulogic_vector(4 downto 0); -- rs2 address
signal rs1, rs2 : std_ulogic_vector(data_width_c-1 downto 0); -- read data
 
begin
 
-- Data Input Mux -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
input_mux: process(rd_is_r0, ctrl_i, alu_i, mem_i)
input_mux: process(rd_is_x0, ctrl_i, alu_i, mem_i, csr_i, pc2_i)
begin
if (rd_is_r0 = '1') then -- write zero if accessing x0 to "emulate" it is hardwired to zero
rf_wdata <= (others => '0');
if (rd_is_x0 = '1') then -- write zero if accessing x0 to "emulate" it is hardwired to zero
rf_wdata <= (others => '0'); -- TODO: FIXME! but how???
else
if (ctrl_i(ctrl_rf_in_mux_c) = '0') then
rf_wdata <= alu_i;
else
rf_wdata <= mem_i;
end if;
case ctrl_i(ctrl_rf_mux1_c downto ctrl_rf_mux0_c) is
when rf_mux_alu_c => rf_wdata <= alu_i; -- ALU result
when rf_mux_mem_c => rf_wdata <= mem_i; -- memory read data
when rf_mux_csr_c => rf_wdata <= csr_i; -- CSR read data
when rf_mux_npc_c => rf_wdata <= pc2_i; -- next PC (branch return/link address)
when others => rf_wdata <= alu_i;
end case;
end if;
end process input_mux;
 
-- check if we are writing to x0 --
rd_is_r0 <= (not or_reduce_f(dst_addr(4 downto 0))) when (CPU_EXTENSION_RISCV_E = false) else (not or_reduce_f(dst_addr(3 downto 0)));
 
 
-- Register File Access -------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
rf_access: process(clk_i)
begin
if rising_edge(clk_i) then -- sync read and write
if (CPU_EXTENSION_RISCV_E = false) then -- normal register file with 32 entries
reg_file_rv32i: -- normal register file with 32 registers
if (CPU_EXTENSION_RISCV_E = false) generate
rf_access: process(clk_i)
begin
if rising_edge(clk_i) then -- sync read and write
if (ctrl_i(ctrl_rf_wb_en_c) = '1') then
reg_file(to_integer(unsigned(opa_addr(4 downto 0)))) <= rf_wdata;
end if;
rs1 <= reg_file(to_integer(unsigned(opa_addr(4 downto 0))));
rs2 <= reg_file(to_integer(unsigned(opb_addr(4 downto 0))));
else -- embedded register file with 16 entries
rs1_o <= reg_file(to_integer(unsigned(opa_addr(4 downto 0))));
rs2_o <= reg_file(to_integer(unsigned(opb_addr(4 downto 0))));
end if;
end process rf_access;
 
-- writing to x0? --
rd_is_x0 <= not or_reduce_f(ctrl_i(ctrl_rf_rd_adr4_c downto ctrl_rf_rd_adr0_c));
end generate;
 
reg_file_rv32e: -- embedded register file with 16 registers
if (CPU_EXTENSION_RISCV_E = true) generate
rf_access: process(clk_i)
begin
if rising_edge(clk_i) then -- sync read and write
if (ctrl_i(ctrl_rf_wb_en_c) = '1') then
reg_file_emb(to_integer(unsigned(opa_addr(3 downto 0)))) <= rf_wdata;
end if;
rs1 <= reg_file_emb(to_integer(unsigned(opa_addr(3 downto 0))));
rs2 <= reg_file_emb(to_integer(unsigned(opb_addr(3 downto 0))));
rs1_o <= reg_file_emb(to_integer(unsigned(opa_addr(3 downto 0))));
rs2_o <= reg_file_emb(to_integer(unsigned(opb_addr(3 downto 0))));
end if;
end if;
end process rf_access;
end process rf_access;
 
-- writing to x0? --
rd_is_x0 <= not or_reduce_f(ctrl_i(ctrl_rf_rd_adr3_c downto ctrl_rf_rd_adr0_c));
end generate;
 
-- access addresses --
dst_addr <= ctrl_i(ctrl_rf_rd_adr4_c downto ctrl_rf_rd_adr0_c);
opa_addr <= dst_addr when (ctrl_i(ctrl_rf_wb_en_c) = '1') else ctrl_i(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c); -- rd/rs1
opa_addr <= ctrl_i(ctrl_rf_rd_adr4_c downto ctrl_rf_rd_adr0_c) when (ctrl_i(ctrl_rf_wb_en_c) = '1') else
ctrl_i(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c); -- rd/rs1
opb_addr <= ctrl_i(ctrl_rf_rs2_adr4_c downto ctrl_rf_rs2_adr0_c); -- rs2
 
-- data output --
rs1_o <= rs1;
rs2_o <= rs2;
 
 
end neorv32_cpu_regfile_rtl;
/rtl/core/neorv32_debug_dm.vhd
681,7 → 681,7
-- Data buffer --
if (dci.data_we = '1') then -- DM write access
data_buf <= dci.wdata;
elsif (acc_en = '1') and (maddr = "10") and (wren = '1') then -- BUS write access
elsif (maddr = "10") and (wren = '1') then -- BUS write access
data_buf <= cpu_data_i;
end if;
-- Control and Status Register --
689,7 → 689,7
dci.resume_ack <= '0';
dci.execute_ack <= '0';
dci.exception_ack <= '0';
if (acc_en = '1') and (maddr = "11") and (wren = '1') then
if (maddr = "11") and (wren = '1') then
dci.halt_ack <= cpu_data_i(sreg_halt_ack_c);
dci.resume_ack <= cpu_data_i(sreg_resume_ack_c);
dci.execute_ack <= cpu_data_i(sreg_execute_ack_c);
/rtl/core/neorv32_icache.vhd
53,6 → 53,7
clk_i : in std_ulogic; -- global clock, rising edge
rstn_i : in std_ulogic; -- global reset, low-active, async
clear_i : in std_ulogic; -- cache clear
miss_o : out std_ulogic; -- cache miss
-- host controller interface --
host_addr_i : in std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
host_rdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
285,7 → 286,10
end case;
end process ctrl_engine_fsm_comb;
 
-- signal cache miss to CPU --
miss_o <= '1' when (ctrl.state = S_CACHE_MISS) else '0';
 
 
-- Cache Memory ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_icache_memory_inst: neorv32_icache_memory
/rtl/core/neorv32_package.vhd
44,7 → 44,7
constant ispace_base_c : std_ulogic_vector(31 downto 0) := x"00000000"; -- default instruction memory address space base address
constant dspace_base_c : std_ulogic_vector(31 downto 0) := x"80000000"; -- default data memory address space base address
 
-- use dedicated hardware reset value for UNCRITICAL registers --
-- use dedicated hardware reset value for UNCRITICAL CPU registers --
-- FALSE=reset value is irrelevant (might simplify HW), default; TRUE=defined LOW reset value
constant dedicated_reset_c : boolean := false;
 
65,7 → 65,7
-- Architecture Constants (do not modify!) ------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant data_width_c : natural := 32; -- native data path width - do not change!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01060800"; -- no touchy!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01060900"; -- no touchy!
constant archid_c : natural := 19; -- official NEORV32 architecture ID - hands off!
 
-- Check if we're inside the Matrix -------------------------------------------------------
89,8 → 89,8
 
-- Internal Interface Types ---------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
type pmp_ctrl_if_t is array (0 to 63) of std_ulogic_vector(07 downto 0);
type pmp_addr_if_t is array (0 to 63) of std_ulogic_vector(33 downto 0);
type pmp_ctrl_if_t is array (0 to 15) of std_ulogic_vector(07 downto 0);
type pmp_addr_if_t is array (0 to 15) of std_ulogic_vector(33 downto 2); -- bits 33:2 of phys. address
 
-- Internal Memory Types Configuration Types ----------------------------------------------
-- -------------------------------------------------------------------------------------------
322,7 → 322,7
-- Main CPU Control Bus -------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- register file --
constant ctrl_rf_in_mux_c : natural := 0; -- input source select lsb (0=MEM, 1=ALU)
constant ctrl_rf_wb_en_c : natural := 0; -- write back enable
constant ctrl_rf_rs1_adr0_c : natural := 1; -- source register 1 address bit 0
constant ctrl_rf_rs1_adr1_c : natural := 2; -- source register 1 address bit 1
constant ctrl_rf_rs1_adr2_c : natural := 3; -- source register 1 address bit 2
338,72 → 338,75
constant ctrl_rf_rd_adr2_c : natural := 13; -- destination register address bit 2
constant ctrl_rf_rd_adr3_c : natural := 14; -- destination register address bit 3
constant ctrl_rf_rd_adr4_c : natural := 15; -- destination register address bit 4
constant ctrl_rf_wb_en_c : natural := 16; -- write back enable
constant ctrl_rf_mux0_c : natural := 16; -- input source select lsb
constant ctrl_rf_mux1_c : natural := 17; -- input source select msb
-- alu --
constant ctrl_alu_op0_c : natural := 17; -- ALU operation select bit 0
constant ctrl_alu_op1_c : natural := 18; -- ALU operation select bit 1
constant ctrl_alu_op2_c : natural := 19; -- ALU operation select bit 2
constant ctrl_alu_func0_c : natural := 20; -- ALU function select command bit 0
constant ctrl_alu_func1_c : natural := 21; -- ALU function select command bit 1
constant ctrl_alu_opa_mux_c : natural := 22; -- operand A select (0=rs1, 1=PC)
constant ctrl_alu_opb_mux_c : natural := 23; -- operand B select (0=rs2, 1=IMM)
constant ctrl_alu_unsigned_c : natural := 24; -- is unsigned ALU operation
constant ctrl_alu_shift_dir_c : natural := 25; -- shift direction (0=left, 1=right)
constant ctrl_alu_shift_ar_c : natural := 26; -- is arithmetic shift
constant ctrl_alu_frm0_c : natural := 27; -- FPU rounding mode bit 0
constant ctrl_alu_frm1_c : natural := 28; -- FPU rounding mode bit 1
constant ctrl_alu_frm2_c : natural := 29; -- FPU rounding mode bit 2
constant ctrl_alu_op0_c : natural := 18; -- ALU operation select bit 0
constant ctrl_alu_op1_c : natural := 19; -- ALU operation select bit 1
constant ctrl_alu_op2_c : natural := 20; -- ALU operation select bit 2
constant ctrl_alu_opa_mux_c : natural := 21; -- operand A select (0=rs1, 1=PC)
constant ctrl_alu_opb_mux_c : natural := 22; -- operand B select (0=rs2, 1=IMM)
constant ctrl_alu_unsigned_c : natural := 23; -- is unsigned ALU operation
constant ctrl_alu_shift_dir_c : natural := 24; -- shift direction (0=left, 1=right)
constant ctrl_alu_shift_ar_c : natural := 25; -- is arithmetic shift
constant ctrl_alu_frm0_c : natural := 26; -- FPU rounding mode bit 0
constant ctrl_alu_frm1_c : natural := 27; -- FPU rounding mode bit 1
constant ctrl_alu_frm2_c : natural := 28; -- FPU rounding mode bit 2
-- bus interface --
constant ctrl_bus_size_lsb_c : natural := 30; -- transfer size lsb (00=byte, 01=half-word)
constant ctrl_bus_size_msb_c : natural := 31; -- transfer size msb (10=word, 11=?)
constant ctrl_bus_rd_c : natural := 32; -- read data request
constant ctrl_bus_wr_c : natural := 33; -- write data request
constant ctrl_bus_if_c : natural := 34; -- instruction fetch request
constant ctrl_bus_mo_we_c : natural := 35; -- memory address and data output register write enable
constant ctrl_bus_mi_we_c : natural := 36; -- memory data input register write enable
constant ctrl_bus_unsigned_c : natural := 37; -- is unsigned load
constant ctrl_bus_ierr_ack_c : natural := 38; -- acknowledge instruction fetch bus exceptions
constant ctrl_bus_derr_ack_c : natural := 39; -- acknowledge data access bus exceptions
constant ctrl_bus_fence_c : natural := 40; -- executed fence operation
constant ctrl_bus_fencei_c : natural := 41; -- executed fencei operation
constant ctrl_bus_lock_c : natural := 42; -- make atomic/exclusive access lock
constant ctrl_bus_de_lock_c : natural := 43; -- remove atomic/exclusive access
constant ctrl_bus_ch_lock_c : natural := 44; -- evaluate atomic/exclusive lock (SC operation)
-- co-processors --
constant ctrl_cp_id_lsb_c : natural := 45; -- cp select ID lsb
constant ctrl_cp_id_hsb_c : natural := 46; -- cp select ID "half" significant bit
constant ctrl_cp_id_msb_c : natural := 47; -- cp select ID msb
-- instruction's control blocks (used by cpu co-processors) --
constant ctrl_ir_funct3_0_c : natural := 48; -- funct3 bit 0
constant ctrl_ir_funct3_1_c : natural := 49; -- funct3 bit 1
constant ctrl_ir_funct3_2_c : natural := 50; -- funct3 bit 2
constant ctrl_ir_funct12_0_c : natural := 51; -- funct12 bit 0
constant ctrl_ir_funct12_1_c : natural := 52; -- funct12 bit 1
constant ctrl_ir_funct12_2_c : natural := 53; -- funct12 bit 2
constant ctrl_ir_funct12_3_c : natural := 54; -- funct12 bit 3
constant ctrl_ir_funct12_4_c : natural := 55; -- funct12 bit 4
constant ctrl_ir_funct12_5_c : natural := 56; -- funct12 bit 5
constant ctrl_ir_funct12_6_c : natural := 57; -- funct12 bit 6
constant ctrl_ir_funct12_7_c : natural := 58; -- funct12 bit 7
constant ctrl_ir_funct12_8_c : natural := 59; -- funct12 bit 8
constant ctrl_ir_funct12_9_c : natural := 60; -- funct12 bit 9
constant ctrl_ir_funct12_10_c : natural := 61; -- funct12 bit 10
constant ctrl_ir_funct12_11_c : natural := 62; -- funct12 bit 11
constant ctrl_ir_opcode7_0_c : natural := 63; -- opcode7 bit 0
constant ctrl_ir_opcode7_1_c : natural := 64; -- opcode7 bit 1
constant ctrl_ir_opcode7_2_c : natural := 65; -- opcode7 bit 2
constant ctrl_ir_opcode7_3_c : natural := 66; -- opcode7 bit 3
constant ctrl_ir_opcode7_4_c : natural := 67; -- opcode7 bit 4
constant ctrl_ir_opcode7_5_c : natural := 68; -- opcode7 bit 5
constant ctrl_ir_opcode7_6_c : natural := 69; -- opcode7 bit 6
-- CPU status --
constant ctrl_priv_lvl_lsb_c : natural := 70; -- privilege level lsb
constant ctrl_priv_lvl_msb_c : natural := 71; -- privilege level msb
constant ctrl_sleep_c : natural := 72; -- set when CPU is in sleep mode
constant ctrl_trap_c : natural := 73; -- set when CPU is entering trap execution
constant ctrl_debug_running_c : natural := 74; -- CPU is in debug mode when set
constant ctrl_bus_size_lsb_c : natural := 29; -- transfer size lsb (00=byte, 01=half-word)
constant ctrl_bus_size_msb_c : natural := 30; -- transfer size msb (10=word, 11=?)
constant ctrl_bus_rd_c : natural := 31; -- read data request
constant ctrl_bus_wr_c : natural := 32; -- write data request
constant ctrl_bus_if_c : natural := 33; -- instruction fetch request
constant ctrl_bus_mo_we_c : natural := 34; -- memory address and data output register write enable
constant ctrl_bus_mi_we_c : natural := 35; -- memory data input register write enable
constant ctrl_bus_unsigned_c : natural := 36; -- is unsigned load
constant ctrl_bus_fence_c : natural := 37; -- executed fence operation
constant ctrl_bus_fencei_c : natural := 38; -- executed fencei operation
constant ctrl_bus_lock_c : natural := 39; -- make atomic/exclusive access lock
constant ctrl_bus_de_lock_c : natural := 40; -- remove atomic/exclusive access
constant ctrl_bus_ch_lock_c : natural := 41; -- evaluate atomic/exclusive lock (SC operation)
-- alu co-processors --
constant ctrl_cp_id_lsb_c : natural := 42; -- cp select ID lsb [ALIAS]
constant ctrl_cp_trig0_c : natural := 42; -- trigger CP0
constant ctrl_cp_trig1_c : natural := 43; -- trigger CP1
constant ctrl_cp_trig2_c : natural := 44; -- trigger CP2
constant ctrl_cp_trig3_c : natural := 45; -- trigger CP3
constant ctrl_cp_trig4_c : natural := 46; -- trigger CP4
constant ctrl_cp_trig5_c : natural := 47; -- trigger CP5
constant ctrl_cp_trig6_c : natural := 48; -- trigger CP6
constant ctrl_cp_trig7_c : natural := 49; -- trigger CP7
constant ctrl_cp_id_msb_c : natural := 49; -- cp select ID msb [ALIAS]
-- instruction word control blocks (used by cpu co-processors) --
constant ctrl_ir_funct3_0_c : natural := 50; -- funct3 bit 0
constant ctrl_ir_funct3_1_c : natural := 51; -- funct3 bit 1
constant ctrl_ir_funct3_2_c : natural := 52; -- funct3 bit 2
constant ctrl_ir_funct12_0_c : natural := 53; -- funct12 bit 0
constant ctrl_ir_funct12_1_c : natural := 54; -- funct12 bit 1
constant ctrl_ir_funct12_2_c : natural := 55; -- funct12 bit 2
constant ctrl_ir_funct12_3_c : natural := 56; -- funct12 bit 3
constant ctrl_ir_funct12_4_c : natural := 57; -- funct12 bit 4
constant ctrl_ir_funct12_5_c : natural := 58; -- funct12 bit 5
constant ctrl_ir_funct12_6_c : natural := 59; -- funct12 bit 6
constant ctrl_ir_funct12_7_c : natural := 60; -- funct12 bit 7
constant ctrl_ir_funct12_8_c : natural := 61; -- funct12 bit 8
constant ctrl_ir_funct12_9_c : natural := 62; -- funct12 bit 9
constant ctrl_ir_funct12_10_c : natural := 63; -- funct12 bit 10
constant ctrl_ir_funct12_11_c : natural := 64; -- funct12 bit 11
constant ctrl_ir_opcode7_0_c : natural := 65; -- opcode7 bit 0
constant ctrl_ir_opcode7_1_c : natural := 66; -- opcode7 bit 1
constant ctrl_ir_opcode7_2_c : natural := 67; -- opcode7 bit 2
constant ctrl_ir_opcode7_3_c : natural := 68; -- opcode7 bit 3
constant ctrl_ir_opcode7_4_c : natural := 69; -- opcode7 bit 4
constant ctrl_ir_opcode7_5_c : natural := 70; -- opcode7 bit 5
constant ctrl_ir_opcode7_6_c : natural := 71; -- opcode7 bit 6
-- cpu status --
constant ctrl_priv_mode_c : natural := 72; -- effective privilege mode
constant ctrl_sleep_c : natural := 73; -- set when CPU is in sleep mode
constant ctrl_trap_c : natural := 74; -- set when CPU is entering trap execution
constant ctrl_debug_running_c : natural := 75; -- set when CPU is in debug mode
-- control bus size --
constant ctrl_width_c : natural := 75; -- control bus size
constant ctrl_width_c : natural := 76; -- control bus size
 
-- Comparator Bus -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
496,7 → 499,7
constant funct3_csrrsi_c : std_ulogic_vector(2 downto 0) := "110"; -- csr read & set bit immediate
constant funct3_csrrci_c : std_ulogic_vector(2 downto 0) := "111"; -- csr read & clear bit immediate
-- fence --
constant funct3_fence_c : std_ulogic_vector(2 downto 0) := "000"; -- fence - order IO/memory access (->NOP)
constant funct3_fence_c : std_ulogic_vector(2 downto 0) := "000"; -- fence - order IO/memory access
constant funct3_fencei_c : std_ulogic_vector(2 downto 0) := "001"; -- fencei - instruction stream sync
 
-- RISC-V Funct12 -------------------------------------------------------------------------
610,24 → 613,13
constant csr_mtval_c : std_ulogic_vector(11 downto 0) := x"343";
constant csr_mip_c : std_ulogic_vector(11 downto 0) := x"344";
-- physical memory protection - configuration --
constant csr_class_pmpcfg_c : std_ulogic_vector(07 downto 0) := x"3a"; -- pmp configuration
constant csr_class_pmpcfg_c : std_ulogic_vector(09 downto 0) := x"3a" & "00"; -- pmp configuration
constant csr_pmpcfg0_c : std_ulogic_vector(11 downto 0) := x"3a0";
constant csr_pmpcfg1_c : std_ulogic_vector(11 downto 0) := x"3a1";
constant csr_pmpcfg2_c : std_ulogic_vector(11 downto 0) := x"3a2";
constant csr_pmpcfg3_c : std_ulogic_vector(11 downto 0) := x"3a3";
constant csr_pmpcfg4_c : std_ulogic_vector(11 downto 0) := x"3a4";
constant csr_pmpcfg5_c : std_ulogic_vector(11 downto 0) := x"3a5";
constant csr_pmpcfg6_c : std_ulogic_vector(11 downto 0) := x"3a6";
constant csr_pmpcfg7_c : std_ulogic_vector(11 downto 0) := x"3a7";
constant csr_pmpcfg8_c : std_ulogic_vector(11 downto 0) := x"3a8";
constant csr_pmpcfg9_c : std_ulogic_vector(11 downto 0) := x"3a9";
constant csr_pmpcfg10_c : std_ulogic_vector(11 downto 0) := x"3aa";
constant csr_pmpcfg11_c : std_ulogic_vector(11 downto 0) := x"3ab";
constant csr_pmpcfg12_c : std_ulogic_vector(11 downto 0) := x"3ac";
constant csr_pmpcfg13_c : std_ulogic_vector(11 downto 0) := x"3ad";
constant csr_pmpcfg14_c : std_ulogic_vector(11 downto 0) := x"3ae";
constant csr_pmpcfg15_c : std_ulogic_vector(11 downto 0) := x"3af";
-- physical memory protection - address --
constant csr_class_pmpaddr_c : std_ulogic_vector(07 downto 0) := x"3b"; -- pmp address
constant csr_pmpaddr0_c : std_ulogic_vector(11 downto 0) := x"3b0";
constant csr_pmpaddr1_c : std_ulogic_vector(11 downto 0) := x"3b1";
constant csr_pmpaddr2_c : std_ulogic_vector(11 downto 0) := x"3b2";
644,54 → 636,6
constant csr_pmpaddr13_c : std_ulogic_vector(11 downto 0) := x"3bd";
constant csr_pmpaddr14_c : std_ulogic_vector(11 downto 0) := x"3be";
constant csr_pmpaddr15_c : std_ulogic_vector(11 downto 0) := x"3bf";
constant csr_pmpaddr16_c : std_ulogic_vector(11 downto 0) := x"3c0";
constant csr_pmpaddr17_c : std_ulogic_vector(11 downto 0) := x"3c1";
constant csr_pmpaddr18_c : std_ulogic_vector(11 downto 0) := x"3c2";
constant csr_pmpaddr19_c : std_ulogic_vector(11 downto 0) := x"3c3";
constant csr_pmpaddr20_c : std_ulogic_vector(11 downto 0) := x"3c4";
constant csr_pmpaddr21_c : std_ulogic_vector(11 downto 0) := x"3c5";
constant csr_pmpaddr22_c : std_ulogic_vector(11 downto 0) := x"3c6";
constant csr_pmpaddr23_c : std_ulogic_vector(11 downto 0) := x"3c7";
constant csr_pmpaddr24_c : std_ulogic_vector(11 downto 0) := x"3c8";
constant csr_pmpaddr25_c : std_ulogic_vector(11 downto 0) := x"3c9";
constant csr_pmpaddr26_c : std_ulogic_vector(11 downto 0) := x"3ca";
constant csr_pmpaddr27_c : std_ulogic_vector(11 downto 0) := x"3cb";
constant csr_pmpaddr28_c : std_ulogic_vector(11 downto 0) := x"3cc";
constant csr_pmpaddr29_c : std_ulogic_vector(11 downto 0) := x"3cd";
constant csr_pmpaddr30_c : std_ulogic_vector(11 downto 0) := x"3ce";
constant csr_pmpaddr31_c : std_ulogic_vector(11 downto 0) := x"3cf";
constant csr_pmpaddr32_c : std_ulogic_vector(11 downto 0) := x"3d0";
constant csr_pmpaddr33_c : std_ulogic_vector(11 downto 0) := x"3d1";
constant csr_pmpaddr34_c : std_ulogic_vector(11 downto 0) := x"3d2";
constant csr_pmpaddr35_c : std_ulogic_vector(11 downto 0) := x"3d3";
constant csr_pmpaddr36_c : std_ulogic_vector(11 downto 0) := x"3d4";
constant csr_pmpaddr37_c : std_ulogic_vector(11 downto 0) := x"3d5";
constant csr_pmpaddr38_c : std_ulogic_vector(11 downto 0) := x"3d6";
constant csr_pmpaddr39_c : std_ulogic_vector(11 downto 0) := x"3d7";
constant csr_pmpaddr40_c : std_ulogic_vector(11 downto 0) := x"3d8";
constant csr_pmpaddr41_c : std_ulogic_vector(11 downto 0) := x"3d9";
constant csr_pmpaddr42_c : std_ulogic_vector(11 downto 0) := x"3da";
constant csr_pmpaddr43_c : std_ulogic_vector(11 downto 0) := x"3db";
constant csr_pmpaddr44_c : std_ulogic_vector(11 downto 0) := x"3dc";
constant csr_pmpaddr45_c : std_ulogic_vector(11 downto 0) := x"3dd";
constant csr_pmpaddr46_c : std_ulogic_vector(11 downto 0) := x"3de";
constant csr_pmpaddr47_c : std_ulogic_vector(11 downto 0) := x"3df";
constant csr_pmpaddr48_c : std_ulogic_vector(11 downto 0) := x"3e0";
constant csr_pmpaddr49_c : std_ulogic_vector(11 downto 0) := x"3e1";
constant csr_pmpaddr50_c : std_ulogic_vector(11 downto 0) := x"3e2";
constant csr_pmpaddr51_c : std_ulogic_vector(11 downto 0) := x"3e3";
constant csr_pmpaddr52_c : std_ulogic_vector(11 downto 0) := x"3e4";
constant csr_pmpaddr53_c : std_ulogic_vector(11 downto 0) := x"3e5";
constant csr_pmpaddr54_c : std_ulogic_vector(11 downto 0) := x"3e6";
constant csr_pmpaddr55_c : std_ulogic_vector(11 downto 0) := x"3e7";
constant csr_pmpaddr56_c : std_ulogic_vector(11 downto 0) := x"3e8";
constant csr_pmpaddr57_c : std_ulogic_vector(11 downto 0) := x"3e9";
constant csr_pmpaddr58_c : std_ulogic_vector(11 downto 0) := x"3ea";
constant csr_pmpaddr59_c : std_ulogic_vector(11 downto 0) := x"3eb";
constant csr_pmpaddr60_c : std_ulogic_vector(11 downto 0) := x"3ec";
constant csr_pmpaddr61_c : std_ulogic_vector(11 downto 0) := x"3ed";
constant csr_pmpaddr62_c : std_ulogic_vector(11 downto 0) := x"3ee";
constant csr_pmpaddr63_c : std_ulogic_vector(11 downto 0) := x"3ef";
-- trigger module registers --
constant csr_class_trigger_c : std_ulogic_vector(07 downto 0) := x"7a"; -- trigger registers
constant csr_tselect_c : std_ulogic_vector(11 downto 0) := x"7a0";
779,9 → 723,70
constant csr_cycle_c : std_ulogic_vector(11 downto 0) := x"c00";
constant csr_time_c : std_ulogic_vector(11 downto 0) := x"c01";
constant csr_instret_c : std_ulogic_vector(11 downto 0) := x"c02";
--
constant csr_hpmcounter3_c : std_ulogic_vector(11 downto 0) := x"c03";
constant csr_hpmcounter4_c : std_ulogic_vector(11 downto 0) := x"c04";
constant csr_hpmcounter5_c : std_ulogic_vector(11 downto 0) := x"c05";
constant csr_hpmcounter6_c : std_ulogic_vector(11 downto 0) := x"c06";
constant csr_hpmcounter7_c : std_ulogic_vector(11 downto 0) := x"c07";
constant csr_hpmcounter8_c : std_ulogic_vector(11 downto 0) := x"c08";
constant csr_hpmcounter9_c : std_ulogic_vector(11 downto 0) := x"c09";
constant csr_hpmcounter10_c : std_ulogic_vector(11 downto 0) := x"c0a";
constant csr_hpmcounter11_c : std_ulogic_vector(11 downto 0) := x"c0b";
constant csr_hpmcounter12_c : std_ulogic_vector(11 downto 0) := x"c0c";
constant csr_hpmcounter13_c : std_ulogic_vector(11 downto 0) := x"c0d";
constant csr_hpmcounter14_c : std_ulogic_vector(11 downto 0) := x"c0e";
constant csr_hpmcounter15_c : std_ulogic_vector(11 downto 0) := x"c0f";
constant csr_hpmcounter16_c : std_ulogic_vector(11 downto 0) := x"c10";
constant csr_hpmcounter17_c : std_ulogic_vector(11 downto 0) := x"c11";
constant csr_hpmcounter18_c : std_ulogic_vector(11 downto 0) := x"c12";
constant csr_hpmcounter19_c : std_ulogic_vector(11 downto 0) := x"c13";
constant csr_hpmcounter20_c : std_ulogic_vector(11 downto 0) := x"c14";
constant csr_hpmcounter21_c : std_ulogic_vector(11 downto 0) := x"c15";
constant csr_hpmcounter22_c : std_ulogic_vector(11 downto 0) := x"c16";
constant csr_hpmcounter23_c : std_ulogic_vector(11 downto 0) := x"c17";
constant csr_hpmcounter24_c : std_ulogic_vector(11 downto 0) := x"c18";
constant csr_hpmcounter25_c : std_ulogic_vector(11 downto 0) := x"c19";
constant csr_hpmcounter26_c : std_ulogic_vector(11 downto 0) := x"c1a";
constant csr_hpmcounter27_c : std_ulogic_vector(11 downto 0) := x"c1b";
constant csr_hpmcounter28_c : std_ulogic_vector(11 downto 0) := x"c1c";
constant csr_hpmcounter29_c : std_ulogic_vector(11 downto 0) := x"c1d";
constant csr_hpmcounter30_c : std_ulogic_vector(11 downto 0) := x"c1e";
constant csr_hpmcounter31_c : std_ulogic_vector(11 downto 0) := x"c1f";
--
constant csr_cycleh_c : std_ulogic_vector(11 downto 0) := x"c80";
constant csr_timeh_c : std_ulogic_vector(11 downto 0) := x"c81";
constant csr_instreth_c : std_ulogic_vector(11 downto 0) := x"c82";
--
constant csr_hpmcounter3h_c : std_ulogic_vector(11 downto 0) := x"c83";
constant csr_hpmcounter4h_c : std_ulogic_vector(11 downto 0) := x"c84";
constant csr_hpmcounter5h_c : std_ulogic_vector(11 downto 0) := x"c85";
constant csr_hpmcounter6h_c : std_ulogic_vector(11 downto 0) := x"c86";
constant csr_hpmcounter7h_c : std_ulogic_vector(11 downto 0) := x"c87";
constant csr_hpmcounter8h_c : std_ulogic_vector(11 downto 0) := x"c88";
constant csr_hpmcounter9h_c : std_ulogic_vector(11 downto 0) := x"c89";
constant csr_hpmcounter10h_c : std_ulogic_vector(11 downto 0) := x"c8a";
constant csr_hpmcounter11h_c : std_ulogic_vector(11 downto 0) := x"c8b";
constant csr_hpmcounter12h_c : std_ulogic_vector(11 downto 0) := x"c8c";
constant csr_hpmcounter13h_c : std_ulogic_vector(11 downto 0) := x"c8d";
constant csr_hpmcounter14h_c : std_ulogic_vector(11 downto 0) := x"c8e";
constant csr_hpmcounter15h_c : std_ulogic_vector(11 downto 0) := x"c8f";
constant csr_hpmcounter16h_c : std_ulogic_vector(11 downto 0) := x"c90";
constant csr_hpmcounter17h_c : std_ulogic_vector(11 downto 0) := x"c91";
constant csr_hpmcounter18h_c : std_ulogic_vector(11 downto 0) := x"c92";
constant csr_hpmcounter19h_c : std_ulogic_vector(11 downto 0) := x"c93";
constant csr_hpmcounter20h_c : std_ulogic_vector(11 downto 0) := x"c94";
constant csr_hpmcounter21h_c : std_ulogic_vector(11 downto 0) := x"c95";
constant csr_hpmcounter22h_c : std_ulogic_vector(11 downto 0) := x"c96";
constant csr_hpmcounter23h_c : std_ulogic_vector(11 downto 0) := x"c97";
constant csr_hpmcounter24h_c : std_ulogic_vector(11 downto 0) := x"c98";
constant csr_hpmcounter25h_c : std_ulogic_vector(11 downto 0) := x"c99";
constant csr_hpmcounter26h_c : std_ulogic_vector(11 downto 0) := x"c9a";
constant csr_hpmcounter27h_c : std_ulogic_vector(11 downto 0) := x"c9b";
constant csr_hpmcounter28h_c : std_ulogic_vector(11 downto 0) := x"c9c";
constant csr_hpmcounter29h_c : std_ulogic_vector(11 downto 0) := x"c9d";
constant csr_hpmcounter30h_c : std_ulogic_vector(11 downto 0) := x"c9e";
constant csr_hpmcounter31h_c : std_ulogic_vector(11 downto 0) := x"c9f";
-- machine information registers --
constant csr_mvendorid_c : std_ulogic_vector(11 downto 0) := x"f11";
constant csr_marchid_c : std_ulogic_vector(11 downto 0) := x"f12";
790,37 → 795,38
constant csr_mconfigptr_c : std_ulogic_vector(11 downto 0) := x"f15";
 
-- <<< NEORV32-specific (custom) read-only CSRs >>> ---
-- machine extended ISA extensionss information --
-- machine extended ISA extensions information --
constant csr_mxisa_c : std_ulogic_vector(11 downto 0) := x"fc0";
 
-- CPU Co-Processor IDs -------------------------------------------------------------------
-- CPU Co-Processor IDs (one-hot!) --------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant cp_sel_shifter_c : std_ulogic_vector(2 downto 0) := "000"; -- CP0: shift operations (base ISA)
constant cp_sel_muldiv_c : std_ulogic_vector(2 downto 0) := "001"; -- CP1: multiplication/division operations ('M' extensions)
constant cp_sel_bitmanip_c : std_ulogic_vector(2 downto 0) := "010"; -- CP2: bit manipulation ('B' extensions)
constant cp_sel_fpu_c : std_ulogic_vector(2 downto 0) := "011"; -- CP3: floating-point unit ('Zfinx' extension)
constant cp_sel_cfu_c : std_ulogic_vector(2 downto 0) := "100"; -- CP4: custom instructions CFU ('Zxcfu' extension)
--constant cp_sel_res1_c : std_ulogic_vector(2 downto 0) := "101"; -- CP5: reserved
--constant cp_sel_res2_c : std_ulogic_vector(2 downto 0) := "110"; -- CP6: reserved
--constant cp_sel_res3_c : std_ulogic_vector(2 downto 0) := "111"; -- CP7: reserved
constant cp_sel_shifter_c : std_ulogic_vector(7 downto 0) := "00000001"; -- CP0: shift operations (base ISA)
constant cp_sel_muldiv_c : std_ulogic_vector(7 downto 0) := "00000010"; -- CP1: multiplication/division operations ('M' extensions)
constant cp_sel_bitmanip_c : std_ulogic_vector(7 downto 0) := "00000100"; -- CP2: bit manipulation ('B' extensions)
constant cp_sel_fpu_c : std_ulogic_vector(7 downto 0) := "00001000"; -- CP3: floating-point unit ('Zfinx' extension)
constant cp_sel_cfu_c : std_ulogic_vector(7 downto 0) := "00010000"; -- CP4: custom instructions CFU ('Zxcfu' extension)
--constant cp_sel_res5_c : std_ulogic_vector(7 downto 0) := "00100000"; -- CP5: reserved
--constant cp_sel_res6_c : std_ulogic_vector(7 downto 0) := "01000000"; -- CP6: reserved
--constant cp_sel_res7_c : std_ulogic_vector(7 downto 0) := "10000000"; -- CP7: reserved
 
-- ALU Function Codes ---------------------------------------------------------------------
-- ALU Function Codes [DO NOT CHANGE ENCODING!] -------------------------------------------
-- -------------------------------------------------------------------------------------------
-- ALU core [DO NOT CHANGE ENCODING!] --
constant alu_op_add_c : std_ulogic_vector(2 downto 0) := "000"; -- alu_result <= A + B
constant alu_op_sub_c : std_ulogic_vector(2 downto 0) := "001"; -- alu_result <= A - B
--constant alu_op_mova_c : std_ulogic_vector(2 downto 0) := "010"; -- alu_result <= A (rs1)
constant alu_op_slt_c : std_ulogic_vector(2 downto 0) := "011"; -- alu_result <= A < B
constant alu_op_movb_c : std_ulogic_vector(2 downto 0) := "100"; -- alu_result <= B
constant alu_op_xor_c : std_ulogic_vector(2 downto 0) := "101"; -- alu_result <= A xor B
constant alu_op_or_c : std_ulogic_vector(2 downto 0) := "110"; -- alu_result <= A or B
constant alu_op_and_c : std_ulogic_vector(2 downto 0) := "111"; -- alu_result <= A and B
-- function select (actual ALU result) --
constant alu_func_core_c : std_ulogic_vector(1 downto 0) := "00"; -- r <= alu_result
constant alu_func_nxpc_c : std_ulogic_vector(1 downto 0) := "01"; -- r <= next_PC
constant alu_func_csrr_c : std_ulogic_vector(1 downto 0) := "10"; -- r <= CSR read
constant alu_func_copro_c : std_ulogic_vector(1 downto 0) := "11"; -- r <= CP result (multi-cycle)
constant alu_op_add_c : std_ulogic_vector(2 downto 0) := "000"; -- result <= A + B
constant alu_op_sub_c : std_ulogic_vector(2 downto 0) := "001"; -- result <= A - B
constant alu_op_cp_c : std_ulogic_vector(2 downto 0) := "010"; -- result <= co-processor
constant alu_op_slt_c : std_ulogic_vector(2 downto 0) := "011"; -- result <= A < B
constant alu_op_movb_c : std_ulogic_vector(2 downto 0) := "100"; -- result <= B
constant alu_op_xor_c : std_ulogic_vector(2 downto 0) := "101"; -- result <= A xor B
constant alu_op_or_c : std_ulogic_vector(2 downto 0) := "110"; -- result <= A or B
constant alu_op_and_c : std_ulogic_vector(2 downto 0) := "111"; -- result <= A and B
 
-- Register File Input Select -------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant rf_mux_alu_c : std_ulogic_vector(1 downto 0) := "00"; -- register file <= alu result
constant rf_mux_mem_c : std_ulogic_vector(1 downto 0) := "01"; -- register file <= memory read data
constant rf_mux_csr_c : std_ulogic_vector(1 downto 0) := "10"; -- register file <= CSR read data
constant rf_mux_npc_c : std_ulogic_vector(1 downto 0) := "11"; -- register file <= next-PC (for branch-and-link)
 
-- Trap ID Codes --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- MSB: 1 = async exception (IRQ), 0 = sync exception (e.g. ebreak)
874,51 → 880,51
-- CPU Control Exception System -----------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- exception source bits --
constant exception_iaccess_c : natural := 0; -- instruction access fault
constant exception_iillegal_c : natural := 1; -- illegal instruction
constant exception_ialign_c : natural := 2; -- instruction address misaligned
constant exception_m_envcall_c : natural := 3; -- ENV call from m-mode
constant exception_u_envcall_c : natural := 4; -- ENV call from u-mode
constant exception_break_c : natural := 5; -- breakpoint
constant exception_salign_c : natural := 6; -- store address misaligned
constant exception_lalign_c : natural := 7; -- load address misaligned
constant exception_saccess_c : natural := 8; -- store access fault
constant exception_laccess_c : natural := 9; -- load access fault
constant exc_iaccess_c : natural := 0; -- instruction access fault
constant exc_iillegal_c : natural := 1; -- illegal instruction
constant exc_ialign_c : natural := 2; -- instruction address misaligned
constant exc_m_envcall_c : natural := 3; -- ENV call from m-mode
constant exc_u_envcall_c : natural := 4; -- ENV call from u-mode
constant exc_break_c : natural := 5; -- breakpoint
constant exc_salign_c : natural := 6; -- store address misaligned
constant exc_lalign_c : natural := 7; -- load address misaligned
constant exc_saccess_c : natural := 8; -- store access fault
constant exc_laccess_c : natural := 9; -- load access fault
-- for debug mode only --
constant exception_db_break_c : natural := 10; -- enter debug mode via ebreak instruction ("sync EXCEPTION")
constant exception_db_hw_c : natural := 11; -- enter debug mode via hw trigger ("sync EXCEPTION")
constant exc_db_break_c : natural := 10; -- enter debug mode via ebreak instruction ("sync EXCEPTION")
constant exc_db_hw_c : natural := 11; -- enter debug mode via hw trigger ("sync EXCEPTION")
--
constant exception_width_c : natural := 12; -- length of this list in bits
constant exc_width_c : natural := 12; -- length of this list in bits
-- interrupt source bits --
constant interrupt_msw_irq_c : natural := 0; -- machine software interrupt
constant interrupt_mtime_irq_c : natural := 1; -- machine timer interrupt
constant interrupt_mext_irq_c : natural := 2; -- machine external interrupt
constant interrupt_firq_0_c : natural := 3; -- fast interrupt channel 0
constant interrupt_firq_1_c : natural := 4; -- fast interrupt channel 1
constant interrupt_firq_2_c : natural := 5; -- fast interrupt channel 2
constant interrupt_firq_3_c : natural := 6; -- fast interrupt channel 3
constant interrupt_firq_4_c : natural := 7; -- fast interrupt channel 4
constant interrupt_firq_5_c : natural := 8; -- fast interrupt channel 5
constant interrupt_firq_6_c : natural := 9; -- fast interrupt channel 6
constant interrupt_firq_7_c : natural := 10; -- fast interrupt channel 7
constant interrupt_firq_8_c : natural := 11; -- fast interrupt channel 8
constant interrupt_firq_9_c : natural := 12; -- fast interrupt channel 9
constant interrupt_firq_10_c : natural := 13; -- fast interrupt channel 10
constant interrupt_firq_11_c : natural := 14; -- fast interrupt channel 11
constant interrupt_firq_12_c : natural := 15; -- fast interrupt channel 12
constant interrupt_firq_13_c : natural := 16; -- fast interrupt channel 13
constant interrupt_firq_14_c : natural := 17; -- fast interrupt channel 14
constant interrupt_firq_15_c : natural := 18; -- fast interrupt channel 15
constant irq_msw_irq_c : natural := 0; -- machine software interrupt
constant irq_mtime_irq_c : natural := 1; -- machine timer interrupt
constant irq_mext_irq_c : natural := 2; -- machine external interrupt
constant irq_firq_0_c : natural := 3; -- fast interrupt channel 0
constant irq_firq_1_c : natural := 4; -- fast interrupt channel 1
constant irq_firq_2_c : natural := 5; -- fast interrupt channel 2
constant irq_firq_3_c : natural := 6; -- fast interrupt channel 3
constant irq_firq_4_c : natural := 7; -- fast interrupt channel 4
constant irq_firq_5_c : natural := 8; -- fast interrupt channel 5
constant irq_firq_6_c : natural := 9; -- fast interrupt channel 6
constant irq_firq_7_c : natural := 10; -- fast interrupt channel 7
constant irq_firq_8_c : natural := 11; -- fast interrupt channel 8
constant irq_firq_9_c : natural := 12; -- fast interrupt channel 9
constant irq_firq_10_c : natural := 13; -- fast interrupt channel 10
constant irq_firq_11_c : natural := 14; -- fast interrupt channel 11
constant irq_firq_12_c : natural := 15; -- fast interrupt channel 12
constant irq_firq_13_c : natural := 16; -- fast interrupt channel 13
constant irq_firq_14_c : natural := 17; -- fast interrupt channel 14
constant irq_firq_15_c : natural := 18; -- fast interrupt channel 15
-- for debug mode only --
constant interrupt_db_halt_c : natural := 19; -- enter debug mode via external halt request ("async IRQ")
constant interrupt_db_step_c : natural := 20; -- enter debug mode via single-stepping ("async IRQ")
constant irq_db_halt_c : natural := 19; -- enter debug mode via external halt request ("async IRQ")
constant irq_db_step_c : natural := 20; -- enter debug mode via single-stepping ("async IRQ")
--
constant interrupt_width_c : natural := 21; -- length of this list in bits
constant irq_width_c : natural := 21; -- length of this list in bits
 
-- CPU Privilege Modes --------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant priv_mode_m_c : std_ulogic_vector(1 downto 0) := "11"; -- machine mode
constant priv_mode_u_c : std_ulogic_vector(1 downto 0) := "00"; -- user mode
constant priv_mode_m_c : std_ulogic := '1'; -- machine mode
constant priv_mode_u_c : std_ulogic := '0'; -- user mode
 
-- HPM Event System -----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
981,8 → 987,8
CPU_CNT_WIDTH : natural := 64; -- total width of CPU cycle and instret counters (0..64)
CPU_IPB_ENTRIES : natural := 2; -- entries is instruction prefetch buffer, has to be a power of 2
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64)
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..16)
PMP_MIN_GRANULARITY : natural := 4; -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS : natural := 0; -- number of implemented HPM counters (0..29)
HPM_CNT_WIDTH : natural := 40; -- total size of HPM counters (0..64)
1142,8 → 1148,8
CPU_CNT_WIDTH : natural; -- total width of CPU cycle and instret counters (0..64)
CPU_IPB_ENTRIES : natural; -- entries is instruction prefetch buffer, has to be a power of 2
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS : natural; -- number of regions (0..64)
PMP_MIN_GRANULARITY : natural; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
PMP_NUM_REGIONS : natural; -- number of regions (0..16)
PMP_MIN_GRANULARITY : natural; -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS : natural; -- number of implemented HPM counters (0..29)
HPM_CNT_WIDTH : natural -- total size of HPM counters (0..64)
1165,7 → 1171,7
i_bus_ack_i : in std_ulogic; -- bus transfer acknowledge
i_bus_err_i : in std_ulogic; -- bus transfer error
i_bus_fence_o : out std_ulogic; -- executed FENCEI operation
i_bus_priv_o : out std_ulogic_vector(1 downto 0); -- privilege level
i_bus_priv_o : out std_ulogic; -- privilege level
-- data bus interface --
d_bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
d_bus_rdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
1177,7 → 1183,7
d_bus_ack_i : in std_ulogic; -- bus transfer acknowledge
d_bus_err_i : in std_ulogic; -- bus transfer error
d_bus_fence_o : out std_ulogic; -- executed FENCE operation
d_bus_priv_o : out std_ulogic_vector(1 downto 0); -- privilege level
d_bus_priv_o : out std_ulogic; -- privilege level
-- system time input from MTIME --
time_i : in std_ulogic_vector(63 downto 0); -- current system time
-- interrupts (risc-v compliant) --
1220,8 → 1226,8
CPU_CNT_WIDTH : natural; -- total width of CPU cycle and instret counters (0..64)
CPU_IPB_ENTRIES : natural; -- entries is instruction prefetch buffer, has to be a power of 2
-- Physical memory protection (PMP) --
PMP_NUM_REGIONS : natural; -- number of regions (0..64)
PMP_MIN_GRANULARITY : natural; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
PMP_NUM_REGIONS : natural; -- number of regions (0..16)
PMP_MIN_GRANULARITY : natural; -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS : natural; -- number of implemented HPM counters (0..29)
HPM_CNT_WIDTH : natural -- total size of HPM counters (0..64)
1284,8 → 1290,10
clk_i : in std_ulogic; -- global clock, rising edge
ctrl_i : in std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
-- data input --
alu_i : in std_ulogic_vector(data_width_c-1 downto 0); -- ALU result
mem_i : in std_ulogic_vector(data_width_c-1 downto 0); -- memory read data
alu_i : in std_ulogic_vector(data_width_c-1 downto 0); -- ALU result
csr_i : in std_ulogic_vector(data_width_c-1 downto 0); -- CSR read data
pc2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- next PC
-- data output --
rs1_o : out std_ulogic_vector(data_width_c-1 downto 0); -- operand 1
rs2_o : out std_ulogic_vector(data_width_c-1 downto 0) -- operand 2
1315,9 → 1323,7
rs1_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 1
rs2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 2
pc_i : in std_ulogic_vector(data_width_c-1 downto 0); -- current PC
pc2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- next PC
imm_i : in std_ulogic_vector(data_width_c-1 downto 0); -- immediate
csr_i : in std_ulogic_vector(data_width_c-1 downto 0); -- CSR read data
-- data output --
cmp_o : out std_ulogic_vector(1 downto 0); -- comparator status
res_o : out std_ulogic_vector(data_width_c-1 downto 0); -- ALU result
1439,8 → 1445,8
CPU_EXTENSION_RISCV_A : boolean; -- implement atomic extension?
CPU_EXTENSION_RISCV_C : boolean; -- implement compressed extension?
-- Physical memory protection (PMP) --
PMP_NUM_REGIONS : natural; -- number of regions (0..64)
PMP_MIN_GRANULARITY : natural -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
PMP_NUM_REGIONS : natural; -- number of regions (0..16)
PMP_MIN_GRANULARITY : natural -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
);
port (
-- global control --
1533,6 → 1539,7
clk_i : in std_ulogic; -- global clock, rising edge
rstn_i : in std_ulogic; -- global reset, low-active, async
clear_i : in std_ulogic; -- cache clear
miss_o : out std_ulogic; -- cache miss
-- host controller interface --
host_addr_i : in std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
host_rdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
1602,6 → 1609,9
-- Component: CPU Compressed Instructions De-Compressor -----------------------------------
-- -------------------------------------------------------------------------------------------
component neorv32_cpu_decompressor
generic (
FPU_ENABLE : boolean -- floating-point instruction enabled
);
port (
-- instruction input --
ci_instr16_i : in std_ulogic_vector(15 downto 0); -- compressed instruction input
1883,7 → 1893,7
ack_o : out std_ulogic; -- transfer acknowledge
err_o : out std_ulogic; -- transfer error
tmo_o : out std_ulogic; -- transfer timeout
priv_i : in std_ulogic_vector(01 downto 0); -- current CPU privilege level
priv_i : in std_ulogic; -- current CPU privilege level
ext_o : out std_ulogic; -- active external access
-- xip configuration --
xip_en_i : in std_ulogic; -- XIP module enabled
2076,7 → 2086,7
CLOCK_FREQUENCY : natural; -- clock frequency of clk_i in Hz
INT_BOOTLOADER_EN : boolean; -- boot configuration: true = boot explicit bootloader; false = boot from int/ext (I)MEM
-- Physical memory protection (PMP) --
PMP_NUM_REGIONS : natural; -- number of regions (0..64)
PMP_NUM_REGIONS : natural; -- number of regions (0..16)
-- Internal Instruction memory --
MEM_INT_IMEM_EN : boolean; -- implement processor-internal instruction memory
MEM_INT_IMEM_SIZE : natural; -- size of processor-internal instruction memory in bytes
/rtl/core/neorv32_sysinfo.vhd
104,7 → 104,7
signal acc_en : std_ulogic; -- module access enable
signal rden : std_ulogic;
signal wren : std_ulogic;
signal iaddr : std_ulogic_vector(02 downto 0);
signal addr : std_ulogic_vector(2 downto 0);
 
-- system information ROM --
type info_mem_t is array (0 to 7) of std_ulogic_vector(31 downto 0);
117,7 → 117,7
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = sysinfo_base_c(hi_abb_c downto lo_abb_c)) else '0';
rden <= acc_en and rden_i; -- read access
wren <= acc_en and wren_i; -- write access
iaddr <= addr_i(index_size_f(sysinfo_size_c)-1 downto 2);
addr <= addr_i(index_size_f(sysinfo_size_c)-1 downto 2);
 
 
-- Construct Info ROM ---------------------------------------------------------------------
190,11 → 190,12
read_access: process(clk_i)
begin
if rising_edge(clk_i) then
ack_o <= rden;
err_o <= wren;
data_o <= (others => '0');
ack_o <= rden;
err_o <= wren; -- read-only!
if (rden = '1') then
data_o <= sysinfo_mem(to_integer(unsigned(iaddr)));
data_o <= sysinfo_mem(to_integer(unsigned(addr)));
else
data_o <= (others => '0');
end if;
end if;
end process read_access;
/rtl/core/neorv32_top.vhd
76,8 → 76,8
CPU_IPB_ENTRIES : natural := 2; -- entries is instruction prefetch buffer, has to be a power of 2
 
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64)
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..16)
PMP_MIN_GRANULARITY : natural := 4; -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
 
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS : natural := 0; -- number of implemented HPM counters (0..29)
280,7 → 280,7
ack : std_ulogic; -- bus transfer acknowledge
err : std_ulogic; -- bus transfer error
fence : std_ulogic; -- fence(i) instruction executed
priv : std_ulogic_vector(1 downto 0); -- current privilege level
priv : std_ulogic; -- current privilege level
src : std_ulogic; -- access source (1=instruction fetch, 0=data access)
lock : std_ulogic; -- exclusive access request
end record;
437,28 → 437,27
begin
if (sys_rstn = '0') then
clk_gen_en_ff <= '-';
clk_div_ff <= (others => '-');
clk_div <= (others => '0'); -- reset required
clk_div_ff <= (others => '-');
clk_gen <= (others => '-');
elsif rising_edge(clk_i) then
clk_gen_en_ff <= or_reduce_f(clk_gen_en);
-- actual clock generator --
if (clk_gen_en_ff = '1') then
clk_div_ff <= clk_div;
if (clk_gen_en_ff = '1') then -- actual clock generator
clk_div <= std_ulogic_vector(unsigned(clk_div) + 1);
end if;
-- clock enables: rising edge detectors --
clk_div_ff <= clk_div;
clk_gen(clk_div2_c) <= clk_div(0) and (not clk_div_ff(0)); -- CLK/2
clk_gen(clk_div4_c) <= clk_div(1) and (not clk_div_ff(1)); -- CLK/4
clk_gen(clk_div8_c) <= clk_div(2) and (not clk_div_ff(2)); -- CLK/8
clk_gen(clk_div64_c) <= clk_div(5) and (not clk_div_ff(5)); -- CLK/64
clk_gen(clk_div128_c) <= clk_div(6) and (not clk_div_ff(6)); -- CLK/128
clk_gen(clk_div1024_c) <= clk_div(9) and (not clk_div_ff(9)); -- CLK/1024
clk_gen(clk_div2048_c) <= clk_div(10) and (not clk_div_ff(10)); -- CLK/2048
clk_gen(clk_div4096_c) <= clk_div(11) and (not clk_div_ff(11)); -- CLK/4096
end if;
end process clock_generator;
 
-- clock enables: rising edge detectors --
clk_gen(clk_div2_c) <= clk_div(0) and (not clk_div_ff(0)); -- CLK/2
clk_gen(clk_div4_c) <= clk_div(1) and (not clk_div_ff(1)); -- CLK/4
clk_gen(clk_div8_c) <= clk_div(2) and (not clk_div_ff(2)); -- CLK/8
clk_gen(clk_div64_c) <= clk_div(5) and (not clk_div_ff(5)); -- CLK/64
clk_gen(clk_div128_c) <= clk_div(6) and (not clk_div_ff(6)); -- CLK/128
clk_gen(clk_div1024_c) <= clk_div(9) and (not clk_div_ff(9)); -- CLK/1024
clk_gen(clk_div2048_c) <= clk_div(10) and (not clk_div_ff(10)); -- CLK/2048
clk_gen(clk_div4096_c) <= clk_div(11) and (not clk_div_ff(11)); -- CLK/4096
 
-- fresh clocks anyone? --
clk_gen_en(0) <= wdt_cg_en;
clk_gen_en(1) <= uart0_cg_en;
501,8 → 500,8
CPU_CNT_WIDTH => CPU_CNT_WIDTH, -- total width of CPU cycle and instret counters (0..64)
CPU_IPB_ENTRIES => CPU_IPB_ENTRIES, -- entries is instruction prefetch buffer, has to be a power of 2
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..64)
PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..16)
PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS => HPM_NUM_CNTS, -- number of implemented HPM counters (0..29)
HPM_CNT_WIDTH => HPM_CNT_WIDTH -- total size of HPM counters (0..64)
592,6 → 591,7
clk_i => clk_i, -- global clock, rising edge
rstn_i => sys_rstn, -- global reset, low-active, async
clear_i => cpu_i.fence, -- cache clear
miss_o => open, -- cache miss
-- host controller interface --
host_addr_i => cpu_i.addr, -- bus access address
host_rdata_o => cpu_i.rdata, -- bus read data
944,7 → 944,7
-- IO Access? -----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
io_acc <= '1' when (p_bus.addr(data_width_c-1 downto index_size_f(io_size_c)) = io_base_c(data_width_c-1 downto index_size_f(io_size_c))) else '0';
io_rden <= io_acc and p_bus.re and (not p_bus.src); -- PMA: no_execute for IO region
io_rden <= io_acc and p_bus.re;
io_wren <= io_acc and p_bus.we and and_reduce_f(p_bus.ben); -- only full-word write accesses are allowed (reduces HW complexity)
 
 
964,7 → 964,7
rstn_i => sys_rstn, -- global reset line, low-active, use as async
addr_i => p_bus.addr, -- address
rden_i => io_rden, -- read enable
wren_i => io_wren, -- byte write enable
wren_i => io_wren, -- word write enable
data_i => p_bus.wdata, -- data in
data_o => resp_bus(RESP_CFS).rdata, -- data out
ack_o => resp_bus(RESP_CFS).ack, -- transfer acknowledge
1500,7 → 1500,7
CLOCK_FREQUENCY => CLOCK_FREQUENCY, -- clock frequency of clk_i in Hz
INT_BOOTLOADER_EN => INT_BOOTLOADER_EN, -- implement processor-internal bootloader?
-- Physical memory protection (PMP) --
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..64)
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..16)
-- internal Instruction memory --
MEM_INT_IMEM_EN => MEM_INT_IMEM_EN, -- implement processor-internal instruction memory
MEM_INT_IMEM_SIZE => MEM_INT_IMEM_SIZE, -- size of processor-internal instruction memory in bytes
/rtl/core/neorv32_wishbone.vhd
77,7 → 77,7
ack_o : out std_ulogic; -- transfer acknowledge
err_o : out std_ulogic; -- transfer error
tmo_o : out std_ulogic; -- transfer timeout
priv_i : in std_ulogic_vector(01 downto 0); -- current CPU privilege level
priv_i : in std_ulogic; -- current CPU privilege level
ext_o : out std_ulogic; -- active external access
-- xip configuration --
xip_en_i : in std_ulogic; -- XIP module enabled
125,7 → 125,7
timeout : std_ulogic_vector(index_size_f(BUS_TIMEOUT) downto 0);
src : std_ulogic;
lock : std_ulogic;
priv : std_ulogic_vector(01 downto 0);
priv : std_ulogic;
end record;
signal ctrl : ctrl_t;
signal stb_int : std_ulogic;
188,7 → 188,7
ctrl.tmo <= def_rst_val_c;
ctrl.src <= def_rst_val_c;
ctrl.lock <= def_rst_val_c;
ctrl.priv <= (others => def_rst_val_c);
ctrl.priv <= def_rst_val_c;
elsif rising_edge(clk_i) then
-- defaults --
ctrl.state_ff <= ctrl.state;
/rtl/processor_templates/neorv32_ProcessorTop_Minimal.vhd
3,7 → 3,7
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
-- # Copyright (c) 2022, Stephan Nolting. All rights reserved. #
-- # #
-- # Redistribution and use in source and binary forms, with or without modification, are #
-- # permitted provided that the following conditions are met: #
59,8 → 59,8
CPU_CNT_WIDTH : natural := 34; -- total width of CPU cycle and instret counters (0..64)
 
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64)
PMP_MIN_GRANULARITY : natural := 8*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..16)
PMP_MIN_GRANULARITY : natural := 4; -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
 
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS : natural := 0; -- number of implemented HPM counters (0..29)
137,7 → 137,7
CPU_CNT_WIDTH => CPU_CNT_WIDTH, -- total width of CPU cycle and instret counters (0..64)
 
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..64)
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..16)
PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
 
-- Hardware Performance Monitors (HPM) --
/rtl/processor_templates/neorv32_ProcessorTop_MinimalBoot.vhd
3,7 → 3,7
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
-- # Copyright (c) 2022, Stephan Nolting. All rights reserved. #
-- # #
-- # Redistribution and use in source and binary forms, with or without modification, are #
-- # permitted provided that the following conditions are met: #
60,8 → 60,8
CPU_CNT_WIDTH : natural := 34; -- total width of CPU cycle and instret counters (0..64)
 
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64)
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..16)
PMP_MIN_GRANULARITY : natural := 4; -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
 
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS : natural := 0; -- number of implemented HPM counters (0..29)
153,7 → 153,7
CPU_CNT_WIDTH => CPU_CNT_WIDTH, -- total width of CPU cycle and instret counters (0..64)
 
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..64)
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..16)
PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
 
-- Hardware Performance Monitors (HPM) --
/rtl/processor_templates/neorv32_ProcessorTop_UP5KDemo.vhd
3,7 → 3,7
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
-- # Copyright (c) 2022, Stephan Nolting. All rights reserved. #
-- # #
-- # Redistribution and use in source and binary forms, with or without modification, are #
-- # permitted provided that the following conditions are met: #
62,8 → 62,8
CPU_CNT_WIDTH : natural := 34; -- total width of CPU cycle and instret counters (0..64)
 
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64)
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..16)
PMP_MIN_GRANULARITY : natural := 4; -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
 
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS : natural := 0; -- number of implemented HPM counters (0..29)
193,7 → 193,7
CPU_CNT_WIDTH => CPU_CNT_WIDTH, -- total width of CPU cycle and instret counters (0..64)
 
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..64)
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..16)
PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
 
-- Hardware Performance Monitors (HPM) --
/rtl/system_integration/neorv32_ProcessorTop_stdlogic.vhd
66,8 → 66,8
FAST_SHIFT_EN : boolean := false; -- use barrel shifter for shift operations
CPU_CNT_WIDTH : natural := 64; -- total width of CPU cycle and instret counters (0..64)
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64)
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..16)
PMP_MIN_GRANULARITY : natural := 4; -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS : natural := 0; -- number of implemented HPM counters (0..29)
HPM_CNT_WIDTH : natural := 40; -- total size of HPM counters (0..64)
291,7 → 291,7
CPU_EXTENSION_RISCV_B => CPU_EXTENSION_RISCV_B, -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension?
CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E, -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, -- implement muld/div extension?
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, -- implement mul/div extension?
CPU_EXTENSION_RISCV_U => CPU_EXTENSION_RISCV_U, -- implement user mode extension?
CPU_EXTENSION_RISCV_Zfinx => CPU_EXTENSION_RISCV_Zfinx, -- implement 32-bit floating-point extension (using INT reg!)
CPU_EXTENSION_RISCV_Zicsr => CPU_EXTENSION_RISCV_Zicsr, -- implement CSR system?
305,8 → 305,8
FAST_SHIFT_EN => FAST_SHIFT_EN, -- use barrel shifter for shift operations
CPU_CNT_WIDTH => CPU_CNT_WIDTH, -- total width of CPU cycle and instret counters (0..64)
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..64)
PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..16)
PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS => HPM_NUM_CNTS, -- number of implemented HPM counters (0..29)
HPM_CNT_WIDTH => HPM_CNT_WIDTH, -- total size of HPM counters (0..64)
/rtl/system_integration/neorv32_SystemTop_AvalonMM.vhd
74,8 → 74,8
CPU_IPB_ENTRIES : natural := 2; -- entries is instruction prefetch buffer, has to be a power of 2
 
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64)
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..16)
PMP_MIN_GRANULARITY : natural := 4; -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
 
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS : natural := 0; -- number of implemented HPM counters (0..29)
/rtl/system_integration/neorv32_SystemTop_axi4lite.vhd
72,8 → 72,8
FAST_SHIFT_EN : boolean := false; -- use barrel shifter for shift operations
CPU_CNT_WIDTH : natural := 64; -- total width of CPU cycle and instret counters (0..64)
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64)
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..16)
PMP_MIN_GRANULARITY : natural := 4; -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS : natural := 0; -- number of implemented HPM counters (0..29)
HPM_CNT_WIDTH : natural := 40; -- total size of HPM counters (0..64)
298,7 → 298,7
CPU_EXTENSION_RISCV_B => CPU_EXTENSION_RISCV_B, -- implement bit-manipulation extension?
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension?
CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E, -- implement embedded RF extension?
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, -- implement muld/div extension?
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, -- implement mul/div extension?
CPU_EXTENSION_RISCV_U => CPU_EXTENSION_RISCV_U, -- implement user mode extension?
CPU_EXTENSION_RISCV_Zfinx => CPU_EXTENSION_RISCV_Zfinx, -- implement 32-bit floating-point extension (using INT reg!)
CPU_EXTENSION_RISCV_Zicsr => CPU_EXTENSION_RISCV_Zicsr, -- implement CSR system?
312,8 → 312,8
FAST_SHIFT_EN => FAST_SHIFT_EN, -- use barrel shifter for shift operations
CPU_CNT_WIDTH => CPU_CNT_WIDTH, -- total width of CPU cycle and instret counters (0..64)
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..64)
PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..16)
PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS => HPM_NUM_CNTS, -- number of implemented HPM counters (0..29)
HPM_CNT_WIDTH => HPM_CNT_WIDTH, -- total size of HPM counters (0..64)
/sim/simple/neorv32_tb.simple.vhd
193,8 → 193,8
FAST_SHIFT_EN => false, -- use barrel shifter for shift operations
CPU_CNT_WIDTH => 64, -- total width of CPU cycle and instret counters (0..64)
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS => 8, -- number of regions (0..64)
PMP_MIN_GRANULARITY => 64*1024, -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
PMP_NUM_REGIONS => 5, -- number of regions (0..16)
PMP_MIN_GRANULARITY => 4, -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS => 12, -- number of implemented HPM counters (0..29)
HPM_CNT_WIDTH => 40, -- total size of HPM counters (0..64)
/sim/neorv32_tb.vhd
301,8 → 301,8
FAST_SHIFT_EN => false, -- use barrel shifter for shift operations
CPU_CNT_WIDTH => 64, -- total width of CPU cycle and instret counters (0..64)
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS => 8, -- number of regions (0..64)
PMP_MIN_GRANULARITY => 64*1024, -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
PMP_NUM_REGIONS => 5, -- number of regions (0..16)
PMP_MIN_GRANULARITY => 4, -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS => 12, -- number of implemented HPM counters (0..29)
HPM_CNT_WIDTH => 40, -- total size of HPM counters (0..64)
/sw/bootloader/bootloader.c
36,7 → 36,7
/**********************************************************************//**
* @file bootloader.c
* @author Stephan Nolting
* @brief NEORV32 bootloader.
* @brief Default NEORV32 bootloader.
**************************************************************************/
 
// Libraries
/sw/common/crt0.S
70,22 → 70,20
// ************************************************************************************************
__crt0_cpu_csr_init:
 
la x10, __crt0_dummy_trap_handler // configure early trap handler
la x10, __crt0_dummy_trap_handler // configure early-boot trap handler
csrw mtvec, x10
csrw mepc, x10 // just to init mepc
 
csrw mstatus, zero // disable global IRQ
csrw mstatus, zero // clear all control flags, also disable global IRQ
csrw mie, zero // absolutely no interrupt sources, thanks
csrw mip, zero // clear all pending interrupts
 
csrw mie, zero // absolutely no interrupts sources, thanks
 
csrw 0x320, zero // stop all counters; use "mcountinhibit" literal address for lagacy toolchain compatibility
csrw mcounteren, zero // no access from less-privileged modes to counter CSRs
 
li x11, ~5 // stop all counters except for [m]cycle[h] and [m]instret[h]
csrw 0x320, x11 // = mcountinhibit (literal address for lagacy toolchain compatibility)
 
csrw mcycle, zero // reset cycle counters
csrw mcycle, zero // reset cycle counter
csrw mcycleh, zero
csrw minstret, zero // reset instruction counters
csrw minstret, zero // reset instructions-retired counter
csrw minstreth, zero
 
 
107,8 → 105,8
//addi x11, x0, 0 // implicitly initialized within crt0
//addi x12, x0, 0 // implicitly initialized within crt0
//addi x13, x0, 0 // implicitly initialized within crt0
addi x14, x0, 0
addi x15, x0, 0
//addi x14, x0, 0 // implicitly initialized within crt0
//addi x15, x0, 0 // implicitly initialized within crt0
 
 
// ************************************************************************************************
153,22 → 151,6
 
 
// ************************************************************************************************
// Clear .bss section (byte-wise) using linker script symbols
// ************************************************************************************************
__crt0_clear_bss:
la x11, __crt0_bss_start
la x12, __crt0_bss_end
 
__crt0_clear_bss_loop:
bge x11, x12, __crt0_clear_bss_loop_end
sb zero, 0(x11)
addi x11, x11, 1
j __crt0_clear_bss_loop
 
__crt0_clear_bss_loop_end:
 
 
// ************************************************************************************************
// Copy initialized .data section from ROM to RAM (byte-wise)
// ************************************************************************************************
__crt0_copy_data:
188,6 → 170,22
 
 
// ************************************************************************************************
// Clear .bss section (byte-wise)
// ************************************************************************************************
__crt0_clear_bss:
la x14, __crt0_bss_start
la x15, __crt0_bss_end
 
__crt0_clear_bss_loop:
bge x14, x15, __crt0_clear_bss_loop_end
sb zero, 0(x14)
addi x14, x14, 1
j __crt0_clear_bss_loop
 
__crt0_clear_bss_loop_end:
 
 
// ************************************************************************************************
// Setup arguments and call main function
// ************************************************************************************************
__crt0_main_entry:
220,9 → 218,8
// ************************************************************************************************
__crt0_shutdown:
csrci mstatus, 8 // disable global IRQs (clear mstatus.mie)
__crt0_shutdown_loop:
wfi // go to sleep mode
j __crt0_shutdown_loop // endless loop
j . // endless loop
 
 
// ************************************************************************************************
/sw/example/bitmanip_test/main.c
603,11 → 603,9
* "after-main" handler that is executed after the application's
* main function returns (called by crt0.S start-up code)
**************************************************************************/
int __neorv32_crt0_after_main(int32_t return_code) {
void __neorv32_crt0_after_main(int32_t return_code) {
 
if (return_code) {
neorv32_uart0_printf("\n<RTE> main function returned with exit code (%i) </RTE>\n", return_code);
}
 
return 0;
}
/sw/example/coremark/core_portme.c
81,8 → 81,8
void
start_time(void)
{
GETMYTIME(&start_time_val);
neorv32_cpu_csr_write(CSR_MCOUNTINHIBIT, 0); // start all counters
GETMYTIME(&start_time_val);
}
/* Function : stop_time
This function will be called right after ending the timed portion of the
103,8 → 103,8
 
Actual value returned may be cpu cycles, milliseconds or any other
value, as long as it can be converted to seconds by <time_in_secs>. This
methodology is taken to accomodate any hardware or simulated platform. The
sample implementation returns millisecs by default, and the resolution is
methodology is taken to accommodate any hardware or simulated platform. The
sample implementation returns milliseconds by default, and the resolution is
controlled by <TIMER_RES_DIVIDER>
*/
CORE_TICKS
233,24 → 233,24
 
neorv32_uart0_printf("\nNEORV32: All reported numbers only show the integer part.\n\n");
 
neorv32_uart0_printf("NEORV32: HPM results\n");
neorv32_uart0_printf("NEORV32: HPM results (low words only)\n");
if (num_hpm_cnts_global == 0) {neorv32_uart0_printf("no HPMs available\n"); }
if (num_hpm_cnts_global > 0) {neorv32_uart0_printf("# Retired compr. instructions: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER3)); }
if (num_hpm_cnts_global > 1) {neorv32_uart0_printf("# I-fetch wait cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER4)); }
if (num_hpm_cnts_global > 2) {neorv32_uart0_printf("# I-issue wait cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER5)); }
if (num_hpm_cnts_global > 3) {neorv32_uart0_printf("# Multi-cycle ALU wait cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER6)); }
if (num_hpm_cnts_global > 4) {neorv32_uart0_printf("# Load operations: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER7)); }
if (num_hpm_cnts_global > 5) {neorv32_uart0_printf("# Store operations: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER8)); }
if (num_hpm_cnts_global > 6) {neorv32_uart0_printf("# Load/store wait cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER9)); }
if (num_hpm_cnts_global > 7) {neorv32_uart0_printf("# Unconditional jumps: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER10)); }
if (num_hpm_cnts_global > 8) {neorv32_uart0_printf("# Conditional branches (all): %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER11)); }
if (num_hpm_cnts_global > 9) {neorv32_uart0_printf("# Conditional branches (taken): %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER12)); }
if (num_hpm_cnts_global > 10) {neorv32_uart0_printf("# Entered traps: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER13)); }
if (num_hpm_cnts_global > 11) {neorv32_uart0_printf("# Illegal operations: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER14)); }
if (num_hpm_cnts_global > 0) {neorv32_uart0_printf(" > Retired compr. instructions: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER3)); }
if (num_hpm_cnts_global > 1) {neorv32_uart0_printf(" > Instr.-fetch wait cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER4)); }
if (num_hpm_cnts_global > 2) {neorv32_uart0_printf(" > Instr.-issue wait cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER5)); }
if (num_hpm_cnts_global > 3) {neorv32_uart0_printf(" > Multi-cycle ALU wait cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER6)); }
if (num_hpm_cnts_global > 4) {neorv32_uart0_printf(" > Load operations: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER7)); }
if (num_hpm_cnts_global > 5) {neorv32_uart0_printf(" > Store operations: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER8)); }
if (num_hpm_cnts_global > 6) {neorv32_uart0_printf(" > Load/store wait cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER9)); }
if (num_hpm_cnts_global > 7) {neorv32_uart0_printf(" > Unconditional jumps: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER10)); }
if (num_hpm_cnts_global > 8) {neorv32_uart0_printf(" > Conditional branches (all): %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER11)); }
if (num_hpm_cnts_global > 9) {neorv32_uart0_printf(" > Conditional branches (taken): %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER12)); }
if (num_hpm_cnts_global > 10) {neorv32_uart0_printf(" > Entered traps: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER13)); }
if (num_hpm_cnts_global > 11) {neorv32_uart0_printf(" > Illegal operations: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER14)); }
neorv32_uart0_printf("\n");
 
neorv32_uart0_printf("NEORV32: Executed instructions 0x%x_%x\n", (uint32_t)exe_instructions.uint32[1], (uint32_t)exe_instructions.uint32[0]);
neorv32_uart0_printf("NEORV32: CoreMark core clock cycles 0x%x_%x\n", (uint32_t)exe_time.uint32[1], (uint32_t)exe_time.uint32[0]);
neorv32_uart0_printf("NEORV32: Executed instructions 0x%x%x\n", (uint32_t)exe_instructions.uint32[1], (uint32_t)exe_instructions.uint32[0]);
neorv32_uart0_printf("NEORV32: CoreMark core clock cycles 0x%x%x\n", (uint32_t)exe_time.uint32[1], (uint32_t)exe_time.uint32[0]);
 
uint64_t average_cpi_int = exe_time.uint64 / exe_instructions.uint64;
neorv32_uart0_printf("NEORV32: Average CPI (integer part only): %u cycles/instruction\n", (uint32_t)average_cpi_int);
/sw/example/demo_gptmr/main.c
113,7 → 113,7
**************************************************************************/
void gptmr_firq_handler(void) {
 
neorv32_cpu_csr_write(CSR_MIP, 1<<GPTMR_FIRQ_PENDING); // clear/ack pending FIRQ
neorv32_cpu_csr_write(CSR_MIP, ~(1<<GPTMR_FIRQ_PENDING)); // clear/ack pending FIRQ
 
neorv32_uart0_putc('.'); // send tick symbol via UART0
neorv32_gpio_pin_toggle(0); // toggle output port bit 0
/sw/example/demo_pmp/main.c
0,0 → 1,177
// #################################################################################################
// # << NEORV32 - Physical Memory Protection Example Program >> #
// # ********************************************************************************************* #
// # BSD 3-Clause License #
// # #
// # Copyright (c) 2022, Stephan Nolting. All rights reserved. #
// # #
// # Redistribution and use in source and binary forms, with or without modification, are #
// # permitted provided that the following conditions are met: #
// # #
// # 1. Redistributions of source code must retain the above copyright notice, this list of #
// # conditions and the following disclaimer. #
// # #
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of #
// # conditions and the following disclaimer in the documentation and/or other materials #
// # provided with the distribution. #
// # #
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to #
// # endorse or promote products derived from this software without specific prior written #
// # permission. #
// # #
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS #
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF #
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE #
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, #
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED #
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED #
// # OF THE POSSIBILITY OF SUCH DAMAGE. #
// # ********************************************************************************************* #
// # The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting #
// #################################################################################################
 
 
/**********************************************************************//**
* @file demo_pmp/main.c
* @author Stephan Nolting
* @brief Physical memory protection (PMP) example program.
**************************************************************************/
#include <neorv32.h>
 
 
/**********************************************************************//**
* @name User configuration
**************************************************************************/
/**@{*/
/** UART BAUD rate */
#define BAUD_RATE 19200
/**@}*/
 
 
/**********************************************************************//**
* Example variable that will be protected by the PMP
**************************************************************************/
uint32_t protected_var[4] = {
0x11223344,
0x55667788,
0x00CAFE00,
0xDEADC0DE
};
 
 
/**********************************************************************//**
* Main function
*
* @note This program requires the CPU PMP extension (with at least 2 regions) and UART0.
*
* @return 0 if execution was successful
**************************************************************************/
int main() {
 
// initialize NEORV32 run-time environment
neorv32_rte_setup();
 
// setup UART0 at default baud rate, no parity bits, no HW flow control
neorv32_uart0_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
 
// check if UART0 is implemented
if (neorv32_uart0_available() == 0) {
return 1; // UART0 not available, exit
}
 
// check if PMP is implemented at all
if ((neorv32_cpu_csr_read(CSR_MXISA) & (1 << CSR_MXISA_PMP)) == 0) {
neorv32_uart0_printf("ERROR! PMP CPU extension not implemented!\n");
return 1;
}
 
 
// intro
neorv32_uart0_printf("\n<<< NEORV32 Physical Memory Protection (PMP) Example Program >>>\n\n");
 
neorv32_uart0_printf("NOTE: This program requires at least 2 PMP regions (PMP_NUM_REGIONS >= 2)\n"
" and a minimal granularity of 4 bytes (PMP_MIN_GRANULARITY = 4).\n\n");
 
neorv32_uart0_printf("NOTE: A 4-word array 'protected_var[4]' is created, which will be probed from\n"
" **machine-mode**. It provides the following access rights:\n"
" - NO_EXECUTE\n"
" - NO_WRITE\n"
" - READ\n"
" - LOCKED - also enforce access rights for machine-mode software\n\n");
 
 
// show PMP configuration
neorv32_uart0_printf("PMP hardware configuration:\n");
neorv32_uart0_printf("> Number of regions: %u\n", neorv32_cpu_pmp_get_num_regions());
neorv32_uart0_printf("> Min. granularity: %u bytes (minimal region size)\n\n", neorv32_cpu_pmp_get_granularity());
 
 
// The "protected_var" variable will be protected: No execute and no write access, just allow read access
 
// create protected region
int pmp_status;
uint8_t permissions;
neorv32_uart0_printf("Creating protected regions (any access within [REGION_BEGIN <= address < REGION_END] will match the PMP rules)...\n");
 
// any access in "region_begin <= address < region_end" will match the PMP rule
uint32_t region_begin = (uint32_t)(&protected_var[0]);
uint32_t region_end = (uint32_t)(&protected_var[4]) + 4;
neorv32_uart0_printf("REGION_BEGIN = 0x%x\n", region_begin);
neorv32_uart0_printf("REGION_END = 0x%x\n", region_end);
 
// base (region begin)
permissions = PMP_OFF << PMPCFG_A_LSB; // mode = OFF
neorv32_uart0_printf("> Region begin (PMP entry 0): Base = 0x%x, Mode = OFF (base of region) ", region_begin);
pmp_status = neorv32_cpu_pmp_configure_region(0, region_begin, permissions);
if (pmp_status) {
neorv32_uart0_printf("[FAILED]\n");
}
else {
neorv32_uart0_printf("[ok]\n");
}
 
// bound (region end)
permissions = (PMP_TOR << PMPCFG_A_LSB) | // enable entry as TOR = top of region
(0 << PMPCFG_X) | // no "execute" permission
(0 << PMPCFG_W) | // no "write" permission
(1 << PMPCFG_R) | // set "read" permission
(1 << PMPCFG_L); // locked: also enforce PMP rule for machine-mode software
neorv32_uart0_printf("> Region end (PMP entry 1): Base = 0x%x, Mode = TOR (top of region) ", region_end);
pmp_status = neorv32_cpu_pmp_configure_region(1, region_end, permissions);
if (pmp_status) {
neorv32_uart0_printf("[FAILED]\n");
}
else {
neorv32_uart0_printf("[ok]\n");
}
 
// test access
neorv32_uart0_printf("\nTesting access to 'protected_var' - invalid accesses will raise an exception, which will be\n"
"captured by the NEORV32 runtime environment's dummy/debug handlers ('<RTE> ... </RTE>').\n\n");
 
neorv32_uart0_printf("Reading protected_var[0] = 0x%x\n", protected_var[0]);
neorv32_uart0_printf("Reading protected_var[1] = 0x%x\n", protected_var[1]);
neorv32_uart0_printf("Reading protected_var[2] = 0x%x\n", protected_var[2]);
neorv32_uart0_printf("Reading protected_var[3] = 0x%x\n\n", protected_var[3]);
 
neorv32_uart0_printf("Trying to write protected_var[0]... ");
protected_var[0] = 0; // should fail!
neorv32_uart0_printf("Trying to write protected_var[1]... ");
protected_var[1] = 0; // should fail!
neorv32_uart0_printf("Trying to write protected_var[2]... ");
protected_var[2] = 0; // should fail!
neorv32_uart0_printf("Trying to write protected_var[3]... ");
protected_var[3] = 0; // should fail!
 
neorv32_uart0_printf("\nReading again protected_var[0] = 0x%x\n", protected_var[0]);
neorv32_uart0_printf("Reading again protected_var[1] = 0x%x\n", protected_var[1]);
neorv32_uart0_printf("Reading again protected_var[2] = 0x%x\n", protected_var[2]);
neorv32_uart0_printf("Reading again protected_var[3] = 0x%x\n\n", protected_var[3]);
 
 
neorv32_uart0_printf("\nPMP demo program completed.\n");
 
return 0;
}
/sw/example/demo_pmp/makefile
0,0 → 1,40
#################################################################################################
# << NEORV32 - Application Makefile >> #
# ********************************************************************************************* #
# Make sure to add the RISC-V GCC compiler's bin folder to your PATH environment variable. #
# ********************************************************************************************* #
# BSD 3-Clause License #
# #
# Copyright (c) 2021, Stephan Nolting. All rights reserved. #
# #
# Redistribution and use in source and binary forms, with or without modification, are #
# permitted provided that the following conditions are met: #
# #
# 1. Redistributions of source code must retain the above copyright notice, this list of #
# conditions and the following disclaimer. #
# #
# 2. Redistributions in binary form must reproduce the above copyright notice, this list of #
# conditions and the following disclaimer in the documentation and/or other materials #
# provided with the distribution. #
# #
# 3. Neither the name of the copyright holder nor the names of its contributors may be used to #
# endorse or promote products derived from this software without specific prior written #
# permission. #
# #
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS #
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF #
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE #
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, #
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED #
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED #
# OF THE POSSIBILITY OF SUCH DAMAGE. #
# ********************************************************************************************* #
# The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting #
#################################################################################################
 
# Modify this variable to fit your NEORV32 setup (neorv32 home folder)
NEORV32_HOME ?= ../../..
 
include $(NEORV32_HOME)/sw/common/common.mk
/sw/example/demo_slink/main.c
3,7 → 3,7
// # ********************************************************************************************* #
// # BSD 3-Clause License #
// # #
// # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
// # Copyright (c) 2022, Stephan Nolting. All rights reserved. #
// # #
// # Redistribution and use in source and binary forms, with or without modification, are #
// # permitted provided that the following conditions are met: #
475,7 → 475,7
**************************************************************************/
void slink_rx_firq_handler(void) {
 
neorv32_cpu_csr_write(CSR_MIP, 1 << SLINK_RX_FIRQ_PENDING); // ACK interrupt
neorv32_cpu_csr_write(CSR_MIP, ~(1 << SLINK_RX_FIRQ_PENDING)); // ACK interrupt
neorv32_uart0_printf("\n<SLINK_RX_IRQ>\n");
}
 
485,7 → 485,7
**************************************************************************/
void slink_tx_firq_handler(void) {
 
neorv32_cpu_csr_write(CSR_MIP, 1 << SLINK_TX_FIRQ_PENDING); // ACK interrupt
neorv32_cpu_csr_write(CSR_MIP, ~(1 << SLINK_TX_FIRQ_PENDING)); // ACK interrupt
neorv32_uart0_printf("\n<SLINK_TX_IRQ>\n");
}
 
/sw/example/newlib_demo/main.c
55,7 → 55,7
/**********************************************************************//**
* Main function: Check some of newlib's core functions.
*
* @note This program requires UART.
* @note This program requires UART0.
*
* @return 0 if execution was successful
**************************************************************************/
87,7 → 87,12
 
neorv32_uart0_printf("newlib version %i.%i\n\n", (int32_t)__NEWLIB__, (int32_t)__NEWLIB_MINOR__);
 
neorv32_uart0_printf("<rand> test... ");
srand(neorv32_cpu_csr_read(CSR_CYCLE)); // set random seed
neorv32_uart0_printf("%i, %i, %i, %i ", rand() % 100, rand() % 100, rand() % 100, rand() % 100);
neorv32_uart0_printf("ok\n");
 
 
char *char_buffer; // pointer for dynamic memory allocation
 
neorv32_uart0_printf("<malloc> test... ");
131,9 → 136,7
* "after-main" handler that is executed after the application's
* main function returns (called by crt0.S start-up code)
**************************************************************************/
int __neorv32_crt0_after_main(int32_t return_code) {
void __neorv32_crt0_after_main(int32_t return_code) {
 
neorv32_uart0_printf("\n<RTE> main function returned with exit code %i. </RTE>\n", return_code);
 
return 0;
neorv32_uart0_printf("\n<RTE> main function returned with exit code %i </RTE>\n", return_code);
}
/sw/example/processor_check/main.c
82,6 → 82,7
 
 
// Prototypes
void __attribute__((naked)) goto_user_mode(void);
void sim_irq_trigger(uint32_t sel);
void global_trap_handler(void);
void xirq_trap_handler0(void);
101,10 → 102,16
/// XIRQ trap handler acknowledge
uint32_t xirq_trap_handler_ack = 0;
 
/// Variable to test store accesses
volatile uint32_t store_access_addr[2];
 
/// Variable to test atomic accesses
uint32_t atomic_access_addr;
volatile uint32_t atomic_access_addr;
 
/// Variable to test PMP
volatile uint32_t pmp_access_addr;
 
 
/**********************************************************************//**
* High-level CPU/processor test program.
*
162,7 → 169,7
}
 
 
// reset performance counter
// reset (performance) counters
// neorv32_cpu_csr_write(CSR_MCYCLEH, 0); -> done in crt0.S
// neorv32_cpu_csr_write(CSR_MCYCLE, 0); -> done in crt0.S
// neorv32_cpu_csr_write(CSR_MINSTRETH, 0); -> done in crt0.S
177,13 → 184,13
 
// fancy intro
// -----------------------------------------------
// logo
// show ASCII logo
neorv32_rte_print_logo();
 
// show project credits
neorv32_rte_print_credits();
 
// show full HW config report
// show full hardware configuration report
neorv32_rte_print_hw_config();
 
 
223,6 → 230,13
 
 
// ----------------------------------------------------------
// Test fence instructions (just make sure CPU does not crash)
// ----------------------------------------------------------
asm volatile ("fence");
asm volatile ("fence.i");
 
 
// ----------------------------------------------------------
// Test performance counter: setup as many events and counter as feasible
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
362,23 → 376,20
tmp_a &= ~(1<<CSR_MCOUNTEREN_CY); // clear access right
neorv32_cpu_csr_write(CSR_MCOUNTEREN, tmp_a);
 
neorv32_cpu_csr_write(CSR_CYCLE, 1); // make sure CSR is != 0 for this test
neorv32_cpu_csr_write(CSR_CYCLEH, 1); // make sure CSR is != 0 for this test
 
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
neorv32_cpu_goto_user_mode();
goto_user_mode();
{
// access to cycle CSR is no longer allowed
asm volatile (" mv %[result], zero \n" // initialize with zero
" rdcycle %[result] " // read CSR_CYCLE, is not allowed and should not alter [result]
asm volatile (" li %[result], 0xcc11aa22 \n" // initialize
" rdcycleh %[result] " // read CSR_CYCLE, is not allowed and should not alter [result]
: [result] "=r" (tmp_a) : );
}
 
if (tmp_a != 0) {
PRINT_CRITICAL("%c[1m<SECURITY FAILURE> %c[0m\n", 27, 27);
}
 
// make sure there was an illegal instruction trap
if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) && (tmp_a == 0)) {
if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) &&
(tmp_a == 0xcc11aa22)) { // destination register not altered
test_ok();
}
else {
400,7 → 411,7
cnt_test++;
 
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
neorv32_cpu_goto_user_mode();
goto_user_mode();
{
asm volatile ("mret");
}
417,7 → 428,7
// External memory interface test
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] External memory access (@ 0x%x): ", cnt_test, (uint32_t)EXT_MEM_BASE);
PRINT_STANDARD("[%i] Ext. memory access (@ 0x%x): ", cnt_test, (uint32_t)EXT_MEM_BASE);
 
if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_EXT)) {
cnt_test++;
456,7 → 467,7
// Illegal CSR access (CSR not implemented)
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] Non-existent CSR access: ", cnt_test);
PRINT_STANDARD("[%i] Non-existent CSR: ", cnt_test);
 
cnt_test++;
 
474,7 → 485,7
// Write-access to read-only CSR
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] Read-only CSR write access: ", cnt_test);
PRINT_STANDARD("[%i] Read-only CSR write: ", cnt_test);
 
cnt_test++;
 
512,7 → 523,7
// Unaligned instruction address
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] I_ALIGN (instr. alignment) EXC: ", cnt_test);
PRINT_STANDARD("[%i] I_ALIGN (instr. align) EXC: ", cnt_test);
 
// skip if C-mode is implemented
if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_C)) == 0) {
614,7 → 625,7
// Breakpoint instruction
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] BREAK (break instr.) EXC: ", cnt_test);
PRINT_STANDARD("[%i] BREAK EXC: ", cnt_test);
cnt_test++;
 
asm volatile("EBREAK");
631,14 → 642,17
// Unaligned load address
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] L_ALIGN (load addr alignment) EXC: ", cnt_test);
PRINT_STANDARD("[%i] L_ALIGN (load align) EXC: ", cnt_test);
cnt_test++;
 
// load from unaligned address
neorv32_cpu_load_unsigned_word(ADDR_UNALIGNED_1);
asm volatile ("li %[da], 0xcafe1230 \n" // initialize destination register with known value
"lw %[da], 0(%[ad]) " // must not update destination register to to exception
: [da] "=r" (tmp_b) : [ad] "r" (ADDR_UNALIGNED_1));
 
if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_L_MISALIGNED) &&
(neorv32_cpu_csr_read(CSR_MTVAL) == ADDR_UNALIGNED_1)) {
(neorv32_cpu_csr_read(CSR_MTVAL) == ADDR_UNALIGNED_1) &&
(tmp_b == 0xcafe1230)) { // make sure dest. reg is not updated
test_ok();
}
else {
650,16 → 664,20
// Load access fault
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] L_ACC (load bus access) EXC: ", cnt_test);
PRINT_STANDARD("[%i] L_ACC (load access) EXC: ", cnt_test);
cnt_test++;
 
tmp_a = (1 << BUSKEEPER_ERR_FLAG) | (1 << BUSKEEPER_ERR_TYPE);
 
// load from unreachable aligned address
neorv32_cpu_load_unsigned_word(ADDR_UNREACHABLE);
asm volatile ("li %[da], 0xcafe1230 \n" // initialize destination register with known value
"lw %[da], 0(%[ad]) " // must not update destination register to to exception
: [da] "=r" (tmp_b) : [ad] "r" (ADDR_UNREACHABLE));
 
if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_L_ACCESS) && // load bus access error exception
(NEORV32_BUSKEEPER.CTRL = tmp_a)) { // buskeeper: error flag + timeout error
(neorv32_cpu_csr_read(CSR_MTVAL) == ADDR_UNREACHABLE) &&
(tmp_b == 0xcafe1230) && // make sure dest. reg is not updated
(NEORV32_BUSKEEPER.CTRL = tmp_a)) { // buskeeper: error flag + timeout error
test_ok();
}
else {
671,13 → 689,22
// Unaligned store address
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] S_ALIGN (store addr alignment) EXC: ", cnt_test);
PRINT_STANDARD("[%i] S_ALIGN (store align) EXC: ", cnt_test);
cnt_test++;
 
// initialize test variable
store_access_addr[0] = 0x11223344;
store_access_addr[1] = 0x55667788;
tmp_a = (uint32_t)(&store_access_addr[0]);
tmp_a += 2; // make word-unaligned
 
// store to unaligned address
neorv32_cpu_store_unsigned_word(ADDR_UNALIGNED_2, 0);
neorv32_cpu_store_unsigned_word(tmp_a, 0);
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_S_MISALIGNED) {
if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_S_MISALIGNED) &&
(neorv32_cpu_csr_read(CSR_MTVAL) == tmp_a) &&
(store_access_addr[0] == 0x11223344) &&
(store_access_addr[1] == 0x55667788)) { // make sure memory was not altered
test_ok();
}
else {
689,7 → 716,7
// Store access fault
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] S_ACC (store bus access) EXC: ", cnt_test);
PRINT_STANDARD("[%i] S_ACC (store access) EXC: ", cnt_test);
cnt_test++;
 
tmp_a = (1 << BUSKEEPER_ERR_FLAG) | (0 << BUSKEEPER_ERR_TYPE);
698,6 → 725,7
neorv32_cpu_store_unsigned_word(ADDR_READONLY, 0);
 
if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_S_ACCESS) && // store bus access error exception
(neorv32_cpu_csr_read(CSR_MTVAL) == ADDR_READONLY) &&
(NEORV32_BUSKEEPER.CTRL == tmp_a)) { // buskeeper: error flag + device error
test_ok();
}
710,10 → 738,10
// Environment call from M-mode
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] ENVCALL (ecall instr.) from M-mode EXC: ", cnt_test);
PRINT_STANDARD("[%i] ENVCALL M-mode EXC: ", cnt_test);
cnt_test++;
 
asm volatile("ECALL");
asm volatile("ecall");
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MENV_CALL) {
test_ok();
727,14 → 755,14
// Environment call from U-mode
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] ENVCALL (ecall instr.) from U-mode EXC: ", cnt_test);
PRINT_STANDARD("[%i] ENVCALL U-mode EXC: ", cnt_test);
 
cnt_test++;
 
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
neorv32_cpu_goto_user_mode();
goto_user_mode();
{
asm volatile("ECALL");
asm volatile("ecall");
}
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_UENV_CALL) {
1408,7 → 1436,7
 
 
// ----------------------------------------------------------
// Test WFI ("sleep") instructions, wakeup via MTIME
// Test WFI ("sleep") instruction (executed in user mode), wakeup via MTIME
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] WFI (sleep instruction, wake-up via MTIME): ", cnt_test);
1421,9 → 1449,15
// enable mtime interrupt
neorv32_cpu_irq_enable(CSR_MIE_MTIE);
 
// put CPU into sleep mode
asm volatile ("wfi");
// clear mstatus.TW to allow execution of WFI also in user-mode
neorv32_cpu_csr_write(CSR_MSTATUS, neorv32_cpu_csr_read(CSR_MSTATUS) & ~(1<<CSR_MSTATUS_TW));
 
// put CPU into sleep mode (from user mode)
goto_user_mode();
{
asm volatile ("wfi");
}
 
// no more mtime interrupts
neorv32_cpu_irq_disable(CSR_MIE_MTIE);
neorv32_mtime_set_timecmp(-1);
1445,7 → 1479,7
cnt_test++;
 
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
neorv32_cpu_goto_user_mode();
goto_user_mode();
{
// access to misa not allowed for user-level programs
tmp_a = neorv32_cpu_csr_read(CSR_MISA);
1488,10 → 1522,10
// ----------------------------------------------------------
// Test physical memory protection
// ----------------------------------------------------------
PRINT_STANDARD("[%i] PMP - Physical memory protection: ", cnt_test);
PRINT_STANDARD("[%i] PMP:\n", cnt_test);
 
// check if PMP is implemented
if (neorv32_cpu_pmp_get_num_regions() != 0) {
// check if PMP is implemented (two regions are required for these tests)
if (neorv32_cpu_pmp_get_num_regions() > 1) {
 
// Create PMP protected region
// ---------------------------------------------
1498,22 → 1532,19
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
cnt_test++;
 
// find out minimal region size (granularity)
tmp_b = neorv32_cpu_pmp_get_granularity();
tmp_a = (uint32_t)(&pmp_access_addr); // base address of protected region
tmp_b = PMP_TOR << PMPCFG_A_LSB; // enable region, but absolutely no access rights
 
tmp_a = NEORV32_SYSINFO.DSPACE_BASE; // base address of protected region
PRINT_STANDARD("Creating protected page (NAPOT, [!X,!W,!R], %u bytes) @ 0x%x: ", tmp_b, tmp_a);
 
// configure
int pmp_return = neorv32_cpu_pmp_configure_region(0, tmp_a, tmp_b, PMPCFG_MODE_NAPOT << PMPCFG_A_LSB); // NAPOT, NO read/write/execute permissions
 
if ((pmp_return == 0) && (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) {
int pmp_res = 0;
PRINT_STANDARD("Setup region 0 OFF [ -, -, -] @ 0x%x\n", tmp_a);
pmp_res += neorv32_cpu_pmp_configure_region(0, tmp_a, 0);
PRINT_STANDARD("Setup region 1 TOR [!X,!W,!R] @ 0x%x ", tmp_a+4);
pmp_res += neorv32_cpu_pmp_configure_region(1, tmp_a+4, tmp_b);
if ((pmp_res == 0) && (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) {
test_ok();
}
else {
if (neorv32_cpu_csr_read(CSR_PMPCFG0) & 0x80) {
PRINT_CRITICAL("%c[1m<Entry LOCKED!> %c[0m\n", 27, 27);
}
test_fail();
}
 
1524,22 → 1555,18
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
 
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
neorv32_cpu_goto_user_mode();
goto_user_mode();
{
asm volatile ("jalr ra, %[input_i]" : : [input_i] "r" (tmp_a)); // call address to execute -> should fail
}
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
// switch back to machine mode (if not already)
asm volatile ("ecall");
 
test_fail();
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ACCESS) {
asm volatile ("ecall"); // switch back to machine mode (if not already)
test_ok();
}
else {
// switch back to machine mode (if not already)
asm volatile ("ecall");
 
test_ok();
asm volatile ("ecall"); // switch back to machine mode (if not already)
test_fail();
}
 
 
1549,17 → 1576,15
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
 
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
neorv32_cpu_goto_user_mode();
tmp_b = 0;
goto_user_mode();
{
tmp_b = neorv32_cpu_load_unsigned_word(tmp_a); // load access -> should fail
asm volatile ("li %[da], 0xcafe0000 \n" // initialize destination register with known value
"lw %[da], 0(%[ad]) " // must not update destination register to to exception
: [da] "=r" (tmp_b) : [ad] "r" (tmp_a));
}
 
if (tmp_b != 0) {
PRINT_CRITICAL("%c[1m<SECURITY FAILURE> %c[0m\n", 27, 27);
}
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_L_ACCESS) {
if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_L_ACCESS) &&
(tmp_b == 0xcafe0000)) { // destination register not altered
// switch back to machine mode (if not already)
asm volatile ("ecall");
 
1579,7 → 1604,7
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
 
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
neorv32_cpu_goto_user_mode();
goto_user_mode();
{
neorv32_cpu_store_unsigned_word(tmp_a, 0); // store access -> should fail
}
1774,9 → 1799,27
}
 
 
 
/**********************************************************************//**
* Simulation-based function to trigger CPU interrupts (MSI, MEI, FIRQ4..7).
* Switch from privilege mode MACHINE to privilege mode USER.
*
* @warning This function requires the U extension to be implemented.
**************************************************************************/
void __attribute__((naked)) goto_user_mode(void) {
 
// make sure to use NO registers in here! -> naked
 
asm volatile ("csrw mepc, ra \n" // move return address to mepc so we can return using "mret". also, we can now use ra as temp register
"li ra, %[input_imm] \n" // bit mask to clear the two MPP bits
"csrrc zero, mstatus, ra \n" // clear MPP bits -> MPP=u-mode
"mret \n" // return and switch to user mode
: : [input_imm] "i" ((1<<CSR_MSTATUS_MPP_H) | (1<<CSR_MSTATUS_MPP_L)));
}
 
 
/**********************************************************************//**
* Simulation-based function to trigger CPU interrupts (MSI, MEI).
*
* @param[in] sel IRQ select mask (bit positions according to #NEORV32_CSR_MIE_enum).
**************************************************************************/
void sim_irq_trigger(uint32_t sel) {
1793,7 → 1836,7
void global_trap_handler(void) {
 
// clear all pending FIRQs
neorv32_cpu_csr_write(CSR_MIP, -1);
neorv32_cpu_csr_write(CSR_MIP, 0);
 
// hack: always come back in MACHINE MODE
register uint32_t mask = (1<<CSR_MSTATUS_MPP_H) | (1<<CSR_MSTATUS_MPP_L);
1844,7 → 1887,7
* main function returns (called by crt0.S start-up code): Output minimal
* test report to physical UART
**************************************************************************/
int __neorv32_crt0_after_main(int32_t return_code) {
void __neorv32_crt0_after_main(int32_t return_code) {
 
// make sure sim mode is disabled and UARTs are actually enabled
NEORV32_UART0.CTRL |= (1 << UART_CTRL_EN);
1853,6 → 1896,4
 
// minimal result report
PRINT_CRITICAL("%u/%u\n", (uint32_t)return_code, (uint32_t)cnt_test);
 
return 0;
}
/sw/lib/include/neorv32.h
114,33 → 114,21
CSR_MTVAL = 0x343, /**< 0x343 - mtval (r/-): Machine bad address or instruction */
CSR_MIP = 0x344, /**< 0x344 - mip (r/-): Machine interrupt pending register */
 
CSR_PMPCFG0 = 0x3a0, /**< 0x3a0 - pmpcfg0 (r/w): Physical memory protection configuration register 0 */
CSR_PMPCFG1 = 0x3a1, /**< 0x3a1 - pmpcfg1 (r/w): Physical memory protection configuration register 1 */
CSR_PMPCFG2 = 0x3a2, /**< 0x3a2 - pmpcfg2 (r/w): Physical memory protection configuration register 2 */
CSR_PMPCFG3 = 0x3a3, /**< 0x3a3 - pmpcfg3 (r/w): Physical memory protection configuration register 3 */
CSR_PMPCFG4 = 0x3a4, /**< 0x3a4 - pmpcfg4 (r/w): Physical memory protection configuration register 4 */
CSR_PMPCFG5 = 0x3a5, /**< 0x3a5 - pmpcfg5 (r/w): Physical memory protection configuration register 5 */
CSR_PMPCFG6 = 0x3a6, /**< 0x3a6 - pmpcfg6 (r/w): Physical memory protection configuration register 6 */
CSR_PMPCFG7 = 0x3a7, /**< 0x3a7 - pmpcfg7 (r/w): Physical memory protection configuration register 7 */
CSR_PMPCFG8 = 0x3a8, /**< 0x3a8 - pmpcfg8 (r/w): Physical memory protection configuration register 8 */
CSR_PMPCFG9 = 0x3a9, /**< 0x3a9 - pmpcfg9 (r/w): Physical memory protection configuration register 9 */
CSR_PMPCFG10 = 0x3aa, /**< 0x3aa - pmpcfg10 (r/w): Physical memory protection configuration register 10 */
CSR_PMPCFG11 = 0x3ab, /**< 0x3ab - pmpcfg11 (r/w): Physical memory protection configuration register 11 */
CSR_PMPCFG12 = 0x3ac, /**< 0x3ac - pmpcfg12 (r/w): Physical memory protection configuration register 12 */
CSR_PMPCFG13 = 0x3ad, /**< 0x3ad - pmpcfg13 (r/w): Physical memory protection configuration register 13 */
CSR_PMPCFG14 = 0x3ae, /**< 0x3ae - pmpcfg14 (r/w): Physical memory protection configuration register 14 */
CSR_PMPCFG15 = 0x3af, /**< 0x3af - pmpcfg15 (r/w): Physical memory protection configuration register 15 */
CSR_PMPCFG0 = 0x3a0, /**< 0x3a0 - pmpcfg0 (r/w): Physical memory protection configuration register 0 (entries 0..3) */
CSR_PMPCFG1 = 0x3a1, /**< 0x3a1 - pmpcfg1 (r/w): Physical memory protection configuration register 1 (entries 4..7) */
CSR_PMPCFG2 = 0x3a2, /**< 0x3a2 - pmpcfg2 (r/w): Physical memory protection configuration register 2 (entries 8..11) */
CSR_PMPCFG3 = 0x3a3, /**< 0x3a3 - pmpcfg3 (r/w): Physical memory protection configuration register 3 (entries 12..15) */
 
CSR_PMPADDR0 = 0x3b0, /**< 0x3b0 - pmpaddr0 (r/w): Physical memory protection address register 0 */
CSR_PMPADDR1 = 0x3b1, /**< 0x3b1 - pmpaddr1 (r/w): Physical memory protection address register 1 */
CSR_PMPADDR2 = 0x3b2, /**< 0x3b2 - pmpaddr2 (r/w): Physical memory protection address register 2 */
CSR_PMPADDR3 = 0x3b3, /**< 0x3b3 - pmpaddr3 (r/w): Physical memory protection address register 3 */
CSR_PMPADDR4 = 0x3b4, /**< 0x3b4 - pmpaddr4 (r/w): Physical memory protection address register 4 */
CSR_PMPADDR5 = 0x3b5, /**< 0x3b5 - pmpaddr5 (r/w): Physical memory protection address register 5 */
CSR_PMPADDR6 = 0x3b6, /**< 0x3b6 - pmpaddr6 (r/w): Physical memory protection address register 6 */
CSR_PMPADDR7 = 0x3b7, /**< 0x3b7 - pmpaddr7 (r/w): Physical memory protection address register 7 */
CSR_PMPADDR8 = 0x3b8, /**< 0x3b8 - pmpaddr8 (r/w): Physical memory protection address register 8 */
CSR_PMPADDR9 = 0x3b9, /**< 0x3b9 - pmpaddr9 (r/w): Physical memory protection address register 9 */
CSR_PMPADDR0 = 0x3b0, /**< 0x3b0 - pmpaddr0 (r/w): Physical memory protection address register 0 */
CSR_PMPADDR1 = 0x3b1, /**< 0x3b1 - pmpaddr1 (r/w): Physical memory protection address register 1 */
CSR_PMPADDR2 = 0x3b2, /**< 0x3b2 - pmpaddr2 (r/w): Physical memory protection address register 2 */
CSR_PMPADDR3 = 0x3b3, /**< 0x3b3 - pmpaddr3 (r/w): Physical memory protection address register 3 */
CSR_PMPADDR4 = 0x3b4, /**< 0x3b4 - pmpaddr4 (r/w): Physical memory protection address register 4 */
CSR_PMPADDR5 = 0x3b5, /**< 0x3b5 - pmpaddr5 (r/w): Physical memory protection address register 5 */
CSR_PMPADDR6 = 0x3b6, /**< 0x3b6 - pmpaddr6 (r/w): Physical memory protection address register 6 */
CSR_PMPADDR7 = 0x3b7, /**< 0x3b7 - pmpaddr7 (r/w): Physical memory protection address register 7 */
CSR_PMPADDR8 = 0x3b8, /**< 0x3b8 - pmpaddr8 (r/w): Physical memory protection address register 8 */
CSR_PMPADDR9 = 0x3b9, /**< 0x3b9 - pmpaddr9 (r/w): Physical memory protection address register 9 */
CSR_PMPADDR10 = 0x3ba, /**< 0x3ba - pmpaddr10 (r/w): Physical memory protection address register 10 */
CSR_PMPADDR11 = 0x3bb, /**< 0x3bb - pmpaddr11 (r/w): Physical memory protection address register 11 */
CSR_PMPADDR12 = 0x3bc, /**< 0x3bc - pmpaddr12 (r/w): Physical memory protection address register 12 */
147,54 → 135,6
CSR_PMPADDR13 = 0x3bd, /**< 0x3bd - pmpaddr13 (r/w): Physical memory protection address register 13 */
CSR_PMPADDR14 = 0x3be, /**< 0x3be - pmpaddr14 (r/w): Physical memory protection address register 14 */
CSR_PMPADDR15 = 0x3bf, /**< 0x3bf - pmpaddr15 (r/w): Physical memory protection address register 15 */
CSR_PMPADDR16 = 0x3c0, /**< 0x3c0 - pmpaddr16 (r/w): Physical memory protection address register 16 */
CSR_PMPADDR17 = 0x3c1, /**< 0x3c1 - pmpaddr17 (r/w): Physical memory protection address register 17 */
CSR_PMPADDR18 = 0x3c2, /**< 0x3c2 - pmpaddr18 (r/w): Physical memory protection address register 18 */
CSR_PMPADDR19 = 0x3c3, /**< 0x3c3 - pmpaddr19 (r/w): Physical memory protection address register 19 */
CSR_PMPADDR20 = 0x3c4, /**< 0x3c4 - pmpaddr20 (r/w): Physical memory protection address register 20 */
CSR_PMPADDR21 = 0x3c5, /**< 0x3c5 - pmpaddr21 (r/w): Physical memory protection address register 21 */
CSR_PMPADDR22 = 0x3c6, /**< 0x3c6 - pmpaddr22 (r/w): Physical memory protection address register 22 */
CSR_PMPADDR23 = 0x3c7, /**< 0x3c7 - pmpaddr23 (r/w): Physical memory protection address register 23 */
CSR_PMPADDR24 = 0x3c8, /**< 0x3c8 - pmpaddr24 (r/w): Physical memory protection address register 24 */
CSR_PMPADDR25 = 0x3c9, /**< 0x3c9 - pmpaddr25 (r/w): Physical memory protection address register 25 */
CSR_PMPADDR26 = 0x3ca, /**< 0x3ca - pmpaddr26 (r/w): Physical memory protection address register 26 */
CSR_PMPADDR27 = 0x3cb, /**< 0x3cb - pmpaddr27 (r/w): Physical memory protection address register 27 */
CSR_PMPADDR28 = 0x3cc, /**< 0x3cc - pmpaddr28 (r/w): Physical memory protection address register 28 */
CSR_PMPADDR29 = 0x3cd, /**< 0x3cd - pmpaddr29 (r/w): Physical memory protection address register 29 */
CSR_PMPADDR30 = 0x3ce, /**< 0x3ce - pmpaddr30 (r/w): Physical memory protection address register 30 */
CSR_PMPADDR31 = 0x3cf, /**< 0x3cf - pmpaddr31 (r/w): Physical memory protection address register 31 */
CSR_PMPADDR32 = 0x3d0, /**< 0x3d0 - pmpaddr32 (r/w): Physical memory protection address register 32 */
CSR_PMPADDR33 = 0x3d1, /**< 0x3d1 - pmpaddr33 (r/w): Physical memory protection address register 33 */
CSR_PMPADDR34 = 0x3d2, /**< 0x3d2 - pmpaddr34 (r/w): Physical memory protection address register 34 */
CSR_PMPADDR35 = 0x3d3, /**< 0x3d3 - pmpaddr35 (r/w): Physical memory protection address register 35 */
CSR_PMPADDR36 = 0x3d4, /**< 0x3d4 - pmpaddr36 (r/w): Physical memory protection address register 36 */
CSR_PMPADDR37 = 0x3d5, /**< 0x3d5 - pmpaddr37 (r/w): Physical memory protection address register 37 */
CSR_PMPADDR38 = 0x3d6, /**< 0x3d6 - pmpaddr38 (r/w): Physical memory protection address register 38 */
CSR_PMPADDR39 = 0x3d7, /**< 0x3d7 - pmpaddr39 (r/w): Physical memory protection address register 39 */
CSR_PMPADDR40 = 0x3d8, /**< 0x3d8 - pmpaddr40 (r/w): Physical memory protection address register 40 */
CSR_PMPADDR41 = 0x3d9, /**< 0x3d9 - pmpaddr41 (r/w): Physical memory protection address register 41 */
CSR_PMPADDR42 = 0x3da, /**< 0x3da - pmpaddr42 (r/w): Physical memory protection address register 42 */
CSR_PMPADDR43 = 0x3db, /**< 0x3db - pmpaddr43 (r/w): Physical memory protection address register 43 */
CSR_PMPADDR44 = 0x3dc, /**< 0x3dc - pmpaddr44 (r/w): Physical memory protection address register 44 */
CSR_PMPADDR45 = 0x3dd, /**< 0x3dd - pmpaddr45 (r/w): Physical memory protection address register 45 */
CSR_PMPADDR46 = 0x3de, /**< 0x3de - pmpaddr46 (r/w): Physical memory protection address register 46 */
CSR_PMPADDR47 = 0x3df, /**< 0x3df - pmpaddr47 (r/w): Physical memory protection address register 47 */
CSR_PMPADDR48 = 0x3e0, /**< 0x3e0 - pmpaddr48 (r/w): Physical memory protection address register 48 */
CSR_PMPADDR49 = 0x3e1, /**< 0x3e1 - pmpaddr49 (r/w): Physical memory protection address register 49 */
CSR_PMPADDR50 = 0x3e2, /**< 0x3e2 - pmpaddr50 (r/w): Physical memory protection address register 50 */
CSR_PMPADDR51 = 0x3e3, /**< 0x3e3 - pmpaddr51 (r/w): Physical memory protection address register 51 */
CSR_PMPADDR52 = 0x3e4, /**< 0x3e4 - pmpaddr52 (r/w): Physical memory protection address register 52 */
CSR_PMPADDR53 = 0x3e5, /**< 0x3e5 - pmpaddr53 (r/w): Physical memory protection address register 53 */
CSR_PMPADDR54 = 0x3e6, /**< 0x3e6 - pmpaddr54 (r/w): Physical memory protection address register 54 */
CSR_PMPADDR55 = 0x3e7, /**< 0x3e7 - pmpaddr55 (r/w): Physical memory protection address register 55 */
CSR_PMPADDR56 = 0x3e8, /**< 0x3e8 - pmpaddr56 (r/w): Physical memory protection address register 56 */
CSR_PMPADDR57 = 0x3e9, /**< 0x3e9 - pmpaddr57 (r/w): Physical memory protection address register 57 */
CSR_PMPADDR58 = 0x3ea, /**< 0x3ea - pmpaddr58 (r/w): Physical memory protection address register 58 */
CSR_PMPADDR59 = 0x3eb, /**< 0x3eb - pmpaddr59 (r/w): Physical memory protection address register 59 */
CSR_PMPADDR60 = 0x3ec, /**< 0x3ec - pmpaddr60 (r/w): Physical memory protection address register 60 */
CSR_PMPADDR61 = 0x3ed, /**< 0x3ed - pmpaddr61 (r/w): Physical memory protection address register 61 */
CSR_PMPADDR62 = 0x3ee, /**< 0x3ee - pmpaddr62 (r/w): Physical memory protection address register 62 */
CSR_PMPADDR63 = 0x3ef, /**< 0x3ef - pmpaddr63 (r/w): Physical memory protection address register 63 */
 
CSR_TSELECT = 0x7a0, /**< 0x7a0 - tselect (r/(w)): Trigger select */
CSR_TDATA1 = 0x7a1, /**< 0x7a1 - tdata1 (r/(w)): Trigger data register 0 */
205,9 → 145,10
CSR_MCONTEXT = 0x7a8, /**< 0x7a8 - mcontext (r/(w)): Machine context register */
CSR_SCONTEXT = 0x7aa, /**< 0x7aa - scontext (r/(w)): Supervisor context register */
 
/* not accessible by m-mode software */
//CSR_DCSR = 0x7b0, /**< 0x7b0 - dcsr (-/-): Debug status and control register */
//CSR_DPC = 0x7b1, /**< 0x7b1 - dpc (-/-): Debug program counter */
//CSR_DSCRATCHC = 0x7b2, /**< 0x7b2 - dscratch (-/-): Debug scratch register */
//CSR_DSCRATCH = 0x7b2, /**< 0x7b2 - dscratch (-/-): Debug scratch register */
 
CSR_MCYCLE = 0xb00, /**< 0xb00 - mcycle (r/w): Machine cycle counter low word */
CSR_MINSTRET = 0xb02, /**< 0xb02 - minstret (r/w): Machine instructions-retired counter low word */
279,10 → 220,72
CSR_TIME = 0xc01, /**< 0xc01 - time (r/-): Timer low word (from MTIME.TIME_LO) */
CSR_INSTRET = 0xc02, /**< 0xc02 - instret (r/-): Instructions-retired counter low word (from MINSTRET) */
 
/* not implemented */
//CSR_HPMCOUNTER3 = 0xc03, /**< 0xc03 - hpmcounter3 (r/-): User hardware performance monitor 3 counter low word */
//CSR_HPMCOUNTER4 = 0xc04, /**< 0xc04 - hpmcounter4 (r/-): User hardware performance monitor 4 counter low word */
//CSR_HPMCOUNTER5 = 0xc05, /**< 0xc05 - hpmcounter5 (r/-): User hardware performance monitor 5 counter low word */
//CSR_HPMCOUNTER6 = 0xc06, /**< 0xc06 - hpmcounter6 (r/-): User hardware performance monitor 6 counter low word */
//CSR_HPMCOUNTER7 = 0xc07, /**< 0xc07 - hpmcounter7 (r/-): User hardware performance monitor 7 counter low word */
//CSR_HPMCOUNTER8 = 0xc08, /**< 0xc08 - hpmcounter8 (r/-): User hardware performance monitor 8 counter low word */
//CSR_HPMCOUNTER9 = 0xc09, /**< 0xc09 - hpmcounter9 (r/-): User hardware performance monitor 9 counter low word */
//CSR_HPMCOUNTER10 = 0xc0a, /**< 0xc0a - hpmcounter10 (r/-): User hardware performance monitor 10 counter low word */
//CSR_HPMCOUNTER11 = 0xc0b, /**< 0xc0b - hpmcounter11 (r/-): User hardware performance monitor 11 counter low word */
//CSR_HPMCOUNTER12 = 0xc0c, /**< 0xc0c - hpmcounter12 (r/-): User hardware performance monitor 12 counter low word */
//CSR_HPMCOUNTER13 = 0xc0d, /**< 0xc0d - hpmcounter13 (r/-): User hardware performance monitor 13 counter low word */
//CSR_HPMCOUNTER14 = 0xc0e, /**< 0xc0e - hpmcounter14 (r/-): User hardware performance monitor 14 counter low word */
//CSR_HPMCOUNTER15 = 0xc0f, /**< 0xc0f - hpmcounter15 (r/-): User hardware performance monitor 15 counter low word */
//CSR_HPMCOUNTER16 = 0xc10, /**< 0xc10 - hpmcounter16 (r/-): User hardware performance monitor 16 counter low word */
//CSR_HPMCOUNTER17 = 0xc11, /**< 0xc11 - hpmcounter17 (r/-): User hardware performance monitor 17 counter low word */
//CSR_HPMCOUNTER18 = 0xc12, /**< 0xc12 - hpmcounter18 (r/-): User hardware performance monitor 18 counter low word */
//CSR_HPMCOUNTER19 = 0xc13, /**< 0xc13 - hpmcounter19 (r/-): User hardware performance monitor 19 counter low word */
//CSR_HPMCOUNTER20 = 0xc14, /**< 0xc14 - hpmcounter20 (r/-): User hardware performance monitor 20 counter low word */
//CSR_HPMCOUNTER21 = 0xc15, /**< 0xc15 - hpmcounter21 (r/-): User hardware performance monitor 21 counter low word */
//CSR_HPMCOUNTER22 = 0xc16, /**< 0xc16 - hpmcounter22 (r/-): User hardware performance monitor 22 counter low word */
//CSR_HPMCOUNTER23 = 0xc17, /**< 0xc17 - hpmcounter23 (r/-): User hardware performance monitor 23 counter low word */
//CSR_HPMCOUNTER24 = 0xc18, /**< 0xc18 - hpmcounter24 (r/-): User hardware performance monitor 24 counter low word */
//CSR_HPMCOUNTER25 = 0xc19, /**< 0xc19 - hpmcounter25 (r/-): User hardware performance monitor 25 counter low word */
//CSR_HPMCOUNTER26 = 0xc1a, /**< 0xc1a - hpmcounter26 (r/-): User hardware performance monitor 26 counter low word */
//CSR_HPMCOUNTER27 = 0xc1b, /**< 0xc1b - hpmcounter27 (r/-): User hardware performance monitor 27 counter low word */
//CSR_HPMCOUNTER28 = 0xc1c, /**< 0xc1c - hpmcounter28 (r/-): User hardware performance monitor 28 counter low word */
//CSR_HPMCOUNTER29 = 0xc1d, /**< 0xc1d - hpmcounter29 (r/-): User hardware performance monitor 29 counter low word */
//CSR_HPMCOUNTER30 = 0xc1e, /**< 0xc1e - hpmcounter30 (r/-): User hardware performance monitor 30 counter low word */
//CSR_HPMCOUNTER31 = 0xc1f, /**< 0xc1f - hpmcounter31 (r/-): User hardware performance monitor 31 counter low word */
 
CSR_CYCLEH = 0xc80, /**< 0xc80 - cycleh (r/-): Cycle counter high word (from MCYCLEH) */
CSR_TIMEH = 0xc81, /**< 0xc81 - timeh (r/-): Timer high word (from MTIME.TIME_HI) */
CSR_INSTRETH = 0xc82, /**< 0xc82 - instreth (r/-): Instructions-retired counter high word (from MINSTRETH) */
 
/* not implemented */
//CSR_HPMCOUNTER3H = 0xc83, /**< 0xc83 - hpmcounter3h (r/-): User hardware performance monitor 3 counter high word */
//CSR_HPMCOUNTER4H = 0xc84, /**< 0xc84 - hpmcounter4h (r/-): User hardware performance monitor 4 counter high word */
//CSR_HPMCOUNTER5H = 0xc85, /**< 0xc85 - hpmcounter5h (r/-): User hardware performance monitor 5 counter high word */
//CSR_HPMCOUNTER6H = 0xc86, /**< 0xc86 - hpmcounter6h (r/-): User hardware performance monitor 6 counter high word */
//CSR_HPMCOUNTER7H = 0xc87, /**< 0xc87 - hpmcounter7h (r/-): User hardware performance monitor 7 counter high word */
//CSR_HPMCOUNTER8H = 0xc88, /**< 0xc88 - hpmcounter8h (r/-): User hardware performance monitor 8 counter high word */
//CSR_HPMCOUNTER9H = 0xc89, /**< 0xc89 - hpmcounter9h (r/-): User hardware performance monitor 9 counter high word */
//CSR_HPMCOUNTER10H = 0xc8a, /**< 0xc8a - hpmcounter10h (r/-): User hardware performance monitor 10 counter high word */
//CSR_HPMCOUNTER11H = 0xc8b, /**< 0xc8b - hpmcounter11h (r/-): User hardware performance monitor 11 counter high word */
//CSR_HPMCOUNTER12H = 0xc8c, /**< 0xc8c - hpmcounter12h (r/-): User hardware performance monitor 12 counter high word */
//CSR_HPMCOUNTER13H = 0xc8d, /**< 0xc8d - hpmcounter13h (r/-): User hardware performance monitor 13 counter high word */
//CSR_HPMCOUNTER14H = 0xc8e, /**< 0xc8e - hpmcounter14h (r/-): User hardware performance monitor 14 counter high word */
//CSR_HPMCOUNTER15H = 0xc8f, /**< 0xc8f - hpmcounter15h (r/-): User hardware performance monitor 15 counter high word */
//CSR_HPMCOUNTER16H = 0xc90, /**< 0xc90 - hpmcounter16h (r/-): User hardware performance monitor 16 counter high word */
//CSR_HPMCOUNTER17H = 0xc91, /**< 0xc91 - hpmcounter17h (r/-): User hardware performance monitor 17 counter high word */
//CSR_HPMCOUNTER18H = 0xc92, /**< 0xc92 - hpmcounter18h (r/-): User hardware performance monitor 18 counter high word */
//CSR_HPMCOUNTER19H = 0xc93, /**< 0xc93 - hpmcounter19h (r/-): User hardware performance monitor 19 counter high word */
//CSR_HPMCOUNTER20H = 0xc94, /**< 0xc94 - hpmcounter20h (r/-): User hardware performance monitor 20 counter high word */
//CSR_HPMCOUNTER21H = 0xc95, /**< 0xc95 - hpmcounter21h (r/-): User hardware performance monitor 21 counter high word */
//CSR_HPMCOUNTER22H = 0xc96, /**< 0xc96 - hpmcounter22h (r/-): User hardware performance monitor 22 counter high word */
//CSR_HPMCOUNTER23H = 0xc97, /**< 0xc97 - hpmcounter23h (r/-): User hardware performance monitor 23 counter high word */
//CSR_HPMCOUNTER24H = 0xc98, /**< 0xc98 - hpmcounter24h (r/-): User hardware performance monitor 24 counter high word */
//CSR_HPMCOUNTER25H = 0xc99, /**< 0xc99 - hpmcounter25h (r/-): User hardware performance monitor 25 counter high word */
//CSR_HPMCOUNTER26H = 0xc9a, /**< 0xc9a - hpmcounter26h (r/-): User hardware performance monitor 26 counter high word */
//CSR_HPMCOUNTER27H = 0xc9b, /**< 0xc9b - hpmcounter27h (r/-): User hardware performance monitor 27 counter high word */
//CSR_HPMCOUNTER28H = 0xc9c, /**< 0xc9c - hpmcounter28h (r/-): User hardware performance monitor 28 counter high word */
//CSR_HPMCOUNTER29H = 0xc9d, /**< 0xc9d - hpmcounter29h (r/-): User hardware performance monitor 29 counter high word */
//CSR_HPMCOUNTER30H = 0xc9e, /**< 0xc9e - hpmcounter30h (r/-): User hardware performance monitor 30 counter high word */
//CSR_HPMCOUNTER31H = 0xc9f, /**< 0xc9f - hpmcounter31h (r/-): User hardware performance monitor 31 counter high word */
 
CSR_MVENDORID = 0xf11, /**< 0xf11 - mvendorid (r/-): Vendor ID */
CSR_MARCHID = 0xf12, /**< 0xf12 - marchid (r/-): Architecture ID */
CSR_MIMPID = 0xf13, /**< 0xf13 - mimpid (r/-): Implementation ID/version */
289,7 → 292,7
CSR_MHARTID = 0xf14, /**< 0xf14 - mhartid (r/-): Hardware thread ID (always 0) */
CSR_MCONFIGPTR = 0xf15, /**< 0xf15 - mconfigptr (r/-): Machine configuration pointer register */
 
CSR_MXISA = 0xfc0 /**< 0xfc0 - xisa (r/-): NEORV32-specific machine "extended CPU ISA and extensions" */
CSR_MXISA = 0xfc0 /**< 0xfc0 - mxisa (r/-): NEORV32-specific machine "extended CPU ISA and extensions" */
};
 
 
300,7 → 303,8
CSR_MSTATUS_MIE = 3, /**< CPU mstatus CSR (3): MIE - Machine interrupt enable bit (r/w) */
CSR_MSTATUS_MPIE = 7, /**< CPU mstatus CSR (7): MPIE - Machine previous interrupt enable bit (r/w) */
CSR_MSTATUS_MPP_L = 11, /**< CPU mstatus CSR (11): MPP_L - Machine previous privilege mode bit low (r/w) */
CSR_MSTATUS_MPP_H = 12 /**< CPU mstatus CSR (12): MPP_H - Machine previous privilege mode bit high (r/w) */
CSR_MSTATUS_MPP_H = 12, /**< CPU mstatus CSR (12): MPP_H - Machine previous privilege mode bit high (r/w) */
CSR_MSTATUS_TW = 21 /**< CPU mstatus CSR (21): TW - Disallow execution of wfi instruction in user mode when set (r/w) */
};
 
 
381,29 → 385,29
 
 
/**********************************************************************//**
* CPU <b>mip</b> CSR (r/-): Machine interrupt pending (RISC-V spec.)
* CPU <b>mip</b> CSR (r/c): Machine interrupt pending (RISC-V spec.)
**************************************************************************/
enum NEORV32_CSR_MIP_enum {
CSR_MIP_MSIP = 3, /**< CPU mip CSR (3): MSIP - Machine software interrupt pending (r/-) */
CSR_MIP_MTIP = 7, /**< CPU mip CSR (7): MTIP - Machine timer interrupt pending (r/-) */
CSR_MIP_MEIP = 11, /**< CPU mip CSR (11): MEIP - Machine external interrupt pending (r/-) */
CSR_MIP_MSIP = 3, /**< CPU mip CSR (3): MSIP - Machine software interrupt pending (r/c) */
CSR_MIP_MTIP = 7, /**< CPU mip CSR (7): MTIP - Machine timer interrupt pending (r/c) */
CSR_MIP_MEIP = 11, /**< CPU mip CSR (11): MEIP - Machine external interrupt pending (r/c) */
 
CSR_MIP_FIRQ0P = 16, /**< CPU mip CSR (16): FIRQ0P - Fast interrupt channel 0 pending (r/-) */
CSR_MIP_FIRQ1P = 17, /**< CPU mip CSR (17): FIRQ1P - Fast interrupt channel 1 pending (r/-) */
CSR_MIP_FIRQ2P = 18, /**< CPU mip CSR (18): FIRQ2P - Fast interrupt channel 2 pending (r/-) */
CSR_MIP_FIRQ3P = 19, /**< CPU mip CSR (19): FIRQ3P - Fast interrupt channel 3 pending (r/-) */
CSR_MIP_FIRQ4P = 20, /**< CPU mip CSR (20): FIRQ4P - Fast interrupt channel 4 pending (r/-) */
CSR_MIP_FIRQ5P = 21, /**< CPU mip CSR (21): FIRQ5P - Fast interrupt channel 5 pending (r/-) */
CSR_MIP_FIRQ6P = 22, /**< CPU mip CSR (22): FIRQ6P - Fast interrupt channel 6 pending (r/-) */
CSR_MIP_FIRQ7P = 23, /**< CPU mip CSR (23): FIRQ7P - Fast interrupt channel 7 pending (r/-) */
CSR_MIP_FIRQ8P = 24, /**< CPU mip CSR (24): FIRQ8P - Fast interrupt channel 8 pending (r/-) */
CSR_MIP_FIRQ9P = 25, /**< CPU mip CSR (25): FIRQ9P - Fast interrupt channel 9 pending (r/-) */
CSR_MIP_FIRQ10P = 26, /**< CPU mip CSR (26): FIRQ10P - Fast interrupt channel 10 pending (r/-) */
CSR_MIP_FIRQ11P = 27, /**< CPU mip CSR (27): FIRQ11P - Fast interrupt channel 11 pending (r/-) */
CSR_MIP_FIRQ12P = 28, /**< CPU mip CSR (28): FIRQ12P - Fast interrupt channel 12 pending (r/-) */
CSR_MIP_FIRQ13P = 29, /**< CPU mip CSR (29): FIRQ13P - Fast interrupt channel 13 pending (r/-) */
CSR_MIP_FIRQ14P = 30, /**< CPU mip CSR (30): FIRQ14P - Fast interrupt channel 14 pending (r/-) */
CSR_MIP_FIRQ15P = 31 /**< CPU mip CSR (31): FIRQ15P - Fast interrupt channel 15 pending (r/-) */
CSR_MIP_FIRQ0P = 16, /**< CPU mip CSR (16): FIRQ0P - Fast interrupt channel 0 pending (r/c) */
CSR_MIP_FIRQ1P = 17, /**< CPU mip CSR (17): FIRQ1P - Fast interrupt channel 1 pending (r/c) */
CSR_MIP_FIRQ2P = 18, /**< CPU mip CSR (18): FIRQ2P - Fast interrupt channel 2 pending (r/c) */
CSR_MIP_FIRQ3P = 19, /**< CPU mip CSR (19): FIRQ3P - Fast interrupt channel 3 pending (r/c) */
CSR_MIP_FIRQ4P = 20, /**< CPU mip CSR (20): FIRQ4P - Fast interrupt channel 4 pending (r/c) */
CSR_MIP_FIRQ5P = 21, /**< CPU mip CSR (21): FIRQ5P - Fast interrupt channel 5 pending (r/c) */
CSR_MIP_FIRQ6P = 22, /**< CPU mip CSR (22): FIRQ6P - Fast interrupt channel 6 pending (r/c) */
CSR_MIP_FIRQ7P = 23, /**< CPU mip CSR (23): FIRQ7P - Fast interrupt channel 7 pending (r/c) */
CSR_MIP_FIRQ8P = 24, /**< CPU mip CSR (24): FIRQ8P - Fast interrupt channel 8 pending (r/c) */
CSR_MIP_FIRQ9P = 25, /**< CPU mip CSR (25): FIRQ9P - Fast interrupt channel 9 pending (r/c) */
CSR_MIP_FIRQ10P = 26, /**< CPU mip CSR (26): FIRQ10P - Fast interrupt channel 10 pending (r/c) */
CSR_MIP_FIRQ11P = 27, /**< CPU mip CSR (27): FIRQ11P - Fast interrupt channel 11 pending (r/c) */
CSR_MIP_FIRQ12P = 28, /**< CPU mip CSR (28): FIRQ12P - Fast interrupt channel 12 pending (r/c) */
CSR_MIP_FIRQ13P = 29, /**< CPU mip CSR (29): FIRQ13P - Fast interrupt channel 13 pending (r/c) */
CSR_MIP_FIRQ14P = 30, /**< CPU mip CSR (30): FIRQ14P - Fast interrupt channel 14 pending (r/c) */
CSR_MIP_FIRQ15P = 31 /**< CPU mip CSR (31): FIRQ15P - Fast interrupt channel 15 pending (r/c) */
};
 
 
474,14 → 478,14
 
 
/**********************************************************************//**
* CPU <b>pmpcfg</b> PMP configuration attributed
* CPU <b>pmpcfg</b> PMP configuration attributes (CSR entry 0)
**************************************************************************/
enum NEORV32_PMPCFG_ATTRIBUTES_enum {
PMPCFG_R = 0, /**< CPU pmpcfg attribute (0): Read */
PMPCFG_W = 1, /**< CPU pmpcfg attribute (1): Write */
PMPCFG_X = 2, /**< CPU pmpcfg attribute (2): Execute */
PMPCFG_A_LSB = 3, /**< CPU pmpcfg attribute (3): Mode LSB */
PMPCFG_A_MSB = 4, /**< CPU pmpcfg attribute (4): Mode MSB */
PMPCFG_A_LSB = 3, /**< CPU pmpcfg attribute (3): Mode LSB #NEORV32_PMP_MODES_enum */
PMPCFG_A_MSB = 4, /**< CPU pmpcfg attribute (4): Mode MSB #NEORV32_PMP_MODES_enum */
PMPCFG_L = 7 /**< CPU pmpcfg attribute (7): Locked */
};
 
488,7 → 492,10
/**********************************************************************//**
* PMP modes
**************************************************************************/
#define PMPCFG_MODE_NAPOT 3
enum NEORV32_PMP_MODES_enum {
PMP_OFF = 0, /**< '00': entry disabled */
PMP_TOR = 1 /**< '01': TOR mode (top of region) */
};
 
 
/**********************************************************************//**
947,9 → 954,8
 
/** BUSKEEPER control/data register bits */
enum NEORV32_BUSKEEPER_CTRL_enum {
BUSKEEPER_ERR_TYPE = 0, /**< BUSKEEPER control register( 0) (r/-): Bus error type: 0=device error, 1=access timeout */
BUSKEEPER_NULL_CHECK_EN = 16, /**< BUSKEEPER control register(16) (r/w): Enable NULL address check */
BUSKEEPER_ERR_FLAG = 31 /**< BUSKEEPER control register(31) (r/-): Sticky error flag, clears after read or write access */
BUSKEEPER_ERR_TYPE = 0, /**< BUSKEEPER control register( 0) (r/-): Bus error type: 0=device error, 1=access timeout */
BUSKEEPER_ERR_FLAG = 31 /**< BUSKEEPER control register(31) (r/-): Sticky error flag, clears after read or write access */
};
/**@}*/
 
/sw/lib/include/neorv32_cpu.h
3,7 → 3,7
// # ********************************************************************************************* #
// # BSD 3-Clause License #
// # #
// # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
// # Copyright (c) 2022, Stephan Nolting. All rights reserved. #
// # #
// # Redistribution and use in source and binary forms, with or without modification, are #
// # permitted provided that the following conditions are met: #
51,10 → 51,9
void neorv32_cpu_set_minstret(uint64_t value);
uint64_t neorv32_cpu_get_systime(void);
void neorv32_cpu_delay_ms(uint32_t time_ms);
void __attribute__((naked)) neorv32_cpu_goto_user_mode(void);
uint32_t neorv32_cpu_pmp_get_num_regions(void);
uint32_t neorv32_cpu_pmp_get_granularity(void);
int neorv32_cpu_pmp_configure_region(uint32_t index, uint32_t base, uint32_t size, uint8_t config);
int neorv32_cpu_pmp_configure_region(uint32_t index, uint32_t base, uint8_t config);
uint32_t neorv32_cpu_hpm_get_counters(void);
uint32_t neorv32_cpu_hpm_get_size(void);
 
63,9 → 62,8
* Prototype for "after-main handler". This function is called if main() returns.
*
* @param[in] return_code Return value of main() function.
* @return Return value is irrelevant (there is no one left to check for it...).
**************************************************************************/
extern int __neorv32_crt0_after_main(int32_t return_code) __attribute__ ((weak));
extern void __attribute__ ((weak)) __neorv32_crt0_after_main(int32_t return_code);
 
 
/**********************************************************************//**
161,11 → 159,10
asm volatile ("lw %[da], 0(%[ad])" : [da] "=r" (reg_data) : [ad] "r" (reg_addr));
#endif
 
return (uint32_t)reg_data;
return reg_data;
}
 
 
 
/**********************************************************************//**
* Load unsigned word from address space.
*
181,7 → 178,7
 
asm volatile ("lw %[da], 0(%[ad])" : [da] "=r" (reg_data) : [ad] "r" (reg_addr));
 
return (uint32_t)reg_data;
return reg_data;
}
 
 
196,15 → 193,34
inline uint16_t __attribute__ ((always_inline)) neorv32_cpu_load_unsigned_half(uint32_t addr) {
 
register uint32_t reg_addr = addr;
register uint32_t reg_data;
register uint16_t reg_data;
 
asm volatile ("lhu %[da], 0(%[ad])" : [da] "=r" (reg_data) : [ad] "r" (reg_addr));
 
return (uint16_t)reg_data;
return reg_data;
}
 
 
/**********************************************************************//**
* Load signed half-word from address space.
*
* @note An unaligned access address will raise an alignment exception.
*
* @param[in] addr Address (32-bit).
* @return Read data half-word (16-bit).
**************************************************************************/
inline int16_t __attribute__ ((always_inline)) neorv32_cpu_load_signed_half(uint32_t addr) {
 
register uint32_t reg_addr = addr;
register int16_t reg_data;
 
asm volatile ("lh %[da], 0(%[ad])" : [da] "=r" (reg_data) : [ad] "r" (reg_addr));
 
return reg_data;
}
 
 
/**********************************************************************//**
* Load unsigned byte from address space.
*
* @param[in] addr Address (32-bit).
213,15 → 229,32
inline uint8_t __attribute__ ((always_inline)) neorv32_cpu_load_unsigned_byte(uint32_t addr) {
 
register uint32_t reg_addr = addr;
register uint32_t reg_data;
register uint8_t reg_data;
 
asm volatile ("lbu %[da], 0(%[ad])" : [da] "=r" (reg_data) : [ad] "r" (reg_addr));
 
return (uint8_t)reg_data;
return reg_data;
}
 
 
/**********************************************************************//**
* Load signed byte from address space.
*
* @param[in] addr Address (32-bit).
* @return Read data byte (8-bit).
**************************************************************************/
inline int8_t __attribute__ ((always_inline)) neorv32_cpu_load_signed_byte(uint32_t addr) {
 
register uint32_t reg_addr = addr;
register int8_t reg_data;
 
asm volatile ("lb %[da], 0(%[ad])" : [da] "=r" (reg_data) : [ad] "r" (reg_addr));
 
return reg_data;
}
 
 
/**********************************************************************//**
* Read data from CPU configuration and status register (CSR).
*
* @param[in] csr_id ID of CSR to read. See #NEORV32_CSR_enum.
/sw/lib/source/neorv32_cpu.c
313,27 → 313,10
 
 
/**********************************************************************//**
* Switch from privilege mode MACHINE to privilege mode USER.
*
* @warning This function requires the U extension to be implemented.
**************************************************************************/
void __attribute__((naked)) neorv32_cpu_goto_user_mode(void) {
 
// make sure to use NO registers in here! -> naked
 
asm volatile ("csrw mepc, ra \n" // move return address to mepc so we can return using "mret". also, we can now use ra as general purpose register in here
"li ra, %[input_imm] \n" // bit mask to clear the two MPP bits
"csrrc zero, mstatus, ra \n" // clear MPP bits -> MPP=u-mode
"mret \n" // return and switch to user mode
: : [input_imm] "i" ((1<<CSR_MSTATUS_MPP_H) | (1<<CSR_MSTATUS_MPP_L)));
}
 
 
/**********************************************************************//**
* Physical memory protection (PMP): Get number of available regions.
*
* @warning This function overrides all available PMPCFG* CSRs.
* @warning This function requires the PMP CPU extension.
* @warning This function overrides all available PMPCFG* CSRs!
* @note This function requires the PMP CPU extension.
*
* @return Returns number of available PMP regions.
**************************************************************************/
344,13 → 327,12
return 0;
}
 
uint32_t i = 0;
 
// try setting R bit in all PMPCFG CSRs
const uint32_t mask = 0x01010101;
for (i=0; i<16; i++) {
__neorv32_cpu_pmp_cfg_write(i, mask);
}
__neorv32_cpu_pmp_cfg_write(0, mask);
__neorv32_cpu_pmp_cfg_write(1, mask);
__neorv32_cpu_pmp_cfg_write(2, mask);
__neorv32_cpu_pmp_cfg_write(3, mask);
 
// sum up all written ones (only available PMPCFG* CSRs/entries will return =! 0)
union {
359,9 → 341,10
} cnt;
 
cnt.uint32 = 0;
for (i=0; i<16; i++) {
cnt.uint32 += __neorv32_cpu_pmp_cfg_read(i) & mask;
}
cnt.uint32 += __neorv32_cpu_pmp_cfg_read(0) & mask;
cnt.uint32 += __neorv32_cpu_pmp_cfg_read(1) & mask;
cnt.uint32 += __neorv32_cpu_pmp_cfg_read(2) & mask;
cnt.uint32 += __neorv32_cpu_pmp_cfg_read(3) & mask;
 
// sum up bytes
uint32_t num_regions = 0;
377,30 → 360,38
/**********************************************************************//**
* Physical memory protection (PMP): Get minimal region size (granularity).
*
* @warning This function overrides PMPCFG0[0] and PMPADDR0 CSRs.
* @warning This function requires the PMP CPU extension.
* @warning This function overrides PMPCFG0[0] and PMPADDR0 CSRs!
* @note This function requires the PMP CPU extension.
*
* @return Returns minimal region size in bytes.
* @return Returns minimal region size in bytes. Returns zero on error.
**************************************************************************/
uint32_t neorv32_cpu_pmp_get_granularity(void) {
 
// check min granulartiy
uint32_t tmp = neorv32_cpu_csr_read(CSR_PMPCFG0);
tmp &= 0xffffff00; // disable entry 0
neorv32_cpu_csr_write(CSR_PMPCFG0, tmp);
neorv32_cpu_csr_write(CSR_PMPADDR0, 0xffffffff);
uint32_t tmp_a = neorv32_cpu_csr_read(CSR_PMPADDR0);
// PMP implemented at all?
if ((neorv32_cpu_csr_read(CSR_MXISA) & (1<<CSR_MXISA_PMP)) == 0) {
return 0;
}
 
uint32_t i;
neorv32_cpu_csr_write(CSR_PMPCFG0, neorv32_cpu_csr_read(CSR_PMPCFG0) & 0xffffff00); // disable entry 0
neorv32_cpu_csr_write(CSR_PMPADDR0, -1UL); // try to set all bits
uint32_t tmp = neorv32_cpu_csr_read(CSR_PMPADDR0);
 
// find least-significat set bit
for (i=31; i!=0; i--) {
if (((tmp_a >> i) & 1) == 0) {
// no bits set at all -> fail
if (tmp == 0) {
return 0;
}
 
// count trailing zeros
uint32_t i = 2;
while(1) {
if (tmp & 1) {
break;
}
tmp >>= 1;
i++;
}
 
return (uint32_t)(1 << (i+1+2));
return 1<<i;
}
 
 
407,124 → 398,67
/**********************************************************************//**
* Physical memory protection (PMP): Configure region.
*
* @note Using NAPOT mode - page base address has to be naturally aligned.
* @warning Only TOR mode is supported.
*
* @warning This function requires the PMP CPU extension.
* @warning Only use available PMP regions. Check before using neorv32_cpu_pmp_get_regions(void).
* @note This function requires the PMP CPU extension.
* @note Only use available PMP regions. Check before using neorv32_cpu_pmp_get_regions(void).
*
* @param[in] index Region number (index, 0..PMP_NUM_REGIONS-1).
* @param[in] base Region base address (has to be naturally aligned!).
* @param[in] size Region size, has to be a power of 2 (min 8 bytes or according to HW's PMP.granularity configuration).
* @param[in] config Region configuration (attributes) byte (for PMPCFGx).
* @param[in] base Region base address.
* @param[in] config Region configuration byte (see #NEORV32_PMPCFG_ATTRIBUTES_enum).
* @return Returns 0 on success, 1 on failure.
**************************************************************************/
int neorv32_cpu_pmp_configure_region(uint32_t index, uint32_t base, uint32_t size, uint8_t config) {
int neorv32_cpu_pmp_configure_region(uint32_t index, uint32_t base, uint8_t config) {
 
if (size < 8) {
return 1; // minimal region size is 8 bytes
if ((index > 15) || ((neorv32_cpu_csr_read(CSR_MXISA) & (1<<CSR_MXISA_PMP)) == 0)) {
return 1;
}
 
if ((size & (size - 1)) != 0) {
return 1; // region size is not a power of two
// set base address
base = base >> 2;
switch(index & 0xf) {
case 0: neorv32_cpu_csr_write(CSR_PMPADDR0, base); break;
case 1: neorv32_cpu_csr_write(CSR_PMPADDR1, base); break;
case 2: neorv32_cpu_csr_write(CSR_PMPADDR2, base); break;
case 3: neorv32_cpu_csr_write(CSR_PMPADDR3, base); break;
case 4: neorv32_cpu_csr_write(CSR_PMPADDR4, base); break;
case 5: neorv32_cpu_csr_write(CSR_PMPADDR5, base); break;
case 6: neorv32_cpu_csr_write(CSR_PMPADDR6, base); break;
case 7: neorv32_cpu_csr_write(CSR_PMPADDR7, base); break;
case 8: neorv32_cpu_csr_write(CSR_PMPADDR8, base); break;
case 9: neorv32_cpu_csr_write(CSR_PMPADDR9, base); break;
case 10: neorv32_cpu_csr_write(CSR_PMPADDR10, base); break;
case 11: neorv32_cpu_csr_write(CSR_PMPADDR11, base); break;
case 12: neorv32_cpu_csr_write(CSR_PMPADDR12, base); break;
case 13: neorv32_cpu_csr_write(CSR_PMPADDR13, base); break;
case 14: neorv32_cpu_csr_write(CSR_PMPADDR14, base); break;
case 15: neorv32_cpu_csr_write(CSR_PMPADDR15, base); break;
default: break;
}
 
// pmpcfg register index
uint32_t pmpcfg_index = index >> 4; // 4 entries per pmpcfg csr
 
// setup configuration
uint32_t tmp;
uint32_t config_int = ((uint32_t)config) << ((index%4)*8);
uint32_t config_mask = ((uint32_t)0xFF) << ((index%4)*8);
config_mask = ~config_mask;
// get current configuration
uint32_t tmp = __neorv32_cpu_pmp_cfg_read(pmpcfg_index);
 
// clear old configuration
__neorv32_cpu_pmp_cfg_write(pmpcfg_index, __neorv32_cpu_pmp_cfg_read(pmpcfg_index) & config_mask);
uint32_t config_mask = (((uint32_t)0xFF) << ((index%4)*8));
tmp = tmp & (~config_mask);
 
// set configuration
uint32_t config_new = ((uint32_t)config) << ((index%4)*8);
tmp = tmp | config_new;
__neorv32_cpu_pmp_cfg_write(pmpcfg_index, tmp);
 
// set base address and region size
uint32_t addr_mask = ~((size - 1) >> 2);
uint32_t size_mask = (size - 1) >> 3;
 
tmp = base & addr_mask;
tmp = tmp | size_mask;
 
switch(index & 63) {
case 0: neorv32_cpu_csr_write(CSR_PMPADDR0, tmp); break;
case 1: neorv32_cpu_csr_write(CSR_PMPADDR1, tmp); break;
case 2: neorv32_cpu_csr_write(CSR_PMPADDR2, tmp); break;
case 3: neorv32_cpu_csr_write(CSR_PMPADDR3, tmp); break;
case 4: neorv32_cpu_csr_write(CSR_PMPADDR4, tmp); break;
case 5: neorv32_cpu_csr_write(CSR_PMPADDR5, tmp); break;
case 6: neorv32_cpu_csr_write(CSR_PMPADDR6, tmp); break;
case 7: neorv32_cpu_csr_write(CSR_PMPADDR7, tmp); break;
case 8: neorv32_cpu_csr_write(CSR_PMPADDR8, tmp); break;
case 9: neorv32_cpu_csr_write(CSR_PMPADDR9, tmp); break;
case 10: neorv32_cpu_csr_write(CSR_PMPADDR10, tmp); break;
case 11: neorv32_cpu_csr_write(CSR_PMPADDR11, tmp); break;
case 12: neorv32_cpu_csr_write(CSR_PMPADDR12, tmp); break;
case 13: neorv32_cpu_csr_write(CSR_PMPADDR13, tmp); break;
case 14: neorv32_cpu_csr_write(CSR_PMPADDR14, tmp); break;
case 15: neorv32_cpu_csr_write(CSR_PMPADDR15, tmp); break;
case 16: neorv32_cpu_csr_write(CSR_PMPADDR16, tmp); break;
case 17: neorv32_cpu_csr_write(CSR_PMPADDR17, tmp); break;
case 18: neorv32_cpu_csr_write(CSR_PMPADDR18, tmp); break;
case 19: neorv32_cpu_csr_write(CSR_PMPADDR19, tmp); break;
case 20: neorv32_cpu_csr_write(CSR_PMPADDR20, tmp); break;
case 21: neorv32_cpu_csr_write(CSR_PMPADDR21, tmp); break;
case 22: neorv32_cpu_csr_write(CSR_PMPADDR22, tmp); break;
case 23: neorv32_cpu_csr_write(CSR_PMPADDR23, tmp); break;
case 24: neorv32_cpu_csr_write(CSR_PMPADDR24, tmp); break;
case 25: neorv32_cpu_csr_write(CSR_PMPADDR25, tmp); break;
case 26: neorv32_cpu_csr_write(CSR_PMPADDR26, tmp); break;
case 27: neorv32_cpu_csr_write(CSR_PMPADDR27, tmp); break;
case 28: neorv32_cpu_csr_write(CSR_PMPADDR28, tmp); break;
case 29: neorv32_cpu_csr_write(CSR_PMPADDR29, tmp); break;
case 30: neorv32_cpu_csr_write(CSR_PMPADDR30, tmp); break;
case 31: neorv32_cpu_csr_write(CSR_PMPADDR31, tmp); break;
case 32: neorv32_cpu_csr_write(CSR_PMPADDR32, tmp); break;
case 33: neorv32_cpu_csr_write(CSR_PMPADDR33, tmp); break;
case 34: neorv32_cpu_csr_write(CSR_PMPADDR34, tmp); break;
case 35: neorv32_cpu_csr_write(CSR_PMPADDR35, tmp); break;
case 36: neorv32_cpu_csr_write(CSR_PMPADDR36, tmp); break;
case 37: neorv32_cpu_csr_write(CSR_PMPADDR37, tmp); break;
case 38: neorv32_cpu_csr_write(CSR_PMPADDR38, tmp); break;
case 39: neorv32_cpu_csr_write(CSR_PMPADDR39, tmp); break;
case 40: neorv32_cpu_csr_write(CSR_PMPADDR40, tmp); break;
case 41: neorv32_cpu_csr_write(CSR_PMPADDR41, tmp); break;
case 42: neorv32_cpu_csr_write(CSR_PMPADDR42, tmp); break;
case 43: neorv32_cpu_csr_write(CSR_PMPADDR43, tmp); break;
case 44: neorv32_cpu_csr_write(CSR_PMPADDR44, tmp); break;
case 45: neorv32_cpu_csr_write(CSR_PMPADDR45, tmp); break;
case 46: neorv32_cpu_csr_write(CSR_PMPADDR46, tmp); break;
case 47: neorv32_cpu_csr_write(CSR_PMPADDR47, tmp); break;
case 48: neorv32_cpu_csr_write(CSR_PMPADDR48, tmp); break;
case 49: neorv32_cpu_csr_write(CSR_PMPADDR49, tmp); break;
case 50: neorv32_cpu_csr_write(CSR_PMPADDR50, tmp); break;
case 51: neorv32_cpu_csr_write(CSR_PMPADDR51, tmp); break;
case 52: neorv32_cpu_csr_write(CSR_PMPADDR52, tmp); break;
case 53: neorv32_cpu_csr_write(CSR_PMPADDR53, tmp); break;
case 54: neorv32_cpu_csr_write(CSR_PMPADDR54, tmp); break;
case 55: neorv32_cpu_csr_write(CSR_PMPADDR55, tmp); break;
case 56: neorv32_cpu_csr_write(CSR_PMPADDR56, tmp); break;
case 57: neorv32_cpu_csr_write(CSR_PMPADDR57, tmp); break;
case 58: neorv32_cpu_csr_write(CSR_PMPADDR58, tmp); break;
case 59: neorv32_cpu_csr_write(CSR_PMPADDR59, tmp); break;
case 60: neorv32_cpu_csr_write(CSR_PMPADDR60, tmp); break;
case 61: neorv32_cpu_csr_write(CSR_PMPADDR61, tmp); break;
case 62: neorv32_cpu_csr_write(CSR_PMPADDR62, tmp); break;
case 63: neorv32_cpu_csr_write(CSR_PMPADDR63, tmp); break;
default: break;
// check if update was successful
tmp = __neorv32_cpu_pmp_cfg_read(pmpcfg_index);
if ((tmp & config_mask) == config_new) {
return 0;
} else {
return 2;
}
 
// wait for HW to compute PMP-internal stuff (address masks)
for (tmp=0; tmp<16; tmp++) {
asm volatile ("nop");
}
 
// set new configuration
__neorv32_cpu_pmp_cfg_write(pmpcfg_index, __neorv32_cpu_pmp_cfg_read(pmpcfg_index) | config_int);
 
return 0;
}
 
 
539,23 → 473,11
static uint32_t __neorv32_cpu_pmp_cfg_read(uint32_t index) {
 
uint32_t tmp = 0;
switch(index & 15) {
case 0: tmp = neorv32_cpu_csr_read(CSR_PMPCFG0); break;
case 1: tmp = neorv32_cpu_csr_read(CSR_PMPCFG1); break;
case 2: tmp = neorv32_cpu_csr_read(CSR_PMPCFG2); break;
case 3: tmp = neorv32_cpu_csr_read(CSR_PMPCFG3); break;
case 4: tmp = neorv32_cpu_csr_read(CSR_PMPCFG4); break;
case 5: tmp = neorv32_cpu_csr_read(CSR_PMPCFG5); break;
case 6: tmp = neorv32_cpu_csr_read(CSR_PMPCFG6); break;
case 7: tmp = neorv32_cpu_csr_read(CSR_PMPCFG7); break;
case 8: tmp = neorv32_cpu_csr_read(CSR_PMPCFG8); break;
case 9: tmp = neorv32_cpu_csr_read(CSR_PMPCFG9); break;
case 10: tmp = neorv32_cpu_csr_read(CSR_PMPCFG10); break;
case 11: tmp = neorv32_cpu_csr_read(CSR_PMPCFG11); break;
case 12: tmp = neorv32_cpu_csr_read(CSR_PMPCFG12); break;
case 13: tmp = neorv32_cpu_csr_read(CSR_PMPCFG13); break;
case 14: tmp = neorv32_cpu_csr_read(CSR_PMPCFG14); break;
case 15: tmp = neorv32_cpu_csr_read(CSR_PMPCFG15); break;
switch(index & 3) {
case 0: tmp = neorv32_cpu_csr_read(CSR_PMPCFG0); break;
case 1: tmp = neorv32_cpu_csr_read(CSR_PMPCFG1); break;
case 2: tmp = neorv32_cpu_csr_read(CSR_PMPCFG2); break;
case 3: tmp = neorv32_cpu_csr_read(CSR_PMPCFG3); break;
default: break;
}
 
564,32 → 486,20
 
 
/**********************************************************************//**
* Internal helper function: Write PMP configuration register 0..15
* Internal helper function: Write PMP configuration register 0..4
*
* @warning This function requires the PMP CPU extension.
*
* @param[in] index PMP CFG configuration register ID (0..15).
* @param[in] index PMP CFG configuration register ID (0..4).
* @param[in] data PMP CFG write data.
**************************************************************************/
static void __neorv32_cpu_pmp_cfg_write(uint32_t index, uint32_t data) {
 
switch(index & 15) {
case 0: neorv32_cpu_csr_write(CSR_PMPCFG0, data); break;
case 1: neorv32_cpu_csr_write(CSR_PMPCFG1, data); break;
case 2: neorv32_cpu_csr_write(CSR_PMPCFG2, data); break;
case 3: neorv32_cpu_csr_write(CSR_PMPCFG3, data); break;
case 4: neorv32_cpu_csr_write(CSR_PMPCFG4, data); break;
case 5: neorv32_cpu_csr_write(CSR_PMPCFG5, data); break;
case 6: neorv32_cpu_csr_write(CSR_PMPCFG6, data); break;
case 7: neorv32_cpu_csr_write(CSR_PMPCFG7, data); break;
case 8: neorv32_cpu_csr_write(CSR_PMPCFG8, data); break;
case 9: neorv32_cpu_csr_write(CSR_PMPCFG9, data); break;
case 10: neorv32_cpu_csr_write(CSR_PMPCFG10, data); break;
case 11: neorv32_cpu_csr_write(CSR_PMPCFG11, data); break;
case 12: neorv32_cpu_csr_write(CSR_PMPCFG12, data); break;
case 13: neorv32_cpu_csr_write(CSR_PMPCFG13, data); break;
case 14: neorv32_cpu_csr_write(CSR_PMPCFG14, data); break;
case 15: neorv32_cpu_csr_write(CSR_PMPCFG15, data); break;
switch(index & 3) {
case 0: neorv32_cpu_csr_write(CSR_PMPCFG0, data); break;
case 1: neorv32_cpu_csr_write(CSR_PMPCFG1, data); break;
case 2: neorv32_cpu_csr_write(CSR_PMPCFG2, data); break;
case 3: neorv32_cpu_csr_write(CSR_PMPCFG3, data); break;
default: break;
}
}
687,19 → 597,21
**************************************************************************/
uint32_t neorv32_cpu_hpm_get_size(void) {
 
uint32_t tmp, size, i;
 
// HPMs implemented at all?
if ((neorv32_cpu_csr_read(CSR_MXISA) & (1<<CSR_MXISA_ZIHPM)) == 0) {
return 0;
}
 
// inhibt auto-update
asm volatile ("csrwi %[addr], %[imm]" : : [addr] "i" (CSR_MCOUNTINHIBIT), [imm] "i" (1<<CSR_MCOUNTINHIBIT_HPM3));
// inhibit auto-update of HPM counter3
tmp = neorv32_cpu_csr_read(CSR_MCOUNTINHIBIT);
tmp |= 1 << CSR_MCOUNTINHIBIT_HPM3;
neorv32_cpu_csr_write(CSR_MCOUNTINHIBIT, tmp);
 
neorv32_cpu_csr_write(CSR_MHPMCOUNTER3, 0xffffffff);
neorv32_cpu_csr_write(CSR_MHPMCOUNTER3H, 0xffffffff);
 
uint32_t tmp, size, i;
 
if (neorv32_cpu_csr_read(CSR_MHPMCOUNTER3H) == 0) {
size = 0;
tmp = neorv32_cpu_csr_read(CSR_MHPMCOUNTER3);
/sw/lib/source/neorv32_gptmr.c
34,7 → 34,7
 
 
/**********************************************************************//**
* @file neorv32_spi.c
* @file neorv32_gptmr.c
* @author Stephan Nolting
* @brief General purpose timer (GPTMR) HW driver source file.
*
/sw/lib/source/neorv32_rte.c
128,7 → 128,7
*
* @warning When using the the RTE, this function is the ONLY function that can use the 'interrupt' attribute!
**************************************************************************/
static void __attribute__((__interrupt__)) __attribute__((aligned(4))) __neorv32_rte_core(void) {
static void __attribute__((__interrupt__)) __attribute__((aligned(4))) __neorv32_rte_core(void) {
 
register uint32_t rte_mepc = neorv32_cpu_csr_read(CSR_MEPC);
neorv32_cpu_csr_write(CSR_MSCRATCH, rte_mepc); // store for later
138,8 → 138,7
if (((int32_t)rte_mcause) >= 0) { // modify pc only if not interrupt (MSB cleared)
 
// get low half word of faulting instruction
register uint32_t rte_trap_inst;
asm volatile ("lh %[result], 0(%[input_i])" : [result] "=r" (rte_trap_inst) : [input_i] "r" (rte_mepc));
register uint32_t rte_trap_inst = neorv32_cpu_load_unsigned_half(rte_mepc);
 
if ((rte_trap_inst & 3) == 3) { // faulting instruction is uncompressed instruction
rte_mepc += 4;
378,7 → 377,7
neorv32_uart0_printf("\nPMP: ");
uint32_t pmp_num_regions = neorv32_cpu_pmp_get_num_regions();
if (pmp_num_regions != 0) {
neorv32_uart0_printf("%u regions, %u bytes minimal granularity\n", pmp_num_regions, neorv32_cpu_pmp_get_granularity());
neorv32_uart0_printf("%u regions, %u bytes minimal granularity, OFF/TOR modes only\n", pmp_num_regions, neorv32_cpu_pmp_get_granularity());
}
else {
neorv32_uart0_printf("not implemented\n");
388,7 → 387,7
// Memory configuration
neorv32_uart0_printf("\n=== << Memory System >> ===\n");
 
neorv32_uart0_printf("Boot Config.: Boot ");
neorv32_uart0_printf("Boot configuration: Boot ");
if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_BOOTLOADER)) {
neorv32_uart0_printf("via Bootloader\n");
}
458,7 → 457,7
 
neorv32_uart0_printf("Ext. bus interface: ");
__neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_EXT));
neorv32_uart0_printf("Ext. bus Endianness: ");
neorv32_uart0_printf("Ext. bus endianness: ");
if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_EXT_ENDIAN)) {
neorv32_uart0_printf("big\n");
}
/sw/lib/source/neorv32_uart.c
57,6 → 57,34
 
 
// #################################################################################################
// Override default STDIO functions
// #################################################################################################
 
/**********************************************************************//**
* Send char via UART0
*
* @param[in] Char to be send.
* @return Char that has been sent.
**************************************************************************/
int putchar(int ch) {
 
neorv32_uart0_putc((char)ch);
return ch;
}
 
 
/**********************************************************************//**
* Read char from UART0.
*
* @return Read char.
**************************************************************************/
int getchar(void) {
 
return (int)neorv32_uart0_getc();
}
 
 
// #################################################################################################
// Primary UART (UART0)
// #################################################################################################
 
/sw/lib/source/neorv32_xirq.c
3,7 → 3,7
// # ********************************************************************************************* #
// # BSD 3-Clause License #
// # #
// # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
// # Copyright (c) 2022, Stephan Nolting. All rights reserved. #
// # #
// # Redistribution and use in source and binary forms, with or without modification, are #
// # permitted provided that the following conditions are met: #
238,7 → 238,7
uint32_t mask = 1 << src;
NEORV32_XIRQ.IPR = ~mask; // clear current pending interrupt
 
neorv32_cpu_csr_write(CSR_MIP, 1 << XIRQ_FIRQ_PENDING); // acknowledge XIRQ FIRQ
neorv32_cpu_csr_write(CSR_MIP, ~(1 << XIRQ_FIRQ_PENDING)); // acknowledge XIRQ FIRQ
 
NEORV32_XIRQ.SCR = 0; // acknowledge current XIRQ interrupt source
 
/sw/svd/neorv32.svd
522,11 → 522,6
<description>Bus error type: 0=device error, 1=access timeout</description>
</field>
<field>
<name>BUSKEEPER_NULL_CHECK_EN</name>
<bitRange>[16:16]</bitRange>
<description>Enable NULL address check when set</description>
</field>
<field>
<name>BUSKEEPER_ERR_FLAG</name>
<bitRange>[31:31]</bitRange>
<description>Sticky error flag, clears after read or write access</description>
/CHANGELOG.md
33,11 → 33,24
 
| Date (*dd.mm.yyyy*) | Version | Comment |
|:----------:|:-------:|:--------|
| 17.02.2022 |[**:rocket:1.6.8**](https://github.com/stnolting/neorv32/releases/tag/v1.6.8) | **New release** |
| 09.03.2022 | [**:rocket:1.6.9**](https://github.com/stnolting/neorv32/releases/tag/v1.6.9) | **New release** |
| 09.03.2022 | 1.6.8.12 | CPU core: minor code clean-up |
| 08.03.2022 | 1.6.8.11 | clean-up of CPU's privilege mode logic |
| 07.03.2022 | 1.6.8.10 | added compressed floating-point instructions (`Zfinx` ISA extensions); minor optimization of compressed instruction decoding logic |
| 05.03.2022 | 1.6.8.9 | CPU core: minor optimizations, code clean-ups and edits; :sparkles: added RISC-V `mstatus.TW` bit to allow/disallow execution of `wfi` instruction in user mode; [PR #285](https://github.com/stnolting/neorv32/pull/285) |
| 02.03.2022 | 1.6.8.8 | :bug: fixed bug in layout of CPU's `pmpaddr` CSRs (**physical memory protection**); [PR #283](https://github.com/stnolting/neorv32/pull/283) |
| 01.03.2022 | 1.6.8.7 | CPU core: minor optimizations, code clean-ups and edits |
| 26.02.2022 | 1.6.8.6 | :warning: :lock: **reworked Physical Memory Protection (PMP)**: replacing `NAPOT` mode by `TOR` mode and fixing several minor PMP CSR-access bugs; maximum number of PMP regions is now limited to 16 entries; :warning: removed **BUSKEEPER's NULL address check** (introduced in version `1.6.5.4`) - use a single PMP entry instead; see [PR #281](https://github.com/stnolting/neorv32/pull/281) |
| 25.02.2022 | 1.6.8.5 | minor BUSMUX (bus multiplexer for CPU's instruction and data buses) and CPU control edits (pipeline front-end) |
| 24.02.2022 | 1.6.8.4 | :bug: **fixed bug in `mip` CSR** (introduced in version `1.6.4.6` with [#236](https://github.com/stnolting/neorv32/pull/236)): to clear/ack a pending interrupt software needs to **clear** the according `mip` bit; see [PR #280](https://github.com/stnolting/neorv32/pull/280) |
| 24.02.2022 | 1.6.8.3 | reworked CPU's data path (use a few _wide_ multiplexers instead of many small ones); [PR #279](https://github.com/stnolting/neorv32/pull/279) |
| 23.02.2022 | 1.6.8.2 | CPU logic optimizations (less area): simplified CPU co-processor interface; minor optimization of bus unit access arbiters; optimized `M` extension's (mul/div co-processor) divider unit |
| 18.02.2022 | 1.6.8.1 | minor CPU control logic optimizations: simplified execute engine; faster execution of SYSTEM instructions (one cycle less) |
| 17.02.2022 | [**:rocket:1.6.8**](https://github.com/stnolting/neorv32/releases/tag/v1.6.8) | **New release** |
| 17.02.2022 | 1.6.7.10 | hardwired `dcsr.stopcount` to `1`: all standard counters (`[m]cycle[h]` and `[m]instret[h]`, but **NOT** `[m]time[h]`!!) and all hardware performance monitor (HPM) counters are _stopped_ when the CPU is in debug mode; [PR #277](https://github.com/stnolting/neorv32/pull/277) |
| 16.02.2022 | 1.6.7.9 | :warning: **added custom `mxisa` CSR replacing SYSINFO's `NEORV32_SYSINFO.CPU` memory-mapped register**: bit-positions remain but names and the actual access mechanism (CSR vs. memory-mapped) have changed! see [PR #276](https://github.com/stnolting/neorv32/pull/276) |
| 11.02.2022 | 1.6.7.8 | :test_tube: added newlib's system calls (stubs) and linker script symbols for heap memory to support **dynamic memory allocation** (e.g. `malloc`) and even **standard IO functions** like `printf`; see [PR #275](https://github.com/stnolting/neorv32/pull/275) |
| 10.02.2022 | 1.6.7.7 | :sparkles: added **RISC-V hardware trigger module** to CPU - allows to set _hardware breakpoints_ (via gdb's `hb`/`hbreak` command) to debug code from ROM; see [PR #274](https://github.com/stnolting/neorv32/pull/274); :bug: minor bug fix in `ebreak` instruction's `dcsr.cause` value (was 0b010 but has to be 0b001) |
| 10.02.2022 | 1.6.7.7 | :test_tube: added **RISC-V hardware trigger module** to CPU - allows to set _hardware breakpoints_ (via gdb's `hb`/`hbreak` command) to debug code from ROM; see [PR #274](https://github.com/stnolting/neorv32/pull/274); :bug: minor bug fix in `ebreak` instruction's `dcsr.cause` value (was 0b010 but has to be 0b001) |
| 08.02.2022 | 1.6.7.6 | :warning: renamed default branch of repository to `main` |
| 07.02.2022 | 1.6.7.5 | removed default values for bi-directional top entity ports `twi_sda_io` and `twi_scl_io` |
| 05.02.2022 | 1.6.7.4 | added `err_o` signal to **IMEM** module; if the IMEM is implemented as true ROM any write attempt will raise a _store access fault_ exception (with a `[DEVICE_ERR]` error); see [PR #273](https://github.com/stnolting/neorv32/pull/273) |
44,7 → 57,7
| 03.02.2022 | 1.6.7.3 | :test_tube: using `LTO` (link-time-optimization) option for **bootloader**; improved bootloader user console; see [PR #268](https://github.com/stnolting/neorv32/pull/268) |
| 31.01.2022 | 1.6.7.2 | :bug: fixed minor bug in **bootloader's MTIME handling** (bootloader crashed if `Zicntr` ISA extension not enabled), fixed minor issues in MTIME and `time` CSRs handling; added MTIME example program; see [PR #267](https://github.com/stnolting/neorv32/pull/267) |
| 30.01.2022 | 1.6.7.1 | :sparkles: added **`Zxcfu` ISA extension for user-defined custom RISC-V instructions**; see [PR #264](https://github.com/stnolting/neorv32/pull/264) |
| 28.01.2022 |[**:rocket:1.6.7**](https://github.com/stnolting/neorv32/releases/tag/v1.6.7) | **New release** |
| 28.01.2022 | [**:rocket:1.6.7**](https://github.com/stnolting/neorv32/releases/tag/v1.6.7) | **New release** |
| 28.01.2022 | 1.6.6.10 | :bug: fixed bug in **bit-manipulation co-processor**: decoding collision between `cpop` and `rol` instructions; :bug: fixed bug in co-processor arbitration when an illegal instruction is detected; added four additional (yet unused) **CPU** co-processor slots; [PR #262](https://github.com/stnolting/neorv32/pull/262) |
| 27.01.2022 | 1.6.6.9 | reworked **CFS** "user" logic; added CFS demo program; see [PR #261](https://github.com/stnolting/neorv32/pull/261) |
| 27.01.2022 | 1.6.6.8 | :sparkles: added support for RISC-V bit-manipulation (`B`) **carry-less multiplication instructions `Zbc`** sub-extension; added test cases and intrinsics; the NEORV32 bit-manipulation ISA extension (`B`) now fully complies to the RISC-V specs. v0.93; see [PR #260](https://github.com/stnolting/neorv32/pull/260) |
55,7 → 68,7
| 21.01.2022 | 1.6.6.3 | reworked **CPU's instruction issue engine** (area optimization: ~100 LUTs less on an Intel Cyclone IV), [PR #256](https://github.com/stnolting/neorv32/pull/256); minor CPU control unit code clean-ups and logic optimizations |
| 18.01.2022 | 1.6.6.2 | :warning: moved `setups` folder to new [neorv32-setups](https://github.com/stnolting/neorv32-setups) repository, [PR #254](https://github.com/stnolting/neorv32/pull/254) |
| 18.01.2022 | 1.6.6.1 | minor **MTIME** VHDL code clean-up; minor logic optimization of **CPU's bus unit** |
| 17.01.2022 |[**:rocket:1.6.6**](https://github.com/stnolting/neorv32/releases/tag/v1.6.6) | **New release** |
| 17.01.2022 | [**:rocket:1.6.6**](https://github.com/stnolting/neorv32/releases/tag/v1.6.6) | **New release** |
| 14.01.2022 | 1.6.5.9 | **GPIO** module: write accesses to the GPIO module's "input" registers will now raise a bus exception; [PR #255](https://github.com/stnolting/neorv32/pull/255) |
| 11.01.2022 | 1.6.5.8 | minor rtl code clean-ups and edits in `rtl/core`; any write access to the SYSINFO module will now show up as a BUSKEEPER's "DEVICE_ERR" |
| 08.01.2022 | 1.6.5.7 | :bug: fixed bug in BUSKEEPER's error type logic (introduced in version `1.6.5.4`); removed "unexpected ERR/ACK" error codes; [PR #253](https://github.com/stnolting/neorv32/pull/253) |
64,7 → 77,7
| 04.01.2022 | 1.6.5.4 | **BUSKEEPER** can now optionally check for NULL address accesses (address `0x00000000`), see [PR #247](https://github.com/stnolting/neorv32/pull/247) |
| 02.01.2022 | 1.6.5.3 | :sparkles: **added Execute In Place (XIP) module** allowing code to be directly executed from an external SPI flash, see [PR #244](https://github.com/stnolting/neorv32/pull/244) |
| 02.01.2022 | 1.6.5.2 | :bug: fixed minor bug in CPU's instruction fetch unit (only issue new instruction fetch request when the previous one has been completed) |
| 16.12.2021 |[**:rocket:1.6.5**](https://github.com/stnolting/neorv32/releases/tag/v1.6.5) | **New release** |
| 16.12.2021 | [**:rocket:1.6.5**](https://github.com/stnolting/neorv32/releases/tag/v1.6.5) | **New release** |
| 15.12.2021 | 1.6.4.10 | minor logic optimization of CPU's pipeline front-end (instruction fetch and instruction issue) |
| 14.12.2021 | 1.6.4.9 | optimized CPU's multiplication/division co-processor: divisions are 1 cycle faster, fast-multiplications (when using DSPs) are 1 cycle faster, slightly less resource utilization, see [PR #240](https://github.com/stnolting/neorv32/pull/240) |
| 11.12.2021 | 1.6.4.8 | watchdog: added new _DBEN_ and _HALF_ flags to control register (enable WDT during debugging, check timeout counter level), see [PR #239](https://github.com/stnolting/neorv32/pull/239) |
75,7 → 88,7
| 02.12.2021 | 1.6.4.3 | :warning: removed legacy software compatibility wrappers (`sw/lib/include/neorv32_legacy.h` and `neorv32_uart_*` functions) |
| 28.11.2021 | 1.6.4.2 | :bug: fixed bug in **UART[0/1]** overrun flag (was not set/cleared correctly); fixed bug in UART0 enable function `neorv32_uart0_enable()` |
| 28.11.2021 | 1.6.4.1 | (:warning:) bootloader now stores executable in _little-endian_ byte-order to SPI flash |
| 26.11.2021 |[**:rocket:1.6.4**](https://github.com/stnolting/neorv32/releases/tag/v1.6.4) | **New release** |
| 26.11.2021 | [**:rocket:1.6.4**](https://github.com/stnolting/neorv32/releases/tag/v1.6.4) | **New release** |
| 22.11.2021 | 1.6.3.11 | on-chip debugger: reworked JTAG signal input/output synchronization logic (see [PR #216](https://github.com/stnolting/neorv32/pull/216)) |
| 22.11.2021 | 1.6.3.10 | reworked **TRNG** (less hardware requirements, improved quality), see [PR #212](https://github.com/stnolting/neorv32/pull/212) and [stnolting/neoTRNG](https://github.com/stnolting/neoTRNG) |
| 21.11.2021 | 1.6.3.9 | minor rtl edits: configuring an IMEM or DMEM size (`MEM_INT_IMEM_SIZE` / `MEM_INT_DMEM_SIZE` generic) of 0 will now exclude the according memory from synthesis (and also clears the according `NEORV32_SYSINFO.SOC` flags) |
87,7 → 100,7
| 05.11.2021 | 1.6.3.3 | :bug: fixed bug in general purpose timer **GPTMR** - clock prescaler had no effect, the timer was always counting at full processor clock speed; minor watchdog (WDT) code edits |
| 04.11.2021 | 1.6.3.2 | added optional _alternative_ IMEM and DMEM architecture-only design files (in `rtl/core/mem`); these are not device-specific ("cyclone 2") as they do not use any FPGA-specific primitives or macros - just a different HDL style for describing memories is used (see [PR #192](https://github.com/stnolting/neorv32/pull/198) and [Issue #197](https://github.com/stnolting/neorv32/issues/197)) |
| 03.11.2021 | 1.6.3.1 | :sparkles: added new peripheral module - **General Purpose 32-bit Timer `GPTMR`** ([see PR #195](https://github.com/stnolting/neorv32/pull/195)) |
| 02.11.2021 |[**:rocket:1.6.3**](https://github.com/stnolting/neorv32/releases/tag/v1.6.3) | **New release** |
| 02.11.2021 | [**:rocket:1.6.3**](https://github.com/stnolting/neorv32/releases/tag/v1.6.3) | **New release** |
| 01.11.2021 | 1.6.2.13 | added new top generics to explicitly control implementation of `Zicntr` (CPU base counters) and `Zihpm` (hardware performance monitors, see [PR #192](https://github.com/stnolting/neorv32/pull/192) |
| 30.10.2021 | 1.6.2.12 | :sparkles: :lock: added memory-mapped register to BUSKEEPER module - software can now retrieve the actual cause of an instruction / data-load / data-store bus access fault exception (access timeout or device error); see [PR #191](https://github.com/stnolting/neorv32/pull/191) |
| 28.10.2021 | 1.6.2.11 | :sparkles: added `Zba` bit-manipulation sub-extension; :warning: removed configuration option for `B` sub-extensions: removed `CPU_EXTENSION_RISCV_Zbb` generic and according SYSINFO flag, added new `CPU_EXTENSION_RISCV_B` generic (to implement bit-manipulation `B` ISA extension with _all_ currently supported subsets), see [PR #190](https://github.com/stnolting/neorv32/pull/190) |
101,7 → 114,7
| 20.10.2021 | 1.6.2.3 | SPI: minor VHDL code optimization and clean-up; NOTE: all serial interfaces (SPI, TWI, UARTs) allow to terminate a running transmission by clearing the enable flag in the module's control register |
| 18.10.2021 | 1.6.2.2 | :bug: `*_reduce_f` VHDL functions did not work for single-bit operands (see [PR #186](https://github.com/stnolting/neorv32/pull/186)) |
| 18.10.2021 | 1.6.2.1 | :sparkles: SPI: added option to configure _clock polarity_ - the SPI module now supports all standard clock modes (0,1,2,3) (see [PR #185](https://github.com/stnolting/neorv32/pull/185)); logic optimization of SPI module |
| 17.10.2021 |[**:rocket:1.6.2**](https://github.com/stnolting/neorv32/releases/tag/v1.6.2) | **New release** |
| 17.10.2021 | [**:rocket:1.6.2**](https://github.com/stnolting/neorv32/releases/tag/v1.6.2) | **New release** |
| 17.10.2021 | 1.6.1.13 | :warning: :warning: main software makefile: modified behavior of `MARCH` and `MABI` variables - the `-march` and `-mabi` flags are no longer required/allowed (example: overriding makefile's default `MARCH` is now done using `make MARCH=rv32imac ...`) ([see PR #184](https://github.com/stnolting/neorv32/pull/184)) |
| 15.10.2021 | 1.6.1.12 | :warning: Custom Functions Subsystem (CFS): removed `sleep` input (indicating CPU is in sleep mode); minor CPU control logic optimization |
| 15.10.2021 | 1.6.1.11 | :sparkles: UARTs: added optional configurable RX and TX FIFOs, added fine-grained RX/TX IRQ configuration options (see [PR #183](https://github.com/stnolting/neorv32/pull/183)) |
115,7 → 128,7
| 03.10.2021 | 1.6.1.3 | :bug: fixed UART signal connection in `rtl/system_integration` wrappers |
| 01.10.2021 | 1.6.1.2 | :warning: removed `mstatus.TW` (timeout wait) bit, `wfi` instruction is now always allowed to be executed in less-privileged modes; minor CPU control unit logic optimizations |
| 01.10.2021 | 1.6.1.1 | on-chip-debugger: `wfi` instruction acts as a simple `nop` when _in_ debug mode or during single-stepping |
| 28.09.2021 |[**:rocket:1.6.1**](https://github.com/stnolting/neorv32/releases/tag/v1.6.1) | **New release** |
| 28.09.2021 | [**:rocket:1.6.1**](https://github.com/stnolting/neorv32/releases/tag/v1.6.1) | **New release** |
| 28.09.2021 | 1.6.0.13 | :bug: fixed elementary bug in MTIME comparator logic (interrupt condition `mtime >= mtimecmp` was not always evaluated correctly) |
| 28.09.2021 | 1.6.0.12 | fixed CPU's IRQ prioritization: (re-)enter debug mode interrupts have to be evaluated _before_ all other interrupts |
| 27.09.2021 | 1.6.0.11 | :warning: `Zifencei` extension is _required_ for the on-chip debugger; executing `fence.i` without having the `Zifencei` extension enabled will now cause an illegal instruction exception |
/README.md
124,8 → 124,7
**Advanced**
 
* on-chip debugger ([OCD](https://stnolting.github.io/neorv32/#_on_chip_debugger_ocd)) accessible via JTAG interface - compliant to
the "Minimal RISC-V Debug Specification Version 0.13.2" and compatible with **OpenOCD** + **gdb** and **Segger Embedded Studio**;
includes RISC-V _hardware trigger module_
the "Minimal RISC-V Debug Specification Version 0.13.2" and compatible with **OpenOCD** + **gdb** and **Segger Embedded Studio**
* _true random_ number generator ([TRNG](https://stnolting.github.io/neorv32/#_true_random_number_generator_trng))
* execute in place module ([XIP](https://stnolting.github.io/neorv32/#_execute_in_place_module_xip)) to directly execute code from SPI flash
* custom functions subsystem ([CFS](https://stnolting.github.io/neorv32/#_custom_functions_subsystem_cfs))
156,7 → 155,7
 
The NEORV32 CPU implements the RISC-V 32-bit `rv32i` ISA with optional extensions (see below). It is compatible to subsets of the
*Unprivileged ISA Specification* [(Version 2.2)](https://github.com/stnolting/neorv32/blob/main/docs/references/riscv-spec.pdf)
and the *Privileged Architecture Specification* [(Version 1.12-draft)](https://github.com/stnolting/neorv32/blob/main/docs/references/riscv-privileged.pdf).
and the *Privileged Architecture Specification* [(Version 1.12)](https://github.com/stnolting/neorv32/blob/main/docs/references/riscv-privileged.pdf).
Compatibility is checked by passing the [official RISC-V architecture tests](https://github.com/riscv/riscv-arch-test).
 
The core is a little-endian Von-Neumann machine implemented as multi-cycle architecture.
172,8 → 171,8
 
### Available ISA Extensions
 
Currently, the following _optional_ RISC-V-compatible ISA extensions are implemented (linked to the according
documentation section).
The following _optional_ RISC-V-compatible and NEORV32-specific ISA extensions are available (linked to the according
documentation section):
 
**RV32
[[`I`](https://stnolting.github.io/neorv32/#_i_base_integer_isa)/
203,16 → 202,16
 
### FPGA Implementation Results - CPU
 
Implementation results for _exemplary_ CPU configuration generated for an **Intel Cyclone IV EP4CE22F17C6N FPGA**
using **Intel Quartus Prime Lite 20.1** ("balanced implementation, Slow 1200mV 0C Model").
Implementation results for _exemplary_ CPU configuration generated for an **Intel Cyclone IV E** `EP4CE22F17C6` FPGA
using **Intel Quartus Prime Lite 21.1** (no timing constrains, _balanced optimization_, f_max from _Slow 1200mV 0C Model_).
 
| CPU Configuration (version [1.5.7.10](https://github.com/stnolting/neorv32/blob/main/CHANGELOG.md)) | LEs | FFs | Memory bits | DSPs | f_max |
| CPU Configuration (version [1.6.8.3](https://github.com/stnolting/neorv32/blob/main/CHANGELOG.md)) | LEs | FFs | Memory bits | DSPs | f_max |
|:------------------------|:----:|:----:|:----:|:-:|:-------:|
| `rv32i` | 806 | 359 | 1024 | 0 | 125 MHz |
| `rv32i_Zicsr_Zicntr` | 1729 | 813 | 1024 | 0 | 124 MHz |
| `rv32imac_Zicsr_Zicntr` | 2511 | 1074 | 1024 | 0 | 124 MHz |
| `rv32i_Zicsr` | 1425 | 673 | 1024 | 0 | 118 MHz |
| `rv32i_Zicsr_Zicntr` | 1778 | 803 | 1024 | 0 | 118 MHz |
| `rv32imac_Zicsr_Zicntr` | 2453 | 994 | 1024 | 0 | 118 MHz |
 
:bulb: An incremental list of CPU extension's hardware utilization can found in the
:bulb: An incremental list of the CPUs ISA extension's hardware utilization can found in the
[_Data Sheet: FPGA Implementation Results - CPU_](https://stnolting.github.io/neorv32/#_cpu).
 
[[back to top](#The-NEORV32-RISC-V-Processor)]
224,7 → 223,7
The average CPI (cycles per instruction) depends on the instruction mix of a specific applications and also on the
available CPU extensions.
 
The following table shows the performance results (scores and average CPI) for exemplary CPU configurations executing
The following table shows the performance results (scores and average CPI) for exemplary CPU configurations (no caches) executing
2000 iterations of the [CoreMark](https://github.com/stnolting/neorv32/blob/main/sw/example/coremark) CPU benchmark
(using plain GCC10 rv32i built-in libraries only!).
 
328,4 → 327,4
 
---------------------------------------
 
**A big shout-out goes to the community and all the [contributors](https://github.com/stnolting/neorv32/graphs/contributors), who helped improving this project! :heart:**
**:heart: A big shout-out goes to the community and all the [contributors](https://github.com/stnolting/neorv32/graphs/contributors), who helped improving this project!**

powered by: WebSVN 2.1.0

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