Line 37... |
Line 37... |
[NOTE]
|
[NOTE]
|
It is recommended to use the **NEORV32 Processor** as default top instance even if you only want to use the actual
|
It is recommended to use the **NEORV32 Processor** as default top instance even if you only want to use the actual
|
CPU. Simply disable all the processor-internal modules via the generics and you will get a "CPU
|
CPU. Simply disable all the processor-internal modules via the generics and you will get a "CPU
|
wrapper" that provides a minimal CPU environment and an external bus interface (like AXI4). This
|
wrapper" that provides a minimal CPU environment and an external bus interface (like AXI4). This
|
setup also allows to further use the default bootloader and software framework. From this base you
|
setup also allows to further use the default bootloader and software framework. From this base you
|
can start building your own SoC. Of course you can also use the CPU in it’s true stand-alone mode.
|
can start building your own SoC. Of course you can also use the CPU in it's true stand-alone mode.
|
|
|
[NOTE]
|
[NOTE]
|
This documentation assumes the reader is familiar with the official RISC-V "User" and "Privileged Architecture" specifications.
|
This documentation assumes the reader is familiar with the official RISC-V "User" and "Privileged Architecture" specifications.
|
|
|
|
|
Line 195... |
Line 195... |
Check srli-01 ... OK
|
Check srli-01 ... OK
|
Check sub-01 ... OK
|
Check sub-01 ... OK
|
Check sw-align-01 ... OK
|
Check sw-align-01 ... OK
|
Check xor-01 ... OK
|
Check xor-01 ... OK
|
Check xori-01 ... OK
|
Check xori-01 ... OK
|
|
Check fence-01 ... OK
|
--------------------------------
|
--------------------------------
|
OK: 38/38 RISCV_TARGET=neorv32 RISCV_DEVICE=I XLEN=32
|
OK: 39/39 RISCV_TARGET=neorv32 RISCV_DEVICE=I XLEN=32
|
...................................
|
...................................
|
|
|
.**RISC-V `rv32_m/M` Tests**
|
.**RISC-V `rv32_m/M` Tests**
|
...................................
|
...................................
|
Check div-01 ... OK
|
Check div-01 ... OK
|
Line 258... |
Line 259... |
Any machine-mode write access to them is ignored and will _not_ cause any exceptions or side-effects to maintain
|
Any machine-mode write access to them is ignored and will _not_ cause any exceptions or side-effects to maintain
|
RISC-V compatibility.
|
RISC-V compatibility.
|
|
|
.Physical Memory Protection
|
.Physical Memory Protection
|
[IMPORTANT]
|
[IMPORTANT]
|
The physical memory protection (see section <<_machine_physical_memory_protection>>)
|
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.
|
only supports the modes _OFF_ and _NAPOT_ yet and a minimal granularity of 8 bytes per region.
|
|
|
.Atomic Memory Operations
|
.Atomic Memory Operations
|
[IMPORTANT]
|
[IMPORTANT]
|
The `A` CPU extension only implements the `lr.w` and `sc.w` instructions yet.
|
The `A` CPU extension only implements the `lr.w` and `sc.w` instructions yet.
|
Line 424... |
Line 425... |
|
|
[IMPORTANT]
|
[IMPORTANT]
|
The NEORV32 `B` extension only implements the _basic bit-manipulation instructions_ (`Zbb`) subset
|
The NEORV32 `B` extension only implements the _basic bit-manipulation instructions_ (`Zbb`) subset
|
and the _address generation instructions_ (`Zba`) subset yet.
|
and the _address generation instructions_ (`Zba`) subset yet.
|
|
|
The `Zbb` sub-extension adds the following instruction:
|
The `Zbb` sub-extension adds the following instructions:
|
|
|
* `andn`, `orn`, `xnor`
|
* `andn` `orn` `xnor`
|
* `clz`, `ctz`, `cpop`
|
* `clz` `ctz` `cpop`
|
* `max`, `maxu`, `min`, `minu`
|
* `max` `maxu` `min` `minu`
|
* `sext.b`, `sext.h`, `zext.h`
|
* `sext.b` `sext.h` `zext.h`
|
* `rol`, `ror`, `rori`
|
* `rol` `ror` `rori`
|
* `orc.b`, `rev8`
|
* `orc.b` `rev8`
|
|
|
The `Zba` sub-extension adds the following instruction:
|
The `Zba` sub-extension adds the following instructions:
|
|
|
* `sh1add`, `sh2add`, `sh3add`
|
* `sh1add` `sh2add` `sh3add`
|
|
|
[TIP]
|
[TIP]
|
By default, the bit-manipulation unit uses an _iterative_ approach to compute shift-related operations
|
By default, the bit-manipulation unit uses an _iterative_ approach to compute shift-related operations
|
like `clz` and `rol`. To increase performance (at the cost of additional hardware resources) the
|
like `clz` and `rol`. To increase performance (at the cost of additional hardware resources) the
|
<<_fast_shift_en>> generic can be enabled to implement full-parallel logic (like barrel shifters) for all
|
<<_fast_shift_en>> generic can be enabled to implement full-parallel logic (like barrel shifters) for all
|
Line 456... |
Line 457... |
|
|
The _compressed_ ISA extension provides 16-bit encodings of commonly used instructions to reduce code space size.
|
The _compressed_ ISA extension provides 16-bit encodings of commonly used instructions to reduce code space size.
|
The `C` extension is available when the `CPU_EXTENSION_RISCV_C` configuration generic is _true_.
|
The `C` extension is available when the `CPU_EXTENSION_RISCV_C` configuration generic is _true_.
|
In this case the following instructions are available:
|
In this case the following instructions are available:
|
|
|
* `c.addi4spn`, `c.lw`, `c.sw`, `c.nop`, `c.addi`, `c.jal`, `c.li`, `c.addi16sp`, `c.lui`, `c.srli`, `c.srai` `c.andi`, `c.sub`,
|
* `c.addi4spn` `c.lw` `c.sw` `c.nop` `c.addi` `c.jal` `c.li` `c.addi16sp` `c.lui` `c.srli` `c.srai` `c.andi` `c.sub`
|
`c.xor`, `c.or`, `c.and`, `c.j`, `c.beqz`, `c.bnez`, `c.slli`, `c.lwsp`, `c.jr`, `c.mv`, `c.ebreak`, `c.jalr`, `c.add`, `c.swsp`
|
`c.xor` `c.or` `c.and` `c.j` `c.beqz` `c.bnez` `c.slli` `c.lwsp` `c.jr` `c.mv` `c.ebreak` `c.jalr` `c.add` `c.swsp`
|
|
|
[NOTE]
|
[NOTE]
|
When the compressed instructions extension is enabled, branches to an _unaligned_ and _uncompressed_ instruction require
|
When the compressed instructions extension is enabled, branches to an _unaligned_ and _uncompressed_ instruction require
|
an additional instruction fetch to load the according second half-word of that instruction. The performance can be increased
|
an additional instruction fetch to load the according second half-word of that instruction. The performance can be increased
|
again by forcing a 32-bit alignment of branch target addresses. By default, this is enforced via the GCC `-falign-functions=4`,
|
again by forcing a 32-bit alignment of branch target addresses. By default, this is enforced via the GCC `-falign-functions=4`,
|
Line 473... |
Line 474... |
The embedded CPU extensions reduces the size of the general purpose register file from 32 entries to 16 entries to
|
The embedded CPU extensions reduces the size of the general purpose register file from 32 entries to 16 entries to
|
decrease physical hardware requirements (for example block RAM). This extensions is enabled when the `CPU_EXTENSION_RISCV_E`
|
decrease physical hardware requirements (for example block RAM). This extensions is enabled when the `CPU_EXTENSION_RISCV_E`
|
configuration generic is _true_. Accesses to registers beyond `x15` will raise and _illegal instruction exception_.
|
configuration generic is _true_. Accesses to registers beyond `x15` will raise and _illegal instruction exception_.
|
This extension does not add any additional instructions or features.
|
This extension does not add any additional instructions or features.
|
|
|
[IMPORTANT]
|
[NOTE]
|
Due to the reduced register file size an alternate toolchain ABI (**`ilp32e`**) is required.
|
Due to the reduced register file size an alternate toolchain ABI (**`ilp32e`**) is required.
|
|
|
|
|
==== **`I`** - Base Integer ISA
|
==== **`I`** - Base Integer ISA
|
|
|
The CPU always supports the complete `rv32i` base integer instruction set. This base set is always enabled
|
The CPU always supports the complete `rv32i` base integer instruction set. This base set is always enabled
|
regardless of the setting of the remaining exceptions. The base instruction set includes the following
|
regardless of the setting of the remaining exceptions. The base instruction set includes the following
|
instructions:
|
instructions:
|
|
|
* immediate: `lui`, `auipc`
|
* immediate: `lui` `auipc`
|
* jumps: `jal`, `jalr`
|
* jumps: `jal` `jalr`
|
* branches: `beq`, `bne`, `blt`, `bge`, `bltu`, `bgeu`
|
* branches: `beq` `bne` `blt` `bge` `bltu` `bgeu`
|
* memory: `lb`, `lh`, `lw`, `lbu`, `lhu`, `sb`, `sh`, `sw`
|
* memory: `lb` `lh` `lw` `lbu` `lhu` `sb` `sh` `sw`
|
* alu: `addi`, `slti`, `sltiu`, `xori`, `ori`, `andi`, `slli`, `srli`, `srai`, `add`, `sub`, `sll`, `slt`, `sltu`, `xor`, `srl`, `sra`, `or`, `and`
|
* alu: `addi` `slti` `sltiu` `xori` `ori` `andi` `slli` `srli` `srai` `add` `sub` `sll` `slt` `sltu` `xor` `srl` `sra` `or` `and`
|
* environment: `ecall`, `ebreak`, `fence`
|
* environment: `ecall` `ebreak` `fence`
|
|
|
[NOTE]
|
[NOTE]
|
In order to keep the hardware footprint low, the CPU's shift unit uses a bit-serial serial approach. Hence, shift operations
|
In order to keep the hardware footprint low, the CPU's shift unit uses a bit-serial approach. Hence, shift operations
|
take up to 32 cycles (plus overhead) depending on the actual shift amount. Alternatively, the shift operations can be processed
|
take up to 32 cycles (plus overhead) depending on the actual shift amount. Alternatively, the shift operations can be processed
|
completely in parallels by a fast (but large) barrel shifter when the `FAST_SHIFT_EN` generic is _true_. In that case, shift operations
|
completely in parallel by a fast (but large) barrel shifter if the `FAST_SHIFT_EN` generic is _true_. In that case, shift operations
|
complete within 2 cycles (plus overhead) regardless of the actual shift amount.
|
complete within 2 cycles (plus overhead) regardless of the actual shift amount.
|
|
|
[NOTE]
|
[NOTE]
|
Internally, the `fence` instruction does not perform any operation inside the CPU. It only sets the
|
Internally, the `fence` instruction does not perform any operation inside the CPU. It only sets the
|
top’s `d_bus_fence_o` signal high for one cycle to inform the memory system a `fence` instruction has been
|
top's `d_bus_fence_o` signal high for one cycle to inform the memory system a `fence` instruction has been
|
executed. Any flags within the `fence` instruction word are ignore by the hardware.
|
executed. Any flags within the `fence` instruction word are ignore by the hardware.
|
|
|
|
|
==== **`M`** - Integer Multiplication and Division
|
==== **`M`** - Integer Multiplication and Division
|
|
|
Hardware-accelerated integer multiplication and division operations are available when the
|
Hardware-accelerated integer multiplication and division operations are available when the
|
`CPU_EXTENSION_RISCV_M` configuration generic is _true_. In this case the following instructions are
|
`CPU_EXTENSION_RISCV_M` configuration generic is _true_. In this case the following instructions are
|
available:
|
available:
|
|
|
* multiplication: `mul`, `mulh`, `mulhsu`, `mulhu`
|
* multiplication: `mul` `mulh` `mulhsu` `mulhu`
|
* division: `div`, `divu`, `rem`, `remu`
|
* division: `div` `divu` `rem` `remu`
|
|
|
[NOTE]
|
[NOTE]
|
By default, multiplication and division operations are executed in a bit-serial approach.
|
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
|
generic is _true_ allowing faster execution. Multiplications and divisions
|
Line 525... |
Line 526... |
This is a _sub-extension_ of the `M` ISA extension. It implements the multiplication-only operations
|
This is a _sub-extension_ of the `M` ISA extension. It implements the multiplication-only operations
|
of the `M` extensions and is intended for size-constrained setups that require hardware-based
|
of the `M` extensions and is intended for size-constrained setups that require hardware-based
|
integer multiplications but not hardware-based divisions, which will be computed entirely in software.
|
integer multiplications but not hardware-based divisions, which will be computed entirely in software.
|
This extension requires only ~50% of the hardware utilization of the "full" `M` extension.
|
This extension requires only ~50% of the hardware utilization of the "full" `M` extension.
|
|
|
* multiplication: `mul`, `mulh`, `mulhsu`, `mulhu`
|
* multiplication: `mul` `mulh` `mulhsu` `mulhu`
|
|
|
If `Zmmul` is enabled, executing any division instruction from the `M` ISA extension (`div`, `divu`, `rem`, `remu`)
|
If `Zmmul` is enabled, executing any division instruction from the `M` ISA extension (`div`, `divu`, `rem`, `remu`)
|
will raise an _illegal instruction exception_.
|
will raise an _illegal instruction exception_.
|
|
|
Note that `M` and `Zmmul` extensions _cannot_ be enabled at the same time.
|
Note that `M` and `Zmmul` extensions _cannot_ be enabled at the same time.
|
Line 567... |
Line 568... |
instead of a dedicated floating-point register file (hence, `F-in-x`). Thus, the `Zfinx` extension requires
|
instead of a dedicated floating-point register file (hence, `F-in-x`). Thus, the `Zfinx` extension requires
|
less hardware resources and features faster context changes. This also implies that there are NO dedicated `f`
|
less hardware resources and features faster context changes. This also implies that there are NO dedicated `f`
|
register file-related load/store or move instructions.
|
register file-related load/store or move instructions.
|
The official RISC-V specifications can be found here: https://github.com/riscv/riscv-zfinx
|
The official RISC-V specifications can be found here: https://github.com/riscv/riscv-zfinx
|
|
|
[TIP]
|
[NOTE]
|
The NEORV32 floating-point unit used by the `Zfinx` extension is compatible to the _IEEE-754_ specifications.
|
The NEORV32 floating-point unit used by the `Zfinx` extension is compatible to the _IEEE-754_ specifications.
|
|
|
The `Zfinx` extensions only supports single-precision (`.s` instruction suffix), so it is a direct alternative
|
The `Zfinx` extensions only supports single-precision (`.s` instruction suffix), so it is a direct alternative
|
to the `F` extension. The `Zfinx` extension is implemented when the `CPU_EXTENSION_RISCV_Zfinx` configuration
|
to the `F` extension. The `Zfinx` extension is implemented when the `CPU_EXTENSION_RISCV_Zfinx` configuration
|
generic is _true_. In this case the following instructions and CSRs are available:
|
generic is _true_. In this case the following instructions and CSRs are available:
|
|
|
* conversion: `fcvt.s.w`, `fcvt.s.wu`, `fcvt.w.s`, `fcvt.wu.s`
|
* conversion: `fcvt.s.w` `fcvt.s.wu` `fcvt.w.s` `fcvt.wu.s`
|
* comparison: `fmin.s`, `fmax.s`, `feq.s`, `flt.s`, `fle.s`
|
* comparison: `fmin.s` `fmax.s` `feq.s` `flt.s` `fle.s`
|
* computational: `fadd.s`, `fsub.s`, `fmul.s`
|
* computational: `fadd.s` `fsub.s` `fmul.s`
|
* sign-injection: `fsgnj.s`, `fsgnjn.s`, `fsgnjx.s`
|
* sign-injection: `fsgnj.s` `fsgnjn.s` `fsgnjx.s`
|
* number classification: `fclass.s`
|
* number classification: `fclass.s`
|
|
|
* additional CSRs: `fcsr`, `frm`, `fflags`
|
* additional CSRs: `fcsr` `frm` `fflags`
|
|
|
[WARNING]
|
[WARNING]
|
Fused multiply-add instructions `f[n]m[add/sub].s` are not supported!
|
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!
|
Division `fdiv.s` and square root `fsqrt.s` instructions are not supported yet!
|
|
|
Line 607... |
Line 608... |
is implemented when the `CPU_EXTENSION_RISCV_Zicsr` configuration generic is _true_.
|
is implemented when the `CPU_EXTENSION_RISCV_Zicsr` configuration generic is _true_.
|
|
|
[IMPORTANT]
|
[IMPORTANT]
|
If the `Zicsr` extension is disabled the CPU does not provide any _privileged architecture_ features at all!
|
If the `Zicsr` extension is disabled the CPU does not provide any _privileged architecture_ features at all!
|
In order to provide the full set of privileged functions that are required to run more complex tasks like
|
In order to provide the full set of privileged functions that are required to run more complex tasks like
|
operating system and to allow a secure execution environment the `Zicsr` extension should always be enabled.
|
operating system and to allow a secure execution environment the `Zicsr` extension should be always enabled.
|
|
|
In this case the following instructions are available:
|
In this case the following instructions are available:
|
|
|
* CSR access: `csrrw`, `csrrs`, `csrrc`, `csrrwi`, `csrrsi`, `csrrci`
|
* CSR access: `csrrw` `csrrs` `csrrc` `csrrwi` `csrrsi` `csrrci`
|
* environment: `mret`, `wfi`
|
* environment: `mret` `wfi`
|
|
|
[NOTE]
|
[NOTE]
|
If `rd=x0` for the `csrrw[i]` instructions there will be no actual read access to the according CSR.
|
If `rd=x0` for the `csrrw[i]` instructions there will be no actual read access to the according CSR.
|
However, access privileges are still enforced so these instruction variants _do_ cause side-effects
|
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").
|
(the RISC-V spec. state that these combinations "_shall_ not cause any side-effects").
|
Line 697... |
Line 698... |
|
|
* `pmpcfg*` (0..15, depending on configuration): PMP configuration registers
|
* `pmpcfg*` (0..15, depending on configuration): PMP configuration registers
|
* `pmpaddr*` (0..63, depending on configuration): PMP address registers
|
* `pmpaddr*` (0..63, depending on configuration): PMP address registers
|
|
|
[TIP]
|
[TIP]
|
See section <<_machine_physical_memory_protection>> for more information regarding the PMP CSRs.
|
See section <<_machine_physical_memory_protection_csrs>> for more information regarding the PMP CSRs.
|
|
|
The actual number of regions and the minimal region granularity are defined via the top entity
|
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
|
`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
|
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.
|
number of available `pmpcfg*` and `pmpaddr*` CSRs.
|
Line 821... |
Line 822... |
* _traps_ = exceptions + interrupts (synchronous or asynchronous exceptions)
|
* _traps_ = exceptions + interrupts (synchronous or asynchronous exceptions)
|
|
|
Whenever an exception or interrupt is triggered, the CPU transfers control to the address stored in `mtvec`
|
Whenever an exception or interrupt is triggered, the CPU transfers control to the address stored in `mtvec`
|
CSR. The cause of the according interrupt or exception can be determined via the content of `mcause`
|
CSR. The cause of the according interrupt or exception can be determined via the content of `mcause`
|
CSR. The address that reflects the current program counter when a trap was taken is stored to `mepc` CSR.
|
CSR. The address that reflects the current program counter when a trap was taken is stored to `mepc` CSR.
|
Additional information regarding the cause of the trap can be retrieved from `mtval` CSR.
|
Additional information regarding the cause of the trap can be retrieved from `mtval` CSR and the processor's
|
|
<<_internal_bus_monitor_buskeeper>> (for memory access exceptions)
|
|
|
The traps are prioritized. If several _exceptions_ occur at once only the one with highest priority is triggered
|
The traps are prioritized. If several _synchronous exceptions_ occur at once only the one with highest priority is triggered
|
while all remaining exceptions are ignored. If several _interrupts_ trigger at once, the one with highest priority
|
while all remaining exceptions are ignored. If several _asynchronous exceptions_ (interrupts) trigger at once, the one with highest priority
|
is serviced first while the remaining ones stay _pending_. After completing the interrupt handler the interrupt with
|
is serviced first while the remaining ones stay _pending_. After completing the interrupt handler the interrupt with
|
the second highest priority will get serviced and so on until no further interrupt are pending.
|
the second highest priority will get serviced and so on until no further interrupts are pending.
|
|
|
.Interrupt Signal Requirements - Standard RISC-V Interrupts
|
.Interrupt Signal Requirements - Standard RISC-V Interrupts
|
[IMPORTANT]
|
[IMPORTANT]
|
All standard RISC-V interrupts request signals are **high-active**. A request has to stay at high-level (=asserted)
|
All standard RISC-V interrupts request signals are **high-active**. A request has to stay at high-level (=asserted)
|
until it is explicitly acknowledged by the CPU software (for example by writing to a specific memory-mapped register).
|
until it is explicitly acknowledged by the CPU software (for example by writing to a specific memory-mapped register).
|
|
|
.Interrupt Signal Requirements - Fast Interrupt Requests
|
.Interrupt Signal Requirements - Fast Interrupt Requests
|
[IMPORTANT]
|
[IMPORTANT]
|
The NEORV32-specific FIRQ request lines are triggered by a rising edge. Each request is buffered in the CPU control
|
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
|
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).
|
the according `mip` CSR bit).
|
|
|
.Instruction Atomicity
|
.Instruction Atomicity
|
[NOTE]
|
[NOTE]
|
All instructions execute as atomic operations - interrupts can only trigger between two instructions.
|
All instructions execute as atomic operations - interrupts can only trigger _between_ two instructions.
|
So if there is a permanent interrupt request, exactly one instruction from the interrupt program will be executed before
|
So even if there is a permanent interrupt request, exactly one instruction from the interrupt program will be executed before
|
a new interrupt handler can start.
|
another interrupt handler can start. This allows program progress even if there are permanent interrupt requests.
|
|
|
|
|
:sectnums:
|
:sectnums:
|
==== Memory Access Exceptions**
|
==== Memory Access Exceptions
|
|
|
If a load operation causes any exception, the instruction's destination register is
|
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
|
_not written_ at all. Load exceptions caused by a misalignment or a physical memory protection fault do not
|
trigger a bus read-operation at all. Exceptions caused by a store address misalignment or a store physical
|
trigger a bus/memory read-operation at all. Vice versa, exceptions caused by a store address misalignment or a store physical
|
memory protection fault do not trigger a bus write-operation at all.
|
memory protection fault do not trigger a bus/memory write-operation at all.
|
|
|
|
|
:sectnums:
|
:sectnums:
|
==== Custom Fast Interrupt Request Lines
|
==== Custom Fast Interrupt Request Lines
|
|
|
Line 880... |
Line 882... |
|
|
**Table Annotations**
|
**Table Annotations**
|
|
|
The "Prio." column shows the priority of each trap. The highest priority is 1. The "`mcause`" column shows the
|
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
|
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 (`sw/lib/include/neorv32.h`) and can
|
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
|
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:
|
`mepc` and `mtval` CSRs when a trap is triggered:
|
|
|
* _I-PC_ - address of interrupted instruction (instruction has not been execute/completed yet)
|
* _I-PC_ - address of interrupted instruction (instruction has not been execute/completed yet)
|
* _B-ADR_- bad memory access address that cause the trap
|
* _B-ADR_- bad memory access address that cause the trap
|
Line 933... |
Line 935... |
|
|
.NEORV32 Trap Description
|
.NEORV32 Trap Description
|
[cols="<3,<7"]
|
[cols="<3,<7"]
|
[options="header",grid="rows"]
|
[options="header",grid="rows"]
|
|=======================
|
|=======================
|
| Trap ID | Triggered when ...
|
| 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 an 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_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_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_MENV_CALL_ | executing `ecall` instruction in machine-mode
|
| _TRAP_CODE_UENV_CALL_ | executing `ecall` instruction in user-mode
|
| _TRAP_CODE_UENV_CALL_ | executing `ecall` instruction in user-mode
|
Line 1001... |
Line 1003... |
| `bus_priv_o` | 2 | current CPU privilege level
|
| `bus_priv_o` | 2 | current CPU privilege level
|
|=======================
|
|=======================
|
|
|
[NOTE]
|
[NOTE]
|
Currently, there a no pipelined or overlapping operations implemented within the same bus interface.
|
Currently, there a no pipelined or overlapping operations implemented within the same bus interface.
|
So only a single transfer request can be "on the fly".
|
So only a single transfer request can be "on the fly" (pending) at once.
|
|
|
:sectnums:
|
:sectnums:
|
===== Protocol
|
===== Protocol
|
|
|
A bus request is triggered either by the `bus_re_o` signal (for reading data) or by the `bus_we_o` signal (for
|
A bus request is triggered either by the `bus_re_o` signal (for reading data) or by the `bus_we_o` signal (for
|
Line 1105... |
Line 1107... |
In order to reduce routing constraints (and by this the actual hardware requirements), most uncritical
|
In order to reduce routing constraints (and by this the actual hardware requirements), most uncritical
|
registers of the NEORV32 CPU as well as most register of the whole NEORV32 Processor do not use **a
|
registers of the NEORV32 CPU as well as most register of the whole NEORV32 Processor do not use **a
|
dedicated hardware reset**. "Uncritical registers" in this context means that the initial value of these registers
|
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.
|
after power-up is not relevant for a defined CPU boot process.
|
|
|
**Rational**
|
**Rationale**
|
|
|
A good example to illustrate the concept of uncritical registers is a pipelined processing engine. Each stage
|
A good example to illustrate the concept of uncritical registers is a pipelined processing engine. Each stage
|
of the engine features an N-bit _data register_ and a 1-bit _status register_. The status register is set when the
|
of the engine features an N-bit _data register_ and a 1-bit _status register_. The status register is set when the
|
data in the according data register is valid. At the end of the pipeline the status register might trigger a write-back
|
data in the according data register is valid. At the end of the pipeline the status register might trigger a write-back
|
of the processing result to some kind of memory. The initial status of the data registers after power-up is
|
of the processing result to some kind of memory. The initial status of the data registers after power-up is
|
irrelevant as long as the status registers are all reset to a defined value that indicates there is no valid data in
|
irrelevant as long as the status registers are all reset to a defined value that indicates there is no valid data in
|
the pipeline’s data register. Therefore, the pipeline data register do no require a dedicated reset as they do not
|
the pipeline's data register. Therefore, the pipeline data register do no require a dedicated reset as they do not
|
control the actual operation (in contrast to the status register). This makes the pipeline data registers from
|
control the actual operation (in contrast to the status register). This makes the pipeline data registers from
|
this example "uncritical registers".
|
this example "uncritical registers".
|
|
|
**NEORV32 CPU Reset**
|
**NEORV32 CPU Reset**
|
|
|
In terms of the NEORV32 CPU, there are several pipeline registers, state machine registers and even status
|
In terms of the NEORV32 CPU, there are several pipeline registers, state machine registers and even status
|
and control registers (CSRs) that do not require a defined initial state to ensure a correct boot process. The
|
and control registers (CSRs) that do not require a defined initial state to ensure a correct boot process. The
|
pipeline register will get initialized by the CPU’s internal state machines, which are initialized from the main
|
pipeline register will get initialized by the CPU's internal state machines, which are initialized from the main
|
control engine that actually features a defined reset. The initialization of most of the CPU's core CSRs (like
|
control engine that actually features a defined reset. The initialization of most of the CPU's core CSRs (like
|
interrupt control) is done by the software (to be more specific, this is done by the `crt0.S` start-up code).
|
interrupt control) is done by the software (to be more specific, this is done by the `crt0.S` start-up code).
|
|
|
During the very early boot process (where `crt0.S` is running) there is no chance for undefined behavior due to
|
During the very early boot process (where `crt0.S` is running) there is no chance for undefined behavior due to
|
the lack of dedicated hardware resets of certain CSRs. For example the machine interrupt-enable CSR (`mie`)
|
the lack of dedicated hardware resets of certain CSRs. For example the machine interrupt-enable CSR (`mie`)
|
does not provide a dedicated reset. The value after reset of this register is uncritical as interrupts cannot fire
|
does not provide a dedicated reset. The value after reset of this register is uncritical as interrupts cannot fire
|
because the global interrupt enabled flag in the status register (`mstatsus(mie)`) provides a dedicated
|
because the global interrupt enabled flag in the status register (`mstatsus(mie)`) _do_ provide a dedicated
|
hardware reset setting it to low (globally disabling interrupts).
|
hardware reset setting this bit to low (globally disabling interrupts).
|
|
|
**Reset Configuration**
|
**Reset Configuration**
|
|
|
Most CPU-internal register do feature an asynchronous reset in the VHDL code, but the "don't care" value
|
Most CPU-internal register do provide an asynchronous reset in the VHDL code, but the "don't care" value
|
(VHDL `'-'`) is used for initialization of the uncritical register, effectively generating a flip-flop without a
|
(VHDL `'-'`) is used for initialization of all uncritical registers, effectively generating a flip-flop without a
|
reset. However, certain applications or situations (like advanced gate-level / timing simulations) might
|
reset. However, certain applications or situations (like advanced gate-level / timing simulations) might
|
require a more deterministic reset state. For this case, a defined reset level (reset-to-low) of all registers can
|
require a more deterministic reset state. For this case, a defined reset level (reset-to-low) of all CPU registers can
|
be enabled via a constant in the main VHDL package file (`rtl/core/neorv32_package.vhd`):
|
be enabled ba enabling a constant in the main VHDL package file (`rtl/core/neorv32_package.vhd`):
|
|
|
[source,vhdl]
|
[source,vhdl]
|
----
|
----
|
-- "critical" number of PMP regions --
|
-- "critical" number of PMP regions --
|
constant dedicated_reset_c : boolean := false; -- use dedicated hardware reset value
|
constant dedicated_reset_c : boolean := false; -- use dedicated hardware reset value for UNCRITICAL registers (FALSE=reset value is irrelevant (might simplify HW), default; TRUE=defined LOW reset value)
|
for UNCRITICAL registers (FALSE=reset value is irrelevant (might simplify HW),
|
|
default; TRUE=defined LOW reset value)
|
|
----
|
----
|