Line 4... |
Line 4... |
image::riscv_logo.png[width=350,align=center]
|
image::riscv_logo.png[width=350,align=center]
|
|
|
**Key Features**
|
**Key Features**
|
|
|
* 32-bit pipelined/multi-cycle in-order `rv32` RISC-V CPU
|
* 32-bit pipelined/multi-cycle in-order `rv32` RISC-V CPU
|
* Optional RISC-V extensions: `rv32[i/e][m][a][c][u]` + `[Zfinx][Zicsr][Zifencei]` + `[debug_mode]` (for on-chip debugging)
|
* Optional RISC-V extensions:
|
|
** `A` - atomic memory access operations
|
|
** `C` - 16-bit compressed instructions
|
|
** `I` - integer base ISA (always enabled)
|
|
** `E` - embedded CPU version (reduced register file size)
|
|
** `M` - integer multiplication and division hardware
|
|
** `U` - less-privileged _user_ mode
|
|
** `Zfinx` - single-precision floating-point unit
|
|
** `Zicsr` - control and status register access (privileged architecture)
|
|
** `Zifencei` - instruction stream synchronization
|
|
** `Zmmul` - integer multiplication hardware
|
|
** `PMP` - physical memory protection
|
|
** `HPM` - hardware performance monitors
|
|
** `DB` - debug mode
|
* 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+)
|
* 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
|
* Official RISC-V open-source architecture ID
|
* Standard RISC-V interrupts (_external_, _timer_, _software_) plus 16 _fast_ interrupts and 1 non-maskable interrupt
|
* Standard RISC-V interrupts (_external_, _timer_, _software_) plus 16 _fast_ interrupts and 1 non-maskable interrupt
|
* Supports most of the traps from the RISC-V specifications (including bus access exceptions) and traps on all unimplemented/illegal/malformed instructions
|
* Supports most of the traps from the RISC-V specifications (including bus access exceptions) and traps on all unimplemented/illegal/malformed instructions
|
* Optional physical memory configuration (PMP), compatible to the RISC-V specifications
|
* Optional physical memory configuration (PMP), compatible to the RISC-V specifications
|
Line 294... |
Line 307... |
[frame="all",grid="none"]
|
[frame="all",grid="none"]
|
|======
|
|======
|
| **CPU_BOOT_ADDR** | _std_ulogic_vector(31 downto 0)_ | 0x00000000
|
| **CPU_BOOT_ADDR** | _std_ulogic_vector(31 downto 0)_ | 0x00000000
|
3+| This address defines the reset address at which the CPU starts fetching instructions after reset. In terms of the NEORV32 processor, this
|
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
|
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 (_BOOTLOADER_EN_ = _false_). See section <<_address_space>> for more information.
|
memory (IMEM) if the bootloader is disabled (_INT_BOOTLOADER_EN_ = _false_). See section <<_address_space>> for more information.
|
|======
|
|======
|
|
|
[cols="4,4,2"]
|
[cols="4,4,2"]
|
[frame="all",grid="none"]
|
[frame="all",grid="none"]
|
|======
|
|======
|
Line 385... |
Line 398... |
* 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 hybrid parallel/serial approach. Shift
|
In order to keep the hardware footprint low, the CPU's shift unit uses a bit-serial serial approach. Hence, shift operations
|
operations are split in coarse shifts (multiples of 4) and a final fine shift (0 to 3). The total execution
|
take up to 32 cycles (plus overhead) depending on the actual shift amount. Alternatively, the shift operations can be processed
|
time depends on the shift amount. Alternatively, the shift operations can be processed completely in parallels by a fast
|
completely in parallels by a fast (but large) barrel shifter when the `FAST_SHIFT_EN` generic is _true_. In that case, shift operations
|
(but large) barrel shifter when 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 regardless of the shift amount. Shift operations can also be executed in a pure serial manner when
|
|
then `TINY_SHIFT_EN` generic is _true_. In that case, shift operations take up to 32 cycles depending on the 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.
|
Line 404... |
Line 415... |
|
|
Hardware-accelerated integer multiplication and division instructions are available when the
|
Hardware-accelerated integer multiplication and division instructions 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
|
always require a fixed amount of cycles to complete - regardless of the input operands.
|
always require a fixed amount of cycles to complete - regardless of the input operands.
|
|
|
|
|
|
==== **`Zmmul`** - Integer Multiplication
|
|
|
|
This is a _sub-extension_ of the `M` ISA extension. It implements the multiplication-only operations
|
|
of the `M` extensions and is intended for small scale applications, that require hardware-based
|
|
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 `M` extension.
|
|
|
|
* multiplication: `mul`, `mulh`, `mulhsu`, `mulhu`
|
|
|
|
If `Zmmul` is enabled, executing any division instruction from the `M` ISA (`div`, `divu`, `rem`, `remu`)
|
|
will raise an illegal instruction exception.
|
|
|
|
Note that `M` and `Zmmul` extensions _cannot_ be enabled in parallel.
|
|
|
|
[TIP]
|
|
If your RISC-V GCC toolchain does not (yet) support the `_Zmmul` ISA extensions, it can be "emulated"
|
|
using a `rv32im` machine architecture and setting the `-mno-div` compiler flag
|
|
(example `$ make MARCH=-march=rv32im USER_FLAGS+=-mno-div clean_all exe`).
|
|
|
|
|
==== **`U`** - Less-Privileged User Mode
|
==== **`U`** - Less-Privileged User Mode
|
|
|
Adds the less-privileged _user mode_ when the `CPU_EXTENSION_RISCV_U` configuration generic is _true_. For
|
Adds the less-privileged _user mode_ when the `CPU_EXTENSION_RISCV_U` configuration generic is _true_. For
|
instance, use-level code cannot access machine-mode CSRs. Furthermore, access to the address space (like
|
instance, use-level code cannot access machine-mode CSRs. Furthermore, access to the address space (like
|
peripheral/IO devices) can be limited via the physical memory protection (_PMP_) unit for code running in user mode.
|
peripheral/IO devices) can be limited via the physical memory protection (_PMP_) unit for code running in user mode.
|
Line 629... |
Line 660... |
|=======================
|
|=======================
|
| Class | ISA | Instruction(s) | Execution cycles
|
| 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 | `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 | `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 | `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.]/4 + SA%4; FAST_SHIFTfootnote:[Barrel shift when `FAST_SHIFT_EN` is enabled.]: 4; TINY_SHIFTfootnote:[Serial shift when `TINS_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 | `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
|
| Branches | `C` | `c.beqz` `c.bnez` | Taken: 5 + MLfootnote:[Memory latency.]; Not taken: 3
|
| Jumps / Calls | `I/E` | `jal` `jalr` | 4 + ML
|
| Jumps / Calls | `I/E` | `jal` `jalr` | 4 + ML
|
| Jumps / Calls | `C` | `c.jal` `c.j` `c.jr` `c.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 | `I/E` | `lb` `lh` `lw` `lbu` `lhu` `sb` `sh` `sw` | 4 + ML
|
Line 707... |
Line 738... |
|
|
// ####################################################################################################################
|
// ####################################################################################################################
|
:sectnums:
|
:sectnums:
|
==== Traps, Exceptions and Interrupts
|
==== Traps, Exceptions and Interrupts
|
|
|
In this document a (maybe) special nomenclature regarding traps is used:
|
In this document the following nomenclature regarding traps is used:
|
|
|
* _interrupt_ = asynchronous exceptions
|
* _interrupt_ = asynchronous exceptions
|
* _exceptions_ = synchronous exceptions
|
* _exceptions_ = synchronous exceptions
|
* _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 the `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 the `mcause`
|
CSR. The cause of the according interrupt or exception can be determined via the content of `mcause`
|
CSR The address that reflected the current program counter when a trap was taken is stored to `mepc`.
|
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`.
|
Additional information regarding the cause of the trap can be retrieved from `mtval` CSR.
|
|
|
The traps are prioritized. If several exceptions occur at once only the one with highest priority is triggered. If
|
The traps are prioritized. If several _exceptions_ occur at once only the one with highest priority is triggered
|
several interrupts trigger at once, the one with highest priority is triggered while the remaining ones are
|
while all remaining exceptions are ignored. If several _interrupts_ trigger at once, the one with highest priority
|
queued. After completing the interrupt handler the interrupt with the second highest priority will issues and
|
is serviced first while the remaining ones are queued. After completing the interrupt handler the interrupt with
|
so on.
|
the second highest priority will get serviced and so on until no further interrupt are pending.
|
|
|
|
|
**Memory Access Exceptions**
|
|
|
|
If a load operation causes any exception, the destination register is not written at all. 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 memory protection fault do not trigger
|
|
a bus write-operation at all.
|
|
|
|
|
|
**Instruction Atomicity**
|
.Trigger Type
|
|
[IMPORTANT]
|
|
All CPU interrupt request signals are high-level triggered. So an interrupt request will be generated if the
|
|
according signal is _high_ for exactly one cycle (being high for several cycles might cause multiple
|
|
triggering of the same interrupt).
|
|
|
|
.Instruction Atomicity
|
|
[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.
|
|
|
|
|
**Custom Fast Interrupt Request Lines**
|
:sectnums:
|
|
==== 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
|
|
trigger a bus read-operation at all. Exceptions caused by a store address misalignment or a store physical
|
|
memory protection fault do not trigger
|
|
a bus write-operation at all.
|
|
|
|
|
|
:sectnums:
|
|
==== Custom Fast Interrupt Request Lines
|
|
|
As a custom extension, the NEORV32 CPU features 16 fast interrupt request lines via the `firq_i` CPU (/Processor) top
|
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
|
entity signals. These interrupts have custom configuration and status flags in the `mie` and `mip` CSRs and also
|
provide custom trap codes in `mcause`.
|
provide custom trap codes in `mcause`. Thes FIRQs are reserved for processor-internal usage only.
|
|
|
|
|
**Non-Maskable Interrupt**
|
:sectnums:
|
|
==== Non-Maskable Interrupt
|
|
|
The NEORV32 CPU features a single non-maskable interrupt source via the `nm_irq_i` CPU (/Processor) top
|
The NEORV32 CPU features a single non-maskable interrupt source via the `nm_irq_i` CPU (/Processor) top
|
entity signal that can be used to signal critical system conditions. This interrupt source _cannot_ be disabled at all (even not in interrupt service routines).
|
entity signal. This interrupt can be used to signal _critical_ system conditions that need immediate handling.
|
|
The non-maskable interrupt _cannot_ be masked/disabled at all (even not in interrupt service routines).
|
Hence, it does _not_ provide configuration/status flags in the `mie` and `mip` CSRs. The RISC-V-compatible
|
Hence, it does _not_ provide configuration/status flags in the `mie` and `mip` CSRs. The RISC-V-compatible
|
`mcause` value `0x80000000` is used to indicate the non-maskable interrupt.
|
`mcause` value `0x80000000` is used to indicate the non-maskable interrupt.
|
|
|
[IMPORTANT]
|
|
All CPU/Processor interrupt request signals are triggered when the signal is _high_ for exactly one cycle (being high for several cycles might
|
|
cause multiple triggering of the interrupt).
|
|
|
|
|
|
|
|
// ####################################################################################################################
|
// ####################################################################################################################
|
:sectnums!:
|
:sectnums!:
|