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!** |