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

Subversion Repositories neorv32

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 64 to Rev 65
    Reverse comparison

Rev 64 → Rev 65

/neorv32/trunk/docs/datasheet/cpu.adoc
21,9 → 21,9
** `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
* 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
* 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 hardware performance monitors (HPM) for application benchmarking
31,7 → 31,7
the NEORV32 processor)
* little-endian byte order
* Configurable hardware reset
* No hardware support of unaligned data/instruction accesses – they will trigger an exception.
* No hardware support of unaligned data/instruction accesses - they will trigger an exception.
 
[NOTE]
It is recommended to use the **NEORV32 Processor** as default top instance even if you only want to use the actual
53,11 → 53,11
 
image::neorv32_cpu.png[align=center]
 
The CPU uses a pipelined architecture with basically two main stages. The first stage (IF – instruction fetch)
The CPU uses a pipelined architecture with basically two main stages. The first stage (IF - instruction fetch)
is responsible for fetching new instruction data from memory via the fetch engine. The instruction data is
stored to a FIFO – the instruction prefetch buffer. The issue engine takes this data and assembles 32-bit
instruction words for the next pipeline stage. Compressed instructions – if enabled – are also decompressed
in this stage. The second stage (EX – execution) is responsible for actually executing the fetched instructions
stored to a FIFO - the instruction prefetch buffer. The issue engine takes this data and assembles 32-bit
instruction words for the next pipeline stage. Compressed instructions - if enabled - are also decompressed
in this stage. The second stage (EX - execution) is responsible for actually executing the fetched instructions
via the execute engine.
 
These two pipeline stages are based on a multi-cycle processing engine. So the processing of each stage for a
223,6 → 223,8
[IMPORTANT]
The `misa`, `mip` and `mtval` CSRs in the NEORV32 are _read-only_.
Any write access to it (in machine mode) to them are ignored and will _not_ cause any exceptions or side-effects.
Pending interrupt can only be cleared by acknowledging the interrupt-causing device. However, pending interrupts
can still be ignored by clearing the according `mie` register bits.
 
.Physical memory protection
[IMPORTANT]
337,9 → 339,9
:sectnums:
=== Instruction Sets and Extensions
 
The NEORV32 is an RISC-V `rv32i` architecture that provides several optional RISC-V CPU and ISA
The basic NEORV32 is a RISC-V `rv32i` architecture that provides several _optional_ RISC-V CPU and ISA
(instruction set architecture) extensions. For more information regarding the RISC-V ISA extensions please
see the The _RISC-V Instruction Set Manual – Volume I: Unprivileged ISA_ and _The RISC-V Instruction Set Manual
see the the _RISC-V Instruction Set Manual - Volume I: Unprivileged ISA_ and _The RISC-V Instruction Set Manual
Volume II: Privileged Architecture_, which are available in the projects `docs/references` folder.
 
[TIP]
348,15 → 350,16
or by executing an instruction and checking for an _illegal instruction exception_.
 
[NOTE]
Executing an instruction from an extension that is not implemented or not enabled (for example via the according
top entity generic) will raise an _illegal instruction_ exception.
Executing an instruction from an extension that is not supported yet or that is currently not enabled
(via the according top entity generic) will raise an _illegal instruction_ exception.
 
 
==== **`A`** - Atomic Memory Access
 
Atomic memory access instructions (for implementing semaphores and mutexes) are available when the
`CPU_EXTENSION_RISCV_A` configuration generic is _true_. In this case the following additional instructions
are available:
Atomic memory access instructions allow more sophisticated memory operations like implementing semaphores and mutexes.
The RICS-C specs. defines a specific _atomic_ extension that provides instructions for atomic memory accesses. The `A`
ISA extension is enabled if the `CPU_EXTENSION_RISCV_A` configuration generic is _true_.
In this case the following additional instructions are available:
 
* `lr.w`: load-reservate
* `sc.w`: store-conditional
364,9 → 367,19
[NOTE]
Even though only `lr.w` and `sc.w` instructions are implemented yet, all further atomic operations
(load-modify-write instruction) can be emulated using these two instruction. Furthermore, the
instruction’s ordering flags (`aq` and `lr`) are ignored by the CPU hardware. Using any other (not yet
implemented) AMO (atomic memory operation) will trigger an illegal instruction exception.
instruction's ordering flags (`aq` and `lr`) are ignored by the CPU hardware. Using any other (not yet
implemented) AMO (atomic memory operation) will raise an illegal instruction exception.
 
The *load-reservate* instruction behaves as a "normal" load-word instruction (`lw`) but will also set a CPU-internal
_data memory access lock_. Executing a *store-conditional* behaves as "normal" store-word instruction (`sw`) that will
only conduct an actual memory write operations if the lock is still intact. Additionally, the store-conditional instruction
will also return the lock state (returns zero if the lock is still intact or non-zero if the lock has been broken).
After the execution of the `sc` instruction, the lock is automatically removed.
 
The lock is broken if at least one of the following conditions occur:
. executing any data memory access instruction other than `lr.w`
. raising _any_ t (for example an interrupt or a memory access exception)
 
[NOTE]
The atomic instructions have special requirements for memory system / bus interconnect. More
information can be found in sections <<_bus_interface>> and <<_processor_external_memory_interface_wishbone_axi4_lite>>, respectively.
374,15 → 387,16
 
==== **`C`** - Compressed Instructions
 
Compressed 16-bit instructions are available when the `CPU_EXTENSION_RISCV_C` configuration generic is
_true_. In this case the following instructions are available:
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_.
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.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]
When the compressed instructions extension is enabled, branches to an _unaligned_ and _uncompressed_ address require
an additional instruction fetch to load the required second half-word of that instruction. The performance can be increased
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
again by forcing a 32-bit alignment of branch target addresses. By default, this is enforced via the GCC `-falign-functions=4`,
`-falign-labels=4`, `-falign-loops=4` and `-falign-jumps=4` compile flags (via the makefile).
 
389,9 → 403,10
 
==== **`E`** - Embedded CPU
 
The embedded CPU extensions reduces the size of the general purpose register file from 32 entries to 16 entries to reduce hardware
requirements. 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_.
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`
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.
 
[IMPORTANT]
Due to the reduced register file size an alternate toolchain ABI (**`ilp32e`**) is required.
398,11 → 413,12
 
 
==== **`I`** - Base Integer ISA
 
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
instructions:
 
* immediates: `lui`, `auipc`
* immediate: `lui`, `auipc`
* jumps: `jal`, `jalr`
* branches: `beq`, `bne`, `blt`, `bge`, `bltu`, `bgeu`
* memory: `lb`, `lh`, `lw`, `lbu`, `lhu`, `sb`, `sh`, `sw`
423,7 → 439,7
 
==== **`M`** - Integer Multiplication and Division
 
Hardware-accelerated integer multiplication and division instructions 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
available:
 
440,9 → 456,9
==== **`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
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.
This extension requires only ~50% of the hardware utilization of the `M` extension.
This extension requires only ~50% of the hardware utilization of the "full" `M` extension.
 
* multiplication: `mul`, `mulh`, `mulhsu`, `mulhu`
 
454,14 → 470,16
[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`).
(example `$ make MARCH=rv32im USER_FLAGS+=-mno-div clean_all exe`).
 
 
==== **`U`** - Less-Privileged User Mode
 
Adds the less-privileged _user mode_ if 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
peripheral/IO devices) can be limited via the physical memory protection (_PMP_) unit for code running in user mode.
In addition to the basic (and highest-privileged) machine-mode, the _user-mode_ ISA extensions adds a second less-privileged
operation mode. It is implemented if the `CPU_EXTENSION_RISCV_U` configuration generic is _true_.
Code executed in user-mode cannot access machine-mode CSRs. Furthermore, user-mode access to the address space (like
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.
 
 
==== **`X`** - NEORV32-Specific (Custom) Extensions
477,19 → 495,18
 
==== **`Zfinx`** Single-Precision Floating-Point Operations
 
[WARNING]
The NEORV32 `Zfinx` extension is specification-compliant and operational but still _experimental_.
The `Zfinx` floating-point extension is an _alternative_ of the standard `F` floating-point ISA extension.
The `Zfinx` extensions also uses the integer register file `x` to store and operate on floating-point data
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`
register file-related load/store or move instructions.
The official RISC-V specifications can be found here: https://github.com/riscv/riscv-zfinx
 
The `Zfinx` floating-point extension is an alternative of the `F` floating-point instruction that also uses the
integer register file `x` to store and operate on floating-point data (hence, `F-in-x`). Since not dedicated floating-point `f`
register file exists, the `Zfinx` extension requires 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. The
official RISC-V specifications can be found here: https://github.com/riscv/riscv-zfinx
 
[TIP]
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` suffix) yet (so it is a direct alternative to the `F`
extension). The `Zfinx` extension is implemented when the `CPU_EXTENSION_RISCV_Zfinx` configuration
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
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`
505,8 → 522,8
Division `fdiv.s` and square root `fsqrt.s` instructions are not supported yet!
 
[WARNING]
Subnormal numbers (also "de-normalized" numbers) are not supported by the NEORV32 FPU.
Subnormal numbers (exponent = 0) are _flushed to zero_ (setting them to +/- 0) before entering the
Subnormal numbers ("de-normalized" numbers) are not supported by the NEORV32 FPU.
Subnormal numbers (exponent = 0) are _flushed to zero_ setting them to +/- 0 before entering the
FPU's processing core. If a computational instruction (like `fmul.s`) generates a subnormal result, the
result is also flushed to zero during normalization.
 
519,9 → 536,6
 
==== **`Zbb`** Basic Bit-Manipulation Operations
 
[WARNING]
The NEORV32 `Zbb` extension is specification-compliant and operational but still _experimental_.
 
The `Zbb` extension implements the _basic_ sub-set of the RISC-V bit-manipulation extensions `B`.
The official RISC-V specifications can be found here: https://github.com/riscv/riscv-bitmanip
 
541,7 → 555,7
<<_fast_shift_en>> generic can be enabled to implement full-parallel logic (like barrel shifters) for all
shift-related `Zbb` instructions.
 
[IMPORTANT]
[WARNING]
The `Zbb` extension is frozen but not officially ratified yet. There is no
software support for this extension in the upstream GCC RISC-V port yet. However, an
intrinsic library is provided to utilize the provided `Zbb` extension from C-language
550,17 → 564,17
 
==== **`Zicsr`** Control and Status Register Access / Privileged Architecture
 
The CSR access instructions as well as the exception and interrupt system (= the privileged architecture) is implemented when the
`CPU_EXTENSION_RISCV_Zicsr` configuration generic is _true_. In this case the following instructions are
available:
The CSR access instructions as well as the exception and interrupt system (= the privileged architecture)
is implemented when the `CPU_EXTENSION_RISCV_Zicsr` configuration generic is _true_.
In this case the following instructions are available:
 
* CSR access: `csrrw`, `csrrs`, `csrrc`, `csrrwi`, `csrrsi`, `csrrci`
* environment: `mret`, `wfi`
 
[WARNING]
If the `Zicsr` extension is disabled the CPU does not provide any kind of interrupt or exception
support at all. In order to provide the full spectrum of functions and to allow a secure executions
environment, the `Zicsr` extension should always be enabled.
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 functions and to allow a secure execution
environment the `Zicsr` extension should always be enabled.
 
[NOTE]
The "wait for interrupt instruction" `wfi` works like a sleep command. When executed, the CPU is
567,9 → 581,9
halted until a valid interrupt request occurs. To wake up again, the according interrupt source has to
be enabled via the `mie` CSR and the global interrupt enable flag in `mstatus` has to be set.
 
[IMPORTANT]
The `wfi` instruction will raise an illegal instruction exception when executed outside of machine-mode
and <<_mstatus>> bit `TW` (timeout wait) is set.
[NOTE]
The `wfi` instruction may also be executed in user-mode without causing an exception as <<_mstatus>> bit
`TW` (timeout wait) is hardwired to zero.
 
 
==== **`Zifencei`** Instruction Stream Synchronization
579,7 → 593,6
 
* `fence.i`
 
[NOTE]
The `fence.i` instruction resets the CPU's internal instruction fetch engine and flushes the prefetch buffer.
This allows a clean re-fetch of modified instructions from memory. Also, the top's `i_bus_fencei_o` signal is set
high for one cycle to inform the memory system (like the i-cache to perform a flush/reload.
588,18 → 601,20
 
==== **`PMP`** Physical Memory Protection
 
The NEORV32 physical memory protection (PMP) is compatible to the PMP specified by the RISC-V specs.
The CPU 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:
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 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:
 
* `pmpcfg*` (0..15, depending on configuration): PMP configuration registers
* `pmpaddr*` (0..63, depending on configuration): PMP address registers
 
[TIP]
See section <<_machine_physical_memory_protection>> for more information regarding the PMP CSRs.
 
**Configuration**
 
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
620,20 → 635,20
 
**Operation**
 
Any memory access address (from the CPU's instruction fetch or data access interface) is tested if it is accessing any
of the specified (configured via `pmpaddr*` and enabled via `pmpcfg*`) PMP regions. If an
address accesses one of these regions, the configured access rights (attributes in `pmpcfg*`) are checked:
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 (attributes) it will raise the according
_instruction/load/store access fault exception_.
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.
 
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 active the _locked bit_ in the according
`pmpcfg*` configuration.
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
641,15 → 656,15
 
[NOTE]
For more information regarding RISC-V physical memory protection see the official _The RISC-V
Instruction Set Manual – Volume II: Privileged Architecture_ specifications.
Instruction Set Manual - Volume II: Privileged Architecture_ specifications.
 
 
==== **`HPM`** Hardware Performance Monitors
 
In additions to the mandatory cycles (`[m]cycle[h]`) and instruction (`[m]instret[h]`) counters the NEORV32 CPU provides
In additions to the mandatory cycle (`[m]cycle[h]`) and instruction (`[m]instret[h]`) counters the NEORV32 CPU provides
up to 29 hardware performance monitors (HPM 3..31), which can be used to benchmark applications. Each HPM consists of an
N-bit wide counter (split in a high-word 32-bit CSR and a low-word 32-bit CSR), where N is defined via the top's
`HPM_CNT_WIDTH` generic (0..64-bit), and a corresponding event configuration CSR. The event configuration
`HPM_CNT_WIDTH` generic (0..64-bit) and a corresponding event configuration CSR. The event configuration
CSR defines the architectural events that lead to an increment of the associated HPM counter.
 
The cycle, time and instructions-retired counters (`[m]cycle[h]`, `time[h]`, `[m]instret[h]`) are
656,29 → 671,32
mandatory performance monitors on every RISC-V platform and have fixed increment events. For example,
the instructions-retired counter increments with each executed instructions. The actual hardware performance
monitors are optional and can be configured to increment on arbitrary hardware events. The number of
available HPM is configured via the top's `HPM_NUM_CNTS` generic at synthesis time. Assigning a zero will exclude
available HPM is configured via the top's `HPM_NUM_CNTS` generic at synthesis time. Assigning a zero will remove
all HPM logic from the design.
 
Depending on the configuration, the following additional CSR are available:
If `HPM_NUM_CNTS` is lower than the maximum value (=29) the remaining HPM CSRs are not implemented and the
according `mcountinhibit` CSR bits are hardwired to zero.
However, accessing their associated CSRs will not raise an illegal instruction exception (if in machine mode).
The according CSRs are read-only and will always return 0.
 
* counters: `mhpmcounter*[h]` (3..31, depending on configuration)
* event configuration: `mhpmevent*` (3..31, depending on configuration)
Depending on the configuration the following additional CSR are available:
 
* counters: `mhpmcounter*[h]` (3..31, depending on `HPM_NUM_CNTS`)
* event configuration: `mhpmevent*` (3..31, depending on `HPM_NUM_CNTS`)
 
[IMPORTANT]
The HPM counter CSR can only be accessed in machine-mode. Hence, the according `mcounteren` CSR bits
are always zero and read-only.
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.
 
If `HPM_NUM_CNTS` is lower than the maximum value (=29) the remaining HPM CSRs are not implemented and the
according `mcountinhibit` CSR bits are hardwired to zero.
However, accessing their associated CSRs will not raise an illegal instruction exception (if in machine mode).
The according CSRs are read-only and will always return 0.
[TIP]
For a list of all HPM-related CSRs and all provided event configurations
see section <<_hardware_performance_monitors_hpm>>.
 
[NOTE]
For a list of all allocated HPM-related CSRs and all provided event configurations see section <<_hardware_performance_monitors_hpm>>.
 
 
<<<
// ####################################################################################################################
:sectnums:
735,7 → 753,7
|=======================
 
[NOTE]
The presented values of the *floating-point execution cycles* are average values – obtained from
The presented values of the *floating-point execution cycles* are average values - obtained from
4096 instruction executions using pseudo-random input values. The execution time for emulating the
instructions (using pure-software libraries) is ~17..140 times higher.
 
766,7 → 784,9
(i.e. there is no speculative execution / no out-of-order states).
* The CPU supports _all_ RISC-V bus exceptions including access exceptions that are triggered if an
accessed address does not respond or encounters an internal error during access.
* The CPU raises an illegal instruction trap for _all_ unimplemented/malformed/illegal instructions.
* The RISC-V specs. state that executing an malformed instruction results in unpredictable behavior. As an additional security feature,
the NEORV32 CPU ensures that _all_ unimplemented/malformed/illegal instructions _do raise an illegal instruction trap_ and
_do not commit any operation_ (like writing registers or triggering memory operations).
* To be continued...
 
 
791,14 → 811,14
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.
 
.RISC-V interrupts
.Interrupt Signal Requirements
[IMPORTANT]
All RISC-V defined machine level interrupts request signals are high-active. A request has to stay at high-level until
it is acknowledged by the CPU (for example by writing to a specific memory-mapped register).
All interrupts request signals (including FIRQs) 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).
 
.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.
So if there is a permanent interrupt request, exactly one instruction from the interrupt program will be executed before
a new interrupt handler can start.
 
817,10 → 837,8
 
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
provide custom trap codes in `mcause`. These FIRQs are reserved for processor-internal usage only.
provide custom trap codes in `mcause`. These FIRQs are reserved for NEORV32 processor-internal usage only.
 
[NOTE]
The fast interrupt request lines trigger on a **rising-edge**.
 
 
<<<
894,7 → 912,7
The CPU is a 32-bit architecture with separated instruction and data interfaces making it a Harvard
Architecture. Each of this interfaces can access an address space of up to 2^32^ bytes (4GB). The memory
system is based on 32-bit words with a minimal granularity of 1 byte. Please note, that the NEORV32 CPU
does not support unaligned memory accesses _in hardware_ – however, a software-based handling can be
does not support unaligned memory accesses _in hardware_ - however, a software-based handling can be
implemented as any unaligned memory access will trigger an according exception.
 
:sectnums:
/neorv32/trunk/docs/datasheet/cpu_csr.adoc
218,7 → 218,6
[options="header",grid="rows"]
|=======================
| Bit | Name [C] | R/W | Function
| 21 | _CSR_MSTATUS_TW_ | r/w | Timeout wait: raise illegal instruction exception if `WFI` instruction is executed outside of M-mode when set
| 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
446,8 → 445,9
|======
| 0x344 | **Machine interrupt Pending** | `mip`
3+| Reset value: _0x00000000_
3+| The `mip` CSR is _partly_ compatible to the RISC-V specifications and also provides custom extensions. It shows currently pending interrupts. Since this register is
read-only, pending interrupts of processor-internal modules can only be cleared by disabling and re-enabling the according `mie` CSR bit.
3+| The `mip` CSR is compatible to the RISC-V specifications and also provides custom extensions. It shows currently _pending_ interrupts.
Since this register is read-only, pending interrupts of processor-internal modules can only be cleared by acknowledging the interrupt-causing
device. However, pending interrupts can be ignored by clearing the accordind <<_mie>> register bits.
The following CSR bits are implemented (all remaining bits are always zero and are read-only).
|======
 
502,7 → 502,7
[options="header",grid="rows"]
|=======================
| Bit | RISC-V name | R/W | Function
| 7 | _L_ | r/w | lock bit, can be set – but not be cleared again (only via CPU reset)
| 7 | _L_ | r/w | lock bit, can be set - but not be cleared again (only via 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
/neorv32/trunk/docs/datasheet/on_chip_debugger.adoc
19,7 → 19,9
.OCD Security Note
[IMPORTANT]
Access via the OCD is _always authenticated_ (`dmstatus.authenticated` == `1`). Hence, the
_whole system_ can always be accessed via the on-chip debugger.
_whole system_ can always be accessed via the on-chip debugger. Currently, there is no option
to disable the OCD via software. The OCD can only be disabled by disabling implementation
(setting _ON_CHIP_DEBUGGER_EN_ generic to _false_).
 
[NOTE]
The OCD requires additional resources for implementation and _might_ also increase the critical path resulting in less
352,15 → 354,15
[cols="^1,^2,<8"]
[options="header",grid="rows"]
|=======================
| Bit | Name [RISC-V] | Description / required value
| 31:24 | `cmdtype` | `00000000` to indicate "access register" command
| 23 | _reserved_ | reserved, has to be `0` when writing
| 22:20 | `aarsize` | `010` to indicate 32-bit accesses
| 21 | `aarpostincrement` | `0`, postincrement is not supported
| 18 | `postexec` | if set the program buffer is executed _after_ the command
| 17 | `transfer` | if set the operation in `write` is conducted
| 16 | `write` | `1`: copy `data0` to `[regno]`; `0` copy `[regno]` to `data0`
| 15:0 | `regno` | GPR-access only; has to be `0x1000` - `0x101f`
| Bit | Name [RISC-V] | R/W | Description / required value
| 31:24 | `cmdtype` | -/w | `00000000` to indicate "access register" command
| 23 | _reserved_ | -/w | reserved, has to be `0` when writing
| 22:20 | `aarsize` | -/w | `010` to indicate 32-bit accesses
| 21 | `aarpostincrement` | -/w | `0`, postincrement is not supported
| 18 | `postexec` | -/w | if set the program buffer is executed _after_ the command
| 17 | `transfer` | -/w | if set the operation in `write` is conducted
| 16 | `write` | -/w | `1`: copy `data0` to `[regno]`; `0` copy `[regno]` to `data0`
| 15:0 | `regno` | -/w | GPR-access only; has to be `0x1000` - `0x101f`
|=======================
 
 
493,8 → 495,14
The CPU _debug mode_ requires the `Zicsr` and `Zifencei` CPU extension to be implemented (top generics _CPU_EXTENSION_RISCV_Zicsr_
and _CPU_EXTENSION_RISCV_Zifencei_ = true).
 
The CPU debug mode is entered when one of the following events appear:
.Hardware Watchpoints and Breakpoints
[NOTE]
The NEORV32 CPU _debug mode_ does not provide a hardware "trigger module" (which is optional in the RISC-V debug spec). However, gdb
provides a native _emulation_ for code (breakpoints using `break` instruction) and data (polling data watchpoints in automated
single-stepping) triggers.
 
The CPU debug-mode is entered when one of the following events appear:
 
[start=1]
. executing `ebreak` instruction (when `dcsr.ebreakm` is set and in machine mode OR when `dcsr.ebreaku` is set and in user mode)
. debug halt request from external DM (via CPU signal `db_halt_req_i`, high-active, triggering on rising-edge)
503,8 → 511,14
From a hardware point of view, these "entry conditions" are special synchronous (`ebreak` instruction) or asynchronous
(single-stepping "interrupt"; halt request "interrupt") traps, that are handled invisibly by the control logic.
 
Whenever the CPU **enters debug mode** it performs the following operations:
.WFI instruction
[WARNING]
The wait-for-interrupt instruction `wfi` puts the CPU into sleep mode. The CPU will resume normale operation
when at least one interrupt source becomes pending (= at least one bit in `mip` CSR is set).
However, the CPU will _also resume_ from sleep mode if there is a halt request from the debug module (DM).
 
Whenever the CPU **enters debug-mode** it performs the following operations:
 
* move `pc` to `dpcs`
* copy the hart's current privilege level to `dcsr.prv`
* set `dcrs.cause` according to the cause why debug mode is entered
511,16 → 525,17
* **no update** of `mtval`, `mcause`, `mtval` and `mstatus` CSRs
* load the address configured via the CPU _CPU_DEBUG_ADDR_ generic to the `pc` to jump to "debugger park loop" code in the debug module (DM)
 
When the CPU **is in debug mode** the following things are important:
When the CPU **is in debug-mode** the following things are important:
 
* while in debug mode, the CPU executes the parking loop and the program buffer provided by the DM if requested
* effective CPU privilege level is `machine` mode, PMP is not active
* if an exception occurs
* if the exception was caused by any debug-mode entry action the CPU jumps to the _normal entry point_
( = _CPU_DEBUG_ADDR_) of the park loop again (for example when executing `ebreak` in debug mode)
* for all other exception sources the CPU jumps to the _exception entry point_ ( = _CPU_DEBUG_ADDR_ + 4)
to signal an exception to the DM and restarts the park loop again afterwards
* interrupts are disabled; however, they will be remain pending and will get executed after the CPU has left debug mode
* effective CPU privilege level is `machine` mode, any PMP configuration is bypassed
* the `wfi` instruction acts as a `nop` (also during single-stepping)
* if an exception occurs:
** if the exception was caused by any debug-mode entry action the CPU jumps to the _normal entry point_
(= _CPU_DEBUG_ADDR_) of the park loop again (for example when executing `ebreak` _in_ debug-mode)
** for all other exception sources the CPU jumps to the _exception entry point_ ( = _CPU_DEBUG_ADDR_ + 4)
to signal an exception to the DM and restarts the park loop again afterwards
* interrupts are disabled; however, they will remain pending and will get executed after the CPU has left debug mode
* if the DM makes a resume request, the park loop exits and the CPU leaves debug mode (executing `dret`)
 
Debug mode is left either by executing the `dret` instruction footnote:[`dret` should only be executed _inside_ the debugger
/neorv32/trunk/docs/datasheet/overview.adoc
11,7 → 11,7
compatible on-chip debugger accessible via JTAG.
 
The software framework of the processor comes with application makefiles, software libraries for all CPU
and processor features, a bootloader, a runtime environment and several example programs – including a port
and processor features, a bootloader, a runtime environment and several example programs - including a port
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]).
 
26,11 → 26,11
 
**Structure**
 
[start=1]
[start=2]
. <<_neorv32_processor_soc>>
. <<_neorv32_central_processing_unit_cpu>>
. <<_software_framework>>
. <<_on_chip_debugger_ocd>>
. <<_software_framework>>
 
[TIP]
Links in this document are <<_overview,highlighted>>.
/neorv32/trunk/docs/datasheet/soc.adoc
13,7 → 13,7
* _optional_ processor-internal data and instruction memories (<<_data_memory_dmem,**DMEM**>>/<<_instruction_memory_imem,**IMEM**>>) + cache (<<_processor_internal_instruction_cache_icache,**iCACHE**>>)
* _optional_ internal bootloader (<<_bootloader_rom_bootrom,**BOOTROM**>>) with UART console & SPI flash boot option
* _optional_ machine system timer (<<_machine_system_timer_mtime,**MTIME**>>), RISC-V-compatible
* _optional_ two independent universal asynchronous receivers and transmitters (<<_primary_universal_asynchronous_receiver_and_transmitter_uart0,**UART0**>>, <<_secondary_universal_asynchronous_receiver_and_transmitter_uart1,**UART1**>>) with optional hardware flow control (RTS/CTS)
* _optional_ two independent universal asynchronous receivers and transmitters (<<_primary_universal_asynchronous_receiver_and_transmitter_uart0,**UART0**>>, <<_secondary_universal_asynchronous_receiver_and_transmitter_uart1,**UART1**>>) with optional hardware flow control (RTS/CTS) and optional RX/TX FIFOs
* _optional_ 8/16/24/32-bit serial peripheral interface controller (<<_serial_peripheral_interface_controller_spi,**SPI**>>) with 8 dedicated CS lines
* _optional_ two wire serial interface controller (<<_two_wire_serial_interface_controller_twi,**TWI**>>), compatible to the I²C standard
* _optional_ general purpose parallel IO port (<<_general_purpose_input_and_output_port_gpio,**GPIO**>>), 64xOut, 64xIn
796,6 → 796,32
 
 
:sectnums!:
===== _IO_UART0_RX_FIFO_
 
[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **IO_UART0_RX_FIFO** | _natural_ | 1
3+| UART0 receiver FIFO depth, has to be a power of two, minimum value is 1 (implementing simple double-buffering).
See section <<_primary_universal_asynchronous_receiver_and_transmitter_uart0>> for
more information.
|======
 
 
:sectnums!:
===== _IO_UART0_TX_FIFO_
 
[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **IO_UART0_TX_FIFO** | _natural_ | 1
3+| UART0 transmitter FIFO depth, has to be a power of two, minimum value is 1 (implementing simple double-buffering).
See section <<_primary_universal_asynchronous_receiver_and_transmitter_uart0>> for
more information.
|======
 
 
:sectnums!:
===== _IO_UART1_EN_
 
[cols="4,4,2"]
808,6 → 834,32
 
 
:sectnums!:
===== _IO_UART1_RX_FIFO_
 
[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **IO_UART1_RX_FIFO** | _natural_ | 1
3+| UART1 receiver FIFO depth, has to be a power of two, minimum value is 1 (implementing simple double-buffering).
See section <<_primary_universal_asynchronous_receiver_and_transmitter_uart0>> for
more information.
|======
 
 
:sectnums!:
===== _IO_UART1_TX_FIFO_
 
[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **IO_UART1_TX_FIFO** | _natural_ | 1
3+| UART1 transmitter FIFO depth, has to be a power of two, minimum value is 1 (implementing simple double-buffering).
See section <<_primary_universal_asynchronous_receiver_and_transmitter_uart0>> for
more information.
|======
 
 
:sectnums!:
===== _IO_SPI_EN_
 
[cols="4,4,2"]
964,8 → 1016,9
 
.Trigger type
[IMPORTANT]
These IRQs trigger on **high-level** and must _stay asserted_ until explicitly acknowledged by the CPU (for example
by writing to a specific memory-mapped register).
The fast interrupt request channel trigger on **high-level** and have to stay asserted until explicitly acknowledged
by the software (for example by writing to a specifc memory-mapped register). Hence, pending interrupts remain pending
as long as the interrupt-causing device's state fulfills it's interrupt condition(s).
 
 
:sectnums:
986,7 → 1039,8
[IMPORTANT]
The trigger for these interrupt can be defined via generics. See section
<<_external_interrupt_controller_xirq>> for more information. Depending on the trigger type, users can
implement custom acknowledge mechanisms.
implement custom acknowledge mechanisms. All _external interrupts_ are mapped to a single processor-internal
_fast interrupt request_ (see below).
 
 
:sectnums:
993,7 → 1047,7
==== NEORV32-Specific Fast Interrupt Requests
 
As part of the custom/NEORV32-specific CPU extensions, the CPU features 16 fast interrupt request signals
(`FIRQ0` – `FIRQ15`). These are used for _processor-internal_ modules only (for example for the communication
(`FIRQ0` - `FIRQ15`). These are reserved for _processor-internal_ modules only (for example for the communication
interfaces to signal "available incoming data" or "ready to send new data").
 
The mapping of the 16 FIRQ channels is shown in the following table (the channel number also corresponds to
1013,16 → 1067,17
| 6 | <<_serial_peripheral_interface_controller_spi,SPI>> | SPI transmission done interrupt
| 7 | <<_two_wire_serial_interface_controller_twi,TWI>> | TWI transmission done interrupt
| 8 | <<_external_interrupt_controller_xirq,XIRQ>> | External interrupt controller interrupt
| 9 | <<_smart_led_interface_neoled,NEOLED>> | NEOLED buffer TX empty / not full interrupt
| 10 | <<_stream_link_interface_slink,SLINK>> | RX data received
| 11 | <<_stream_link_interface_slink,SLINK>> | TX data send
| 9 | <<_smart_led_interface_neoled,NEOLED>> | NEOLED TX buffer interrupt
| 10 | <<_stream_link_interface_slink,SLINK>> | RX data buffer interrupt
| 11 | <<_stream_link_interface_slink,SLINK>> | TX data buffer interrupt
| 12:15 | - | _reserved_, will never fire
|=======================
 
.Trigger type
[IMPORTANT]
The fast interrupt request channel trigger on a single **rising-edge** and do not require any kind of explicit
acknowledgment at all.
The fast interrupt request channel trigger on **high-level** and have to stay asserted until explicitly acknowledged
by the software (for example by writing to a specifc memory-mapped register). Hence, pending interrupts remain pending
as long as the interrupt-causing device's state fulfills it's interrupt condition(s).
 
 
 
1031,21 → 1086,18
:sectnums:
=== Address Space
 
The NEORV32 Processor provides 32-bit physical addresses accessing up to 4GB of address space.
By default, this address space is divided into four main regions:
The NEORV32 Processor provides a 32-bit / 4GB (physical) address space
By default, this address space is divided into five main regions:
 
1. **Instruction address space** – for instructions (=code) and constants. A configurable section of this address space is used by
internal and/or external _instruction memory_ (IMEM).
2. **Data address space** – for application runtime data (heap, stack, etc.). A configurable section of this address space is used by
internal and/or external _data memory_ (DMEM).
3. **Bootloader address space**. A _fixed_ section of this address space is used by
1. **Instruction address space** - memory address space for instructions (=code) and constants.
A configurable section of this address space is used by the internal/external _instruction memory_ (<<_mem_int_imem_size>> for the internal IMEM).
2. **Data address space** - memory address space for application runtime data (heap, stack, etc.).
A configurable section of this address space is used by the internal/external _data memory_ (<<_mem_int_dmem_size>> for the internal DMEM).
3. **Bootloader address space**. A _fixed_ section of this address space is used by the
internal _bootloader memory_ (BOOTLDROM).
4. **IO/peripheral address space** – for the processor-internal IO/peripheral devices (e.g., UART).
4. **On-Chip Debugger address space**. This _fixed_ section is entirely used by the processor's <<_on_chip_debugger_ocd>>.
5. **IO/peripheral address space**. Also a _fixed_ section used for the processor-internal memory-mapped IO/peripheral devices (e.g., UART).
 
[TIP]
These four memory regions are handled by the linker when compiling a NEORV32 executable.
See section <<_executable_image_format>> for more information.
 
.NEORV32 processor - address space (default configuration)
image::address_space.png[900]
 
1102,7 → 1154,7
[NOTE]
The base address of the internal bootloader (at _0xFFFF0000_) and the internal IO region (at _0xFFFFFE00_) for
peripheral devices are also defined in the package and are fixed. These address regions cannot not be used for other
applications – even if the bootloader or all IO devices are not implemented - without modifying the core's
applications - even if the bootloader or all IO devices are not implemented - without modifying the core's
hardware sources.
 
 
1113,32 → 1165,36
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, e.g. via "load")
* `w` – write access (from CPU data access interface, e.g. via "store")
* `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)
* `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 (i.e. loads) can always access data in word, half-word and byte quantities (requiring an accordingly aligned address).
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>>.
 
[cols="^1,^2,^2,^3,^2"]
[options="header",grid="rows"]
|=======================
| # | Region | Base address | Size | Attributes
| 4 | IO/peripheral devices | 0xfffffe00 | 512 bytes | `r/w/a/32`
| 3 | bootloader ROM | 0xffff0000 | up to 32kB| `r/x/a`
| 2 | DMEM | 0x80000000 | up to 2GB (-64kB) | `r/w/x/a/8/16/32`
| 1 | IMEM | 0x00000000 | up to 2GB | `r/w/x/a/8/16/32`
| # | 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`
|=======================
 
[TIP]
The following table shows the provided physical memory attributes of each region. Additional attributes (for example
controlling certain right for specific address space regions) can be provided using the RISC-V <<_machine_physical_memory_protection>> extension.
 
 
:sectnums:
==== Memory Configuration
 
1263,7 → 1319,7
 
**Internal Reset Generator**
 
Most processor-internal modules – except for the CPU and the watchdog timer – do not have a dedicated
Most processor-internal modules - except for the CPU and the watchdog timer - do not have a dedicated
reset signal. However, all devices can be reset by software by clearing the corresponding unit's control
register. The automatically included application start-up code (`crt0.S`) will perform a software-reset of all
modules to ensure a clean system reset state.
/neorv32/trunk/docs/datasheet/soc_cfs.adoc
19,18 → 19,27
 
**Theory of Operation**
 
The custom functions subsystem can be used to implement application-specific user-defined co-processors
(like encryption or arithmetic accelerators) or peripheral/communication interfaces. In contrast to connecting
custom hardware accelerators via the external memory interface, the CFS provide a convenient and low-latency
extension and customization option.
The custom functions subsystem is meant for implementing application-specific user-defined co-processors
IP footnote:[Intellectual IP; proprietary circuit blocks.] blocks. The CFS provides up to 32x 32-bit memory-mapped
registers (`REG`, see register map table 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.
 
The CFS provides up to 32x 32-bit memory-mapped registers `REG` (see register map table below). The actual
functionality of these register has to be defined by the hardware designer.
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
customization option.
 
Just like any other externally-connected IP, logic implemented within the custom functions subsystem can operate
_independently_ of the CPU providing true parallel processing capabilities. Potential use cases might include
dedicated hardware accelerators for en-/decryption (AES), signal processing (FFT) or AI applications
(CNNs) as well as custom IO systems like fast memory interfaces (DDR) and mass storage (SDIO), networking (CAN)
or real-time data transport (I2S).
 
[INFO]
Take a look at the template CFS VHDL source file (`rtl/core/neorv32_cfs.vhd`). The file is highly
commented to illustrate all aspects that are relevant for implementing custom CFS-based co-processor designs.
 
 
**CFS Software Access**
 
The CFS memory-mapped registers can be accessed by software using the provided C-language aliases (see
43,26 → 52,35
uint32_t temp = NEORV32_CFS.REG[20]; // read from CFS register 20
----
 
 
**CFS Interrupt**
 
The CFS provides a single one-shot interrupt request signal mapped to the CPU's fast interrupt channel 1.
See section <<_processor_interrupts>> for more information.
The CFS provides a single high-level-triggered interrupt request signal mapped to the CPU's fast interrupt channel 1.
Once set, the interrupt has to stay asserted until explicitly acknowledged by the software (for example by
writing to a specific CFS register). See section <<_processor_interrupts>> for more information.
 
 
**CFS Configuration Generic**
 
By default, the CFS provides a single 32-bit `std_(u)logic_vector` configuration generic _IO_CFS_CONFIG_
that is available in the processor's top entity. This generic can be used to pass custom configuration options
from the top entity down to the CFS entity.
from the top entity directly down to the CFS. The actual definition of the generics and it'S usage inside the
CFS is left to the hardware designer.
 
 
**CFS Custom IOs**
 
By default, the CFS also provides two unidirectional input and output conduits `cfs_in_i` and `cfs_out_o`.
These signals are propagated to the processor's top entity. The actual use of these signals has to be defined
by the hardware designer. The size of the input signal conduit `cfs_in_i` is defined via the (top's) _IO_CFS_IN_SIZE_ configuration
generic (default = 32-bit). The size of the output signal conduit `cfs_out_o` is defined via the (top's)
These signals are directly propagated to the processor's top entity. These conduits can be used to implement
application-specific interfaces like memory or network connections. The actual use case of these signals
has to be defined by the hardware designer.
 
The size of the input signal conduit `cfs_in_i` is defined via the top's _IO_CFS_IN_SIZE_ configuration
generic (default = 32-bit). The size of the output signal conduit `cfs_out_o` is defined via the top's
_IO_CFS_OUT_SIZE_ configuration generic (default = 32-bit). If the custom function subsystem is not implemented
(_IO_CFS_EN_ = false) the `cfs_out_o` signal is tied to all-zero.
 
 
.CFS register map (`struct NEORV32_CFS`)
[cols="^4,<5,^2,^3,<14"]
[options="header",grid="all"]
/neorv32/trunk/docs/datasheet/soc_imem.adoc
29,8 → 29,8
 
By default, the IMEM is implemented as RAM, so the content can be modified during run time. This is
required when using a bootloader that can update the content of the IMEM at any time. If you do not need
the bootloader anymore – since your application development has completed and you want the program to
permanently reside in the internal instruction memory – the IMEM is automatically implemented as _pre-intialized_
the bootloader anymore - since your application development has completed and you want the program to
permanently reside in the internal instruction memory - the IMEM is automatically implemented as _pre-intialized_
ROM when the processor-internal bootloader is disabled (_INT_BOOTLOADER_EN_ = _false_).
 
When the IMEM is implemented as ROM, it will be initialized during synthesis with the actual application
/neorv32/trunk/docs/datasheet/soc_mtime.adoc
26,9 → 26,10
and the `MTI` machine timer CPU interrupt (`MTI`) is directly connected to the top's `mtime_irq_i` input.
 
The 64-bit system time can be accessed via the `TIME_LO` and `TIME_HI` memory-mapped registers (read/write) and also via
the CPU's `time[h]` CSRs (read-only). A 64-bit time compare register – accessible via memory-mapped `TIMECMP_LO` and `TIMECMP_HI`
registers – is used to configure an interrupt to the CPU. The interrupt is triggered
the CPU's `time[h]` CSRs (read-only). A 64-bit time compare register - accessible via memory-mapped `TIMECMP_LO` and `TIMECMP_HI`
registers - is used to configure an interrupt to the CPU. The interrupt is triggered
whenever `TIME` (high & low part) >= `TIMECMP` (high & low part) and is directly forwarded to the CPU's `MTI` interrupt.
The interrupt remain active (=pending) until `TIME` < `TIMECMP` (either by modifying `TIME` or `TIMECMP`).
 
.MTIME register map (`struct NEORV32_MTIME`)
[cols="<3,<3,^1,^1,<6"]
/neorv32/trunk/docs/datasheet/soc_neoled.adoc
30,7 → 30,7
NEOLED module provides 24-bit and 32-bit operating modes, a mixed setup with RGB LEDs (24-bit color)
and RGBW LEDs (32-bit color including a dedicated white LED chip) is possible.
 
**Theory of Operation – NEOLED Module**
**Theory of Operation - NEOLED Module**
 
The NEOLED modules provides two accessible interface registers: the control register `CTRL` and the
TX data register `DATA`. The NEOLED module is globally enabled via the control register's
55,7 → 55,7
an arbitrary setup of RGB and RGBW LEDs.
 
 
**Theory of Operation – Protocol**
**Theory of Operation - Protocol**
 
The interface of the WS2812 LEDs uses an 800kHz carrier signal. Data is transmitted in a serial manner
starting with LSB-first. The intensity for each R, G & B (& W) LED chip (= color code) is defined via an 8-bit
97,7 → 97,7
WS2811).
 
 
**Timing Configuration – Example (WS2812)**
**Timing Configuration - Example (WS2812)**
 
Generate the base clock f~TX~ for the NEOLED TX engine:
 
159,20 → 159,31
the actually written data is irrelevant) will trigger an idle phase (`neoled_o` = zero) of 127 periods (= _**T~carrier~**_).
This idle time will cause the LEDs to strobe the color data into the PWM driver registers.
 
Since the _NEOLED_CTRL_STROBE_ flag is also buffered in the TX buffer, the RESET command is treated as just another
Since the _NEOLED_CTRL_STROBE_ flag is also buffered in the TX buffer, the RESET command is treated just as another
data word being written to the TX buffer making busy wait concepts obsolete and allowing maximum refresh rates.
 
 
**Interrupt**
 
The NEOLED modules features a single interrupt that is triggered whenever the TX FIFO's fill level
falls below _half-full_ level. In this case software can write up to _IO_NEOLED_TX_FIFO_/2 new data
words to `DATA` without checking the FIFO status flags.
The NEOLED modules features a single interrupt that becomes pending based on the current TX buffer fill level.
The interrupt can only become pending if the NEOLED module is enabled. The specific interrupt condition
is configured via the _NEOLED_CTRL_IRQ_CONF_ in the control register `NEORV32_NEOLED.CTRL`.
 
This highly relaxes time constraints for sending a continuous data stream to the LEDs
(as an idle time beyond 50μs will trigger the LED's a RESET command).
If _NEOLED_CTRL_IRQ_CONF_ is cleared, an interrupt is generated whenever the TX FIFO is _less than half-full_.
In this case software can write up to _IO_NEOLED_TX_FIFO_/2 new data words to `DATA` without checking the FIFO
status flags. The interrupt request is cleared whenever the FIFO fill level is above _half-full_ level or if
the NEOLED module is disabled.
 
If _NEOLED_CTRL_IRQ_CONF_ is set, an interrupt is generated whenever the TX FIFO is _empty_. The interrupt
request is cleared again when the FIFO contains at least one data word.
 
[NOTE]
The _NEOLED_CTRL_IRQ_CONF_ is hardwired to one if _IO_NEOLED_TX_FIFO_ = 1 (-> IRQ if FIFO is empty).
 
If the FIFO is configured to contain only a single entry (_IO_NEOLED_TX_FIFO_ = 1) the interrupt
will become pending if the FIFO (which is just a single register providing simple _double-buffering_) is empty.
 
 
<<<
.NEOLED register map (`struct NEORV32_NEOLED`)
[cols="<4,<5,<9,^2,<9"]
179,30 → 190,35
[options="header",grid="all"]
|=======================
| Address | Name [C] | Bit(s), Name [C] | R/W | Function
.25+<| `0xffffffd8` .25+<| `NEORV32_NEOLED.CTRL` <|`0` _NEOLED_CTRL_EN_ ^| r/w <| NEOLED enable
<|`1` _NEOLED_CTRL_MODE_ ^| r/w <| data transfer size; `0`=24-bit; `1`=32-bit
<|`2` _NEOLED_CTRL_STROBE_ ^| r/w <| `0`=send normal color data; `1`=send RESET command on data write access
<|`3` _NEOLED_CTRL_PRSC0_ ^| r/w <| 3-bit clock prescaler, bit 0
<|`4` _NEOLED_CTRL_PRSC1_ ^| r/w <| 3-bit clock prescaler, bit 1
<|`5` _NEOLED_CTRL_PRSC2_ ^| r/w <| 3-bit clock prescaler, bit 2
<|`6` _NEOLED_CTRL_BUFS0_ ^| r/- .4+<| 4-bit log2(_IO_NEOLED_TX_FIFO_)
<|`7` _NEOLED_CTRL_BUFS1_ ^| r/-
<|`8` _NEOLED_CTRL_BUFS2_ ^| r/-
<|`9` _NEOLED_CTRL_BUFS3_ ^| r/-
<|`10` _NEOLED_CTRL_T_TOT_0_ ^| r/w .5+<| 5-bit pulse clock ticks per total single-bit period (T~total~)
<|`11` _NEOLED_CTRL_T_TOT_1_ ^| r/w
<|`12` _NEOLED_CTRL_T_TOT_2_ ^| r/w
<|`13` _NEOLED_CTRL_T_TOT_3_ ^| r/w
<|`14` _NEOLED_CTRL_T_TOT_4_ ^| r/w
<|`20` _NEOLED_CTRL_ONE_H_0_ ^| r/w .5+<| 5-bit pulse clock ticks per high-time for sending a one-bit (T~H1~)
<|`21` _NEOLED_CTRL_ONE_H_1_ ^| r/w
<|`22` _NEOLED_CTRL_ONE_H_2_ ^| r/w
<|`23` _NEOLED_CTRL_ONE_H_3_ ^| r/w
<|`24` _NEOLED_CTRL_ONE_H_4_ ^| r/w
<|`30` _NEOLED_CTRL_TX_STATUS_ ^| r/- <| transmit engine busy when `1`
<|`31` _NEOLED_CTRL_TX_EMPTY_ ^| r/- <| TX FIFO is empty
<|`31` _NEOLED_CTRL_TX_HALF_ ^| r/- <| TX FIFO is _at least_ half full
<|`31` _NEOLED_CTRL_TX_FULL_ ^| r/- <| TX FIFO is full
<|`31` _NEOLED_CTRL_TX_BUSY_ ^| r/- <| TX serial engine is busy when set
.30+<| `0xffffffd8` .30+<| `NEORV32_NEOLED.CTRL` <|`0` _NEOLED_CTRL_EN_ ^| r/w <| NEOLED enable
<|`1` _NEOLED_CTRL_MODE_ ^| r/w <| data transfer size; `0`=24-bit; `1`=32-bit
<|`2` _NEOLED_CTRL_STROBE_ ^| r/w <| `0`=send normal color data; `1`=send RESET command on data write access
<|`3` _NEOLED_CTRL_PRSC0_ ^| r/w <| 3-bit clock prescaler, bit 0
<|`4` _NEOLED_CTRL_PRSC1_ ^| r/w <| 3-bit clock prescaler, bit 1
<|`5` _NEOLED_CTRL_PRSC2_ ^| r/w <| 3-bit clock prescaler, bit 2
<|`6` _NEOLED_CTRL_BUFS0_ ^| r/- .4+<| 4-bit log2(_IO_NEOLED_TX_FIFO_)
<|`7` _NEOLED_CTRL_BUFS1_ ^| r/-
<|`8` _NEOLED_CTRL_BUFS2_ ^| r/-
<|`9` _NEOLED_CTRL_BUFS3_ ^| r/-
<|`10` _NEOLED_CTRL_T_TOT_0_ ^| r/w .5+<| 5-bit pulse clock ticks per total single-bit period (T~total~)
<|`11` _NEOLED_CTRL_T_TOT_1_ ^| r/w
<|`12` _NEOLED_CTRL_T_TOT_2_ ^| r/w
<|`13` _NEOLED_CTRL_T_TOT_3_ ^| r/w
<|`14` _NEOLED_CTRL_T_TOT_4_ ^| r/w
<|`15` _NEOLED_CTRL_T_ZERO_H_0_ ^| r/w .5+<| 5-bit pulse clock ticks per high-time for sending a zero-bit (T~0H~)
<|`16` _NEOLED_CTRL_T_ZERO_H_1_ ^| r/w
<|`17` _NEOLED_CTRL_T_ZERO_H_2_ ^| r/w
<|`18` _NEOLED_CTRL_T_ZERO_H_3_ ^| r/w
<|`19` _NEOLED_CTRL_T_ZERO_H_4_ ^| r/w
<|`20` _NEOLED_CTRL_T_ONE_H_0_ ^| r/w .5+<| 5-bit pulse clock ticks per high-time for sending a one-bit (T~1H~)
<|`21` _NEOLED_CTRL_T_ONE_H_1_ ^| r/w
<|`22` _NEOLED_CTRL_T_ONE_H_2_ ^| r/w
<|`23` _NEOLED_CTRL_T_ONE_H_3_ ^| r/w
<|`24` _NEOLED_CTRL_T_ONE_H_4_ ^| r/w
<|`27` _NEOLED_CTRL_IRQ_CONF_ ^| r/w <| TX FIFO interrupt configuration: `0`=IRQ if FIFO is less than half-full, `1`=IRQ if FIFO is empty
<|`28` _NEOLED_CTRL_TX_EMPTY_ ^| r/- <| TX FIFO is empty
<|`29` _NEOLED_CTRL_TX_HALF_ ^| r/- <| TX FIFO is _at least_ half full
<|`30` _NEOLED_CTRL_TX_FULL_ ^| r/- <| TX FIFO is full
<|`31` _NEOLED_CTRL_TX_BUSY_ ^| r/- <| TX serial engine is busy when set
| `0xffffffdc` | `NEORV32_NEOLED.DATA` <|`31:0` / `23:0` ^| -/w <| TX data (32-/24-bit)
|=======================
/neorv32/trunk/docs/datasheet/soc_slink.adoc
44,6 → 44,7
via the external memory bus interface or use some of the processor's GPIO ports to implement custom data
tag signals.
 
 
**Theory of Operation**
 
The SLINK provides eight data registers (`DATA[i]`) to access the links (read accesses will access the RX links, write
82,6 → 83,7
from an _empty_ RX link. Hence, this concept should only be used when evaluating the half-full FIFO condition
(for example via the SLINK interrupts) before actual accessing links.
 
 
**Non-Blocking Link Access**
 
For a non-blocking link access concept, the FIFO status flags in `STATUS` need to be checked _before_
94,25 → 96,7
However, non-blocking accesses require additional instructions to check the according status flags prior
to the actual link access, which will reduce performance for high-bandwidth data streams.
 
**Interrupts**
 
The stream interface provides two interrupts that are _globally_ driven by the RX and TX link's
FIFO fill level status. The behavior of these interrupts differs if the FIFO depth is exactly 1 (minimal)
or if it is greater than 1.
 
When _SLINK_*X_FIFO_ is 1 a TX interrupt will fire if **any** TX link _was full_ and _becomes empty_ again.
Accordingly, if the FIFO of **any** RX link _was empty_ and a _new data word_ appears in it, the RX interrupt fires.
 
When _SLINK_*X_FIFO_ is greater than 1 the TX interrupt will fire if _any_ TX link's FIFO _falls below_ half-full fill level.
Accordingly, the RX interrupt will fire if _any_ RX link's FIFO _exceeds_ half-full fill level.
 
The interrupt service handler has to evaluate the SLINK status register is order to detect which link(s) has caused the
interrupt. No further interrupt can fire until the CPU acknowledges the last interrupt by _reading the SLINK status register_.
However, further IRQ conditions are buffered and will trigger another interrupt after the current one has been acknowledged.
 
Note that these interrupts can only fire if the SLINK module is actually enabled by setting the
_SLINK_CTRL_EN_ bit in the unit's control register.
 
**Stream Link Interface & Protocol**
 
The SLINK interface consists of three signals `dat`, `val` and `rdy` for each RX and TX link.
133,6 → 117,44
[TIP]
The SLINK handshake protocol is compatible with the https://developer.arm.com/documentation/ihi0051/a/Introduction/About-the-AXI4-Stream-protocol[AXI4-Stream] base protocol.
 
 
**Interrupts**
 
The stream interface provides two independent interrupts that are _globally_ driven by the RX and TX link's
FIFO fill level status. Each RX and TX link provides an individual interrupt enable flag and an individual
interrupt type flag that allows to configure interrupts only for certain (or all) links and for application-
specific interrupt conditions. The interrupt configuration is done using the `NEORV32_SLINK.IRQ` register.
Any interrupt can only become pending if the SLINK module is enabled at all.
 
The current FIFO fill-level of a specific **RX link** can only raise an interrupt request if it's interrupt enable flag
_SLINK_IRQ_RX_EN_ is set. Vice versa, the current FIFO fill-level of a specific **TX link** can only raise an interrupt
request if it's interrupt enable flag _SLINK_IRQ_TX_EN_ is set.
 
The **RX link's** _SLINK_IRQ_RX_MODE_ flags define the FIFO fill-level condition for raising an RX interrupt request:
* If a link's interrupt mode flag is `1` an IRQ is generated when the link's FIFO is _not empty_ ("RX data available").
* If a link's interrupt mode flag is `0` an IRQ is generated when the link's FIFO is _at least half-full_ ("time to get data from RX FIFO to prevent overflow").
 
The **TX link's** _SLINK_IRQ_TX_MODE_ flags define the FIFO fill-level condition for raising an TX interrupt request:
* If a link's interrupt mode flag is `1` an IRQ is generated when the link's FIFO is _not full_ ("space left in FIFO for new TX data").
* If a link's interrupt mode flag is `0` an IRQ is generated when the link's FIFO is _less than half-full_ ("SW can send _SLINK_TX_FIFO_/2 data words without checking any flags").
 
[NOTE]
If _SLINK_RX_FIFO_ is 1 the _SLINK_IRQ_RX_MODE_ bits are hardwired to one.
If _SLINK_TX_FIFO_ is 1 the _SLINK_IRQ_TX_MODE_ bits are hardwired to one.
 
[NOTE]
There is no RX FIFO overflow mechanism available yet.
 
If _any_ configured interrupt condition is fulfilled, the according global SLINK RX / SLINK TX CPU
interrupt becomes pending.
If the interrupt enable flags of several links are set, the interrupt service handler has to evaluate the SLINK
status register is order to detect which link(s) caused the interrupt.
 
[NOTE]
If the programmed interrupt condition is fulfilled, the corresponding IRQ will become _pending_ until
the causing interrupt conditions is resolved (for example by reading data from the according RX FIFO).
 
 
.SLINK register map (`struct NEORV32_SLINK`)
[cols="^4,<5,^2,^2,<14"]
[options="header",grid="all"]
144,12 → 166,17
<| `11:8` _SLINK_CTRL_RX_FIFO_S3_ : _SLINK_CTRL_RX_FIFO_S0_ ^| r/- <| RX links FIFO depth, log2 of_SLINK_RX_FIFO_ generic
<| `7:4` _SLINK_CTRL_TX_NUM3_ : _SLINK_CTRL_TX_NUM0_ ^| r/- <| Number of implemented TX links
<| `3:0` _SLINK_CTRL_RX_NUM3_ : _SLINK_CTRL_RX_NUM0_ ^| r/- <| Number of implemented RX links
| `0xfffffec4` : `0xfffffeec` | - |`31:0` | | _reserved
.4+<| `0xfffffed0` .4+<| `NEORV32_SLINK.STATUS` <| `31:24` _SLINK_STATUS_TX7_HALF_ : _SLINK_STATUS_TX0_HALF_ ^| r/- | TX link 7..0 FIFO fill level is > half-full
| `0xfffffec4` | - |`31:0` | r/- | _reserved_
.4+<| `0xfffffec8` .4+<| `NEORV32_SLINK.IRQ` <|`31:24` _SLINK_IRQ_RX_EN_MSB_ : _SLINK_IRQ_RX_EN_LSB_ ^| r/w <| RX interrupt enable for link 7..0
<|`23:16` _SLINK_IRQ_RX_MODE_MSB_ : _SLINK_IRQ_RX_MODE_LSB_ ^| r/w <| RX IRQ mode for link 7..0: `0` = FIFO at least half-full; `1` = FIFO not empty
<|`15:8` _SLINK_IRQ_TX_EN_MSB_ : _SLINK_IRQ_TX_EN_LSB_ ^| r/w <| TX interrupt enable for link 7..0
<|`7:0` _SLINK_IRQ_TX_MODE_MSB_ : _SLINK_IRQ_TX_MODE_LSB_ ^| r/w <| TX IRQ mode for link 7..0: `0` = FIFO less than half-full; `1` = FIFO not full
| `0xfffffeec` | - |`31:0` | r/- | _reserved_
.4+<| `0xfffffed0` .4+<| `NEORV32_SLINK.STATUS` <| `31:24` _SLINK_STATUS_TX7_HALF_ : _SLINK_STATUS_TX0_HALF_ ^| r/- <| TX link 7..0 FIFO fill level is >= half-full
<| `23:16` _SLINK_STATUS_RX7_HALF_ : _SLINK_STATUS_RX0_HALF_ ^| r/- <| RX link 7..0 FIFO fill level is >= half-full
<| `15:8` _SLINK_STATUS_TX7_FREE_ : _SLINK_STATUS_TX0_FREE_ ^| r/- <| At least one free TX FIFO entry available for link 7..0
<| `7:0` _SLINK_STATUS_RX7_AVAIL_ : _SLINK_STATUS_RX0_AVAIL_ ^| r/- <| At least one data word in RX FIFO available for link 7..0
| `0xfffffed4` : `0xfffffedc` | - |`31:0` | | _reserved_
| `0xfffffed4` : `0xfffffedc` | - |`31:0` | r/- | _reserved_
| `0xfffffee0` | `NEORV32_SLINK.DATA[0]` | `31:0` | r/w | Link 0 RX/TX data
| `0xfffffee4` | `NEORV32_SLINK.DATA[1]` | `31:0` | r/w | Link 1 RX/TX data
| `0xfffffee8` | `NEORV32_SLINK.DATA[2]` | `31:0` | r/w | Link 2 RX/TX data
/neorv32/trunk/docs/datasheet/soc_spi.adoc
9,31 → 9,77
| Software driver file(s): | neorv32_spi.c |
| | neorv32_spi.h |
| Top entity port: | `spi_sck_o` | 1-bit serial clock output
| | `spi_sdo_i` | 1-bit serial data output
| | `spi_sdi_o` | 1-bit serial data input
| | `spi_sdo_o` | 1-bit serial data output
| | `spi_sdi_i` | 1-bit serial data input
| | `spi_csn_i` | 8-bit dedicated chip select (low-active)
| Configuration generics: | _IO_SPI_EN_ | implement SPI controller when _true_
| CPU interrupts: | fast IRQ channel 6 | transmission done interrupt (see <<_processor_interrupts>>)
|=======================
 
 
**Theory of Operation**
 
SPI is a synchronous serial transmission interface. The NEORV32 SPI transceiver allows 8-, 16-, 24- and 32-
bit long transmissions. The unit provides 8 dedicated chip select signals via the top entity's `spi_csn_o`
signal.
SPI is a synchronous serial transmission interface for fast on-board communications.
The NEORV32 SPI transceiver supports 8-, 16-, 24- and 32-bit wide transmissions.
The unit provides 8 dedicated chip select signals via the top entity's `spi_csn_o` signal, which are
directly controlled by the SPI module (no additional GPIO required).
 
The SPI unit is enabled via the _SPI_CTRL_EN_ bit in the `CTRL` control register. The idle clock polarity is configured via the _SPI_CTRL_CPHA_
bit and can be low (`0`) or high (`1`) during idle. The data quantity to be transferred within a
single transmission is defined via the _SPI_CTRL_SIZEx bits_. The unit supports 8-bit (`00`), 16-bit (`01`), 24-
bit (`10`) and 32-bit (`11`) transfers. Whenever a transfer is completed, the "transmission done interrupt" is triggered.
A transmission is still in progress as long as the _SPI_CTRL_BUSY_ flag is set.
The SPI unit is enabled by setting the _SPI_CTRL_EN_ bit in the `CTRL` control register. No transfer can be initiated
and no interrupt request will be triggered if this bit is cleared. Furthermore, a transfer being in process
can be terminated at any time by clearing this bit.
 
The SPI controller features 8 dedicated chip-select lines. These lines are controlled via the control register's _SPI_CTRL_CSx_ bits. When
a specifc _SPI_CTRL_CSx_ bit is **set**, the according chip select line `spi_csn_o(x)` goes **low** (low-active chip select lines).
The data quantity to be transferred within a single transmission is defined via the _SPI_CTRL_SIZEx_ bits.
The SPI module supports 8-bit (`00`), 16-bit (`01`), 24-
bit (`10`) and 32-bit (`11`) transfers.
 
The SPI clock frequency is defined via the 3-bit _SPI_CTRL_PRSCx_ clock prescaler. The following prescalers
are available:
A transmission is started when writing data to the `DATA` register. The data must be LSB-aligned. So if
the SPI transceiver is configured for less than 32-bit transfers data quantity, the transmit data must be placed
into the lowest 8/16/24 bit of `DATA`. Vice versa, the received data is also always LSB-aligned. Application
software should only actually process the amount of bits that were configured using _SPI_CTRL_SIZEx_ when
reading `DATA`.
 
The SPI controller features 8 dedicated chip-select lines. These lines are controlled via the control register's
_SPI_CTRL_CSx_ bits. When a specific _SPI_CTRL_CSx_ bit is **set**, the according chip-select line `spi_csn_o(x)`
goes **low** (low-active chip-select lines).
 
[IMPORTANT]
Changes to the `CTRL` control register should be made only when the SPI module is idle as they directly effect
transmissions being in-progress.
 
[TIP]
The actual transmission length is left to the user: after asserting chip-select an arbitrary amount of
transmission with arbitrary data quantity (_SPI_CTRL_SIZEx_) can be made before de-asserting chip-select again.
 
[NOTE]
The NEORV32 SPI module only supports _host mode_. Transmission are initiated only by the processor's SPI module
(and not by an external SPI module).
 
[NOTE]
The NEORV32 SPI module only support MSB-first mode. Data can be reversed before writing `DATA` (for TX) / after
reading `DATA` (for RX) to provide LSB-first transmissions.
 
 
**SPI Clock Configuration**
 
The SPI module supports all _standard SPI clock modes_ (0, 1, 2, 3), which is via the two control register bits
_SPI_CTRL_CPHA_ and _SPI_CTRL_CPOL_. The _SPI_CTRL_CPHA_ bit defines the _clock phase_ and the _SPI_CTRL_CPOL_
bit defines the _clock polarity_.
 
.SPI clock modes; image from https://en.wikipedia.org/wiki/File:SPI_timing_diagram2.svg (license: (Wikimedia) https://en.wikipedia.org/wiki/Creative_Commons[Creative Commons] https://creativecommons.org/licenses/by-sa/3.0/deed.en[Attribution-Share Alike 3.0 Unported])
image::SPI_timing_diagram2.wikimedia.png[]
 
.SPI standard clock modes
[cols="<2,^1,^1,^1,^1"]
[options="header",grid="rows"]
|=======================
| | Mode 0 | Mode 1 | Mode 2 | Mode 4
| _SPI_CTRL_CPOL_ | `0` | `0` | `1` | `1`
| _SPI_CTRL_CPHA_ | `0` | `1` | `0` | `1`
|=======================
 
The SPI clock frequency (`spi_sck_o`) is programmed by the 3-bit _SPI_CTRL_PRSCx_ clock prescaler.
The following prescalers are available:
 
.SPI prescaler configuration
[cols="<4,^1,^1,^1,^1,^1,^1,^1,^1"]
[options="header",grid="rows"]
42,34 → 88,43
| Resulting `clock_prescaler` | 2 | 4 | 8 | 64 | 128 | 1024 | 2048 | 4096
|=======================
 
Based on the _SPI_CTRL_PRSCx_ configuration, the actual SPI clock frequency f~SPI~ is derived from the processor's main clock f~main~ and is determined by:
Based on the _SPI_CTRL_PRSCx_ configuration, the actual SPI clock frequency f~SPI~ is derived from the processor's
main clock f~main~ and is determined by:
 
_**f~SPI~**_ = _f~main~[Hz]_ / (2 * `clock_prescaler`)
 
A transmission is started when writing data to the `DATA` register. The data must be LSB-aligned. So if
the SPI transceiver is configured for less than 32-bit transfers data quantity, the transmit data must be placed
into the lowest 8/16/24 bit of `DATA`. Vice versa, the received data is also always LSB-aligned.
Hence, the maximum SPI clock is f~main~ / 4.
 
 
**SPI Interrupt**
 
The SPI module provides a single interrupt to signal "ready for new transmission" to the CPU. Whenever the SPI
module is currently idle (and enabled), the interrupt request is active. A pending interrupt request is cleared
by triggering a new SPI transmission or by disabling the SPI module.
 
 
.SPI register map (`struct NEORV32_SPI`)
[cols="<2,<2,<4,^1,<7"]
[options="header",grid="all"]
|=======================
| Address | Name [C] | Bit(s), Name [C] | R/W | Function
.16+<| `0xffffffa8` .16+<| `NEORV32_SPI.CTRL` <|`0` _SPI_CTRL_CS0_ ^| r/w .8+<| Direct chip-select 0..7; setting `spi_csn_o(x)` low when set
<|`1` _SPI_CTRL_CS1_ ^| r/w
<|`2` _SPI_CTRL_CS2_ ^| r/w
<|`3` _SPI_CTRL_CS3_ ^| r/w
<|`4` _SPI_CTRL_CS4_ ^| r/w
<|`5` _SPI_CTRL_CS5_ ^| r/w
<|`6` _SPI_CTRL_CS6_ ^| r/w
<|`7` _SPI_CTRL_CS7_ ^| r/w
<|`8` _SPI_CTRL_EN_ ^| r/w <| SPI enable
<|`9` _SPI_CTRL_CPHA_ ^| r/w <| polarity of `spi_sck_o` when idle
<|`10` _SPI_CTRL_PRSC0_ ^| r/w .3+| 3-bit clock prescaler select
<|`11` _SPI_CTRL_PRSC1_ ^| r/w
<|`12` _SPI_CTRL_PRSC2_ ^| r/w
<|`14` _SPI_CTRL_SIZE0_ ^| r/w .2+<| transfer size (`00`=8-bit, `01`=16-bit, `10`=24-bit, `11`=32-bit)
<|`15` _SPI_CTRL_SIZE1_ ^| r/w
<|`31` _SPI_CTRL_BUSY_ ^| r/- <| transmission in progress when set
.18+<| `0xffffffa8` .18+<| `NEORV32_SPI.CTRL` <|`0` _SPI_CTRL_CS0_ ^| r/w .8+<| Direct chip-select 0..7; setting `spi_csn_o(x)` low when set
<|`1` _SPI_CTRL_CS1_ ^| r/w
<|`2` _SPI_CTRL_CS2_ ^| r/w
<|`3` _SPI_CTRL_CS3_ ^| r/w
<|`4` _SPI_CTRL_CS4_ ^| r/w
<|`5` _SPI_CTRL_CS5_ ^| r/w
<|`6` _SPI_CTRL_CS6_ ^| r/w
<|`7` _SPI_CTRL_CS7_ ^| r/w
<|`8` _SPI_CTRL_EN_ ^| r/w <| SPI enable
<|`9` _SPI_CTRL_CPHA_ ^| r/w <| clock phase (`0`=sample RX on rising edge & update TX on falling edge; `1`=sample RX on falling edge & update TX on rising edge)
<|`10` _SPI_CTRL_PRSC0_ ^| r/w .3+| 3-bit clock prescaler select
<|`11` _SPI_CTRL_PRSC1_ ^| r/w
<|`12` _SPI_CTRL_PRSC2_ ^| r/w
<|`13` _SPI_CTRL_SIZE0_ ^| r/w .2+<| transfer size (`00`=8-bit, `01`=16-bit, `10`=24-bit, `11`=32-bit)
<|`14` _SPI_CTRL_SIZE1_ ^| r/w
<|`15` _SPI_CTRL_CPOL_ ^| r/w <| clock polarity
<|`16` .. `30` ^| r/- <| _reserved, read as zero
<|`31` _SPI_CTRL_BUSY_ ^| r/- <| transmission in progress when set
| `0xffffffac` | `NEORV32_SPI.DATA` |`31:0` | r/w | receive/transmit data, LSB-aligned
|=======================
/neorv32/trunk/docs/datasheet/soc_sysinfo.adoc
17,7 → 17,7
The SYSINFO allows the application software to determine the setting of most of the processor's top entity
generics that are related to processor/SoC configuration. All registers of this unit are read-only.
 
This device is always implemented – regardless of the actual hardware configuration. The bootloader as well
This device is always implemented - regardless of the actual hardware configuration. The bootloader as well
as the NEORV32 software runtime environment require information from this device (like memory layout
and default clock speed) for correct operation.
 
/neorv32/trunk/docs/datasheet/soc_twi.adoc
16,9 → 16,9
 
**Theory of Operation**
 
The two wire interface – also called "I²C" – is a quite famous interface for connecting several on-board
The two wire interface - also called "I²C" - is a quite famous interface for connecting several on-board
components. Since this interface only needs two signals (the serial data line `twi_sda_io` and the serial
clock line `twi_scl_io`) – despite of the number of connected devices – it allows easy interconnections of
clock line `twi_scl_io`) - despite of the number of connected devices - it allows easy interconnections of
several peripheral nodes.
 
The NEORV32 TWI implements a **TWI controller**. It features "clock stretching" (if enabled via the control
65,6 → 65,14
 
_**f~SCL~**_ = _f~main~[Hz]_ / (4 * `clock_prescaler`)
 
 
**Interrupt**
 
The TWI module provides a single interrupt to singal _idle state_ (= read for new transmission) to the CPU. Whenever TWI SPI module
is currently idle (and enabled), the interrupt request is active. A pending interrupt request is cleared
by triggering a new TWI transmission or by disabling the device.
 
 
.TWI register map (`struct NEORV32_TWI`)
[cols="<2,<2,<4,^1,<7"]
[options="header",grid="all"]
/neorv32/trunk/docs/datasheet/soc_uart.adoc
12,30 → 12,37
| | `uart0_rxd_i` | serial receiver input UART0
| | `uart0_rts_o` | flow control: RX ready to receive
| | `uart0_cts_i` | flow control: TX allowed to send
| Configuration generics: | _IO_UART0_EN_ | implement UART0 when _true_
| CPU interrupts: | fast IRQ channel 2 | RX done interrupt
| | fast IRQ channel 3 | TX done interrupt (see <<_processor_interrupts>>)
| Configuration generics: | _IO_UART0_EN_ | implement UART0 when _true_
| | _UART0_RX_FIFO_ | RX FIFO depth (power of 2, min 1)
| | _UART0_TX_FIFO_ | TX FIFO depth (power of 2, min 1)
| CPU interrupts: | fast IRQ channel 2 | RX interrupt
| | fast IRQ channel 3 | TX interrupt (see <<_processor_interrupts>>)
|=======================
 
[IMPORTANT]
The UART is a standard serial interface mainly used to establish a communication channel between a host computer
computer/user and an application running on the embedded processor.
 
The NEORV32 UARTs feature independent transmitter and receiver with a fixed frame configuration of 8 data bits,
an optional parity bit (even or odd) and a fixed stop bit. The actual transmission rate - the Baudrate - is
programmable via software. Optional FIFOs with custom sizes can be configured for the transmitter and receiver
independently.
 
The UART features two memory-mapped registers `CTRL` and `DATA`, which are used for configuration, status
check and data transfer.
 
[NOTE]
Please note that ALL default example programs and software libraries of the NEORV32 software
framework (including the bootloader and the runtime environment) use the primary UART
(_UART0_) as default user console interface. For compatibility, all C-language function calls to
`neorv32_uart_*` are mapped to the according primary UART (_UART0_) `neorv32_uart0_*`
functions.
(_UART0_) as default user console interface.
 
 
**Theory of Operation**
 
In most cases, the UART is a standard interface used to establish a communication channel between the
computer/user and an application running on the processor platform. The NEORV32 UARTs features a
standard configuration frame configuration: 8 data bits, an optional parity bit (even or odd) and 1 stop bit.
The parity and the actual Baudrate are configurable by software.
UART0 is enabled by setting the _UART_CTRL_EN_ bit in the UART0 control register `CTRL`. The Baudrate
is configured via a 12-bit _UART_CTRL_BAUDxx_ baud prescaler (`baud_prsc`) and a 3-bit _UART_CTRL_PRSCx_
clock prescaler (`clock_prescaler`) that scales the processor's primary clock (_f~main~_).
 
The UART0 is enabled by setting the _UART_CTRL_EN_ bit in the UART control register `CTRL`. The actual
transmission Baudrate (like 19200) is configured via the 12-bit _UART_CTRL_BAUDxx_ baud prescaler (`baud_rate`) and the
3-bit _UART_CTRL_PRSCx_ clock prescaler.
 
.UART prescaler configuration
.UART0 prescaler configuration
[cols="<4,^1,^1,^1,^1,^1,^1,^1,^1"]
[options="header",grid="rows"]
|=======================
43,109 → 50,129
| Resulting `clock_prescaler` | 2 | 4 | 8 | 64 | 128 | 1024 | 2048 | 4096
|=======================
 
_**Baudrate**_ = (_f~main~[Hz]_ / `clock_prescaler`) / (`baud_rate` + 1)
_**Baudrate**_ = (_f~main~[Hz]_ / `clock_prescaler`) / (`baud_prsc` + 1)
 
A new transmission is started by writing the data byte to be send to the lowest byte of the `DATA` register. The
transfer is completed when the _UART_CTRL_TX_BUSY_ control register flag returns to zero. A new received byte
is available when the _UART_DATA_AVAIL_ flag of the UART0_DATA register is set. A "frame error" in a received byte
(broken stop bit) is indicated via the _UART_DATA_FERR_ flag in the UART0_DATA register.
is available when the _UART_DATA_AVAIL_ flag of the `DATA` register is set. A "frame error" in a received byte
(invalid stop bit) is indicated via the _UART_DATA_FERR_ flag in the `DATA` register. The flag is cleared by
reading the `DATA` register.
 
**RX Double-Buffering**
 
The UART receive engine provides a simple data buffer with two entries. These two entries are transparent
for the user. The transmitting device can send up to 2 chars to the UART without risking data loss. If another
char is sent before at least one char has been read from the buffer data loss occurs. This situation can be
detected via the receiver overrun flag _UART_DATA_OVERR_ in the `DATA` register. The flag is
automatically cleared after reading `DATA`.
**RX and TX FIFOs**
 
**Parity Modes**
UART0 provides optional FIFO buffers for the transmitter and the receiver. The _UART0_RX_FIFO_ generic defines
the depth of the RX FIFO (for receiving data) while the _UART0_TX_FIFO_ defines the depth of the TX FIFO
(for sending data). Both generics have to be a power of two with a minimal allowed value of 1. This minimal
value will implement simple "double-buffering" instead of full-featured FIFOs.
Both FIFOs are cleared whenever UART0 is disabled (clearing _UART_CTRL_EN_ in `CTRL`).
 
The parity flag is added if the _UART_CTRL_PMODE1_ flag is set. When _UART_CTRL_PMODE0_ is zero the UART
operates in "even parity" mode. If this flag is set, the UART operates in "odd parity" mode. Parity errors in
received data are indicated via the _UART_DATA_PERR_ flag in the _UART_DATA_ registers. This flag is updated with each new
received character. A frame error in the received data (i.e. stop bit is not set) is indicated via the
_UART_DATA_FERR_ flag in the `DATA`. This flag is also updated with each new received character
The state of both FIFO (_empty_, _at lest half-full_, _full_) is available via the _UART_CTRL_?X_EMPTY_,
_UART_CTRL_?X_HALF_ and _UART_CTRL_*X_FULL_ flags in the `CTRL` register.
 
**Hardware Flow Control – RTS/CTS**
If the RX FIFO is already full and new data is received by the receiver unit, the _UART_DATA_OVERR_ flag
in the `DATA` register is set indicating an "overrun". This flag is cleared by reading the `DATA` register.
 
The UART supports hardware flow control using the standard CTS (clear to send) and/or RTS (ready to send
/ ready to receive "RTR") signals. Both hardware control flow mechanisms can be individually enabled.
 
If **RTS hardware flow control** is enabled by setting the _UART_CTRL_RTS_EN_ control register flag, the UART
will pull the `uart0_rts_o` signal low if the UART's receiver is idle and no received data is waiting to get read by
application software. As long as this signal is low the connected device can send new data. `uart0_rts_o` is always LOW if the UART is disabled.
 
The RTS line is de-asserted (going high) as soon as the start bit of a new incoming char has been
detected. The transmitting device continues sending the current char and can also send another char
(due to the RX double-buffering), which is done by most terminal programs. Any additional data send
when RTS is still asserted will override the RX input buffer causing data loss. This will set the _UART_DATA_OVERR_ flag in the
`DATA` register. Any read access to this register clears the flag again.
**Hardware Flow Control - RTS/CTS**
 
If **CTS hardware flow control** is enabled by setting the _UART_CTRL_CTS_EN_ control register flag, the UART's
transmitter will not start sending a new char until the `uart0_cts_i` signal goes low. If a new data to be
send is written to the UART data register while `uart0_cts_i` is not asserted (=low), the UART will wait for
`uart0_cts_i` to become asserted (=high) before sending starts. During this time, the UART busy flag
_UART_CTRL_TX_BUSY_ remains set.
UART0 supports optional hardware flow control using the standard CTS (clear to send) and/or RTS (ready to send
/ ready to receive "RTR") signals. Both hardware control flow mechanisms can be enabled individually.
 
If `uart0_cts_i` is asserted, no new data transmission will be started by the UART. The state of the `uart0_cts_i`
signals has no effect on a transmission being already in progress.
* If **RTS hardware flow control** is enabled by setting the _UART_CTRL_RTS_EN_ control register flag, the UART
will pull the `uart0_rts_o` signal low if the UART's receiver is ready to receive new data.
As long as this signal is low the connected device can send new data. `uart0_rts_o` is always LOW if the UART is disabled.
The RTS line is de-asserted (going high) as soon as the start bit of a new incoming char has been
detected.
 
Signal changes on `uart0_cts_i` during an active transmission are ignored. Application software can check
* If **CTS hardware flow control** is enabled by setting the _UART_CTRL_CTS_EN_ control register flag, the UART's
transmitter will not start sending a new data until the `uart0_cts_i` signal goes low. During this time, the UART busy flag
_UART_CTRL_TX_BUSY_ remains set. If `uart0_cts_i` is asserted, no new data transmission will be started by the UART.
The state of the `uart0_cts_i` signal has no effect on a transmission being already in progress. Application software can check
the current state of the `uart0_cts_o` input signal via the _UART_CTRL_CTS_ control register flag.
 
[TIP]
Please note that – just like the RXD and TXD signals – the RTS and CTS signals have to be **cross**-coupled
between devices.
 
**Parity Modes**
 
An optional parity bit can be added to the data stream if the _UART_CTRL_PMODE1_ flag is set.
When _UART_CTRL_PMODE0_ is zero, the UART operates in "even parity" mode. If this flag is set, the UART operates in "odd parity" mode.
Parity errors in received data are indicated via the _UART_DATA_PERR_ flag in the `DATA` register. This flag is updated with each new
received character and is cleared by reading the `DATA` register.
 
 
**Interrupts**
 
The UART features two interrupts: the "TX done interrupt" is triggered when a transmit operation (sending) has finished. The "RX
done interrupt" is triggered when a data byte has been received. If the UART0 is not implemented, the UART0 interrupts are permanently tied to zero.
UART0 features two independent interrupt for signaling certain RX and TX conditions. The behavior of these interrupts differ
based on the configured FIFO size. If the according FIFO size is greater than 1, the _UART_CTRL_RX_IRQ_ and _UART_CTRL_TX_IRQ_
`CTRL` flags allow a more fine-grained IRQ configuration.
 
[NOTE]
The UART's RX interrupt is always triggered when a new data word has arrived – regardless of the
state of the RX double-buffer.
* If _UART0_RX_FIFO_ is exactly 1, the RX interrupt becomes pending as soon as there is data available in the RX FIFO
(-> _UART_CTRL_RX_EMPTY_ clears). This flag is hardwired to `0` if _UART0_RX_FIFO_ = 1.
* If _UART0_TX_FIFO_ is exactly 1, the TX interrupt becomes pending as soon as there is a free entry left in the TX FIFO
(-> _UART_CTRL_TX_FULL_ clears). This flag is hardwired to `0` if _UART0_RX_FIFO_ = 1.
 
* If _UART0_RX_FIFO_ is greater than 1: If _UART_CTRL_RX_IRQ_ is `0` the RX interrupt becomes pending as soon as there is data
available in the RX FIFO (-> _UART_CTRL_RX_EMPTY_ clears). If _UART_CTRL_RX_IRQ_ is `1` the RX interrupt becomes pending as soon as
the RX FIFO is at least half-full (-> _UART_CTRL_RX_HALF_ sets).
* If _UART0_TX_FIFO_ is greater than 1: If _UART_CTRL_TX_IRQ_ is `0` the TX interrupt becomes pending as soon as there is a free
entry left in the TX FIFO (-> _UART_CTRL_TX_FULL_ clears). If _UART_CTRL_TX_IRQ_ is `1` the TX interrupt becomes pending as soon as
the RX FIFO is less than half-full (-> _UART_CTRL_TX_HALF_ clears).
 
An interrupt can only become pending if the according interrupt condition is fulfilled and the UART is enabled at all.
A pending interrupt is removed by resolving the interrupt-triggering conditions (for example by reading data from the
more-than-half-full RX FIFO).
 
 
**Simulation Mode**
 
The default UART0 operation will transmit any data written to the `DATA` register via the serial TX line at
the defined baud rate. Even though the default testbench provides a simulated UART0 receiver, which
outputs any received char to the simulator console, such a transmission takes a lot of time. To accelerate
UART0 output during simulation (and also to dump large amounts of data for further processing like
verification) the UART0 features a **simulation mode**.
the defined baud rate via the physical link. To accelerate UART0 output during simulation
(and also to dump large amounts of data) the UART0 features a _simulation mode_.
 
The simulation mode is enabled by setting the _UART_CTRL_SIM_MODE_ bit in the UART0's control register
`CTRL`. Any other UART0 configuration bits are irrelevant, but the UART0 has to be enabled via the
_UART_CTRL_EN_ bit. When the simulation mode is enabled, any written char to `DATA` (bits 7:0) is
directly output as ASCII char to the simulator console. Additionally, all text is also stored to a text file
`neorv32.uart0.sim_mode.text.out` in the simulation home folder. Furthermore, the whole 32-bit word
written to `DATA` is stored as plain 8-char hexadecimal value to a second text file
`neorv32.uart0.sim_mode.data.out` also located in the simulation home folder.
Simulation mode is enabled by setting the _UART_CTRL_SIM_MODE_ bit in the UART0's control register
`CTRL`. Any other UART0 configuration bits are irrelevant for this mode but UART0 has to be enabled via the
_UART_CTRL_EN_ bit. There will be no physical UART0 transmissions via `uart0_txd_o` at all when
simulation mode is enabled. Furthermore, no interrupts (RX & TX) will be triggered.
 
If the UART is configured for simulation mode there will be **NO physical UART0 transmissions via
`uart0_txd_o`** at all. Furthermore, no interrupts (RX done or TX done) will be triggered in any situation.
When the simulation mode is enabled any data written to `DATA[7:0]` is
directly output as ASCII char to the simulator console. Additionally, all chars are also stored to a text file
`neorv32.uart0.sim_mode.text.out` in the simulation home folder.
 
Furthermore, the whole 32-bit word written to `DATA[31:0]` is stored as plain 8-char hexadecimal value to a
second text file `neorv32.uart0.sim_mode.data.out` also located in the simulation home folder.
 
[TIP]
More information regarding the simulation-mode of the UART0 can be found in the Uer Guide
More information regarding the simulation-mode of the UART0 can be found in the User Guide
section https://stnolting.github.io/neorv32/ug/#_simulating_the_processor[Simulating the Processor].
 
 
.UART0 register map (`struct NEORV32_UART0`)
[cols="<6,<7,<10,^2,<18"]
[options="header",grid="all"]
|=======================
| Address | Name [C] | Bit(s), Name [C] | R/W | Function
.12+<| `0xffffffa0` .12+<| `NEORV32_UART0.CTRL` <|`11:0` _UART_CT_BAUDxx_ ^| r/w <| 12-bit BAUD value configuration value
<|`12` _UART_CT_SIM_MODE_ ^| r/w <| enable **simulation mode**
<|`20` _UART_CT_RTS_EN_ ^| r/w <| enable RTS hardware flow control
<|`21` _UART_CT_CTS_EN_ ^| r/w <| enable CTS hardware flow control
<|`22` _UART_CT_PMODE0_ ^| r/w .2+<| parity bit enable and configuration (`00`/`01`= no parity; `10`=even parity; `11`=odd parity)
<|`23` _UART_CT_PMODE1_ ^| r/w
<|`24` _UART_CT_PRSC0_ ^| r/w .3+<| 3-bit baudrate clock prescaler select
<|`25` _UART_CT_PRSC1_ ^| r/w
<|`26` _UART_CT_PRSC2_ ^| r/w
<|`27` _UART_CT_CTS_ ^| r/- <| current state of UART's CTS input signal
<|`28` _UART_CT_EN_ ^| r/w <| UART enable
<|`31` _UART_CT_TX_BUSY_ ^| r/- <| trasmitter busy flag
.21+<| `0xffffffa0` .21+<| `NEORV32_UART0.CTRL` <|`11:0` _UART_CTRL_BAUDxx_ ^| r/w <| 12-bit BAUD value configuration value
<|`12` _UART_CTRL_SIM_MODE_ ^| r/w <| enable **simulation mode**
<|`13` _UART_CTRL_RX_EMPTY_ ^| r/- <| RX FIFO is empty
<|`14` _UART_CTRL_RX_HALF_ ^| r/- <| RX FIFO is at least half-full
<|`15` _UART_CTRL_RX_FULL_ ^| r/- <| RX FIFO is full
<|`16` _UART_CTRL_TX_EMPTY_ ^| r/- <| TX FIFO is empty
<|`17` _UART_CTRL_TX_HALF_ ^| r/- <| TX FIFO is at least half-full
<|`18` _UART_CTRL_TX_FULL_ ^| r/- <| TX FIFO is full
<|`19` - ^| r/- <| _reserved_, read as zero
<|`20` _UART_CTRL_RTS_EN_ ^| r/w <| enable RTS hardware flow control
<|`21` _UART_CTRL_CTS_EN_ ^| r/w <| enable CTS hardware flow control
<|`22` _UART_CTRL_PMODE0_ ^| r/w .2+<| parity bit enable and configuration (`00`/`01`= no parity; `10`=even parity; `11`=odd parity)
<|`23` _UART_CTRL_PMODE1_ ^| r/w
<|`24` _UART_CTRL_PRSC0_ ^| r/w .3+<| 3-bit baudrate clock prescaler select
<|`25` _UART_CTRL_PRSC1_ ^| r/w
<|`26` _UART_CTRL_PRSC2_ ^| r/w
<|`27` _UART_CTRL_CTS_ ^| r/- <| current state of UART's CTS input signal
<|`28` _UART_CTRL_EN_ ^| r/w <| UART enable
<|`29` _UART_CTRL_RX_IRQ_ ^| r/w <| RX IRQ mode: `1`=FIFO at least half-full; `0`=FIFO not empty
<|`30` _UART_CTRL_TX_IRQ_ ^| r/w <| TX IRQ mode: `1`=FIFO less than half-full; `0`=FIFO not full
<|`31` _UART_CTRL_TX_BUSY_ ^| r/- <| transmitter busy flag
.6+<| `0xffffffa4` .6+<| `NEORV32_UART0.DATA` <|`7:0` _UART_DATA_MSB_ : _UART_DATA_LSB_ ^| r/w <| receive/transmit data (8-bit)
<|`31:0` - ^| -/w <| **simulation data output**
<|`28` _UART_DATA_PERR_ ^| r/- <| RX parity error
171,43 → 198,56
| | `uart1_rxd_i` | serial receiver input UART1
| | `uart1_rts_o` | flow control: RX ready to receive
| | `uart1_cts_i` | flow control: TX allowed to send
| Configuration generics: | _IO_UART1_EN_ | implement UART1 when _true_
| CPU interrupts: | fast IRQ channel 4 | RX done interrupt
| | fast IRQ channel 5 | TX done interrupt (see <<_processor_interrupts>>)
| Configuration generics: | _IO_UART1_EN_ | implement UART1 when _true_
| | _UART1_RX_FIFO_ | RX FIFO depth (power of 2, min 1)
| | _UART1_TX_FIFO_ | TX FIFO depth (power of 2, min 1)
| CPU interrupts: | fast IRQ channel 4 | RX interrupt
| | fast IRQ channel 5 | TX interrupt (see <<_processor_interrupts>>)
|=======================
 
 
**Theory of Operation**
 
The secondary UART (UART1) is functional identical to the primary UART (<<_primary_universal_asynchronous_receiver_and_transmitter_uart0>>).
Obviously, UART1 has different addresses for
the control register (`CTRL`) and the data register (`DATA`) – see the register map below. However, the
register bits/flags use the same bit positions and naming. Furthermore, the "RX done" and "TX done" interrupts are
mapped to different CPU fast interrupt channels.
Obviously, UART1 has different addresses for the control register (`CTRL`) and the data register (`DATA`) - see the register map below.
The register's bits/flags use the same bit positions and naming as for the primary UART. The RX and TX interrupts of UART1 are
mapped to different CPU fast interrupt (FIRQ) channels.
 
 
**Simulation Mode**
 
The secondary UART (UART1) provides the same simulation options as the primary UART. However,
output data is written to UART1-specific files: `neorv32.uart1.sim_mode.text.out` is used to store
plain ASCII text and `neorv32.uart1.sim_mode.data.out` is used to store full 32-bit hexadecimal
encoded data words.
data words.
 
 
.UART1 register map (`struct NEORV32_UART1`)
[cols="<6,<7,<10,^2,<18"]
[options="header",grid="all"]
|=======================
| Address | Name [C] | Bit(s), Name [C] | R/W | Function
.12+<| `0xffffffd0` .12+<| `NEORV32_UART1.CTRL` <|`11:0` _UART_CT_BAUDxx_ ^| r/w <| 12-bit BAUD value configuration value
<|`12` _UART_CT_SIM_MODE_ ^| r/w <| enable **simulation mode**
<|`20` _UART_CT_RTS_EN_ ^| r/w <| enable RTS hardware flow control
<|`21` _UART_CT_CTS_EN_ ^| r/w <| enable CTS hardware flow control
<|`22` _UART_CT_PMODE0_ ^| r/w .2+<| parity bit enable and configuration (`00`/`01`= no parity; `10`=even parity; `11`=odd parity)
<|`23` _UART_CT_PMODE1_ ^| r/w
<|`24` _UART_CT_PRSC0_ ^| r/w .3+<| 3-bit baudrate clock prescaler select
<|`25` _UART_CT_PRSC1_ ^| r/w
<|`26` _UART_CT_PRSC2_ ^| r/w
<|`27` _UART_CT_CTS_ ^| r/- <| current state of UART's CTS input signal
<|`28` _UART_CT_EN_ ^| r/w <| UART enable
<|`31` _UART_CT_TX_BUSY_ ^| r/- <| trasmitter busy flag
.21+<| `0xffffffd0` .21+<| `NEORV32_UART1.CTRL` <|`11:0` _UART_CTRL_BAUDxx_ ^| r/w <| 12-bit BAUD value configuration value
<|`12` _UART_CTRL_SIM_MODE_ ^| r/w <| enable **simulation mode**
<|`13` _UART_CTRL_RX_EMPTY_ ^| r/- <| RX FIFO is empty
<|`14` _UART_CTRL_RX_HALF_ ^| r/- <| RX FIFO is at least half-full
<|`15` _UART_CTRL_RX_FULL_ ^| r/- <| RX FIFO is full
<|`16` _UART_CTRL_TX_EMPTY_ ^| r/- <| TX FIFO is empty
<|`17` _UART_CTRL_TX_HALF_ ^| r/- <| TX FIFO is at least half-full
<|`18` _UART_CTRL_TX_FULL_ ^| r/- <| TX FIFO is full
<|`19` - ^| r/- <| _reserved_, read as zero
<|`20` _UART_CTRL_RTS_EN_ ^| r/w <| enable RTS hardware flow control
<|`21` _UART_CTRL_CTS_EN_ ^| r/w <| enable CTS hardware flow control
<|`22` _UART_CTRL_PMODE0_ ^| r/w .2+<| parity bit enable and configuration (`00`/`01`= no parity; `10`=even parity; `11`=odd parity)
<|`23` _UART_CTRL_PMODE1_ ^| r/w
<|`24` _UART_CTRL_PRSC0_ ^| r/w .3+<| 3-bit baudrate clock prescaler select
<|`25` _UART_CTRL_PRSC1_ ^| r/w
<|`26` _UART_CTRL_PRSC2_ ^| r/w
<|`27` _UART_CTRL_CTS_ ^| r/- <| current state of UART's CTS input signal
<|`28` _UART_CTRL_EN_ ^| r/w <| UART enable
<|`29` _UART_CTRL_RX_IRQ_ ^| r/w <| RX IRQ mode: `1`=FIFO at least half-full; `0`=FIFO not empty; hardwired to zero if _UART0_RX_FIFO_ = 1
<|`30` _UART_CTRL_TX_IRQ_ ^| r/w <| TX IRQ mode: `1`=FIFO less than half-full; `0`=FIFO not full; hardwired to zero if _UART0_TX_FIFO_ = 1
<|`31` _UART_CTRL_TX_BUSY_ ^| r/- <| transmitter busy flag
.6+<| `0xffffffd4` .6+<| `NEORV32_UART1.DATA` <|`7:0` _UART_DATA_MSB_ : _UART_DATA_LSB_ ^| r/w <| receive/transmit data (8-bit)
<|`31:0` - ^| -/w <| **simulation data output**
<|`28` _UART_DATA_PERR_ ^| r/- <| RX parity error
/neorv32/trunk/docs/datasheet/soc_wdt.adoc
39,10 → 39,13
 
Whenever the internal timer overflows the watchdog executes one of two possible actions: Either a hard
processor reset is triggered or an interrupt is requested at CPU's fast interrupt channel #0. The
WDT_CTRL_MODE bit defines the action to be taken on an overflow: When cleared, the Watchdog will trigger an
IRQ, when set the WDT will cause a system reset. The configured actions can also be triggered manually at
WDT_CTRL_MODE bit definess the action to be taken on an overflow: When cleared, the Watchdog will assert an
IRQ, when set the WDT will cause a system reset. The configured action can also be triggered manually at
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 pending interrupt is cleared by either disabling the watchdog or by resetting the watchdog.
 
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
initiated by the watchdog.
/neorv32/trunk/docs/datasheet/soc_wishbone.adoc
64,7 → 64,7
 
[TOP]
A detailed description of the implemented Wishbone bus protocol and the according interface signals
can be found in the data sheet "Wishbone B4 – WISHBONE System-on-Chip (SoC) Interconnection
can be found in the data sheet "Wishbone B4 - WISHBONE System-on-Chip (SoC) Interconnection
Architecture for Portable IP Cores". A copy of this document can be found in the docs folder of this
project.
 
/neorv32/trunk/docs/datasheet/soc_xirq.adoc
34,7 → 34,7
[NOTE]
A disabled interrupt channel can still be pending if it has been triggered before clearing the according `IER` bit.
 
The CPU can determine firing interrupt request either by checking the bits in the `IPR` register, which show all
The CPU can determine active external interrupt request either by checking the bits in the `IPR` register, which show all
pending interrupt channels, or by reading the interrupt source register `SCR`.
This register provides a 5-bit wide ID (0..31) that shows the interrupt request with _highest priority_.
Interrupt channel `xirq_i(0)` has highest priority and `xirq_i(_XIRQ_NUM_CH_-1)` has lowest priority.
42,8 → 42,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 acknowledge the interrupt from the external interrupt controller, the CPU has to write _any_
value to interrupt source register `SRC`.
In order to clear a pending FIRQ interrupt from the external interrupt controller, the CPU has to write _any_
value to the interrupt source register `SRC`.
 
[NOTE]
An interrupt handler should clear the interrupt pending bit that caused the interrupt first before
/neorv32/trunk/docs/datasheet/software.adoc
124,12 → 124,14
info - show makefile/toolchain configuration
exe - compile and generate <neorv32_exe.bin> executable for upload via bootloader
hex - compile and generate <neorv32_exe.hex> executable raw file
image - compile and generate VHDL IMEM boot image (for application) in local folder
install - compile, generate and install VHDL IMEM boot image (for application)
sim - in-console simulation using the default testbench and GHDL
sim - in-console simulation using default/simple testbench and GHDL
all - exe + hex + install
elf_info - show ELF layout info
clean - clean up project
clean_all - clean up project, core libraries and image generator
bl_image - compile and generate VHDL BOOTROM boot image (for bootloader only!) in local folder
bootloader - compile, generate and install VHDL BOOTROM boot image (for bootloader only!)
----
 
142,7 → 144,7
 
[TIP]
The makefile configuration variables can be (re-)defined directly when invoking the makefile. For
example via `$ make MARCH=-march=rv32ic clean_all exe`. You can also make project-specific definitions
example via `$ make MARCH=rv32ic clean_all exe`. You can also make project-specific definitions
of all variables inside the project's actual makefile (e.g., `sw/example/blink_led/makefile`).
 
[source,makefile]
162,8 → 164,8
# Compiler toolchain
RISCV_PREFIX ?= riscv32-unknown-elf-
# CPU architecture and ABI
MARCH ?= -march=rv32i
MABI ?= -mabi=ilp32
MARCH ?= rv32i
MABI ?= ilp32
# User flags for additional configuration (will be added to compiler flags)
USER_FLAGS ?=
# Relative or absolute path to the NEORV32 home folder
179,7 → 181,7
| _ASM_INC_ | Include file folders that are used only for the assembly source files (`*.S`/`*.s`).
| _EFFORT_ | Optimization level, optimize for size (`-Os`) is default; legal values: `-O0`, `-O1`, `-O2`, `-O3`, `-Os`
| _RISCV_PREFIX_ | The toolchain prefix to be used; follows the naming convention "architecture-vendor-output-"
| _MARCH_ | The targetd RISC-V architecture/ISA. Only `rv32` is supported by the NEORV32. Enable compiler support of optional CPU extension by adding the according extension letter (e.g. `rv32im` for _M_ CPU extension). See https://stnolting.github.io/neorv32/ug/#_enabling_risc_v_cpu_extensions[User Guide: Enabling RISC-V CPU Extensions] for more information.
| _MARCH_ | The targeted RISC-V architecture/ISA. Only `rv32` is supported by the NEORV32. Enable compiler support of optional CPU extension by adding the according extension letter (e.g. `rv32im` for _M_ CPU extension). See https://stnolting.github.io/neorv32/ug/#_enabling_risc_v_cpu_extensions[User Guide: Enabling RISC-V CPU Extensions] for more information.
| _MABI_ | The default 32-bit integer ABI.
| _USER_FLAGS_ | Additional flags that will be forwarded to the compiler tools
| _NEORV32_HOME_ | Relative or absolute path to the NEORV32 project home folder. Adapt this if the makefile/project is not in the project's `sw/example folder`.
374,7 → 376,7
----
int __neorv32_crt0_after_main(int32_t return_code) {
 
neorv32_uart_printf("Main returned with code: %i\n", return_code);
neorv32_uart0_printf("Main returned with code: %i\n", return_code);
return 0;
}
----
/neorv32/trunk/docs/figures/SPI_timing_diagram2.wikimedia.png Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
neorv32/trunk/docs/figures/SPI_timing_diagram2.wikimedia.png Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: neorv32/trunk/docs/figures/address_space.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: neorv32/trunk/docs/figures/license.md =================================================================== --- neorv32/trunk/docs/figures/license.md (nonexistent) +++ neorv32/trunk/docs/figures/license.md (revision 65) @@ -0,0 +1,11 @@ +# :copyright: + +Figures are own work if not otherwise stated. License: https://github.com/stnolting/neorv32/blob/master/LICENSE + +## `SPI_timing_diagram2.wikimedia.png` + +source: https://en.wikipedia.org/wiki/File:SPI_timing_diagram2.svg + +License: +* Creative Commons: https://en.wikipedia.org/wiki/Creative_Commons +* Attribution-Share Alike 3.0 Unported: https://creativecommons.org/licenses/by-sa/3.0/deed.en \ No newline at end of file Index: neorv32/trunk/docs/userguide/content.adoc =================================================================== --- neorv32/trunk/docs/userguide/content.adoc (revision 64) +++ neorv32/trunk/docs/userguide/content.adoc (revision 65) @@ -29,21 +29,20 @@ :sectnums: === Building the Toolchain from Scratch -To build the toolchain by yourself you can follow the guide from the official https://github.com/riscv/riscv-gnu-toolchain GitHub page. +To build the toolchain by yourself you can follow the guide from the official https://github.com/riscv-collab/riscv-gnu-toolchain GitHub page. You need to make sure the generated toolchain fits the architecture of the NEORV32 core. To get a toolchain that even supports minimal ISA extension configurations, it is recommend to compile for `rv32i` only. Please note that this minimal ISA also provides further ISA -extensions like `m` or `c`. Of course you can use a `multilib` approach to generate -toolchains for several target ISAs. +extensions like `m` or `c`. Of course you can use a _multilib_ approach to generate toolchains for several target ISAs at once. .Configuring GCC build for `rv32i` (minimal ISA) [source,bash] ---- -riscv-gnu-toolchain$ ./configure --prefix=/opt/riscv --with-arch=rv32i –-with-abi=ilp32 +riscv-gnu-toolchain$ ./configure --prefix=/opt/riscv --with-arch=rv32i --with-abi=ilp32 riscv-gnu-toolchain$ make ---- [IMPORTANT] -Keep in mind that – for instance – a toolchain build with `--with-arch=rv32imc` only provides library code compiled with +Keep in mind that - for instance - a toolchain build with `--with-arch=rv32imc` only provides library code compiled with compressed (`C`) and `mul`/`div` instructions (`M`)! Hence, this code cannot be executed (without emulation) on an architecture without these extensions! @@ -196,8 +195,8 @@ <3> Default size of internal data memory: 8kB [start=7] -. If you feel like it – or if your FPGA does not provide sufficient resources – you can modify the -_memory sizes_ (`MEM_INT_IMEM_SIZE` and `MEM_INT_DMEM_SIZE` – marked with notes "2" and "3"). But as mentioned +. If you feel like it - or if your FPGA does not provide sufficient resources - you can modify the +_memory sizes_ (`MEM_INT_IMEM_SIZE` and `MEM_INT_DMEM_SIZE` - marked with notes "2" and "3"). But as mentioned above, let's keep things simple at first and use the standard configuration for now. . There is one generic that _has to be set according to your FPGA board_ setup: the actual clock frequency of the top's clock input signal (`clk_i`). Use the `CLOCK_FREQUENCY` generic to specify your clock source's @@ -205,7 +204,7 @@ [NOTE] If you have changed the default memory configuration (`MEM_INT_IMEM_SIZE` and `MEM_INT_DMEM_SIZE` generics) -keep those new sizes in mind – these values are required for setting +keep those new sizes in mind - these values are required for setting up the software framework in the next section <<_general_software_framework_setup>>. [start=9] @@ -249,7 +248,7 @@ [start=10] . Attach the clock input `clk_i` to your clock source and connect the reset line `rstn_i` to a button of -your FPGA board. Check whether it is low-active or high-active – the reset signal of the processor is +your FPGA board. Check whether it is low-active or high-active - the reset signal of the processor is **low-active**, so maybe you need to invert the input signal. . If possible, connected _at least_ bit `0` of the GPIO output port `gpio_o` to a LED (see "Signal Polarity" note above). . Finally, if your are using the UART-based test setup (`neorv32_testsetup_bootloader.vhd`) @@ -288,7 +287,7 @@ ---- MEMORY { - ram (rwx) : ORIGIN = 0x80000000, LENGTH = DEFINED(make_bootloader) ? 512 : 8*1024 # <1> + ram (rwx) : ORIGIN = 0x80000000, LENGTH = DEFINED(make_bootloader) ? 512 : 8*1024 <1> ... ---- <1> Size of the data memory address space (right-most value) (internal/external DMEM); here 8kB @@ -616,8 +615,8 @@ [source,makefile] ---- # CPU architecture and ABI -MARCH = -march=rv32i # <1> -MABI = -mabi=ilp32 # <2> +MARCH ?= rv32i <1> +MABI ?= ilp32 <2> ---- <1> MARCH = Machine architecture ("ISA string") <2> MABI = Machine binary interface @@ -642,7 +641,7 @@ [source,bash] ---- -$ make MARCH=-march=rv32ic clean_all all +$ make MARCH=rv32ic clean_all all ---- [NOTE] @@ -1037,9 +1036,13 @@ . Save everything, let VIVADO create a HDL-Wrapper for the block-design and choose this as your _Top Level Design_. . Define your constraints and generate your bitstream. +.TWI Tri-State Drivers +[IMPORTANT] +Set the synthesis option "global" when generating the block design to maintain the internal TWI tri-state drivers. + [NOTE] -Guide provided by GitHub user https://github.com/AWenzel83[`AWenzel83`] from -https://github.com/stnolting/neorv32/discussions/52#discussioncomment-819013 +Guide provided by GitHub user https://github.com/AWenzel83[`AWenzel83`] (see +https://github.com/stnolting/neorv32/discussions/52#discussioncomment-819013). ❤️ @@ -1181,7 +1184,7 @@ To do a quick test of the NEORV32 make sure to have https://github.com/ghdl/ghdl[GHDL] and a [RISC-V gcc toolchain](https://github.com/stnolting/riscv-gcc-prebuilt) installed. -Navigate to the project's `sw/example/hello_world` folder and run `make USER_FLAGS+=-DUART0_SIM_MODE MARCH=-march=rv32imac clean_all sim`: +Navigate to the project's `sw/example/hello_world` folder and run `make USER_FLAGS+=-DUART0_SIM_MODE MARCH=rv32imac clean_all sim`: [TIP] The simulator will output some _sanity check_ notes (and warnings or even errors if something is ill-configured) @@ -1189,7 +1192,7 @@ [source, bash] ---- -stnolting@Einstein:/mnt/n/Projects/neorv32/sw/example/hello_world$ make USER_FLAGS+=-DUART0_SIM_MODE MARCH=-march=rv32imac clean_all sim +stnolting@Einstein:/mnt/n/Projects/neorv32/sw/example/hello_world$ make USER_FLAGS+=-DUART0_SIM_MODE MARCH=rv32imac clean_all sim ../../../sw/lib/source/neorv32_uart.c: In function 'neorv32_uart0_setup': ../../../sw/lib/source/neorv32_uart.c:301:4: warning: #warning UART0_SIM_MODE (primary UART) enabled! Sending all UART0.TX data to text.io simulation output instead of real UART0 transmitter. Use this for simulations only! [-Wcpp] 301 | #warning UART0_SIM_MODE (primary UART) enabled! Sending all UART0.TX data to text.io simulation output instead of real UART0 transmitter. Use this for simulations only! <1> @@ -1310,6 +1313,23 @@ <<< // #################################################################################################################### :sectnums: +== Zephyr RTOS Support 🪁 + +The NEORV32 processor is supported by upstream Zephyr RTOS: https://docs.zephyrproject.org/latest/boards/riscv/neorv32/doc/index.html + +[IMPORTANT] +The absolute path to the NEORV32 executable image generator binary (`.../neorv32/sw/image_gen`) has to be added to the `PATH` variable +so the Zephyr build system can generate executables and memory-initialization images. + +[NOTE] +Zephyr OS port provided by GitHub user https://github.com/henrikbrixandersen[henrikbrixandersen] +(see https://github.com/stnolting/neorv32/discussions/172). ❤️ + + + +<<< +// #################################################################################################################### +:sectnums: == FreeRTOS Support A NEORV32-specific port and a simple demo for FreeRTOS (https://github.com/FreeRTOS/FreeRTOS) are @@ -1436,7 +1456,7 @@ .Compile the test application [source, bash] -------------------------- -.../neorv32/sw/example/blink_led$ make MARCH=-march=rv32i USER_FLAGS+=-g clean_all all +.../neorv32/sw/example/blink_led$ make MARCH=rv32i USER_FLAGS+=-g clean_all all -------------------------- .Adding debug symbols to the executable
/neorv32/trunk/docs/attrs.adoc
1,7 → 1,8
:author: Dipl.-Ing. Stephan Nolting
: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.1
:revnumber: v1.6.2
:doctype: book
:sectnums:
:stem:
/neorv32/trunk/docs/legal.adoc
106,7 → 106,8
 
.DOI
[TIP]
This project also provides a _digital object identifier_ provided by https://zenodo.org[zenodo]: https://zenodo.org/record/5121427
This project also provides a _digital object identifier_ provided by https://zenodo.org[zenodo]:
https://doi.org/10.5281/zenodo.5018888[image:https://zenodo.org/badge/DOI/10.5281/zenodo.5018888.svg[title='zenodo']]
 
 
:sectnums!:
/neorv32/trunk/rtl/core/neorv32_application_image.vhd
113,17 → 113,17
00000099 => x"00000593",
00000100 => x"b0050513",
00000101 => x"00112623",
00000102 => x"118000ef",
00000102 => x"088000ef",
00000103 => x"718000ef",
00000104 => x"00050c63",
00000105 => x"6c8000ef",
00000106 => x"00001537",
00000107 => x"a6050513",
00000108 => x"170000ef",
00000108 => x"118000ef",
00000109 => x"020000ef",
00000110 => x"00001537",
00000111 => x"a3c50513",
00000112 => x"160000ef",
00000112 => x"108000ef",
00000113 => x"00c12083",
00000114 => x"00100513",
00000115 => x"01010113",
140,7 → 140,7
00000126 => x"0ff57513",
00000127 => x"6c8000ef",
00000128 => x"0c800513",
00000129 => x"14c000ef",
00000129 => x"148000ef",
00000130 => x"00040513",
00000131 => x"fe5ff06f",
00000132 => x"fe802503",
183,12 → 183,12
00000169 => x"f9dff06f",
00000170 => x"0017d793",
00000171 => x"ff1ff06f",
00000172 => x"f71ff06f",
00000172 => x"00040737",
00000173 => x"fa002783",
00000174 => x"fe07cee3",
00000175 => x"faa02223",
00000176 => x"00008067",
00000177 => x"ff1ff06f",
00000174 => x"00e7f7b3",
00000175 => x"fe079ce3",
00000176 => x"faa02223",
00000177 => x"00008067",
00000178 => x"ff010113",
00000179 => x"00812423",
00000180 => x"01212023",
207,69 → 207,69
00000193 => x"00008067",
00000194 => x"01249663",
00000195 => x"00d00513",
00000196 => x"fa5ff0ef",
00000196 => x"fa1ff0ef",
00000197 => x"00048513",
00000198 => x"f9dff0ef",
00000198 => x"f99ff0ef",
00000199 => x"fc9ff06f",
00000200 => x"fa9ff06f",
00000201 => x"ff010113",
00000202 => x"c81026f3",
00000203 => x"c0102773",
00000204 => x"c81027f3",
00000205 => x"fed79ae3",
00000206 => x"00e12023",
00000207 => x"00f12223",
00000208 => x"00012503",
00000209 => x"00412583",
00000210 => x"01010113",
00000211 => x"00008067",
00000212 => x"fd010113",
00000213 => x"00a12623",
00000214 => x"fe002503",
00000215 => x"3e800593",
00000216 => x"02112623",
00000217 => x"02812423",
00000218 => x"02912223",
00000219 => x"03212023",
00000220 => x"01312e23",
00000221 => x"61c000ef",
00000222 => x"00c12603",
00000223 => x"00000693",
00000224 => x"00000593",
00000225 => x"574000ef",
00000226 => x"00050413",
00000227 => x"00058993",
00000228 => x"f95ff0ef",
00000229 => x"00058913",
00000230 => x"00050493",
00000231 => x"f89ff0ef",
00000232 => x"00b96663",
00000233 => x"05259263",
00000234 => x"04a4f063",
00000235 => x"008484b3",
00000236 => x"0084b433",
00000237 => x"01390933",
00000238 => x"01240433",
00000239 => x"f69ff0ef",
00000240 => x"fe85eee3",
00000241 => x"00b41463",
00000242 => x"fe956ae3",
00000243 => x"02c12083",
00000244 => x"02812403",
00000245 => x"02412483",
00000246 => x"02012903",
00000247 => x"01c12983",
00000248 => x"03010113",
00000249 => x"00008067",
00000250 => x"01c99913",
00000251 => x"00445413",
00000252 => x"00896433",
00000253 => x"00040a63",
00000254 => x"00040863",
00000255 => x"fff40413",
00000256 => x"00000013",
00000257 => x"ff1ff06f",
00000258 => x"fc5ff06f",
00000200 => x"ff010113",
00000201 => x"c81026f3",
00000202 => x"c0102773",
00000203 => x"c81027f3",
00000204 => x"fed79ae3",
00000205 => x"00e12023",
00000206 => x"00f12223",
00000207 => x"00012503",
00000208 => x"00412583",
00000209 => x"01010113",
00000210 => x"00008067",
00000211 => x"fd010113",
00000212 => x"00a12623",
00000213 => x"fe002503",
00000214 => x"3e800593",
00000215 => x"02112623",
00000216 => x"02812423",
00000217 => x"02912223",
00000218 => x"03212023",
00000219 => x"01312e23",
00000220 => x"620000ef",
00000221 => x"00c12603",
00000222 => x"00000693",
00000223 => x"00000593",
00000224 => x"578000ef",
00000225 => x"00050413",
00000226 => x"00058993",
00000227 => x"f95ff0ef",
00000228 => x"00058913",
00000229 => x"00050493",
00000230 => x"f89ff0ef",
00000231 => x"00b96663",
00000232 => x"05259263",
00000233 => x"04a4f063",
00000234 => x"008484b3",
00000235 => x"0084b433",
00000236 => x"01390933",
00000237 => x"01240433",
00000238 => x"f69ff0ef",
00000239 => x"fe85eee3",
00000240 => x"00b41463",
00000241 => x"fe956ae3",
00000242 => x"02c12083",
00000243 => x"02812403",
00000244 => x"02412483",
00000245 => x"02012903",
00000246 => x"01c12983",
00000247 => x"03010113",
00000248 => x"00008067",
00000249 => x"01c99913",
00000250 => x"00445413",
00000251 => x"00896433",
00000252 => x"00040a63",
00000253 => x"00040863",
00000254 => x"fff40413",
00000255 => x"00000013",
00000256 => x"ff1ff06f",
00000257 => x"fc5ff06f",
00000258 => x"00000000",
00000259 => x"00000000",
00000260 => x"fc010113",
00000261 => x"02112e23",
421,7 → 421,7
00000407 => x"00f487b3",
00000408 => x"0007c503",
00000409 => x"ffc40413",
00000410 => x"c4dff0ef",
00000410 => x"c49ff0ef",
00000411 => x"ff3414e3",
00000412 => x"01c12083",
00000413 => x"01812403",
438,7 → 438,7
00000424 => x"18050463",
00000425 => x"00001537",
00000426 => x"b2450513",
00000427 => x"c75ff0ef",
00000427 => x"c1dff0ef",
00000428 => x"34202473",
00000429 => x"00900713",
00000430 => x"00f47793",
463,7 → 463,7
00000449 => x"10f40663",
00000450 => x"00001537",
00000451 => x"c8450513",
00000452 => x"c11ff0ef",
00000452 => x"bb9ff0ef",
00000453 => x"00040513",
00000454 => x"f05ff0ef",
00000455 => x"0380006f",
473,21 → 473,21
00000459 => x"fcf76ee3",
00000460 => x"00001537",
00000461 => x"c7450513",
00000462 => x"be9ff0ef",
00000462 => x"b91ff0ef",
00000463 => x"00048513",
00000464 => x"b85ff0ef",
00000464 => x"b71ff0ef",
00000465 => x"0100006f",
00000466 => x"00001537",
00000467 => x"b2c50513",
00000468 => x"bd1ff0ef",
00000468 => x"b79ff0ef",
00000469 => x"00001537",
00000470 => x"c9c50513",
00000471 => x"bc5ff0ef",
00000471 => x"b6dff0ef",
00000472 => x"34002573",
00000473 => x"eb9ff0ef",
00000474 => x"00001537",
00000475 => x"ca450513",
00000476 => x"bb1ff0ef",
00000476 => x"b59ff0ef",
00000477 => x"34302573",
00000478 => x"ea5ff0ef",
00000479 => x"00812403",
496,7 → 496,7
00000482 => x"00001537",
00000483 => x"cb050513",
00000484 => x"01010113",
00000485 => x"b8dff06f",
00000485 => x"b35ff06f",
00000486 => x"00001537",
00000487 => x"b4c50513",
00000488 => x"fb1ff06f",
/neorv32/trunk/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: 4048 bytes
-- Size: 4088 bytes
 
library ieee;
use ieee.std_logic_1164.all;
51,7 → 51,7
00000037 => x"00158593",
00000038 => x"ff5ff06f",
00000039 => x"00001597",
00000040 => x"f3458593",
00000040 => x"f5c58593",
00000041 => x"80010617",
00000042 => x"f5c60613",
00000043 => x"80010697",
105,924 → 105,934
00000091 => x"0007a023",
00000092 => x"8001a223",
00000093 => x"ffff07b7",
00000094 => x"4b878793",
00000094 => x"4bc78793",
00000095 => x"30579073",
00000096 => x"00000613",
00000097 => x"00000593",
00000098 => x"00200513",
00000099 => x"381000ef",
00000100 => x"409000ef",
00000101 => x"00048493",
00000102 => x"00050863",
00000103 => x"00100513",
00000104 => x"00000593",
00000105 => x"435000ef",
00000106 => x"00005537",
00000107 => x"00000613",
00000108 => x"00000593",
00000109 => x"b0050513",
00000110 => x"225000ef",
00000111 => x"1bd000ef",
00000112 => x"02050a63",
00000113 => x"1c5000ef",
00000114 => x"fe002783",
00000115 => x"0027d793",
00000116 => x"00a78533",
00000117 => x"00f537b3",
00000118 => x"00b785b3",
00000119 => x"1d9000ef",
00000120 => x"08000793",
00000121 => x"30479073",
00000122 => x"30046073",
00000123 => x"00000013",
00000096 => x"00000693",
00000097 => x"00000613",
00000098 => x"00000593",
00000099 => x"00200513",
00000100 => x"399000ef",
00000101 => x"42d000ef",
00000102 => x"00048493",
00000103 => x"00050863",
00000104 => x"00100513",
00000105 => x"00000593",
00000106 => x"459000ef",
00000107 => x"00005537",
00000108 => x"00000613",
00000109 => x"00000593",
00000110 => x"b0050513",
00000111 => x"1f9000ef",
00000112 => x"1bd000ef",
00000113 => x"02050a63",
00000114 => x"325000ef",
00000115 => x"fe002783",
00000116 => x"0027d793",
00000117 => x"00a78533",
00000118 => x"00f537b3",
00000119 => x"00b785b3",
00000120 => x"1ad000ef",
00000121 => x"08000793",
00000122 => x"30479073",
00000123 => x"30046073",
00000124 => x"00000013",
00000125 => x"ffff1537",
00000126 => x"f0050513",
00000127 => x"2a9000ef",
00000128 => x"f1302573",
00000129 => x"244000ef",
00000130 => x"ffff1537",
00000131 => x"f3850513",
00000132 => x"295000ef",
00000133 => x"fe002503",
00000134 => x"230000ef",
00000135 => x"ffff1537",
00000136 => x"f4050513",
00000137 => x"281000ef",
00000138 => x"30102573",
00000139 => x"21c000ef",
00000140 => x"ffff1537",
00000141 => x"f4850513",
00000142 => x"26d000ef",
00000143 => x"fe402503",
00000144 => x"ffff1437",
00000145 => x"204000ef",
00000146 => x"ffff1537",
00000147 => x"f5050513",
00000148 => x"255000ef",
00000149 => x"fe802503",
00000150 => x"1f0000ef",
00000151 => x"ffff1537",
00000152 => x"f5850513",
00000153 => x"241000ef",
00000154 => x"ff802503",
00000155 => x"1dc000ef",
00000156 => x"f6040513",
00000157 => x"231000ef",
00000158 => x"ff002503",
00000159 => x"1cc000ef",
00000160 => x"ffff1537",
00000161 => x"f6c50513",
00000162 => x"21d000ef",
00000163 => x"ffc02503",
00000164 => x"1b8000ef",
00000165 => x"f6040513",
00000166 => x"20d000ef",
00000167 => x"ff402503",
00000168 => x"1a8000ef",
00000169 => x"0d5000ef",
00000170 => x"06050663",
00000171 => x"ffff1537",
00000172 => x"f7450513",
00000173 => x"1f1000ef",
00000174 => x"0d1000ef",
00000175 => x"fe002403",
00000176 => x"00341413",
00000177 => x"00a40933",
00000178 => x"00893433",
00000179 => x"00b40433",
00000180 => x"0fd000ef",
00000181 => x"02051663",
00000182 => x"0b1000ef",
00000183 => x"fe85eae3",
00000184 => x"00b41463",
00000185 => x"ff2566e3",
00000186 => x"00100513",
00000187 => x"4d4000ef",
00000188 => x"ffff1537",
00000189 => x"f9c50513",
00000190 => x"1ad000ef",
00000191 => x"0cc000ef",
00000192 => x"199000ef",
00000193 => x"fc050ae3",
00000194 => x"ffff1537",
00000195 => x"fa050513",
00000196 => x"195000ef",
00000197 => x"0a8000ef",
00000198 => x"ffff19b7",
00000199 => x"ffff1a37",
00000200 => x"07200a93",
00000201 => x"06800b13",
00000202 => x"07500b93",
00000203 => x"07300c13",
00000204 => x"ffff1937",
00000205 => x"ffff1cb7",
00000206 => x"fac98513",
00000207 => x"169000ef",
00000208 => x"149000ef",
00000209 => x"00050413",
00000210 => x"125000ef",
00000211 => x"f9ca0513",
00000212 => x"155000ef",
00000213 => x"01541863",
00000214 => x"ffff02b7",
00000215 => x"00028067",
00000216 => x"fd9ff06f",
00000217 => x"01641663",
00000218 => x"054000ef",
00000219 => x"fcdff06f",
00000220 => x"00000513",
00000221 => x"01740e63",
00000222 => x"01841663",
00000223 => x"680000ef",
00000224 => x"fb9ff06f",
00000225 => x"06c00793",
00000226 => x"00f41863",
00000227 => x"00100513",
00000228 => x"430000ef",
00000229 => x"fa5ff06f",
00000230 => x"06500793",
00000231 => x"00f41c63",
00000232 => x"0004a783",
00000233 => x"f4079ce3",
00000234 => x"ea8c8513",
00000235 => x"0f9000ef",
00000236 => x"f89ff06f",
00000237 => x"fb490513",
00000238 => x"ff5ff06f",
00000239 => x"ffff1537",
00000240 => x"de850513",
00000241 => x"0e10006f",
00000242 => x"ff010113",
00000243 => x"00112623",
00000244 => x"30047073",
00000245 => x"00000013",
00000125 => x"00000013",
00000126 => x"ffff1537",
00000127 => x"f2850513",
00000128 => x"295000ef",
00000129 => x"f1302573",
00000130 => x"244000ef",
00000131 => x"ffff1537",
00000132 => x"f6050513",
00000133 => x"281000ef",
00000134 => x"fe002503",
00000135 => x"230000ef",
00000136 => x"ffff1537",
00000137 => x"f6850513",
00000138 => x"26d000ef",
00000139 => x"30102573",
00000140 => x"21c000ef",
00000141 => x"ffff1537",
00000142 => x"f7050513",
00000143 => x"259000ef",
00000144 => x"fe402503",
00000145 => x"ffff1437",
00000146 => x"204000ef",
00000147 => x"ffff1537",
00000148 => x"f7850513",
00000149 => x"241000ef",
00000150 => x"fe802503",
00000151 => x"1f0000ef",
00000152 => x"ffff1537",
00000153 => x"f8050513",
00000154 => x"22d000ef",
00000155 => x"ff802503",
00000156 => x"1dc000ef",
00000157 => x"f8840513",
00000158 => x"21d000ef",
00000159 => x"ff002503",
00000160 => x"1cc000ef",
00000161 => x"ffff1537",
00000162 => x"f9450513",
00000163 => x"209000ef",
00000164 => x"ffc02503",
00000165 => x"1b8000ef",
00000166 => x"f8840513",
00000167 => x"1f9000ef",
00000168 => x"ff402503",
00000169 => x"1a8000ef",
00000170 => x"0d5000ef",
00000171 => x"06050663",
00000172 => x"ffff1537",
00000173 => x"f9c50513",
00000174 => x"1dd000ef",
00000175 => x"231000ef",
00000176 => x"fe002403",
00000177 => x"00341413",
00000178 => x"00a40933",
00000179 => x"00893433",
00000180 => x"00b40433",
00000181 => x"0d1000ef",
00000182 => x"02051663",
00000183 => x"211000ef",
00000184 => x"fe85eae3",
00000185 => x"00b41463",
00000186 => x"ff2566e3",
00000187 => x"00100513",
00000188 => x"4d4000ef",
00000189 => x"ffff1537",
00000190 => x"fc450513",
00000191 => x"199000ef",
00000192 => x"0cc000ef",
00000193 => x"185000ef",
00000194 => x"fc050ae3",
00000195 => x"ffff1537",
00000196 => x"fc850513",
00000197 => x"181000ef",
00000198 => x"0a8000ef",
00000199 => x"ffff19b7",
00000200 => x"ffff1a37",
00000201 => x"07200a93",
00000202 => x"06800b13",
00000203 => x"07500b93",
00000204 => x"07300c13",
00000205 => x"ffff1937",
00000206 => x"ffff1cb7",
00000207 => x"fd498513",
00000208 => x"155000ef",
00000209 => x"135000ef",
00000210 => x"00050413",
00000211 => x"0f9000ef",
00000212 => x"fc4a0513",
00000213 => x"141000ef",
00000214 => x"01541863",
00000215 => x"ffff02b7",
00000216 => x"00028067",
00000217 => x"fd9ff06f",
00000218 => x"01641663",
00000219 => x"054000ef",
00000220 => x"fcdff06f",
00000221 => x"00000513",
00000222 => x"01740e63",
00000223 => x"01841663",
00000224 => x"680000ef",
00000225 => x"fb9ff06f",
00000226 => x"06c00793",
00000227 => x"00f41863",
00000228 => x"00100513",
00000229 => x"430000ef",
00000230 => x"fa5ff06f",
00000231 => x"06500793",
00000232 => x"00f41c63",
00000233 => x"0004a783",
00000234 => x"f4079ce3",
00000235 => x"ed0c8513",
00000236 => x"0e5000ef",
00000237 => x"f89ff06f",
00000238 => x"fdc90513",
00000239 => x"ff5ff06f",
00000240 => x"ffff1537",
00000241 => x"e1050513",
00000242 => x"0cd0006f",
00000243 => x"ff010113",
00000244 => x"00112623",
00000245 => x"30047073",
00000246 => x"00000013",
00000247 => x"ffff1537",
00000248 => x"e4c50513",
00000249 => x"0c1000ef",
00000250 => x"095000ef",
00000251 => x"fe051ee3",
00000252 => x"ff002783",
00000253 => x"00078067",
00000254 => x"0000006f",
00000255 => x"ff010113",
00000256 => x"00812423",
00000257 => x"00050413",
00000258 => x"ffff1537",
00000259 => x"e5c50513",
00000260 => x"00112623",
00000261 => x"091000ef",
00000262 => x"03040513",
00000263 => x"0ff57513",
00000264 => x"04d000ef",
00000265 => x"30047073",
00000266 => x"00000013",
00000247 => x"00000013",
00000248 => x"ffff1537",
00000249 => x"e7450513",
00000250 => x"0ad000ef",
00000251 => x"071000ef",
00000252 => x"fe051ee3",
00000253 => x"ff002783",
00000254 => x"00078067",
00000255 => x"0000006f",
00000256 => x"ff010113",
00000257 => x"00812423",
00000258 => x"00050413",
00000259 => x"ffff1537",
00000260 => x"e8450513",
00000261 => x"00112623",
00000262 => x"07d000ef",
00000263 => x"03040513",
00000264 => x"0ff57513",
00000265 => x"021000ef",
00000266 => x"30047073",
00000267 => x"00000013",
00000268 => x"169000ef",
00000269 => x"00050863",
00000270 => x"00100513",
00000271 => x"00000593",
00000272 => x"199000ef",
00000273 => x"0000006f",
00000274 => x"fe010113",
00000275 => x"01212823",
00000276 => x"00050913",
00000277 => x"ffff1537",
00000278 => x"00912a23",
00000279 => x"e6850513",
00000280 => x"ffff14b7",
00000281 => x"00812c23",
00000282 => x"01312623",
00000283 => x"00112e23",
00000284 => x"01c00413",
00000285 => x"031000ef",
00000286 => x"fc048493",
00000287 => x"ffc00993",
00000288 => x"008957b3",
00000289 => x"00f7f793",
00000290 => x"00f487b3",
00000291 => x"0007c503",
00000292 => x"ffc40413",
00000293 => x"7d8000ef",
00000294 => x"ff3414e3",
00000295 => x"01c12083",
00000296 => x"01812403",
00000297 => x"01412483",
00000298 => x"01012903",
00000299 => x"00c12983",
00000300 => x"02010113",
00000301 => x"00008067",
00000302 => x"fb010113",
00000303 => x"04112623",
00000304 => x"04512423",
00000305 => x"04612223",
00000306 => x"04712023",
00000307 => x"02812e23",
00000308 => x"02912c23",
00000309 => x"02a12a23",
00000310 => x"02b12823",
00000311 => x"02c12623",
00000312 => x"02d12423",
00000313 => x"02e12223",
00000314 => x"02f12023",
00000315 => x"01012e23",
00000316 => x"01112c23",
00000317 => x"01c12a23",
00000318 => x"01d12823",
00000319 => x"01e12623",
00000320 => x"01f12423",
00000321 => x"342024f3",
00000322 => x"800007b7",
00000323 => x"00778793",
00000324 => x"08f49463",
00000325 => x"085000ef",
00000326 => x"00050663",
00000327 => x"00000513",
00000328 => x"089000ef",
00000329 => x"654000ef",
00000330 => x"02050063",
00000331 => x"65c000ef",
00000332 => x"fe002783",
00000333 => x"0027d793",
00000334 => x"00a78533",
00000335 => x"00f537b3",
00000336 => x"00b785b3",
00000337 => x"670000ef",
00000338 => x"03c12403",
00000339 => x"04c12083",
00000340 => x"04812283",
00000341 => x"04412303",
00000342 => x"04012383",
00000343 => x"03812483",
00000344 => x"03412503",
00000345 => x"03012583",
00000346 => x"02c12603",
00000347 => x"02812683",
00000348 => x"02412703",
00000349 => x"02012783",
00000350 => x"01c12803",
00000351 => x"01812883",
00000352 => x"01412e03",
00000353 => x"01012e83",
00000354 => x"00c12f03",
00000355 => x"00812f83",
00000356 => x"05010113",
00000357 => x"30200073",
00000358 => x"00700793",
00000359 => x"00f49a63",
00000360 => x"8041a783",
00000361 => x"00078663",
00000362 => x"00100513",
00000363 => x"e51ff0ef",
00000364 => x"34102473",
00000365 => x"618000ef",
00000366 => x"04050263",
00000367 => x"ffff1537",
00000368 => x"e6c50513",
00000369 => x"6e0000ef",
00000370 => x"00048513",
00000371 => x"e7dff0ef",
00000372 => x"02000513",
00000373 => x"698000ef",
00000374 => x"00040513",
00000375 => x"e6dff0ef",
00000376 => x"02000513",
00000377 => x"688000ef",
00000378 => x"34302573",
00000379 => x"e5dff0ef",
00000380 => x"ffff1537",
00000381 => x"e7450513",
00000382 => x"6ac000ef",
00000383 => x"00440413",
00000384 => x"34141073",
00000385 => x"f45ff06f",
00000386 => x"ff010113",
00000387 => x"00000513",
00000388 => x"00112623",
00000389 => x"00812423",
00000390 => x"728000ef",
00000391 => x"09e00513",
00000392 => x"764000ef",
00000393 => x"00000513",
00000394 => x"75c000ef",
00000395 => x"00050413",
00000396 => x"00000513",
00000397 => x"72c000ef",
00000398 => x"00c12083",
00000399 => x"0ff47513",
00000400 => x"00812403",
00000401 => x"01010113",
00000402 => x"00008067",
00000403 => x"ff010113",
00000404 => x"00112623",
00000405 => x"00812423",
00000406 => x"00000513",
00000407 => x"6e4000ef",
00000408 => x"00500513",
00000409 => x"720000ef",
00000410 => x"00000513",
00000411 => x"718000ef",
00000412 => x"00050413",
00000413 => x"00147413",
00000414 => x"00000513",
00000415 => x"6e4000ef",
00000416 => x"fc041ce3",
00000417 => x"00c12083",
00000418 => x"00812403",
00000419 => x"01010113",
00000420 => x"00008067",
00000421 => x"ff010113",
00000422 => x"00000513",
00000423 => x"00112623",
00000424 => x"6a0000ef",
00000425 => x"00600513",
00000426 => x"6dc000ef",
00000427 => x"00c12083",
00000428 => x"00000513",
00000429 => x"01010113",
00000430 => x"6a80006f",
00000431 => x"ff010113",
00000432 => x"00812423",
00000433 => x"00050413",
00000434 => x"01055513",
00000435 => x"0ff57513",
00000436 => x"00112623",
00000437 => x"6b0000ef",
00000438 => x"00845513",
00000439 => x"0ff57513",
00000440 => x"6a4000ef",
00000441 => x"0ff47513",
00000442 => x"00812403",
00000443 => x"00c12083",
00000444 => x"01010113",
00000445 => x"6900006f",
00000446 => x"ff010113",
00000447 => x"00812423",
00000448 => x"00050413",
00000449 => x"00000513",
00000450 => x"00112623",
00000451 => x"634000ef",
00000452 => x"00300513",
00000453 => x"670000ef",
00000454 => x"00040513",
00000455 => x"fa1ff0ef",
00000456 => x"00000513",
00000457 => x"660000ef",
00000458 => x"00050413",
00000459 => x"00000513",
00000460 => x"630000ef",
00000461 => x"00c12083",
00000462 => x"0ff47513",
00000463 => x"00812403",
00000464 => x"01010113",
00000465 => x"00008067",
00000466 => x"fd010113",
00000467 => x"02812423",
00000468 => x"02912223",
00000469 => x"03212023",
00000470 => x"01312e23",
00000471 => x"01412c23",
00000472 => x"02112623",
00000473 => x"00050913",
00000474 => x"00058993",
00000475 => x"00c10493",
00000476 => x"00000413",
00000477 => x"00400a13",
00000478 => x"02091e63",
00000479 => x"50c000ef",
00000480 => x"00a48023",
00000481 => x"00140413",
00000482 => x"00148493",
00000483 => x"ff4416e3",
00000484 => x"02c12083",
00000485 => x"02812403",
00000486 => x"00c12503",
00000487 => x"02412483",
00000488 => x"02012903",
00000489 => x"01c12983",
00000490 => x"01812a03",
00000491 => x"03010113",
00000492 => x"00008067",
00000493 => x"00898533",
00000494 => x"f41ff0ef",
00000495 => x"fc5ff06f",
00000496 => x"fd010113",
00000497 => x"01412c23",
00000498 => x"02812423",
00000499 => x"80418793",
00000500 => x"02112623",
00000501 => x"02912223",
00000502 => x"03212023",
00000503 => x"01312e23",
00000504 => x"01512a23",
00000505 => x"01612823",
00000506 => x"01712623",
00000507 => x"01812423",
00000508 => x"00100713",
00000509 => x"00e7a023",
00000510 => x"00050413",
00000511 => x"80418a13",
00000512 => x"02051863",
00000513 => x"ffff1537",
00000514 => x"e7850513",
00000515 => x"498000ef",
00000516 => x"080005b7",
00000517 => x"00040513",
00000518 => x"f31ff0ef",
00000519 => x"4788d7b7",
00000520 => x"afe78793",
00000521 => x"02f50a63",
00000522 => x"00000513",
00000523 => x"01c0006f",
00000524 => x"ffff1537",
00000525 => x"e9850513",
00000526 => x"46c000ef",
00000527 => x"4c0000ef",
00000528 => x"00051663",
00000529 => x"00300513",
00000530 => x"bb5ff0ef",
00000531 => x"dbdff0ef",
00000532 => x"fc0510e3",
00000533 => x"ff1ff06f",
00000534 => x"080009b7",
00000535 => x"00498593",
00000536 => x"00040513",
00000537 => x"ee5ff0ef",
00000538 => x"00050a93",
00000539 => x"00898593",
00000540 => x"00040513",
00000541 => x"ed5ff0ef",
00000542 => x"ff002c03",
00000543 => x"00050b13",
00000544 => x"ffcafb93",
00000545 => x"00000913",
00000546 => x"00000493",
00000547 => x"00c98993",
00000548 => x"013905b3",
00000549 => x"052b9c63",
00000550 => x"016484b3",
00000551 => x"00200513",
00000552 => x"fa0494e3",
00000553 => x"ffff1537",
00000554 => x"ea450513",
00000555 => x"3f8000ef",
00000556 => x"02c12083",
00000557 => x"02812403",
00000558 => x"800007b7",
00000559 => x"0157a023",
00000560 => x"000a2023",
00000561 => x"02412483",
00000562 => x"02012903",
00000563 => x"01c12983",
00000564 => x"01812a03",
00000565 => x"01412a83",
00000566 => x"01012b03",
00000567 => x"00c12b83",
00000568 => x"00812c03",
00000569 => x"03010113",
00000570 => x"00008067",
00000571 => x"00040513",
00000572 => x"e59ff0ef",
00000573 => x"012c07b3",
00000574 => x"00a484b3",
00000575 => x"00a7a023",
00000576 => x"00490913",
00000577 => x"f8dff06f",
00000578 => x"ff010113",
00000579 => x"00112623",
00000580 => x"00812423",
00000581 => x"00912223",
00000582 => x"00058413",
00000583 => x"00050493",
00000584 => x"d75ff0ef",
00000585 => x"00000513",
00000586 => x"418000ef",
00000587 => x"00200513",
00000588 => x"454000ef",
00000589 => x"00048513",
00000590 => x"d85ff0ef",
00000591 => x"00040513",
00000592 => x"444000ef",
00000593 => x"00000513",
00000594 => x"418000ef",
00000595 => x"00812403",
00000596 => x"00c12083",
00000597 => x"00412483",
00000598 => x"01010113",
00000599 => x"cf1ff06f",
00000600 => x"fe010113",
00000601 => x"00812c23",
00000602 => x"00912a23",
00000603 => x"01212823",
00000604 => x"00112e23",
00000605 => x"00050493",
00000606 => x"00b12623",
00000607 => x"00000413",
00000608 => x"00400913",
00000609 => x"00c10793",
00000610 => x"008787b3",
00000611 => x"0007c583",
00000612 => x"00848533",
00000613 => x"00140413",
00000614 => x"f71ff0ef",
00000615 => x"ff2414e3",
00000616 => x"01c12083",
00000617 => x"01812403",
00000618 => x"01412483",
00000619 => x"01012903",
00000620 => x"02010113",
00000621 => x"00008067",
00000622 => x"ff010113",
00000623 => x"00112623",
00000624 => x"00812423",
00000625 => x"00050413",
00000626 => x"ccdff0ef",
00000627 => x"00000513",
00000628 => x"370000ef",
00000629 => x"0d800513",
00000630 => x"3ac000ef",
00000631 => x"00040513",
00000632 => x"cddff0ef",
00000633 => x"00000513",
00000634 => x"378000ef",
00000635 => x"00812403",
00000636 => x"00c12083",
00000637 => x"01010113",
00000638 => x"c55ff06f",
00000639 => x"fe010113",
00000640 => x"800007b7",
00000641 => x"00812c23",
00000642 => x"0007a403",
00000643 => x"00112e23",
00000644 => x"00912a23",
00000645 => x"01212823",
00000646 => x"01312623",
00000647 => x"01412423",
00000648 => x"01512223",
00000649 => x"02041863",
00000650 => x"ffff1537",
00000651 => x"ea850513",
00000652 => x"01812403",
00000653 => x"01c12083",
00000654 => x"01412483",
00000655 => x"01012903",
00000656 => x"00c12983",
00000657 => x"00812a03",
00000658 => x"00412a83",
00000659 => x"02010113",
00000660 => x"2540006f",
00000661 => x"ffff1537",
00000662 => x"ec450513",
00000663 => x"248000ef",
00000664 => x"00040513",
00000665 => x"9e5ff0ef",
00000666 => x"ffff1537",
00000667 => x"ecc50513",
00000668 => x"234000ef",
00000669 => x"08000537",
00000670 => x"9d1ff0ef",
00000671 => x"ffff1537",
00000672 => x"ee450513",
00000673 => x"220000ef",
00000674 => x"200000ef",
00000675 => x"00050493",
00000676 => x"1dc000ef",
00000677 => x"07900793",
00000678 => x"0af49e63",
00000679 => x"b6dff0ef",
00000680 => x"00051663",
00000681 => x"00300513",
00000682 => x"955ff0ef",
00000683 => x"ffff1537",
00000684 => x"ef050513",
00000685 => x"01045493",
00000686 => x"1ec000ef",
00000687 => x"00148493",
00000688 => x"08000937",
00000689 => x"fff00993",
00000690 => x"00010a37",
00000691 => x"fff48493",
00000692 => x"07349063",
00000693 => x"4788d5b7",
00000694 => x"afe58593",
00000695 => x"08000537",
00000696 => x"e81ff0ef",
00000697 => x"08000537",
00000698 => x"00040593",
00000699 => x"00450513",
00000700 => x"e71ff0ef",
00000701 => x"ff002a03",
00000702 => x"080009b7",
00000703 => x"ffc47413",
00000704 => x"00000493",
00000705 => x"00000913",
00000706 => x"00c98a93",
00000707 => x"01548533",
00000708 => x"009a07b3",
00000709 => x"02849663",
00000710 => x"00898513",
00000711 => x"412005b3",
00000712 => x"e41ff0ef",
00000713 => x"ffff1537",
00000714 => x"ea450513",
00000715 => x"f05ff06f",
00000716 => x"00090513",
00000717 => x"e85ff0ef",
00000718 => x"01490933",
00000719 => x"f91ff06f",
00000720 => x"0007a583",
00000721 => x"00448493",
00000722 => x"00b90933",
00000723 => x"e15ff0ef",
00000724 => x"fbdff06f",
00000725 => x"01c12083",
00000726 => x"01812403",
00000727 => x"01412483",
00000728 => x"01012903",
00000729 => x"00c12983",
00000730 => x"00812a03",
00000731 => x"00412a83",
00000732 => x"02010113",
00000733 => x"00008067",
00000734 => x"fe802503",
00000735 => x"01155513",
00000736 => x"00157513",
00000737 => x"00008067",
00000738 => x"ff010113",
00000739 => x"f9402783",
00000740 => x"f9002703",
00000741 => x"f9402683",
00000742 => x"fed79ae3",
00000743 => x"00e12023",
00000744 => x"00f12223",
00000745 => x"00012503",
00000746 => x"00412583",
00000747 => x"01010113",
00000268 => x"00000013",
00000269 => x"18d000ef",
00000270 => x"00050863",
00000271 => x"00100513",
00000272 => x"00000593",
00000273 => x"1bd000ef",
00000274 => x"0000006f",
00000275 => x"fe010113",
00000276 => x"01212823",
00000277 => x"00050913",
00000278 => x"ffff1537",
00000279 => x"00912a23",
00000280 => x"e9050513",
00000281 => x"ffff14b7",
00000282 => x"00812c23",
00000283 => x"01312623",
00000284 => x"00112e23",
00000285 => x"01c00413",
00000286 => x"01d000ef",
00000287 => x"fe848493",
00000288 => x"ffc00993",
00000289 => x"008957b3",
00000290 => x"00f7f793",
00000291 => x"00f487b3",
00000292 => x"0007c503",
00000293 => x"ffc40413",
00000294 => x"7ac000ef",
00000295 => x"ff3414e3",
00000296 => x"01c12083",
00000297 => x"01812403",
00000298 => x"01412483",
00000299 => x"01012903",
00000300 => x"00c12983",
00000301 => x"02010113",
00000302 => x"00008067",
00000303 => x"fb010113",
00000304 => x"04112623",
00000305 => x"04512423",
00000306 => x"04612223",
00000307 => x"04712023",
00000308 => x"02812e23",
00000309 => x"02912c23",
00000310 => x"02a12a23",
00000311 => x"02b12823",
00000312 => x"02c12623",
00000313 => x"02d12423",
00000314 => x"02e12223",
00000315 => x"02f12023",
00000316 => x"01012e23",
00000317 => x"01112c23",
00000318 => x"01c12a23",
00000319 => x"01d12823",
00000320 => x"01e12623",
00000321 => x"01f12423",
00000322 => x"342024f3",
00000323 => x"800007b7",
00000324 => x"00778793",
00000325 => x"08f49463",
00000326 => x"0a9000ef",
00000327 => x"00050663",
00000328 => x"00000513",
00000329 => x"0ad000ef",
00000330 => x"654000ef",
00000331 => x"02050063",
00000332 => x"7bc000ef",
00000333 => x"fe002783",
00000334 => x"0027d793",
00000335 => x"00a78533",
00000336 => x"00f537b3",
00000337 => x"00b785b3",
00000338 => x"644000ef",
00000339 => x"03c12403",
00000340 => x"04c12083",
00000341 => x"04812283",
00000342 => x"04412303",
00000343 => x"04012383",
00000344 => x"03812483",
00000345 => x"03412503",
00000346 => x"03012583",
00000347 => x"02c12603",
00000348 => x"02812683",
00000349 => x"02412703",
00000350 => x"02012783",
00000351 => x"01c12803",
00000352 => x"01812883",
00000353 => x"01412e03",
00000354 => x"01012e83",
00000355 => x"00c12f03",
00000356 => x"00812f83",
00000357 => x"05010113",
00000358 => x"30200073",
00000359 => x"00700793",
00000360 => x"00f49a63",
00000361 => x"8041a783",
00000362 => x"00078663",
00000363 => x"00100513",
00000364 => x"e51ff0ef",
00000365 => x"34102473",
00000366 => x"5ec000ef",
00000367 => x"04050263",
00000368 => x"ffff1537",
00000369 => x"e9450513",
00000370 => x"6cc000ef",
00000371 => x"00048513",
00000372 => x"e7dff0ef",
00000373 => x"02000513",
00000374 => x"66c000ef",
00000375 => x"00040513",
00000376 => x"e6dff0ef",
00000377 => x"02000513",
00000378 => x"65c000ef",
00000379 => x"34302573",
00000380 => x"e5dff0ef",
00000381 => x"ffff1537",
00000382 => x"e9c50513",
00000383 => x"698000ef",
00000384 => x"00440413",
00000385 => x"34141073",
00000386 => x"f45ff06f",
00000387 => x"ff010113",
00000388 => x"00000513",
00000389 => x"00112623",
00000390 => x"00812423",
00000391 => x"74c000ef",
00000392 => x"09e00513",
00000393 => x"788000ef",
00000394 => x"00000513",
00000395 => x"780000ef",
00000396 => x"00050413",
00000397 => x"00000513",
00000398 => x"750000ef",
00000399 => x"00c12083",
00000400 => x"0ff47513",
00000401 => x"00812403",
00000402 => x"01010113",
00000403 => x"00008067",
00000404 => x"ff010113",
00000405 => x"00112623",
00000406 => x"00812423",
00000407 => x"00000513",
00000408 => x"708000ef",
00000409 => x"00500513",
00000410 => x"744000ef",
00000411 => x"00000513",
00000412 => x"73c000ef",
00000413 => x"00050413",
00000414 => x"00147413",
00000415 => x"00000513",
00000416 => x"708000ef",
00000417 => x"fc041ce3",
00000418 => x"00c12083",
00000419 => x"00812403",
00000420 => x"01010113",
00000421 => x"00008067",
00000422 => x"ff010113",
00000423 => x"00000513",
00000424 => x"00112623",
00000425 => x"6c4000ef",
00000426 => x"00600513",
00000427 => x"700000ef",
00000428 => x"00c12083",
00000429 => x"00000513",
00000430 => x"01010113",
00000431 => x"6cc0006f",
00000432 => x"ff010113",
00000433 => x"00812423",
00000434 => x"00050413",
00000435 => x"01055513",
00000436 => x"0ff57513",
00000437 => x"00112623",
00000438 => x"6d4000ef",
00000439 => x"00845513",
00000440 => x"0ff57513",
00000441 => x"6c8000ef",
00000442 => x"0ff47513",
00000443 => x"00812403",
00000444 => x"00c12083",
00000445 => x"01010113",
00000446 => x"6b40006f",
00000447 => x"ff010113",
00000448 => x"00812423",
00000449 => x"00050413",
00000450 => x"00000513",
00000451 => x"00112623",
00000452 => x"658000ef",
00000453 => x"00300513",
00000454 => x"694000ef",
00000455 => x"00040513",
00000456 => x"fa1ff0ef",
00000457 => x"00000513",
00000458 => x"684000ef",
00000459 => x"00050413",
00000460 => x"00000513",
00000461 => x"654000ef",
00000462 => x"00c12083",
00000463 => x"0ff47513",
00000464 => x"00812403",
00000465 => x"01010113",
00000466 => x"00008067",
00000467 => x"fd010113",
00000468 => x"02812423",
00000469 => x"02912223",
00000470 => x"03212023",
00000471 => x"01312e23",
00000472 => x"01412c23",
00000473 => x"02112623",
00000474 => x"00050913",
00000475 => x"00058993",
00000476 => x"00c10493",
00000477 => x"00000413",
00000478 => x"00400a13",
00000479 => x"02091e63",
00000480 => x"4f8000ef",
00000481 => x"00a48023",
00000482 => x"00140413",
00000483 => x"00148493",
00000484 => x"ff4416e3",
00000485 => x"02c12083",
00000486 => x"02812403",
00000487 => x"00c12503",
00000488 => x"02412483",
00000489 => x"02012903",
00000490 => x"01c12983",
00000491 => x"01812a03",
00000492 => x"03010113",
00000493 => x"00008067",
00000494 => x"00898533",
00000495 => x"f41ff0ef",
00000496 => x"fc5ff06f",
00000497 => x"fd010113",
00000498 => x"01412c23",
00000499 => x"02812423",
00000500 => x"80418793",
00000501 => x"02112623",
00000502 => x"02912223",
00000503 => x"03212023",
00000504 => x"01312e23",
00000505 => x"01512a23",
00000506 => x"01612823",
00000507 => x"01712623",
00000508 => x"01812423",
00000509 => x"00100713",
00000510 => x"00e7a023",
00000511 => x"00050413",
00000512 => x"80418a13",
00000513 => x"02051863",
00000514 => x"ffff1537",
00000515 => x"ea050513",
00000516 => x"484000ef",
00000517 => x"080005b7",
00000518 => x"00040513",
00000519 => x"f31ff0ef",
00000520 => x"4788d7b7",
00000521 => x"afe78793",
00000522 => x"02f50a63",
00000523 => x"00000513",
00000524 => x"01c0006f",
00000525 => x"ffff1537",
00000526 => x"ec050513",
00000527 => x"458000ef",
00000528 => x"4d8000ef",
00000529 => x"00051663",
00000530 => x"00300513",
00000531 => x"bb5ff0ef",
00000532 => x"dbdff0ef",
00000533 => x"fc0510e3",
00000534 => x"ff1ff06f",
00000535 => x"080009b7",
00000536 => x"00498593",
00000537 => x"00040513",
00000538 => x"ee5ff0ef",
00000539 => x"00050a93",
00000540 => x"00898593",
00000541 => x"00040513",
00000542 => x"ed5ff0ef",
00000543 => x"ff002c03",
00000544 => x"00050b13",
00000545 => x"ffcafb93",
00000546 => x"00000913",
00000547 => x"00000493",
00000548 => x"00c98993",
00000549 => x"013905b3",
00000550 => x"052b9c63",
00000551 => x"016484b3",
00000552 => x"00200513",
00000553 => x"fa0494e3",
00000554 => x"ffff1537",
00000555 => x"ecc50513",
00000556 => x"3e4000ef",
00000557 => x"02c12083",
00000558 => x"02812403",
00000559 => x"800007b7",
00000560 => x"0157a023",
00000561 => x"000a2023",
00000562 => x"02412483",
00000563 => x"02012903",
00000564 => x"01c12983",
00000565 => x"01812a03",
00000566 => x"01412a83",
00000567 => x"01012b03",
00000568 => x"00c12b83",
00000569 => x"00812c03",
00000570 => x"03010113",
00000571 => x"00008067",
00000572 => x"00040513",
00000573 => x"e59ff0ef",
00000574 => x"012c07b3",
00000575 => x"00a484b3",
00000576 => x"00a7a023",
00000577 => x"00490913",
00000578 => x"f8dff06f",
00000579 => x"ff010113",
00000580 => x"00112623",
00000581 => x"00812423",
00000582 => x"00912223",
00000583 => x"00058413",
00000584 => x"00050493",
00000585 => x"d75ff0ef",
00000586 => x"00000513",
00000587 => x"43c000ef",
00000588 => x"00200513",
00000589 => x"478000ef",
00000590 => x"00048513",
00000591 => x"d85ff0ef",
00000592 => x"00040513",
00000593 => x"468000ef",
00000594 => x"00000513",
00000595 => x"43c000ef",
00000596 => x"00812403",
00000597 => x"00c12083",
00000598 => x"00412483",
00000599 => x"01010113",
00000600 => x"cf1ff06f",
00000601 => x"fe010113",
00000602 => x"00812c23",
00000603 => x"00912a23",
00000604 => x"01212823",
00000605 => x"00112e23",
00000606 => x"00050493",
00000607 => x"00b12623",
00000608 => x"00000413",
00000609 => x"00400913",
00000610 => x"00c10793",
00000611 => x"008787b3",
00000612 => x"0007c583",
00000613 => x"00848533",
00000614 => x"00140413",
00000615 => x"f71ff0ef",
00000616 => x"ff2414e3",
00000617 => x"01c12083",
00000618 => x"01812403",
00000619 => x"01412483",
00000620 => x"01012903",
00000621 => x"02010113",
00000622 => x"00008067",
00000623 => x"ff010113",
00000624 => x"00112623",
00000625 => x"00812423",
00000626 => x"00050413",
00000627 => x"ccdff0ef",
00000628 => x"00000513",
00000629 => x"394000ef",
00000630 => x"0d800513",
00000631 => x"3d0000ef",
00000632 => x"00040513",
00000633 => x"cddff0ef",
00000634 => x"00000513",
00000635 => x"39c000ef",
00000636 => x"00812403",
00000637 => x"00c12083",
00000638 => x"01010113",
00000639 => x"c55ff06f",
00000640 => x"fe010113",
00000641 => x"800007b7",
00000642 => x"00812c23",
00000643 => x"0007a403",
00000644 => x"00112e23",
00000645 => x"00912a23",
00000646 => x"01212823",
00000647 => x"01312623",
00000648 => x"01412423",
00000649 => x"01512223",
00000650 => x"02041863",
00000651 => x"ffff1537",
00000652 => x"ed050513",
00000653 => x"01812403",
00000654 => x"01c12083",
00000655 => x"01412483",
00000656 => x"01012903",
00000657 => x"00c12983",
00000658 => x"00812a03",
00000659 => x"00412a83",
00000660 => x"02010113",
00000661 => x"2400006f",
00000662 => x"ffff1537",
00000663 => x"eec50513",
00000664 => x"234000ef",
00000665 => x"00040513",
00000666 => x"9e5ff0ef",
00000667 => x"ffff1537",
00000668 => x"ef450513",
00000669 => x"220000ef",
00000670 => x"08000537",
00000671 => x"9d1ff0ef",
00000672 => x"ffff1537",
00000673 => x"f0c50513",
00000674 => x"20c000ef",
00000675 => x"1ec000ef",
00000676 => x"00050493",
00000677 => x"1b0000ef",
00000678 => x"07900793",
00000679 => x"0af49e63",
00000680 => x"b6dff0ef",
00000681 => x"00051663",
00000682 => x"00300513",
00000683 => x"955ff0ef",
00000684 => x"ffff1537",
00000685 => x"f1850513",
00000686 => x"01045493",
00000687 => x"1d8000ef",
00000688 => x"00148493",
00000689 => x"08000937",
00000690 => x"fff00993",
00000691 => x"00010a37",
00000692 => x"fff48493",
00000693 => x"07349063",
00000694 => x"4788d5b7",
00000695 => x"afe58593",
00000696 => x"08000537",
00000697 => x"e81ff0ef",
00000698 => x"08000537",
00000699 => x"00040593",
00000700 => x"00450513",
00000701 => x"e71ff0ef",
00000702 => x"ff002a03",
00000703 => x"080009b7",
00000704 => x"ffc47413",
00000705 => x"00000493",
00000706 => x"00000913",
00000707 => x"00c98a93",
00000708 => x"01548533",
00000709 => x"009a07b3",
00000710 => x"02849663",
00000711 => x"00898513",
00000712 => x"412005b3",
00000713 => x"e41ff0ef",
00000714 => x"ffff1537",
00000715 => x"ecc50513",
00000716 => x"f05ff06f",
00000717 => x"00090513",
00000718 => x"e85ff0ef",
00000719 => x"01490933",
00000720 => x"f91ff06f",
00000721 => x"0007a583",
00000722 => x"00448493",
00000723 => x"00b90933",
00000724 => x"e15ff0ef",
00000725 => x"fbdff06f",
00000726 => x"01c12083",
00000727 => x"01812403",
00000728 => x"01412483",
00000729 => x"01012903",
00000730 => x"00c12983",
00000731 => x"00812a03",
00000732 => x"00412a83",
00000733 => x"02010113",
00000734 => x"00008067",
00000735 => x"fe802503",
00000736 => x"01155513",
00000737 => x"00157513",
00000738 => x"00008067",
00000739 => x"f9000793",
00000740 => x"fff00713",
00000741 => x"00e7a423",
00000742 => x"00b7a623",
00000743 => x"00a7a423",
00000744 => x"00008067",
00000745 => x"fe802503",
00000746 => x"01255513",
00000747 => x"00157513",
00000748 => x"00008067",
00000749 => x"f9000793",
00000750 => x"fff00713",
00000751 => x"00e7a423",
00000752 => x"00b7a623",
00000753 => x"00a7a423",
00000754 => x"00008067",
00000755 => x"fe802503",
00000756 => x"01255513",
00000757 => x"00157513",
00000758 => x"00008067",
00000759 => x"fa002023",
00000760 => x"fe002703",
00000761 => x"00151513",
00000762 => x"00000793",
00000763 => x"04a77463",
00000764 => x"000016b7",
00000765 => x"00000713",
00000766 => x"ffe68693",
00000767 => x"04f6e663",
00000768 => x"00367613",
00000769 => x"0035f593",
00000770 => x"fff78793",
00000771 => x"01461613",
00000772 => x"00c7e7b3",
00000773 => x"01659593",
00000774 => x"01871713",
00000775 => x"00b7e7b3",
00000776 => x"00e7e7b3",
00000777 => x"10000737",
00000778 => x"00e7e7b3",
00000779 => x"faf02023",
00000780 => x"00008067",
00000781 => x"00178793",
00000782 => x"01079793",
00000783 => x"40a70733",
00000784 => x"0107d793",
00000785 => x"fa9ff06f",
00000786 => x"ffe70513",
00000787 => x"0fd57513",
00000788 => x"00051a63",
00000789 => x"0037d793",
00000790 => x"00170713",
00000791 => x"0ff77713",
00000792 => x"f9dff06f",
00000793 => x"0017d793",
00000794 => x"ff1ff06f",
00000795 => x"fa002783",
00000796 => x"fe07cee3",
00000797 => x"faa02223",
00000798 => x"00008067",
00000799 => x"fa002503",
00000800 => x"01f55513",
00000749 => x"fa002023",
00000750 => x"fe002703",
00000751 => x"00151513",
00000752 => x"00000793",
00000753 => x"04a77463",
00000754 => x"000016b7",
00000755 => x"00000713",
00000756 => x"ffe68693",
00000757 => x"04f6e663",
00000758 => x"00367613",
00000759 => x"0035f593",
00000760 => x"fff78793",
00000761 => x"01461613",
00000762 => x"00c7e7b3",
00000763 => x"01659593",
00000764 => x"01871713",
00000765 => x"00b7e7b3",
00000766 => x"00e7e7b3",
00000767 => x"10000737",
00000768 => x"00e7e7b3",
00000769 => x"faf02023",
00000770 => x"00008067",
00000771 => x"00178793",
00000772 => x"01079793",
00000773 => x"40a70733",
00000774 => x"0107d793",
00000775 => x"fa9ff06f",
00000776 => x"ffe70513",
00000777 => x"0fd57513",
00000778 => x"00051a63",
00000779 => x"0037d793",
00000780 => x"00170713",
00000781 => x"0ff77713",
00000782 => x"f9dff06f",
00000783 => x"0017d793",
00000784 => x"ff1ff06f",
00000785 => x"00040737",
00000786 => x"fa002783",
00000787 => x"00e7f7b3",
00000788 => x"fe079ce3",
00000789 => x"faa02223",
00000790 => x"00008067",
00000791 => x"fa002783",
00000792 => x"00100513",
00000793 => x"0007c863",
00000794 => x"0107d513",
00000795 => x"00154513",
00000796 => x"00157513",
00000797 => x"00008067",
00000798 => x"fa402503",
00000799 => x"fe055ee3",
00000800 => x"0ff57513",
00000801 => x"00008067",
00000802 => x"fa402503",
00000803 => x"fe055ee3",
00000804 => x"0ff57513",
00000805 => x"00008067",
00000806 => x"fa402503",
00000807 => x"01f55513",
00000808 => x"00008067",
00000809 => x"ff010113",
00000810 => x"00812423",
00000811 => x"01212023",
00000812 => x"00112623",
00000813 => x"00912223",
00000814 => x"00050413",
00000815 => x"00a00913",
00000816 => x"00044483",
00000817 => x"00140413",
00000818 => x"00049e63",
00000819 => x"00c12083",
00000820 => x"00812403",
00000821 => x"00412483",
00000822 => x"00012903",
00000823 => x"01010113",
00000824 => x"00008067",
00000825 => x"01249663",
00000826 => x"00d00513",
00000827 => x"f81ff0ef",
00000828 => x"00048513",
00000829 => x"f79ff0ef",
00000830 => x"fc9ff06f",
00000831 => x"fe802503",
00000832 => x"01355513",
00000833 => x"00157513",
00000834 => x"00008067",
00000835 => x"00757513",
00000836 => x"00367613",
00000837 => x"0015f593",
00000838 => x"00a51513",
00000839 => x"00d61613",
00000840 => x"00c56533",
00000841 => x"00959593",
00000842 => x"fa800793",
00000843 => x"00b56533",
00000844 => x"0007a023",
00000845 => x"10056513",
00000846 => x"00a7a023",
00000847 => x"00008067",
00000848 => x"fa800713",
00000849 => x"00072683",
00000850 => x"00757793",
00000851 => x"00100513",
00000852 => x"00f51533",
00000853 => x"00d56533",
00000854 => x"00a72023",
00000855 => x"00008067",
00000856 => x"fa800713",
00000857 => x"00072683",
00000858 => x"00757513",
00000859 => x"00100793",
00000860 => x"00a797b3",
00000861 => x"fff7c793",
00000862 => x"00d7f7b3",
00000863 => x"00f72023",
00000864 => x"00008067",
00000865 => x"faa02623",
00000866 => x"fa802783",
00000867 => x"fe07cee3",
00000868 => x"fac02503",
00000869 => x"00008067",
00000870 => x"fe802503",
00000871 => x"01055513",
00000872 => x"00157513",
00000873 => x"00008067",
00000874 => x"00100793",
00000875 => x"01f00713",
00000876 => x"00a797b3",
00000877 => x"00a74a63",
00000878 => x"fc802703",
00000879 => x"00f747b3",
00000880 => x"fcf02423",
00000881 => x"00008067",
00000882 => x"fcc02703",
00000883 => x"00f747b3",
00000884 => x"fcf02623",
00000885 => x"00008067",
00000886 => x"fc000793",
00000887 => x"00a7a423",
00000888 => x"00b7a623",
00000889 => x"00008067",
00000890 => x"69617641",
00000891 => x"6c62616c",
00000892 => x"4d432065",
00000893 => x"0a3a7344",
00000894 => x"203a6820",
00000895 => x"706c6548",
00000896 => x"3a72200a",
00000897 => x"73655220",
00000898 => x"74726174",
00000899 => x"3a75200a",
00000900 => x"6c705520",
00000901 => x"0a64616f",
00000902 => x"203a7320",
00000903 => x"726f7453",
00000904 => x"6f742065",
00000905 => x"616c6620",
00000906 => x"200a6873",
00000907 => x"4c203a6c",
00000908 => x"2064616f",
00000909 => x"6d6f7266",
00000910 => x"616c6620",
00000911 => x"200a6873",
00000912 => x"45203a65",
00000913 => x"75636578",
00000914 => x"00006574",
00000915 => x"746f6f42",
00000916 => x"2e676e69",
00000917 => x"0a0a2e2e",
00000918 => x"00000000",
00000919 => x"52450a07",
00000920 => x"5f524f52",
00000921 => x"00000000",
00000922 => x"00007830",
00000923 => x"58455b0a",
00000924 => x"00002043",
00000925 => x"00000a5d",
00000926 => x"69617741",
00000927 => x"676e6974",
00000928 => x"6f656e20",
00000929 => x"32337672",
00000930 => x"6578655f",
00000931 => x"6e69622e",
00000932 => x"202e2e2e",
00000933 => x"00000000",
00000934 => x"64616f4c",
00000935 => x"2e676e69",
00000936 => x"00202e2e",
00000937 => x"00004b4f",
00000938 => x"65206f4e",
00000939 => x"75636578",
00000940 => x"6c626174",
00000941 => x"76612065",
00000942 => x"616c6961",
00000943 => x"2e656c62",
00000944 => x"00000000",
00000945 => x"74697257",
00000946 => x"00002065",
00000947 => x"74796220",
00000948 => x"74207365",
00000949 => x"5053206f",
00000950 => x"6c662049",
00000951 => x"20687361",
00000952 => x"00002040",
00000953 => x"7928203f",
00000954 => x"20296e2f",
00000955 => x"00000000",
00000956 => x"616c460a",
00000957 => x"6e696873",
00000958 => x"2e2e2e67",
00000959 => x"00000020",
00000960 => x"3c0a0a0a",
00000961 => x"454e203c",
00000962 => x"3356524f",
00000963 => x"6f422032",
00000964 => x"6f6c746f",
00000965 => x"72656461",
00000966 => x"0a3e3e20",
00000967 => x"444c420a",
00000968 => x"53203a56",
00000969 => x"32207065",
00000970 => x"30322031",
00000971 => x"480a3132",
00000972 => x"203a5657",
00000973 => x"00000020",
00000974 => x"4b4c430a",
00000975 => x"0020203a",
00000976 => x"53494d0a",
00000977 => x"00203a41",
00000978 => x"5550430a",
00000979 => x"0020203a",
00000980 => x"434f530a",
00000981 => x"0020203a",
00000982 => x"454d490a",
00000983 => x"00203a4d",
00000984 => x"74796220",
00000985 => x"40207365",
00000986 => x"00000000",
00000987 => x"454d440a",
00000988 => x"00203a4d",
00000989 => x"75410a0a",
00000990 => x"6f626f74",
00000991 => x"6920746f",
00000992 => x"7338206e",
00000993 => x"7250202e",
00000994 => x"20737365",
00000995 => x"2079656b",
00000996 => x"61206f74",
00000997 => x"74726f62",
00000998 => x"00000a2e",
00000999 => x"0000000a",
00001000 => x"726f6241",
00001001 => x"2e646574",
00001002 => x"00000a0a",
00001003 => x"444d430a",
00001004 => x"00203e3a",
00001005 => x"61766e49",
00001006 => x"2064696c",
00001007 => x"00444d43",
00001008 => x"33323130",
00001009 => x"37363534",
00001010 => x"62613938",
00001011 => x"66656463"
00000803 => x"01f55513",
00000804 => x"00008067",
00000805 => x"ff010113",
00000806 => x"00812423",
00000807 => x"01212023",
00000808 => x"00112623",
00000809 => x"00912223",
00000810 => x"00050413",
00000811 => x"00a00913",
00000812 => x"00044483",
00000813 => x"00140413",
00000814 => x"00049e63",
00000815 => x"00c12083",
00000816 => x"00812403",
00000817 => x"00412483",
00000818 => x"00012903",
00000819 => x"01010113",
00000820 => x"00008067",
00000821 => x"01249663",
00000822 => x"00d00513",
00000823 => x"f69ff0ef",
00000824 => x"00048513",
00000825 => x"f61ff0ef",
00000826 => x"fc9ff06f",
00000827 => x"ff010113",
00000828 => x"c81026f3",
00000829 => x"c0102773",
00000830 => x"c81027f3",
00000831 => x"fed79ae3",
00000832 => x"00e12023",
00000833 => x"00f12223",
00000834 => x"00012503",
00000835 => x"00412583",
00000836 => x"01010113",
00000837 => x"00008067",
00000838 => x"fe802503",
00000839 => x"01355513",
00000840 => x"00157513",
00000841 => x"00008067",
00000842 => x"00757513",
00000843 => x"0036f793",
00000844 => x"00167613",
00000845 => x"00a51513",
00000846 => x"00d79793",
00000847 => x"0015f593",
00000848 => x"00f567b3",
00000849 => x"00f61613",
00000850 => x"00c7e7b3",
00000851 => x"00959593",
00000852 => x"fa800713",
00000853 => x"00b7e7b3",
00000854 => x"00072023",
00000855 => x"1007e793",
00000856 => x"00f72023",
00000857 => x"00008067",
00000858 => x"fa800713",
00000859 => x"00072683",
00000860 => x"00757793",
00000861 => x"00100513",
00000862 => x"00f51533",
00000863 => x"00d56533",
00000864 => x"00a72023",
00000865 => x"00008067",
00000866 => x"fa800713",
00000867 => x"00072683",
00000868 => x"00757513",
00000869 => x"00100793",
00000870 => x"00a797b3",
00000871 => x"fff7c793",
00000872 => x"00d7f7b3",
00000873 => x"00f72023",
00000874 => x"00008067",
00000875 => x"faa02623",
00000876 => x"fa802783",
00000877 => x"fe07cee3",
00000878 => x"fac02503",
00000879 => x"00008067",
00000880 => x"fe802503",
00000881 => x"01055513",
00000882 => x"00157513",
00000883 => x"00008067",
00000884 => x"00100793",
00000885 => x"01f00713",
00000886 => x"00a797b3",
00000887 => x"00a74a63",
00000888 => x"fc802703",
00000889 => x"00f747b3",
00000890 => x"fcf02423",
00000891 => x"00008067",
00000892 => x"fcc02703",
00000893 => x"00f747b3",
00000894 => x"fcf02623",
00000895 => x"00008067",
00000896 => x"fc000793",
00000897 => x"00a7a423",
00000898 => x"00b7a623",
00000899 => x"00008067",
00000900 => x"69617641",
00000901 => x"6c62616c",
00000902 => x"4d432065",
00000903 => x"0a3a7344",
00000904 => x"203a6820",
00000905 => x"706c6548",
00000906 => x"3a72200a",
00000907 => x"73655220",
00000908 => x"74726174",
00000909 => x"3a75200a",
00000910 => x"6c705520",
00000911 => x"0a64616f",
00000912 => x"203a7320",
00000913 => x"726f7453",
00000914 => x"6f742065",
00000915 => x"616c6620",
00000916 => x"200a6873",
00000917 => x"4c203a6c",
00000918 => x"2064616f",
00000919 => x"6d6f7266",
00000920 => x"616c6620",
00000921 => x"200a6873",
00000922 => x"45203a65",
00000923 => x"75636578",
00000924 => x"00006574",
00000925 => x"746f6f42",
00000926 => x"2e676e69",
00000927 => x"0a0a2e2e",
00000928 => x"00000000",
00000929 => x"52450a07",
00000930 => x"5f524f52",
00000931 => x"00000000",
00000932 => x"00007830",
00000933 => x"58455b0a",
00000934 => x"00002043",
00000935 => x"00000a5d",
00000936 => x"69617741",
00000937 => x"676e6974",
00000938 => x"6f656e20",
00000939 => x"32337672",
00000940 => x"6578655f",
00000941 => x"6e69622e",
00000942 => x"202e2e2e",
00000943 => x"00000000",
00000944 => x"64616f4c",
00000945 => x"2e676e69",
00000946 => x"00202e2e",
00000947 => x"00004b4f",
00000948 => x"65206f4e",
00000949 => x"75636578",
00000950 => x"6c626174",
00000951 => x"76612065",
00000952 => x"616c6961",
00000953 => x"2e656c62",
00000954 => x"00000000",
00000955 => x"74697257",
00000956 => x"00002065",
00000957 => x"74796220",
00000958 => x"74207365",
00000959 => x"5053206f",
00000960 => x"6c662049",
00000961 => x"20687361",
00000962 => x"00002040",
00000963 => x"7928203f",
00000964 => x"20296e2f",
00000965 => x"00000000",
00000966 => x"616c460a",
00000967 => x"6e696873",
00000968 => x"2e2e2e67",
00000969 => x"00000020",
00000970 => x"3c0a0a0a",
00000971 => x"454e203c",
00000972 => x"3356524f",
00000973 => x"6f422032",
00000974 => x"6f6c746f",
00000975 => x"72656461",
00000976 => x"0a3e3e20",
00000977 => x"444c420a",
00000978 => x"4f203a56",
00000979 => x"31207463",
00000980 => x"30322037",
00000981 => x"480a3132",
00000982 => x"203a5657",
00000983 => x"00000020",
00000984 => x"4b4c430a",
00000985 => x"0020203a",
00000986 => x"53494d0a",
00000987 => x"00203a41",
00000988 => x"5550430a",
00000989 => x"0020203a",
00000990 => x"434f530a",
00000991 => x"0020203a",
00000992 => x"454d490a",
00000993 => x"00203a4d",
00000994 => x"74796220",
00000995 => x"40207365",
00000996 => x"00000000",
00000997 => x"454d440a",
00000998 => x"00203a4d",
00000999 => x"75410a0a",
00001000 => x"6f626f74",
00001001 => x"6920746f",
00001002 => x"7338206e",
00001003 => x"7250202e",
00001004 => x"20737365",
00001005 => x"2079656b",
00001006 => x"61206f74",
00001007 => x"74726f62",
00001008 => x"00000a2e",
00001009 => x"0000000a",
00001010 => x"726f6241",
00001011 => x"2e646574",
00001012 => x"00000a0a",
00001013 => x"444d430a",
00001014 => x"00203e3a",
00001015 => x"61766e49",
00001016 => x"2064696c",
00001017 => x"00444d43",
00001018 => x"33323130",
00001019 => x"37363534",
00001020 => x"62613938",
00001021 => x"66656463"
);
 
end neorv32_bootloader_image;
/neorv32/trunk/rtl/core/neorv32_cfs.vhd
1,9 → 1,9
-- #################################################################################################
-- # << NEORV32 - Custom Functions Subsystem (CFS) >> #
-- # ********************************************************************************************* #
-- # For tightly-coupled custom co-processors. Provides 32x32-bit memory-mapped registers. This is #
-- # just an "example/illustration template". Modify this file to implement your own custom design #
-- # logic. #
-- # For tightly-coupled custom co-processors. Provides 32x32-bit memory-mapped registers. #
-- # This is just an "example/illustration template". Modify this file to implement your own #
-- # custom design logic. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
62,8 → 62,6
-- clock generator --
clkgen_en_o : out std_ulogic; -- enable clock generator
clkgen_i : in std_ulogic_vector(07 downto 0); -- "clock" inputs
-- CPU state --
sleep_i : in std_ulogic; -- set if cpu is in sleep mode
-- interrupt --
irq_o : out std_ulogic; -- interrupt request
-- custom io (conduits) --
165,21 → 163,13
clkgen_en_o <= '0'; -- not used for this minimal example
 
 
-- Further Power Optimization -------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- The CFS can decide to go into low-power mode (by disabling all switching activity) when the CPU enters sleep mode.
-- The sleep_i signal is high when the CPU is in sleep mode. Any interrupt including the CFS's irq_o interrupt request signal
-- will wake up the CPU again.
 
-- sleep_i
 
 
-- Interrupt ------------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- The CFS features a single interrupt signal. This interrupt is connected to the CPU's "fast interrupt" channel 1.
-- The interrupt is single-shot. Setting the irq_o signal high for one cycle will generate an interrupt request.
-- It is recommended to implement some CFS mechanisms (like a register that needs to be written) in order to allow
-- another generation on an interrupt request (simple acknowledgement).
-- The CFS features a single interrupt signal, which is connected to the CPU's "fast interrupt" channel 1.
-- The interrupt is high-level-active. When set, the interrupt appears as "pending" in the CPU's mie register
-- ready to trigger execution of the according interrupt handler.
-- Once set, the irq_o signal **has to stay set** until explicitly acknowledged by the CPU
-- (for example by reading/writing from/to a specific CFS interface register address).
 
irq_o <= '0'; -- not used for this minimal example
 
/neorv32/trunk/rtl/core/neorv32_cpu.vhd
326,8 → 326,7
alu_i => alu_res, -- ALU result
-- data output --
rs1_o => rs1, -- operand 1
rs2_o => rs2, -- operand 2
cmp_o => comparator -- comparator status
rs2_o => rs2 -- operand 2
);
 
 
355,8 → 354,8
pc2_i => curr_pc, -- delayed PC
imm_i => imm, -- immediate
csr_i => csr_rdata, -- CSR read data
cmp_i => comparator, -- comparator status
-- data output --
cmp_o => comparator, -- comparator status
res_o => alu_res, -- ALU result
add_o => alu_add, -- address computation result
fpu_flags_o => fpu_flags, -- FPU exception flags
/neorv32/trunk/rtl/core/neorv32_cpu_alu.vhd
63,8 → 63,8
pc2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- delayed 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
cmp_i : in std_ulogic_vector(1 downto 0); -- comparator status
-- 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
add_o : out std_ulogic_vector(data_width_c-1 downto 0); -- address computation result
fpu_flags_o : out std_ulogic_vector(4 downto 0); -- FPU exception flags
75,6 → 75,11
 
architecture neorv32_cpu_cpu_rtl of neorv32_cpu_alu is
 
-- comparator --
signal cmp_opx : std_ulogic_vector(data_width_c downto 0);
signal cmp_opy : std_ulogic_vector(data_width_c downto 0);
signal cmp : std_ulogic_vector(1 downto 0); -- comparator status
 
-- operands --
signal opa, opb : std_ulogic_vector(data_width_c-1 downto 0);
 
102,8 → 107,18
 
begin
 
-- Operand Mux ----------------------------------------------------------------------------
-- Comparator Unit (for conditional branches) ---------------------------------------------
-- -------------------------------------------------------------------------------------------
cmp_opx <= (rs1_i(rs1_i'left) and (not ctrl_i(ctrl_alu_unsigned_c))) & rs1_i;
cmp_opy <= (rs2_i(rs2_i'left) and (not ctrl_i(ctrl_alu_unsigned_c))) & rs2_i;
 
cmp(cmp_equal_c) <= '1' when (rs1_i = rs2_i) else '0';
cmp(cmp_less_c) <= '1' when (signed(cmp_opx) < signed(cmp_opy)) else '0';
cmp_o <= cmp;
 
 
-- ALU Input Operand Mux ------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
opa <= pc2_i when (ctrl_i(ctrl_alu_opa_mux_c) = '1') else rs1_i; -- operand a (first ALU input operand), only required for arithmetic ops
opb <= imm_i when (ctrl_i(ctrl_alu_opb_mux_c) = '1') else rs2_i; -- operand b (second ALU input operand)
 
228,24 → 243,24
 
-- Co-Processor 0: Shifter (CPU Core ISA) --------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_cp_shifter_inst: neorv32_cpu_cp_shifter
generic map (
FAST_SHIFT_EN => FAST_SHIFT_EN -- use barrel shifter for shift operations
)
port map (
-- global control --
clk_i => clk_i, -- global clock, rising edge
rstn_i => rstn_i, -- global reset, low-active, async
ctrl_i => ctrl_i, -- main control bus
start_i => cp_start(0), -- trigger operation
-- data input --
rs1_i => rs1_i, -- rf source 1
rs2_i => rs2_i, -- rf source 2
imm_i => imm_i, -- immediate
-- result and status --
res_o => cp_result(0), -- operation result
valid_o => cp_valid(0) -- data output valid
);
neorv32_cpu_cp_shifter_inst: neorv32_cpu_cp_shifter
generic map (
FAST_SHIFT_EN => FAST_SHIFT_EN -- use barrel shifter for shift operations
)
port map (
-- global control --
clk_i => clk_i, -- global clock, rising edge
rstn_i => rstn_i, -- global reset, low-active, async
ctrl_i => ctrl_i, -- main control bus
start_i => cp_start(0), -- trigger operation
-- data input --
rs1_i => rs1_i, -- rf source 1
rs2_i => rs2_i, -- rf source 2
imm_i => imm_i, -- immediate
-- result and status --
res_o => cp_result(0), -- operation result
valid_o => cp_valid(0) -- data output valid
);
 
 
-- Co-Processor 1: Integer Multiplication/Division ('M' Extension) ------------------------
279,7 → 294,7
end generate;
 
 
-- Co-Processor 2: Bit-Manipulation Unit ('Zbb' Extension) --------------------------------
-- Co-Processor 2: Bit-Manipulation Unit ('B'/'Zbb' Extension) ----------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_cp_bitmanip_inst_true:
if (CPU_EXTENSION_RISCV_Zbb = true) generate
294,7 → 309,7
ctrl_i => ctrl_i, -- main control bus
start_i => cp_start(2), -- trigger operation
-- data input --
cmp_i => cmp_i, -- comparator status
cmp_i => cmp, -- comparator status
rs1_i => rs1_i, -- rf source 1
rs2_i => rs2_i, -- rf source 2
-- result and status --
322,7 → 337,7
ctrl_i => ctrl_i, -- main control bus
start_i => cp_start(3), -- trigger operation
-- data input --
cmp_i => cmp_i, -- comparator status
cmp_i => cmp, -- comparator status
rs1_i => rs1_i, -- rf source 1
rs2_i => rs2_i, -- rf source 2
-- result and status --
/neorv32/trunk/rtl/core/neorv32_cpu_control.vhd
184,7 → 184,6
-- instruction decoding helper logic --
type decode_aux_t is record
alu_immediate : std_ulogic;
rs1_is_r0 : std_ulogic;
is_atomic_lr : std_ulogic;
is_atomic_sc : std_ulogic;
is_float_op : std_ulogic;
233,8 → 232,6
irq_buf : std_ulogic_vector(interrupt_width_c-1 downto 0);
irq_fire : std_ulogic; -- set if there is a valid source in the interrupt buffer
exc_ack : std_ulogic; -- acknowledge all exceptions
irq_ack : std_ulogic_vector(interrupt_width_c-1 downto 0); -- acknowledge specific interrupt
irq_ack_nxt : std_ulogic_vector(interrupt_width_c-1 downto 0);
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
271,8 → 268,6
addr : std_ulogic_vector(11 downto 0); -- csr address
we : std_ulogic; -- csr write enable
we_nxt : std_ulogic;
re : std_ulogic; -- csr read enable
re_nxt : std_ulogic;
wdata : std_ulogic_vector(data_width_c-1 downto 0); -- csr write data
rdata : std_ulogic_vector(data_width_c-1 downto 0); -- csr read data
--
279,7 → 274,6
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_tw : std_ulogic; -- mstatus:TW trigger illegal instruction exception if WFI is executed outside of M-mode
--
mie_msie : std_ulogic; -- mie.MSIE: machine software interrupt enable (R/W)
mie_meie : std_ulogic; -- mie.MEIE: machine external interrupt enable (R/W)
471,6 → 465,8
clk_i => clk_i, -- clock, rising edge
rstn_i => '1', -- async reset, low-active
clear_i => ipb.clear, -- sync reset, high-active
level_o => open,
half_o => open,
-- write port --
wdata_i => ipb.wdata, -- write data
we_i => ipb.we, -- write enable
714,7 → 710,7
end if;
--
execute_engine.state <= execute_engine.state_nxt;
execute_engine.sleep <= execute_engine.sleep_nxt and (not debug_ctrl.running); -- do not execute when in debug mode
execute_engine.sleep <= execute_engine.sleep_nxt;
execute_engine.branched <= execute_engine.branched_nxt;
--
execute_engine.state_prev <= execute_engine.state;
775,6 → 771,10
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;
-- register addresses --
812,7 → 812,6
begin
-- defaults --
decode_aux.alu_immediate <= '0';
decode_aux.rs1_is_r0 <= '0';
decode_aux.is_atomic_lr <= '0';
decode_aux.is_atomic_sc <= '0';
decode_aux.is_float_op <= '0';
824,9 → 823,6
-- is immediate ALU operation? --
decode_aux.alu_immediate <= not execute_engine.i_reg(instr_opcode_msb_c-1);
 
-- is rs1 == r0? --
decode_aux.rs1_is_r0 <= not or_reduce_f(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c));
 
-- is atomic load-reservate/store-conditional? --
if (CPU_EXTENSION_RISCV_A = true) and (execute_engine.i_reg(instr_opcode_lsb_c+3 downto instr_opcode_lsb_c+2) = "11") then -- valid atomic sub-opcode
decode_aux.is_atomic_lr <= not execute_engine.i_reg(instr_funct5_lsb_c);
892,7 → 888,7
-- Execute Engine FSM Comb ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
execute_engine_fsm_comb: process(execute_engine, debug_ctrl, trap_ctrl, decode_aux, fetch_engine, cmd_issue,
csr, ctrl, csr_acc_valid, alu_idone_i, bus_d_wait_i, excl_state_i)
csr, ctrl, alu_idone_i, bus_d_wait_i, excl_state_i)
variable opcode_v : std_ulogic_vector(6 downto 0);
begin
-- arbiter defaults --
924,7 → 920,6
 
-- CSR access --
csr.we_nxt <= '0';
csr.re_nxt <= '0';
 
-- CONTROL DEFAULTS --
ctrl_nxt <= (others => '0'); -- default: all off
1080,7 → 1075,7
-- ------------------------------------------------------------
ctrl_nxt(ctrl_alu_opa_mux_c) <= '1'; -- ALU.OPA = PC (for AUIPC only)
ctrl_nxt(ctrl_alu_opb_mux_c) <= '1'; -- use IMM as ALU.OPB
ctrl_nxt(ctrl_alu_arith_c) <= alu_arith_cmd_addsub_c; -- actual ALU operation = ADD
ctrl_nxt(ctrl_alu_arith_c) <= alu_arith_cmd_addsub_c; -- ADD
ctrl_nxt(ctrl_alu_logic1_c downto ctrl_alu_logic0_c) <= alu_logic_cmd_movb_c; -- MOVB
if (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_lui_c(5)) then -- LUI
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_logic_c; -- actual ALU operation = MOVB
1127,7 → 1122,6
when opcode_syscsr_c => -- system/csr access
-- ------------------------------------------------------------
if (CPU_EXTENSION_RISCV_Zicsr = true) then
csr.re_nxt <= csr_acc_valid; -- always read CSR if valid access, only relevant for CSR-instructions
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_env_c) then -- system/environment
execute_engine.state_nxt <= SYS_ENV;
else -- CSR access
1158,14 → 1152,20
-- ------------------------------------------------------------
execute_engine.state_nxt <= SYS_WAIT; -- default
case decode_aux.sys_env_cmd is -- use a simplified input here (with permanent zeros)
when funct12_ecall_c => trap_ctrl.env_call <= '1'; -- ECALL
when funct12_ebreak_c => trap_ctrl.break_point <= '1'; -- EBREAK
when funct12_wfi_c => execute_engine.sleep_nxt <= '1'; -- WFI
when funct12_mret_c => -- MRET
when funct12_ecall_c => trap_ctrl.env_call <= '1'; -- ECALL
when funct12_ebreak_c => trap_ctrl.break_point <= '1'; -- EBREAK
when funct12_wfi_c => -- WFI
if (CPU_EXTENSION_RISCV_DEBUG = true) and
((debug_ctrl.running = '1') or (csr.dcsr_step = '1')) then -- act as 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 funct12_mret_c => -- MRET
if (csr.priv_m_mode = '1') then -- only allowed in M-mode
execute_engine.state_nxt <= TRAP_EXIT;
else
NULL;
NULL; -- executed as NOP
end if;
when funct12_dret_c => -- DRET
if (CPU_EXTENSION_RISCV_DEBUG = true) and (debug_ctrl.running = '1') then -- only allowed in debug-mode
1172,9 → 1172,9
execute_engine.state_nxt <= TRAP_EXIT;
debug_ctrl.dret <= '1';
else
NULL;
NULL; -- executed as NOP
end if;
when others => NULL; -- undefined
when others => NULL; -- undefined / execute as NOP
end case;
 
 
1183,9 → 1183,9
-- CSR write access --
case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is
when funct3_csrrw_c | funct3_csrrwi_c => -- CSRRW(I)
csr.we_nxt <= csr_acc_valid; -- always write CSR if valid access
csr.we_nxt <= '1'; -- always write CSR
when funct3_csrrs_c | funct3_csrrsi_c | funct3_csrrc_c | funct3_csrrci_c => -- CSRRS(I) / CSRRC(I)
csr.we_nxt <= (not decode_aux.rs1_is_r0) and csr_acc_valid; -- write CSR if rs1/imm is not zero and if valid access
csr.we_nxt <= or_reduce_f(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c)); -- write CSR if rs1/imm is not zero
when others => -- invalid
csr.we_nxt <= '0';
end case;
1274,8 → 1274,7
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)
-- wait for memory response / exception --
if (trap_ctrl.env_start = '1') and -- only abort if BUS EXCEPTION
((trap_ctrl.cause = trap_lma_c) or (trap_ctrl.cause = trap_lbe_c) or (trap_ctrl.cause = trap_sma_c) or (trap_ctrl.cause = trap_sbe_c)) then
if (trap_ctrl.env_start = '1') and (trap_ctrl.cause(6 downto 5) = "00") then -- only abort if SYNC EXCEPTION (from bus) / no IRQs and NOT DEBUG-MODE-related
execute_engine.state_nxt <= SYS_WAIT;
elsif (bus_d_wait_i = '0') then -- wait for bus to finish transaction
-- data write-back --
1318,23 → 1317,23
end if;
 
-- check CSR access --
csr_acc_valid <= '0'; -- default = invalid access
case csr.addr is
 
-- floating-point CSRs --
when csr_fflags_c | csr_frm_c | csr_fcsr_c =>
if (CPU_EXTENSION_RISCV_Zfinx = true) then -- FPU implemented?
csr_acc_valid <= '1'; -- full access for everyone
else
NULL;
end if;
csr_acc_valid <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zfinx); -- full access for everyone if FPU implemented
 
-- machine trap setup & handling --
when csr_mstatus_c | csr_mstatush_c | csr_misa_c | csr_mie_c | csr_mtvec_c | csr_mscratch_c | csr_mepc_c | csr_mcause_c | csr_mip_c | csr_mtval_c =>
when csr_mstatus_c | csr_mstatush_c | csr_misa_c | csr_mie_c | csr_mtvec_c | csr_mscratch_c | csr_mepc_c | csr_mcause_c | csr_mip_c | csr_mtval_c |
csr_mcycle_c | csr_mcycleh_c | csr_minstret_c | csr_minstreth_c | csr_mcountinhibit_c =>
-- NOTE: MISA, MIP 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.
-- 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
 
-- machine information registers, read-only --
when csr_mvendorid_c | csr_marchid_c | csr_mimpid_c | csr_mhartid_c | csr_mconfigptr_c =>
csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only
 
when csr_mcounteren_c | csr_menvcfg_c | csr_menvcfgh_c => -- only available if U mode is implemented
csr_acc_valid <= csr.priv_m_mode and bool_to_ulogic_f(CPU_EXTENSION_RISCV_U);
 
1349,11 → 1348,7
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 =>
if (PMP_NUM_REGIONS > 0) then
csr_acc_valid <= csr.priv_m_mode; -- M-mode only
else
NULL;
end if;
csr_acc_valid <= csr.priv_m_mode and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS > 0)); -- M-mode only
 
-- hardware performance monitors (HPM) --
when csr_mhpmcounter3_c | csr_mhpmcounter4_c | csr_mhpmcounter5_c | csr_mhpmcounter6_c | csr_mhpmcounter7_c | csr_mhpmcounter8_c | -- counter LOW
1371,40 → 1366,24
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 =>
if (HPM_NUM_CNTS > 0) then
csr_acc_valid <= csr.priv_m_mode; -- M-mode only
else
NULL;
end if;
csr_acc_valid <= csr.priv_m_mode and bool_to_ulogic_f(boolean(HPM_NUM_CNTS > 0)); -- M-mode only
 
-- counters/timers --
when csr_mcycle_c | csr_mcycleh_c | csr_minstret_c | csr_minstreth_c =>
csr_acc_valid <= csr.priv_m_mode; -- M-mode only
when csr_cycle_c | csr_cycleh_c =>
csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_cy); -- M-mode, U-mode if authorized, read-only
when csr_instret_c | csr_instreth_c =>
csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_ir); -- M-mode, U-mode if authorized, read-only
when csr_time_c | csr_timeh_c =>
csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_tm); -- M-mode, U-mode if authorized, read-only
-- user-level counters/timers --
when csr_cycle_c | csr_cycleh_c | csr_instret_c | csr_instreth_c | csr_time_c | csr_timeh_c =>
case csr.addr(1 downto 0) is
when "00" => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_cy); -- cyle[h]: M-mode, U-mode if authorized, read-only
when "01" => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_tm); -- time[h]: M-mode, U-mode if authorized, read-only
when "10" => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_ir); -- instret[h]: M-mode, U-mode if authorized, read-only
when others => csr_acc_valid <= '0';
end case;
 
when csr_mcountinhibit_c =>
csr_acc_valid <= csr.priv_m_mode; -- M-mode only
 
-- machine information registers, read-only --
when csr_mvendorid_c | csr_marchid_c | csr_mimpid_c | csr_mhartid_c | csr_mconfigptr_c =>
csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only
 
-- debug mode CSRs --
when csr_dcsr_c | csr_dpc_c | csr_dscratch0_c =>
if (CPU_EXTENSION_RISCV_DEBUG = true) then
csr_acc_valid <= debug_ctrl.running; -- access only in debug-mode
else
NULL;
end if;
csr_acc_valid <= debug_ctrl.running and bool_to_ulogic_f(CPU_EXTENSION_RISCV_DEBUG); -- access only in debug-mode
 
-- undefined / not implemented --
when others =>
NULL; -- invalid access
csr_acc_valid <= '0'; -- invalid access
end case;
end process csr_access_check;
 
1414,7 → 1393,7
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 stage
-- illegal instructions are checked in the EXECUTE state
-- the execute engine should not commit any illegal instruction
if (execute_engine.state = EXECUTE) then
-- defaults --
1587,7 → 1566,7
(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) and ((csr.priv_m_mode = '1') or (csr.mstatus_tw = '0'))) then -- WFI allowed in M-mode or if mstatus.TW=0
(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';
1646,9 → 1625,8
trap_ctrl.exc_buf <= (others => '0');
trap_ctrl.irq_buf <= (others => '0');
trap_ctrl.exc_ack <= '0';
trap_ctrl.irq_ack <= (others => '0');
trap_ctrl.env_start <= '0';
trap_ctrl.cause <= (others => def_rst_val_c);
trap_ctrl.cause <= (others => '0');
elsif rising_edge(clk_i) then
if (CPU_EXTENSION_RISCV_Zicsr = true) then
 
1694,7 → 1672,7
trap_ctrl.irq_buf(interrupt_mtime_irq_c) <= csr.mie_mtie and mtime_irq_i;
-- interrupt queue: NEORV32-specific fast interrupts
for i in 0 to 15 loop
trap_ctrl.irq_buf(interrupt_firq_0_c+i) <= csr.mie_firqe(i) and (trap_ctrl.irq_buf(interrupt_firq_0_c+i) or firq_i(i)) and (not trap_ctrl.irq_ack(interrupt_firq_0_c+i));
trap_ctrl.irq_buf(interrupt_firq_0_c+i) <= csr.mie_firqe(i) and firq_i(i);
end loop;
 
-- trap control --
1701,15 → 1679,13
if (trap_ctrl.env_start = '0') then -- no started trap handler
if (trap_ctrl.exc_fire = '1') or ((trap_ctrl.irq_fire = '1') and -- trap 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_ack <= '1'; -- clear exceptions (no ack mask: these have highest priority and are always evaluated first!)
trap_ctrl.irq_ack <= trap_ctrl.irq_ack_nxt; -- clear interrupt with ACK mask
trap_ctrl.env_start <= '1'; -- now execute engine can start trap handler
trap_ctrl.cause <= trap_ctrl.cause_nxt; -- capture source ID for program (for mcause csr)
trap_ctrl.exc_ack <= '1'; -- clear exceptions (no ack mask: these have highest priority and are always evaluated first!)
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_ack <= '0';
trap_ctrl.irq_ack <= (others => '0');
trap_ctrl.env_start <= '0';
end if;
end if;
1731,8 → 1707,7
trap_priority: process(trap_ctrl)
begin
-- defaults --
trap_ctrl.cause_nxt <= (others => '0');
trap_ctrl.irq_ack_nxt <= (others => '0'); -- used for internal IRQ queues only
trap_ctrl.cause_nxt <= (others => '0');
 
-- NOTE: Synchronous exceptions (from trap_ctrl.exc_buf) have higher priority than asynchronous
-- exceptions (from trap_ctrl.irq_buf).
1810,91 → 1785,73
-- ----------------------------------------------------------------------------------------
 
-- custom FAST interrupt requests --
-- here we do need a specific acknowledge mask for the FIRQs only since they are edge-triggered and internally buffered
 
-- interrupt: 1.16 fast interrupt channel 0 --
elsif (trap_ctrl.irq_buf(interrupt_firq_0_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq0_c;
trap_ctrl.irq_ack_nxt(interrupt_firq_0_c) <= '1';
 
-- interrupt: 1.17 fast interrupt channel 1 --
elsif (trap_ctrl.irq_buf(interrupt_firq_1_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq1_c;
trap_ctrl.irq_ack_nxt(interrupt_firq_1_c) <= '1';
 
-- interrupt: 1.18 fast interrupt channel 2 --
elsif (trap_ctrl.irq_buf(interrupt_firq_2_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq2_c;
trap_ctrl.irq_ack_nxt(interrupt_firq_2_c) <= '1';
 
-- interrupt: 1.19 fast interrupt channel 3 --
elsif (trap_ctrl.irq_buf(interrupt_firq_3_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq3_c;
trap_ctrl.irq_ack_nxt(interrupt_firq_3_c) <= '1';
 
-- interrupt: 1.20 fast interrupt channel 4 --
elsif (trap_ctrl.irq_buf(interrupt_firq_4_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq4_c;
trap_ctrl.irq_ack_nxt(interrupt_firq_4_c) <= '1';
 
-- interrupt: 1.21 fast interrupt channel 5 --
elsif (trap_ctrl.irq_buf(interrupt_firq_5_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq5_c;
trap_ctrl.irq_ack_nxt(interrupt_firq_5_c) <= '1';
 
-- interrupt: 1.22 fast interrupt channel 6 --
elsif (trap_ctrl.irq_buf(interrupt_firq_6_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq6_c;
trap_ctrl.irq_ack_nxt(interrupt_firq_6_c) <= '1';
 
-- interrupt: 1.23 fast interrupt channel 7 --
elsif (trap_ctrl.irq_buf(interrupt_firq_7_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq7_c;
trap_ctrl.irq_ack_nxt(interrupt_firq_7_c) <= '1';
 
-- interrupt: 1.24 fast interrupt channel 8 --
elsif (trap_ctrl.irq_buf(interrupt_firq_8_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq8_c;
trap_ctrl.irq_ack_nxt(interrupt_firq_8_c) <= '1';
 
-- interrupt: 1.25 fast interrupt channel 9 --
elsif (trap_ctrl.irq_buf(interrupt_firq_9_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq9_c;
trap_ctrl.irq_ack_nxt(interrupt_firq_9_c) <= '1';
 
-- interrupt: 1.26 fast interrupt channel 10 --
elsif (trap_ctrl.irq_buf(interrupt_firq_10_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq10_c;
trap_ctrl.irq_ack_nxt(interrupt_firq_10_c) <= '1';
 
-- interrupt: 1.27 fast interrupt channel 11 --
elsif (trap_ctrl.irq_buf(interrupt_firq_11_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq11_c;
trap_ctrl.irq_ack_nxt(interrupt_firq_11_c) <= '1';
 
-- interrupt: 1.28 fast interrupt channel 12 --
elsif (trap_ctrl.irq_buf(interrupt_firq_12_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq12_c;
trap_ctrl.irq_ack_nxt(interrupt_firq_12_c) <= '1';
 
-- interrupt: 1.29 fast interrupt channel 13 --
elsif (trap_ctrl.irq_buf(interrupt_firq_13_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq13_c;
trap_ctrl.irq_ack_nxt(interrupt_firq_13_c) <= '1';
 
-- interrupt: 1.30 fast interrupt channel 14 --
elsif (trap_ctrl.irq_buf(interrupt_firq_14_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq14_c;
trap_ctrl.irq_ack_nxt(interrupt_firq_14_c) <= '1';
 
-- interrupt: 1.31 fast interrupt channel 15 --
elsif (trap_ctrl.irq_buf(interrupt_firq_15_c) = '1') then
trap_ctrl.cause_nxt <= trap_firq15_c;
trap_ctrl.irq_ack_nxt(interrupt_firq_15_c) <= '1';
 
 
-- standard RISC-V interrupts --
-- these will stay asserted until explicitly ACKed by the software - no irq_ack_nxt required
 
-- interrupt: 1.11 machine external interrupt --
elsif (trap_ctrl.irq_buf(interrupt_mext_irq_c) = '1') then
1940,6 → 1897,7
-- Control and Status Registers - Write Access --------------------------------------------
-- -------------------------------------------------------------------------------------------
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 '-'. Register that reset to <def_rst_val_c> do
-- NOT actually have a real reset by default (def_rst_val_c = '-') and have to be explicitly initialized by software!
1950,7 → 1908,6
csr.mstatus_mie <= '0';
csr.mstatus_mpie <= '0';
csr.mstatus_mpp <= (others => '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;
1994,7 → 1951,7
-- --------------------------------------------------------------------------------
-- CSR access by application software
-- --------------------------------------------------------------------------------
if (csr.we = '1') then -- manual update
if (csr.we = '1') and (trap_ctrl.exc_buf(exception_iillegal_c) = '0') then -- manual update if not illegal instruction
 
-- user floating-point CSRs --
-- --------------------------------------------------------------------
2023,7 → 1980,6
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_tw <= csr.wdata(21);
end if;
end if;
-- R/W: mie - machine interrupt enable register --
2107,8 → 2063,8
if (csr.addr(11 downto 5) = csr_cnt_setup_c) then -- counter configuration CSR class
-- R/W: mcountinhibit - machine counter-inhibit register --
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
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?
csr.mcountinhibit_hpm <= csr.wdata(csr.mcountinhibit_hpm'left+3 downto 3); -- enable auto-increment of [m]hpmcounter*[h] counter
end if;
2134,8 → 2090,8
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);
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;
end if;
2181,11 → 2137,13
end if;
 
-- trap value --
case trap_ctrl.cause is
cause_v := trap_ctrl.cause;
cause_v(5) := '0'; -- bit 5 is always zero here (= normal trapping), so we do not need to check that again
case cause_v is
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; -- address of breakpoint instruction
csr.mtval <= execute_engine.last_pc(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
2257,7 → 2215,6
if (CPU_EXTENSION_RISCV_U = false) then
csr.privilege <= priv_mode_m_c;
csr.mstatus_mpp <= priv_mode_m_c;
csr.mstatus_tw <= '0';
csr.mcounteren_cy <= '0';
csr.mcounteren_tm <= '0';
csr.mcounteren_ir <= '0';
2494,7 → 2451,7
cnt_event_nxt(hpmcnt_event_cir_c) <= '1' when (execute_engine.state = EXECUTE) and (execute_engine.is_ci = '1') else '0'; -- retired compressed instruction
cnt_event_nxt(hpmcnt_event_wait_if_c) <= '1' when (fetch_engine.state = IFETCH_ISSUE) and (fetch_engine.state_prev = IFETCH_ISSUE) else '0'; -- instruction fetch memory wait cycle
cnt_event_nxt(hpmcnt_event_wait_ii_c) <= '1' when (execute_engine.state = DISPATCH) and (execute_engine.state_prev = DISPATCH) else '0'; -- instruction issue wait cycle
cnt_event_nxt(hpmcnt_event_wait_mc_c) <= '1' when (execute_engine.state = ALU_WAIT) and (execute_engine.state_prev = ALU_WAIT) else '0'; -- multi-cycle alu-operation wait cycle
cnt_event_nxt(hpmcnt_event_wait_mc_c) <= '1' when (execute_engine.state = ALU_WAIT) else '0'; -- multi-cycle alu-operation wait cycle
 
cnt_event_nxt(hpmcnt_event_load_c) <= '1' when (execute_engine.state = LOADSTORE_1) and (ctrl(ctrl_bus_rd_c) = '1') else '0'; -- load operation
cnt_event_nxt(hpmcnt_event_store_c) <= '1' when (execute_engine.state = LOADSTORE_1) and (ctrl(ctrl_bus_wr_c) = '1') else '0'; -- store operation
2514,9 → 2471,8
variable csr_addr_v : std_ulogic_vector(11 downto 0);
begin
if rising_edge(clk_i) then
csr.re <= csr.re_nxt; -- read access?
csr.rdata <= (others => '0'); -- default output
if (CPU_EXTENSION_RISCV_Zicsr = true) and (csr.re = '1') then
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);
2538,7 → 2494,6
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
csr.rdata(21) <= csr.mstatus_tw; -- TW: WFI timeout wait
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(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C); -- C CPU extension
2797,7 → 2752,7
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 not assigned yet
-- when csr_mconfigptr_c => NULL; -- mconfigptr (r/-): machine configuration pointer register, implemented but always zero
 
-- debug mode CSRs --
-- --------------------------------------------------------------------
2808,7 → 2763,7
-- undefined/unavailable --
-- --------------------------------------------------------------------
when others =>
NULL; -- not implemented, read as zero if read access is granted
NULL; -- not implemented, read as zero
 
end case;
end if;
/neorv32/trunk/rtl/core/neorv32_cpu_decompressor.vhd
116,26 → 116,24
 
when "000" => -- Illegal_instruction, C.ADDI4SPN
-- ----------------------------------------------------------------------------------------------------------
if (ci_instr16_i(12 downto 2) = "00000000000") then -- "official illegal instruction"
ci_illegal_o <= '1';
else
-- C.ADDI4SPN
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alui_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) <= "01" & ci_instr16_i(ci_rd_3_msb_c downto ci_rd_3_lsb_c);
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_subadd_c;
ci_instr32_o(instr_imm12_msb_c downto instr_imm12_lsb_c) <= (others => '0'); -- zero extend
ci_instr32_o(instr_imm12_lsb_c + 0) <= '0';
ci_instr32_o(instr_imm12_lsb_c + 1) <= '0';
ci_instr32_o(instr_imm12_lsb_c + 2) <= ci_instr16_i(6);
ci_instr32_o(instr_imm12_lsb_c + 3) <= ci_instr16_i(5);
ci_instr32_o(instr_imm12_lsb_c + 4) <= ci_instr16_i(11);
ci_instr32_o(instr_imm12_lsb_c + 5) <= ci_instr16_i(12);
ci_instr32_o(instr_imm12_lsb_c + 6) <= ci_instr16_i(7);
ci_instr32_o(instr_imm12_lsb_c + 7) <= ci_instr16_i(8);
ci_instr32_o(instr_imm12_lsb_c + 8) <= ci_instr16_i(9);
ci_instr32_o(instr_imm12_lsb_c + 9) <= ci_instr16_i(10);
end if;
-- C.ADDI4SPN
ci_instr32_o(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alui_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) <= "01" & ci_instr16_i(ci_rd_3_msb_c downto ci_rd_3_lsb_c);
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_subadd_c;
ci_instr32_o(instr_imm12_msb_c downto instr_imm12_lsb_c) <= (others => '0'); -- zero extend
ci_instr32_o(instr_imm12_lsb_c + 0) <= '0';
ci_instr32_o(instr_imm12_lsb_c + 1) <= '0';
ci_instr32_o(instr_imm12_lsb_c + 2) <= ci_instr16_i(6);
ci_instr32_o(instr_imm12_lsb_c + 3) <= ci_instr16_i(5);
ci_instr32_o(instr_imm12_lsb_c + 4) <= ci_instr16_i(11);
ci_instr32_o(instr_imm12_lsb_c + 5) <= ci_instr16_i(12);
ci_instr32_o(instr_imm12_lsb_c + 6) <= ci_instr16_i(7);
ci_instr32_o(instr_imm12_lsb_c + 7) <= ci_instr16_i(8);
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
 
when "010" | "011" => -- C.LW / C.FLW
-- ----------------------------------------------------------------------------------------------------------
173,6 → 171,7
 
when others => -- undefined
-- ----------------------------------------------------------------------------------------------------------
ci_instr32_o <= (others => '-');
ci_illegal_o <= '1';
 
end case;
233,9 → 232,6
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);
if (ci_instr16_i(ci_rd_5_msb_c downto ci_rd_5_lsb_c) = "00000") then -- HINT
ci_illegal_o <= '1';
end if;
 
when "011" => -- C.LUI / C.ADDI16SP
-- ----------------------------------------------------------------------------------------------------------
347,6 → 343,7
 
when others => -- undefined
-- ----------------------------------------------------------------------------------------------------------
ci_instr32_o <= (others => '-');
ci_illegal_o <= '1';
 
end case;
439,6 → 436,7
 
when others => -- undefined
-- ----------------------------------------------------------------------------------------------------------
ci_instr32_o <= (others => '-');
ci_illegal_o <= '1';
 
end case;
445,7 → 443,8
 
when others => -- not a compressed instruction
-- ----------------------------------------------------------------------------------------------------------
NULL;
ci_instr32_o <= (others => '-');
ci_illegal_o <= '0';
 
end case;
end process decompressor;
/neorv32/trunk/rtl/core/neorv32_cpu_regfile.vhd
4,12 → 4,12
-- # 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 reg that has to be initialized to zero by the #
-- # CPU control system. For normal operations register zero cannot be written. #
-- # 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. #
-- # #
-- # The register file uses synchronous read accesses and a *single* (multiplexed) address port #
-- # for writing and reading rs1 and a single read-only port for rs2. Therefore, the whole #
-- # register file can be mapped to a single true dual-port block RAM. #
-- # for writing and reading rd/rs1 and a single read-only port for rs2. Therefore, the whole #
-- # register file can be mapped to a single true-dual-port block RAM. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
62,8 → 62,7
alu_i : in std_ulogic_vector(data_width_c-1 downto 0); -- ALU result
-- 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
cmp_o : out std_ulogic_vector(1 downto 0) -- comparator status
rs2_o : out std_ulogic_vector(data_width_c-1 downto 0) -- operand 2
);
end neorv32_cpu_regfile;
 
81,10 → 80,6
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
 
-- comparator --
signal cmp_opx : std_ulogic_vector(data_width_c downto 0);
signal cmp_opy : std_ulogic_vector(data_width_c downto 0);
 
begin
 
-- Data Input Mux -------------------------------------------------------------------------
137,13 → 132,4
rs2_o <= rs2;
 
 
-- Comparator Unit (for conditional branches) ---------------------------------------------
-- -------------------------------------------------------------------------------------------
cmp_opx <= (rs1(rs1'left) and (not ctrl_i(ctrl_alu_unsigned_c))) & rs1;
cmp_opy <= (rs2(rs2'left) and (not ctrl_i(ctrl_alu_unsigned_c))) & rs2;
 
cmp_o(cmp_equal_c) <= '1' when (rs1 = rs2) else '0';
cmp_o(cmp_less_c) <= '1' when (signed(cmp_opx) < signed(cmp_opy)) else '0';
 
 
end neorv32_cpu_regfile_rtl;
/neorv32/trunk/rtl/core/neorv32_fifo.vhd
52,6 → 52,7
rstn_i : in std_ulogic; -- async reset, low-active
clear_i : in std_ulogic; -- sync reset, high-active
level_o : out std_ulogic_vector(index_size_f(FIFO_DEPTH) downto 0); -- fill level
half_o : out std_ulogic; -- FIFO is at least half full
-- write port --
wdata_i : in std_ulogic_vector(FIFO_WIDTH-1 downto 0); -- write data
we_i : in std_ulogic; -- write enable
83,6 → 84,8
end record;
signal fifo : fifo_t;
 
signal level_diff : std_ulogic_vector(index_size_f(FIFO_DEPTH) downto 0);
 
begin
 
-- Sanity Checks --------------------------------------------------------------------------
93,8 → 96,8
 
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
fifo.re <= re_i when (FIFO_SAFE = false) else (re_i and fifo.avail);
fifo.we <= we_i when (FIFO_SAFE = false) else (we_i and fifo.free);
fifo.re <= re_i when (FIFO_SAFE = false) else (re_i and fifo.avail); -- read only if data available
fifo.we <= we_i when (FIFO_SAFE = false) else (we_i and fifo.free); -- write only if space left
 
 
-- FIFO Control ---------------------------------------------------------------------------
126,7 → 129,8
fifo.empty <= '1' when (fifo.r_pnt(fifo.r_pnt'left) = fifo.w_pnt(fifo.w_pnt'left)) and (fifo.match = '1') else '0';
fifo.free <= not fifo.full;
fifo.avail <= not fifo.empty;
fifo.level <= std_ulogic_vector(to_unsigned(FIFO_DEPTH, fifo.level'length)) when (fifo.full = '1') else std_ulogic_vector(unsigned(fifo.w_pnt) - unsigned(fifo.r_pnt));
level_diff <= std_ulogic_vector(unsigned(fifo.w_pnt) - unsigned(fifo.r_pnt));
fifo.level <= std_ulogic_vector(to_unsigned(FIFO_DEPTH, fifo.level'length)) when (fifo.full = '1') else level_diff;
 
-- status output --
level_o <= fifo.level;
133,7 → 137,17
free_o <= fifo.free;
avail_o <= fifo.avail;
 
fifo_half_level:
if (FIFO_DEPTH > 1) generate
half_o <= level_diff(level_diff'left-1) or fifo.full;
end generate;
 
fifo_half_level_simple:
if (FIFO_DEPTH = 1) generate
half_o <= fifo.full;
end generate;
 
 
-- FIFO Memory ----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
fifo_memory_write: process(clk_i)
161,12 → 175,10
fifo_memory_read: process(clk_i)
begin
if rising_edge(clk_i) then
if (fifo.re = '1') then
if (FIFO_DEPTH = 1) then
rdata_o <= fifo.datas;
else
rdata_o <= fifo.data(to_integer(unsigned(fifo.r_pnt(fifo.r_pnt'left-1 downto 0))));
end if;
if (FIFO_DEPTH = 1) then
rdata_o <= fifo.datas;
else
rdata_o <= fifo.data(to_integer(unsigned(fifo.r_pnt(fifo.r_pnt'left-1 downto 0))));
end if;
end if;
end process fifo_memory_read;
/neorv32/trunk/rtl/core/neorv32_mtime.vhd
169,7 → 169,7
cmp_sync: process(clk_i)
begin
if rising_edge(clk_i) then
cmp_lo_ge_ff <= cmp_lo_ge;
cmp_lo_ge_ff <= cmp_lo_ge; -- there is one cycle delay between low (earlier) and high (later) word
irq_o <= cmp_hi_gt or (cmp_hi_eq and cmp_lo_ge_ff);
end if;
end process cmp_sync;
/neorv32/trunk/rtl/core/neorv32_neoled.vhd
13,8 → 13,7
-- # configured using the ctrl_t_0h_*_c and ctrl_t_1h_*_c bits, respectively. 32-bit transfers #
-- # (for RGBW modules) and 24-bit transfers (for RGB modules) are supported via ctrl_mode__c. #
-- # #
-- # The device features a TX buffer (FIFO) with <FIFO_DEPTH> entries. An IRQ is triggered if the #
-- # FIFO falls below "half-full" fill level. #
-- # The device features a TX buffer (FIFO) with <FIFO_DEPTH> entries with configurable interrupt. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
90,41 → 89,42
signal rden : std_ulogic; -- read enable
 
-- Control register bits --
constant ctrl_enable_c : natural := 0; -- r/w: module enable
constant ctrl_mode_c : natural := 1; -- r/w: 0 = 24-bit RGB mode, 1 = 32-bit RGBW mode
constant ctrl_strobe_c : natural := 2; -- r/w: 0 = send normal data, 1 = send LED strobe command (RESET) on data write
constant ctrl_enable_c : natural := 0; -- r/w: module enable
constant ctrl_mode_c : natural := 1; -- r/w: 0 = 24-bit RGB mode, 1 = 32-bit RGBW mode
constant ctrl_strobe_c : natural := 2; -- r/w: 0 = send normal data, 1 = send LED strobe command (RESET) on data write
--
constant ctrl_clksel0_c : natural := 3; -- r/w: prescaler select bit 0
constant ctrl_clksel1_c : natural := 4; -- r/w: prescaler select bit 1
constant ctrl_clksel2_c : natural := 5; -- r/w: prescaler select bit 2
constant ctrl_clksel0_c : natural := 3; -- r/w: prescaler select bit 0
constant ctrl_clksel1_c : natural := 4; -- r/w: prescaler select bit 1
constant ctrl_clksel2_c : natural := 5; -- r/w: prescaler select bit 2
--
constant ctrl_bufs_0_c : natural := 6; -- r/-: log2(FIFO_DEPTH) bit 0
constant ctrl_bufs_1_c : natural := 7; -- r/-: log2(FIFO_DEPTH) bit 1
constant ctrl_bufs_2_c : natural := 8; -- r/-: log2(FIFO_DEPTH) bit 2
constant ctrl_bufs_3_c : natural := 9; -- r/-: log2(FIFO_DEPTH) bit 3
constant ctrl_bufs_0_c : natural := 6; -- r/-: log2(FIFO_DEPTH) bit 0
constant ctrl_bufs_1_c : natural := 7; -- r/-: log2(FIFO_DEPTH) bit 1
constant ctrl_bufs_2_c : natural := 8; -- r/-: log2(FIFO_DEPTH) bit 2
constant ctrl_bufs_3_c : natural := 9; -- r/-: log2(FIFO_DEPTH) bit 3
--
constant ctrl_t_tot_0_c : natural := 10; -- r/w: pulse-clock ticks per total period bit 0
constant ctrl_t_tot_1_c : natural := 11; -- r/w: pulse-clock ticks per total period bit 1
constant ctrl_t_tot_2_c : natural := 12; -- r/w: pulse-clock ticks per total period bit 2
constant ctrl_t_tot_3_c : natural := 13; -- r/w: pulse-clock ticks per total period bit 3
constant ctrl_t_tot_4_c : natural := 14; -- r/w: pulse-clock ticks per total period bit 4
constant ctrl_t_tot_0_c : natural := 10; -- r/w: pulse-clock ticks per total period bit 0
constant ctrl_t_tot_1_c : natural := 11; -- r/w: pulse-clock ticks per total period bit 1
constant ctrl_t_tot_2_c : natural := 12; -- r/w: pulse-clock ticks per total period bit 2
constant ctrl_t_tot_3_c : natural := 13; -- r/w: pulse-clock ticks per total period bit 3
constant ctrl_t_tot_4_c : natural := 14; -- r/w: pulse-clock ticks per total period bit 4
--
constant ctrl_t_0h_0_c : natural := 15; -- r/w: pulse-clock ticks per ZERO high-time bit 0
constant ctrl_t_0h_1_c : natural := 16; -- r/w: pulse-clock ticks per ZERO high-time bit 1
constant ctrl_t_0h_2_c : natural := 17; -- r/w: pulse-clock ticks per ZERO high-time bit 2
constant ctrl_t_0h_3_c : natural := 18; -- r/w: pulse-clock ticks per ZERO high-time bit 3
constant ctrl_t_0h_4_c : natural := 19; -- r/w: pulse-clock ticks per ZERO high-time bit 4
constant ctrl_t_0h_0_c : natural := 15; -- r/w: pulse-clock ticks per ZERO high-time bit 0
constant ctrl_t_0h_1_c : natural := 16; -- r/w: pulse-clock ticks per ZERO high-time bit 1
constant ctrl_t_0h_2_c : natural := 17; -- r/w: pulse-clock ticks per ZERO high-time bit 2
constant ctrl_t_0h_3_c : natural := 18; -- r/w: pulse-clock ticks per ZERO high-time bit 3
constant ctrl_t_0h_4_c : natural := 19; -- r/w: pulse-clock ticks per ZERO high-time bit 4
--
constant ctrl_t_1h_0_c : natural := 20; -- r/w: pulse-clock ticks per ONE high-time bit 0
constant ctrl_t_1h_1_c : natural := 21; -- r/w: pulse-clock ticks per ONE high-time bit 1
constant ctrl_t_1h_2_c : natural := 22; -- r/w: pulse-clock ticks per ONE high-time bit 2
constant ctrl_t_1h_3_c : natural := 23; -- r/w: pulse-clock ticks per ONE high-time bit 3
constant ctrl_t_1h_4_c : natural := 24; -- r/w: pulse-clock ticks per ONE high-time bit 4
constant ctrl_t_1h_0_c : natural := 20; -- r/w: pulse-clock ticks per ONE high-time bit 0
constant ctrl_t_1h_1_c : natural := 21; -- r/w: pulse-clock ticks per ONE high-time bit 1
constant ctrl_t_1h_2_c : natural := 22; -- r/w: pulse-clock ticks per ONE high-time bit 2
constant ctrl_t_1h_3_c : natural := 23; -- r/w: pulse-clock ticks per ONE high-time bit 3
constant ctrl_t_1h_4_c : natural := 24; -- r/w: pulse-clock ticks per ONE high-time bit 4
--
constant ctrl_tx_empty_c : natural := 28; -- r/-: TX FIFO is empty
constant ctrl_tx_half_c : natural := 29; -- r/-: TX FIFO is at least half-full
constant ctrl_tx_full_c : natural := 30; -- r/-: TX FIFO is full
constant ctrl_tx_busy_c : natural := 31; -- r/-: serial TX engine busy when set
constant ctrl_irq_conf_c : natural := 27; -- r/w: interrupt config: 1=IRQ when buffer is empty, 0=IRQ when buffer is half-empty
constant ctrl_tx_empty_c : natural := 28; -- r/-: TX FIFO is empty
constant ctrl_tx_half_c : natural := 29; -- r/-: TX FIFO is at least half-full
constant ctrl_tx_full_c : natural := 30; -- r/-: TX FIFO is full
constant ctrl_tx_busy_c : natural := 31; -- r/-: serial TX engine busy when set
 
-- control register --
type ctrl_t is record
132,6 → 132,7
mode : std_ulogic;
strobe : std_ulogic;
clk_prsc : std_ulogic_vector(2 downto 0);
irq_conf : std_ulogic;
-- pulse config --
t_total : std_ulogic_vector(4 downto 0);
t0_high : std_ulogic_vector(4 downto 0);
141,16 → 142,14
 
-- transmission buffer --
type tx_buffer_t is record
we : std_ulogic; -- write enable
re : std_ulogic; -- read enable
clear : std_ulogic; -- sync reset, high-active
level : std_ulogic_vector(index_size_f(FIFO_DEPTH) downto 0);
wdata : std_ulogic_vector(31+2 downto 0); -- write data (excluding mode)
rdata : std_ulogic_vector(31+2 downto 0); -- read data (including mode)
avail : std_ulogic; -- data available?
free : std_ulogic; -- free entry available?
half : std_ulogic; -- half full
half_ff : std_ulogic;
we : std_ulogic; -- write enable
re : std_ulogic; -- read enable
clear : std_ulogic; -- sync reset, high-active
wdata : std_ulogic_vector(31+2 downto 0); -- write data (excluding mode)
rdata : std_ulogic_vector(31+2 downto 0); -- read data (including mode)
avail : std_ulogic; -- data available?
free : std_ulogic; -- free entry available?
half : std_ulogic; -- half full
end record;
signal tx_buffer : tx_buffer_t;
 
204,6 → 203,7
ctrl.mode <= data_i(ctrl_mode_c);
ctrl.strobe <= data_i(ctrl_strobe_c);
ctrl.clk_prsc <= data_i(ctrl_clksel2_c downto ctrl_clksel0_c);
ctrl.irq_conf <= data_i(ctrl_irq_conf_c);
ctrl.t_total <= data_i(ctrl_t_tot_4_c downto ctrl_t_tot_0_c);
ctrl.t0_high <= data_i(ctrl_t_0h_4_c downto ctrl_t_0h_0_c);
ctrl.t1_high <= data_i(ctrl_t_1h_4_c downto ctrl_t_1h_0_c);
216,6 → 216,7
data_o(ctrl_mode_c) <= ctrl.mode;
data_o(ctrl_strobe_c) <= ctrl.strobe;
data_o(ctrl_clksel2_c downto ctrl_clksel0_c) <= ctrl.clk_prsc;
data_o(ctrl_irq_conf_c) <= ctrl.irq_conf or bool_to_ulogic_f(boolean(FIFO_DEPTH = 1)); -- tie to one if FIFO_DEPTH is 1
data_o(ctrl_bufs_3_c downto ctrl_bufs_0_c) <= std_ulogic_vector(to_unsigned(index_size_f(FIFO_DEPTH), 4));
data_o(ctrl_t_tot_4_c downto ctrl_t_tot_0_c) <= ctrl.t_total;
data_o(ctrl_t_0h_4_c downto ctrl_t_0h_0_c) <= ctrl.t0_high;
243,8 → 244,19
irq_generator: process(clk_i)
begin
if rising_edge(clk_i) then
tx_buffer.half_ff <= tx_buffer.half;
irq_o <= ctrl.enable and tx_buffer.half and (not tx_buffer.half_ff); -- FIFO _becomes_ half-full
if (ctrl.enable = '0') then
irq_o <= '0'; -- no interrupt if unit is disabled
else
if (FIFO_DEPTH = 1) then
irq_o <= tx_buffer.free; -- fire IRQ if FIFO is empty
else
if (ctrl.irq_conf = '0') then -- fire IRQ if FIFO is less than half-full
irq_o <= not tx_buffer.half;
else -- fire IRQ if FIFO is empty
irq_o <= tx_buffer.free;
end if;
end if;
end if;
end if;
end process irq_generator;
 
263,7 → 275,8
clk_i => clk_i, -- clock, rising edge
rstn_i => '1', -- async reset, low-active
clear_i => tx_buffer.clear, -- sync reset, high-active
level_o => tx_buffer.level, -- fill level
level_o => open, -- fill level
half_o => tx_buffer.half, -- FIFO is at least half full
-- write port --
wdata_i => tx_buffer.wdata, -- write data
we_i => tx_buffer.we, -- write enable
274,8 → 287,8
avail_o => tx_buffer.avail -- data available when set
);
 
-- FIFO half-full? --
tx_buffer.half <= '1' when (unsigned(tx_buffer.level) >= to_unsigned(cond_sel_natural_f(boolean(FIFO_DEPTH > 1), FIFO_DEPTH/2, 1), tx_buffer.level'length)) else '0';
-- try to get new TX data --
tx_buffer.re <= '1' when (serial.state = S_IDLE) else '0';
 
 
-- Serial TX Engine -----------------------------------------------------------------------
322,16 → 335,17
serial.sreg <= serial.sreg(serial.sreg'left-1 downto 0) & '0'; -- shift left by one position (MSB-first)
serial.bit_cnt <= std_ulogic_vector(unsigned(serial.bit_cnt) - 1);
serial.pulse_cnt <= (others => '0');
if (serial.next_bit = '0') then -- send zero-bit
serial.t_high <= ctrl.t0_high;
else -- send one-bit
serial.t_high <= ctrl.t1_high;
end if;
if (serial.bit_cnt = "000000") then -- all done?
serial.state <= S_IDLE;
else -- check current data MSB
if (serial.next_bit = '0') then -- send zero-bit
serial.t_high <= ctrl.t0_high;
else -- send one-bit
serial.t_high <= ctrl.t1_high;
end if;
serial.tx_out <= '0';
serial.state <= S_IDLE;
else -- send current data MSB
serial.tx_out <= '1';
serial.state <= S_PULSE; -- transmit single pulse
serial.tx_out <= '1';
end if;
 
when S_PULSE => -- send pulse with specific duty cycle
381,11 → 395,8
-- SREG's TX data: bit 23 for RGB mode (24-bit), bit 31 for RGBW mode (32-bit) --
serial.next_bit <= serial.sreg(23) when (serial.mode = '0') else serial.sreg(31);
 
-- get new TX data --
tx_buffer.re <= '1' when (serial.state = S_IDLE) and (tx_buffer.avail = '1') else '0';
 
-- TX engine status --
serial.busy <= '0' when (serial.state = S_IDLE) or (ctrl.enable = '0') else '1';
serial.busy <= '0' when (serial.state = S_IDLE) else '1';
 
 
end neorv32_neoled_rtl;
/neorv32/trunk/rtl/core/neorv32_package.vhd
64,7 → 64,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"01060100"; -- no touchy!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01060202"; -- no touchy!
constant archid_c : natural := 19; -- official NEORV32 architecture ID - hands off!
 
-- External Interface Types ---------------------------------------------------------------
949,7 → 949,11
IO_GPIO_EN : boolean := false; -- implement general purpose input/output port unit (GPIO)?
IO_MTIME_EN : boolean := false; -- implement machine system timer (MTIME)?
IO_UART0_EN : boolean := false; -- implement primary universal asynchronous receiver/transmitter (UART0)?
IO_UART0_RX_FIFO : natural := 1; -- RX fifo depth, has to be a power of two, min 1
IO_UART0_TX_FIFO : natural := 1; -- TX fifo depth, has to be a power of two, min 1
IO_UART1_EN : boolean := false; -- implement secondary universal asynchronous receiver/transmitter (UART1)?
IO_UART1_RX_FIFO : natural := 1; -- RX fifo depth, has to be a power of two, min 1
IO_UART1_TX_FIFO : natural := 1; -- TX fifo depth, has to be a power of two, min 1
IO_SPI_EN : boolean := false; -- implement serial peripheral interface (SPI)?
IO_TWI_EN : boolean := false; -- implement two-wire interface (TWI)?
IO_PWM_NUM_CH : natural := 0; -- number of PWM channels to implement (0..60); 0 = disabled
1200,8 → 1204,7
alu_i : in std_ulogic_vector(data_width_c-1 downto 0); -- ALU result
-- 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
cmp_o : out std_ulogic_vector(1 downto 0) -- comparator status
rs2_o : out std_ulogic_vector(data_width_c-1 downto 0) -- operand 2
);
end component;
 
1229,8 → 1232,8
pc2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- delayed 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
cmp_i : in std_ulogic_vector(1 downto 0); -- comparator status
-- 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
add_o : out std_ulogic_vector(data_width_c-1 downto 0); -- address computation result
fpu_flags_o : out std_ulogic_vector(4 downto 0); -- FPU exception flags
1621,7 → 1624,9
-- -------------------------------------------------------------------------------------------
component neorv32_uart
generic (
UART_PRIMARY : boolean -- true = primary UART (UART0), false = secondary UART (UART1)
UART_PRIMARY : boolean; -- true = primary UART (UART0), false = secondary UART (UART1)
UART_RX_FIFO : natural; -- RX fifo depth, has to be a power of two, min 1
UART_TX_FIFO : natural -- TX fifo depth, has to be a power of two, min 1
);
port (
-- host access --
1801,8 → 1806,6
-- clock generator --
clkgen_en_o : out std_ulogic; -- enable clock generator
clkgen_i : in std_ulogic_vector(07 downto 0); -- "clock" inputs
-- CPU state --
sleep_i : in std_ulogic; -- set if cpu is in sleep mode
-- interrupt --
irq_o : out std_ulogic; -- interrupt request
-- custom io (conduit) --
1970,6 → 1973,7
rstn_i : in std_ulogic; -- async reset, low-active
clear_i : in std_ulogic; -- sync reset, high-active
level_o : out std_ulogic_vector(index_size_f(FIFO_DEPTH) downto 0); -- fill level
half_o : out std_ulogic; -- FIFO is at least half full
-- write port --
wdata_i : in std_ulogic_vector(FIFO_WIDTH-1 downto 0); -- write data
we_i : in std_ulogic; -- write enable
2132,11 → 2136,9
variable tmp_v : std_ulogic;
begin
tmp_v := '0';
if (a'low < a'high) then -- not null range?
for i in a'low to a'high loop
tmp_v := tmp_v or a(i);
end loop; -- i
end if;
for i in a'range loop
tmp_v := tmp_v or a(i);
end loop; -- i
return tmp_v;
end function or_reduce_f;
 
2146,11 → 2148,9
variable tmp_v : std_ulogic;
begin
tmp_v := '1';
if (a'low < a'high) then -- not null range?
for i in a'low to a'high loop
tmp_v := tmp_v and a(i);
end loop; -- i
end if;
for i in a'range loop
tmp_v := tmp_v and a(i);
end loop; -- i
return tmp_v;
end function and_reduce_f;
 
2160,11 → 2160,9
variable tmp_v : std_ulogic;
begin
tmp_v := '0';
if (a'low < a'high) then -- not null range?
for i in a'low to a'high loop
tmp_v := tmp_v xor a(i);
end loop; -- i
end if;
for i in a'range loop
tmp_v := tmp_v xor a(i);
end loop; -- i
return tmp_v;
end function xor_reduce_f;
 
/neorv32/trunk/rtl/core/neorv32_slink.vhd
95,17 → 95,30
--
constant ctrl_en_c : natural := 31; -- r/w: global enable
 
-- interrupt configuration register bits --
constant irq_rx_en_lsb_c : natural := 0; -- r/w: enable RX interrupt for link 0..7
constant irq_rx_en_msb_c : natural := 7;
--
constant irq_rx_mode_lsb_c : natural := 8; -- r/w: RX IRQ mode: 0=FIFO at least half-full; 1=FIFO not empty
constant irq_rx_mode_msb_c : natural := 15;
--
constant irq_tx_en_lsb_c : natural := 16; -- r/w: enable TX interrupt for link 0..7
constant irq_tx_en_msb_c : natural := 23;
--
constant irq_tx_mode_lsb_c : natural := 24; -- r/w: TX IRQ mode: 0=FIFO less than half-full; 1=FIFO not full
constant irq_tx_mode_msb_c : natural := 31;
 
-- status register bits --
constant status_rx_avail_lsb_c : natural := 0; -- r/-: set if TX link 0..7 is ready to send
constant status_rx_avail_lsb_c : natural := 0; -- r/-: set if RX link 0..7 FIFO is NOT empty
constant status_rx_avail_msb_c : natural := 7;
--
constant status_tx_free_lsb_c : natural := 8; -- r/-: set if RX link 0..7 data available
constant status_tx_free_lsb_c : natural := 8; -- r/-: set if TX link 0..7 FIFO is NOT full
constant status_tx_free_msb_c : natural := 15;
--
constant status_rx_half_lsb_c : natural := 16; -- r/-: set if TX link 0..7 FIFO fill-level is >= half-full
constant status_rx_half_lsb_c : natural := 16; -- r/-: set if RX link 0..7 FIFO fill-level is >= half-full
constant status_rx_half_msb_c : natural := 23;
--
constant status_tx_half_lsb_c : natural := 24; -- r/-: set if RX link 0..7 FIFO fill-level is > half-full
constant status_tx_half_lsb_c : natural := 24; -- r/-: set if TX link 0..7 FIFO fill-level is > half-full
constant status_tx_half_msb_c : natural := 31;
 
-- bus access control --
117,34 → 130,24
-- control register --
signal enable : std_ulogic; -- global enable
 
-- IRQ configuration register --
signal irq_rx_en : std_ulogic_vector(7 downto 0);
signal irq_rx_mode : std_ulogic_vector(7 downto 0);
signal irq_tx_en : std_ulogic_vector(7 downto 0);
signal irq_tx_mode : std_ulogic_vector(7 downto 0);
 
-- stream link fifo interface --
type fifo_data_t is array (0 to 7) of std_ulogic_vector(31 downto 0);
type fifo_rx_level_t is array (0 to 7) of std_ulogic_vector(index_size_f(SLINK_RX_FIFO) downto 0);
type fifo_tx_level_t is array (0 to 7) of std_ulogic_vector(index_size_f(SLINK_TX_FIFO) downto 0);
signal rx_fifo_rdata : fifo_data_t;
signal rx_fifo_level : fifo_rx_level_t;
signal tx_fifo_level : fifo_tx_level_t;
signal fifo_clear : std_ulogic;
signal link_sel : std_ulogic_vector(7 downto 0);
signal tx_fifo_we, rx_fifo_re : std_ulogic_vector(7 downto 0);
signal rx_fifo_avail, rx_fifo_avail_ff : std_ulogic_vector(7 downto 0);
signal tx_fifo_free, tx_fifo_free_ff : std_ulogic_vector(7 downto 0);
signal rx_fifo_half, rx_fifo_half_ff : std_ulogic_vector(7 downto 0);
signal tx_fifo_half, tx_fifo_half_ff : std_ulogic_vector(7 downto 0);
signal rx_fifo_rdata : fifo_data_t;
signal fifo_clear : std_ulogic;
signal link_sel : std_ulogic_vector(7 downto 0);
signal tx_fifo_we : std_ulogic_vector(7 downto 0);
signal rx_fifo_re : std_ulogic_vector(7 downto 0);
signal rx_fifo_avail : std_ulogic_vector(7 downto 0);
signal tx_fifo_free : std_ulogic_vector(7 downto 0);
signal rx_fifo_half : std_ulogic_vector(7 downto 0);
signal tx_fifo_half : std_ulogic_vector(7 downto 0);
 
-- interrupt controller --
type irq_t is record
rx_pending : std_ulogic;
rx_pending_ff : std_ulogic;
rx_fire : std_ulogic;
tx_pending : std_ulogic;
tx_pending_ff : std_ulogic;
tx_fire : std_ulogic;
wr_ack : std_ulogic;
rd_ack : std_ulogic;
end record;
signal irq : irq_t;
 
begin
 
-- Sanity Checks --------------------------------------------------------------------------
174,15 → 177,22
begin
if rising_edge(clk_i) then
-- write access --
irq.wr_ack <= '0';
ack_write <= '0';
ack_write <= '0';
if (acc_en = '1') and (wren_i = '1') then
if (addr(5) = '0') then -- control/status
if (addr(4) = '0') then -- control register
if (addr(5) = '0') then -- control/status/irq
if (addr(4 downto 3) = "00") then -- control register
enable <= data_i(ctrl_en_c);
else -- status register
irq.wr_ack <= '1';
end if;
if (addr(4 downto 3) = "01") then -- IRQ configuration register
for i in 0 to SLINK_NUM_RX-1 loop
irq_rx_en(i) <= data_i(i + irq_rx_en_lsb_c);
irq_rx_mode(i) <= data_i(i + irq_rx_mode_lsb_c);
end loop;
for i in 0 to SLINK_NUM_TX-1 loop
irq_tx_en(i) <= data_i(i + irq_tx_en_lsb_c);
irq_tx_mode(i) <= data_i(i + irq_tx_mode_lsb_c);
end loop;
end if;
ack_write <= '1';
else -- TX links
ack_write <= or_reduce_f(link_sel and tx_fifo_free);
190,25 → 200,35
end if;
 
-- read access --
irq.rd_ack <= '0';
data_o <= (others => '0');
ack_read <= '0';
data_o <= (others => '0');
ack_read <= '0';
if (acc_en = '1') and (rden_i = '1') then
if (addr(5) = '0') then -- control/status registers
ack_read <= '1';
if (addr(4) = '0') then -- control register
data_o(ctrl_rx_num_msb_c downto ctrl_rx_num_lsb_c) <= std_ulogic_vector(to_unsigned(SLINK_NUM_RX, 4));
data_o(ctrl_tx_num_msb_c downto ctrl_tx_num_lsb_c) <= std_ulogic_vector(to_unsigned(SLINK_NUM_TX, 4));
data_o(ctrl_rx_size_msb_c downto ctrl_rx_size_lsb_c) <= std_ulogic_vector(to_unsigned(index_size_f(SLINK_RX_FIFO), 4));
data_o(ctrl_tx_size_msb_c downto ctrl_tx_size_lsb_c) <= std_ulogic_vector(to_unsigned(index_size_f(SLINK_TX_FIFO), 4));
data_o(ctrl_en_c) <= enable;
else -- fifo status register
data_o(status_rx_avail_msb_c downto status_rx_avail_lsb_c) <= rx_fifo_avail;
data_o(status_tx_free_msb_c downto status_tx_free_lsb_c) <= tx_fifo_free;
data_o(status_rx_half_msb_c downto status_rx_half_lsb_c) <= rx_fifo_half;
data_o(status_tx_half_msb_c downto status_tx_half_lsb_c) <= tx_fifo_half;
irq.rd_ack <= '1';
end if;
case addr(4 downto 3) is
when "00" => -- control register
data_o(ctrl_rx_num_msb_c downto ctrl_rx_num_lsb_c) <= std_ulogic_vector(to_unsigned(SLINK_NUM_RX, 4));
data_o(ctrl_tx_num_msb_c downto ctrl_tx_num_lsb_c) <= std_ulogic_vector(to_unsigned(SLINK_NUM_TX, 4));
data_o(ctrl_rx_size_msb_c downto ctrl_rx_size_lsb_c) <= std_ulogic_vector(to_unsigned(index_size_f(SLINK_RX_FIFO), 4));
data_o(ctrl_tx_size_msb_c downto ctrl_tx_size_lsb_c) <= std_ulogic_vector(to_unsigned(index_size_f(SLINK_TX_FIFO), 4));
data_o(ctrl_en_c) <= enable;
when "01" => -- IRQ configuration register
for i in 0 to SLINK_NUM_RX-1 loop
data_o(irq_rx_en_lsb_c + i) <= irq_rx_en(i);
data_o(irq_rx_mode_lsb_c + i) <= irq_rx_mode(i) or bool_to_ulogic_f(boolean(SLINK_RX_FIFO = 1)); -- tie to one if SLINK_RX_FIFO is 1
end loop;
for i in 0 to SLINK_NUM_TX-1 loop
data_o(irq_tx_en_lsb_c + i) <= irq_tx_en(i);
data_o(irq_tx_mode_lsb_c + i) <= irq_tx_mode(i) or bool_to_ulogic_f(boolean(SLINK_TX_FIFO = 1)); -- tie to one if SLINK_TX_FIFO is 1
end loop;
when "10" | "11" => -- fifo status register
data_o(status_rx_avail_msb_c downto status_rx_avail_lsb_c) <= rx_fifo_avail;
data_o(status_tx_free_msb_c downto status_tx_free_lsb_c) <= tx_fifo_free;
data_o(status_rx_half_msb_c downto status_rx_half_lsb_c) <= rx_fifo_half;
data_o(status_tx_half_msb_c downto status_tx_half_lsb_c) <= tx_fifo_half;
when others =>
data_o <= (others => '0');
end case;
else -- RX links
data_o <= rx_fifo_rdata(to_integer(unsigned(addr(4 downto 2))));
ack_read <= or_reduce_f(link_sel and rx_fifo_avail);
224,75 → 244,52
fifo_clear <= not enable;
 
 
-- FIFO Level Monitoring ------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
level_monitor: process(rx_fifo_level, tx_fifo_level)
begin
-- RX FIFO --
rx_fifo_half <= (others => '0');
for i in 0 to SLINK_NUM_RX-1 loop
if (unsigned(rx_fifo_level(i)) >= to_unsigned(cond_sel_natural_f(boolean(SLINK_RX_FIFO > 1), SLINK_RX_FIFO/2, 1), rx_fifo_level(i)'length)) then
rx_fifo_half(i) <= '1';
end if;
end loop;
-- TX FIFO --
tx_fifo_half <= (others => '0');
for i in 0 to SLINK_NUM_TX-1 loop
if (unsigned(tx_fifo_level(i)) >= to_unsigned(cond_sel_natural_f(boolean(SLINK_TX_FIFO > 1), SLINK_TX_FIFO/2, 1), tx_fifo_level(i)'length)) then
tx_fifo_half(i) <= '1';
end if;
end loop;
end process level_monitor;
 
 
-- Interrupt Generator --------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
irq_arbiter: process(clk_i)
variable rx_tmp_v : std_ulogic_vector(SLINK_NUM_RX-1 downto 0);
variable tx_tmp_v : std_ulogic_vector(SLINK_NUM_TX-1 downto 0);
begin
if rising_edge(clk_i) then
if (enable = '0') then
irq.rx_pending <= '0';
irq.tx_pending <= '0';
if (enable = '0') then -- no interrupts if unit is disabled
irq_rx_o <= '0';
irq_tx_o <= '0';
else
-- RX IRQ --
if (irq.rx_pending = '0') then
irq.rx_pending <= irq.rx_fire;
elsif (irq.rd_ack = '1') or (irq.wr_ack = '1') then
irq.rx_pending <= '0';
 
-- RX interrupt --
if (SLINK_RX_FIFO = 1) then
irq_rx_o <= or_reduce_f(irq_rx_en and rx_fifo_avail); -- fire if any RX_FIFO is not empty
else
rx_tmp_v := (others => '0');
for i in 0 to SLINK_NUM_RX-1 loop
if (irq_rx_mode(i) = '0') then -- fire if any RX_FIFO is at least half-full
rx_tmp_v(i) := rx_fifo_half(i);
else -- fire if any RX_FIFO is not empty (= data available)
rx_tmp_v(i) := rx_fifo_avail(i);
end if;
end loop;
irq_rx_o <= or_reduce_f(irq_rx_en and rx_tmp_v);
end if;
-- TX IRQ --
if (irq.tx_pending = '0') then
irq.tx_pending <= irq.tx_fire;
elsif (irq.rd_ack = '1') or (irq.wr_ack = '1') then
irq.tx_pending <= '0';
 
-- TX interrupt --
if (SLINK_TX_FIFO = 1) then
irq_tx_o <= or_reduce_f(irq_tx_en and tx_fifo_free); -- fire if any TX_FIFO is not full
else
tx_tmp_v := (others => '0');
for i in 0 to SLINK_NUM_TX-1 loop
if (irq_tx_mode(i) = '0') then -- fire if any RX_FIFO is less than half-full
tx_tmp_v(i) := not rx_fifo_half(i);
else -- fire if any RX_FIFO is not full (= free buffer space available)
tx_tmp_v(i) := tx_fifo_free(i);
end if;
end loop;
irq_tx_o <= or_reduce_f(irq_tx_en and tx_tmp_v);
end if;
end if;
-- CPU IRQs --
irq.rx_pending_ff <= irq.rx_pending;
irq.tx_pending_ff <= irq.tx_pending;
irq_rx_o <= irq.rx_pending and (not irq.rx_pending_ff);
irq_tx_o <= irq.tx_pending and (not irq.tx_pending_ff);
end if;
end process irq_arbiter;
 
-- status buffer --
irq_generator_sync: process(clk_i)
begin
if rising_edge(clk_i) then
rx_fifo_avail_ff <= rx_fifo_avail;
rx_fifo_half_ff <= rx_fifo_half;
tx_fifo_free_ff <= tx_fifo_free;
tx_fifo_half_ff <= tx_fifo_half;
end if;
end process irq_generator_sync;
 
-- IRQ event detector --
-- RX interrupt: fire if any RX_FIFO gets full / fire if any RX_FIFO.level becomes half-full
irq.rx_fire <= or_reduce_f(rx_fifo_avail and (not rx_fifo_avail_ff)) when (SLINK_RX_FIFO = 1) else or_reduce_f(rx_fifo_half and (not rx_fifo_half_ff));
-- TX interrupt: fire if any TX_FIFO gets empty / fire if any TX_FIFO.level falls below half-full level
irq.tx_fire <= or_reduce_f(tx_fifo_free and (not tx_fifo_free_ff)) when (SLINK_TX_FIFO = 1) else or_reduce_f((not tx_fifo_half) and tx_fifo_half_ff);
 
 
-- Link Select ----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
link_select: process(addr)
325,8 → 322,8
generic map (
FIFO_DEPTH => SLINK_TX_FIFO, -- number of fifo entries; has to be a power of two; min 1
FIFO_WIDTH => 32, -- size of data elements in fifo
FIFO_RSYNC => false, -- false = async read; true = sync read
FIFO_SAFE => true -- true = allow read/write only if entry available
FIFO_RSYNC => false, -- async read
FIFO_SAFE => true -- safe access
)
port map (
-- control --
333,7 → 330,8
clk_i => clk_i, -- clock, rising edge
rstn_i => '1', -- async reset, low-active
clear_i => fifo_clear, -- sync reset, high-active
level_o => tx_fifo_level(i), -- fill level
level_o => open, -- fill level
half_o => tx_fifo_half(i), -- FIFO is at least half full
-- write port --
wdata_i => data_i, -- write data
we_i => tx_fifo_we(i), -- write enable
351,7 → 349,7
tx_fifo_free(i) <= '0';
slink_tx_dat_o(i) <= (others => '0');
slink_tx_val_o(i) <= '0';
tx_fifo_level(i) <= (others => '0');
tx_fifo_half(i) <= '0';
end generate;
 
 
363,8 → 361,8
generic map (
FIFO_DEPTH => SLINK_RX_FIFO, -- number of fifo entries; has to be a power of two; min 1
FIFO_WIDTH => 32, -- size of data elements in fifo
FIFO_RSYNC => false, -- false = async read; true = sync read
FIFO_SAFE => true -- true = allow read/write only if entry available
FIFO_RSYNC => false, -- async read
FIFO_SAFE => true -- safe access
)
port map (
-- control --
371,7 → 369,8
clk_i => clk_i, -- clock, rising edge
rstn_i => '1', -- async reset, low-active
clear_i => fifo_clear, -- sync reset, high-active
level_o => rx_fifo_level(i), -- fill level
level_o => open, -- fill level
half_o => rx_fifo_half(i), -- FIFO is at least half full
-- write port --
wdata_i => slink_rx_dat_i(i), -- write data
we_i => slink_rx_val_i(i), -- write enable
389,7 → 388,7
rx_fifo_avail(i) <= '0';
slink_rx_rdy_o(i) <= '0';
rx_fifo_rdata(i) <= (others => '0');
rx_fifo_level(i) <= (others => '0');
rx_fifo_half(i) <= '0';
end generate;
 
 
/neorv32/trunk/rtl/core/neorv32_spi.vhd
72,25 → 72,28
constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit
constant lo_abb_c : natural := index_size_f(spi_size_c); -- low address boundary bit
 
-- control reg bits --
constant ctrl_spi_cs0_c : natural := 0; -- r/w: spi CS 0
constant ctrl_spi_cs1_c : natural := 1; -- r/w: spi CS 1
constant ctrl_spi_cs2_c : natural := 2; -- r/w: spi CS 2
constant ctrl_spi_cs3_c : natural := 3; -- r/w: spi CS 3
constant ctrl_spi_cs4_c : natural := 4; -- r/w: spi CS 4
constant ctrl_spi_cs5_c : natural := 5; -- r/w: spi CS 5
constant ctrl_spi_cs6_c : natural := 6; -- r/w: spi CS 6
constant ctrl_spi_cs7_c : natural := 7; -- r/w: spi CS 7
-- control register --
constant ctrl_spi_cs0_c : natural := 0; -- r/w: spi CS 0
constant ctrl_spi_cs1_c : natural := 1; -- r/w: spi CS 1
constant ctrl_spi_cs2_c : natural := 2; -- r/w: spi CS 2
constant ctrl_spi_cs3_c : natural := 3; -- r/w: spi CS 3
constant ctrl_spi_cs4_c : natural := 4; -- r/w: spi CS 4
constant ctrl_spi_cs5_c : natural := 5; -- r/w: spi CS 5
constant ctrl_spi_cs6_c : natural := 6; -- r/w: spi CS 6
constant ctrl_spi_cs7_c : natural := 7; -- r/w: spi CS 7
--
constant ctrl_spi_en_c : natural := 8; -- r/w: spi enable
constant ctrl_spi_cpha_c : natural := 9; -- r/w: spi clock phase
constant ctrl_spi_prsc0_c : natural := 10; -- r/w: spi prescaler select bit 0
constant ctrl_spi_prsc1_c : natural := 11; -- r/w: spi prescaler select bit 1
constant ctrl_spi_prsc2_c : natural := 12; -- r/w: spi prescaler select bit 2
constant ctrl_spi_size0_c : natural := 13; -- r/w: data size (00: 8-bit, 01: 16-bit)
constant ctrl_spi_size1_c : natural := 14; -- r/w: data size (10: 24-bit, 11: 32-bit)
constant ctrl_spi_en_c : natural := 8; -- r/w: spi enable
constant ctrl_spi_cpha_c : natural := 9; -- r/w: spi clock phase
constant ctrl_spi_prsc0_c : natural := 10; -- r/w: spi prescaler select bit 0
constant ctrl_spi_prsc1_c : natural := 11; -- r/w: spi prescaler select bit 1
constant ctrl_spi_prsc2_c : natural := 12; -- r/w: spi prescaler select bit 2
constant ctrl_spi_size0_c : natural := 13; -- r/w: data size (00: 8-bit, 01: 16-bit)
constant ctrl_spi_size1_c : natural := 14; -- r/w: data size (10: 24-bit, 11: 32-bit)
constant ctrl_spi_cpol_c : natural := 15; -- r/w: spi clock polarity
--
constant ctrl_spi_busy_c : natural := 31; -- r/-: spi transceiver is busy
constant ctrl_spi_busy_c : natural := 31; -- r/-: spi transceiver is busy
--
signal ctrl : std_ulogic_vector(15 downto 0);
 
-- access control --
signal acc_en : std_ulogic; -- module access enable
98,25 → 101,21
signal wren : std_ulogic; -- word write enable
signal rden : std_ulogic; -- read enable
 
-- accessible regs --
signal ctrl : std_ulogic_vector(14 downto 0);
signal tx_data_reg : std_ulogic_vector(31 downto 0);
signal rx_data : std_ulogic_vector(31 downto 0);
 
-- clock generator --
signal spi_clk : std_ulogic;
signal spi_clk_en : std_ulogic;
 
-- spi transceiver --
signal spi_start : std_ulogic;
signal spi_busy : std_ulogic;
signal spi_state0 : std_ulogic;
signal spi_state1 : std_ulogic;
signal spi_rtx_sreg : std_ulogic_vector(31 downto 0);
signal spi_rx_data : std_ulogic_vector(31 downto 0);
signal spi_bitcnt : std_ulogic_vector(05 downto 0);
signal spi_bitcnt_max : std_ulogic_vector(05 downto 0);
signal spi_sdi_ff0 : std_ulogic;
signal spi_sdi_ff1 : std_ulogic;
type rtx_engine_t is record
busy : std_ulogic;
state0 : std_ulogic;
state1 : std_ulogic;
rtx_sreg : std_ulogic_vector(31 downto 0);
bitcnt : std_ulogic_vector(05 downto 0);
bytecnt : std_ulogic_vector(02 downto 0);
sdi_ff0 : std_ulogic;
sdi_ff1 : std_ulogic;
end record;
signal rtx_engine : rtx_engine_t;
 
begin
 
133,60 → 132,85
rw_access: process(clk_i)
begin
if rising_edge(clk_i) then
ack_o <= acc_en and (rden_i or wren_i);
-- bus access acknowledge --
ack_o <= rden or wren;
 
-- write access --
spi_start <= '0';
if (wren = '1') then
if (addr = spi_ctrl_addr_c) then -- control
ctrl <= data_i(ctrl'left downto 0);
if (addr = spi_ctrl_addr_c) then -- control register
ctrl(ctrl_spi_cs0_c) <= data_i(ctrl_spi_cs0_c);
ctrl(ctrl_spi_cs1_c) <= data_i(ctrl_spi_cs1_c);
ctrl(ctrl_spi_cs2_c) <= data_i(ctrl_spi_cs2_c);
ctrl(ctrl_spi_cs3_c) <= data_i(ctrl_spi_cs3_c);
ctrl(ctrl_spi_cs4_c) <= data_i(ctrl_spi_cs4_c);
ctrl(ctrl_spi_cs5_c) <= data_i(ctrl_spi_cs5_c);
ctrl(ctrl_spi_cs6_c) <= data_i(ctrl_spi_cs6_c);
ctrl(ctrl_spi_cs7_c) <= data_i(ctrl_spi_cs7_c);
--
ctrl(ctrl_spi_en_c) <= data_i(ctrl_spi_en_c);
ctrl(ctrl_spi_cpha_c) <= data_i(ctrl_spi_cpha_c);
ctrl(ctrl_spi_prsc0_c) <= data_i(ctrl_spi_prsc0_c);
ctrl(ctrl_spi_prsc1_c) <= data_i(ctrl_spi_prsc1_c);
ctrl(ctrl_spi_prsc2_c) <= data_i(ctrl_spi_prsc2_c);
ctrl(ctrl_spi_size0_c) <= data_i(ctrl_spi_size0_c);
ctrl(ctrl_spi_size1_c) <= data_i(ctrl_spi_size1_c);
ctrl(ctrl_spi_cpol_c) <= data_i(ctrl_spi_cpol_c);
end if;
if (addr = spi_rtx_addr_c) then -- tx data
tx_data_reg <= data_i;
spi_start <= '1';
end if;
end if;
 
-- read access --
data_o <= (others => '0');
if (rden = '1') then
if (addr = spi_ctrl_addr_c) then
data_o(ctrl_spi_cs0_c) <= ctrl(ctrl_spi_cs0_c);
data_o(ctrl_spi_cs1_c) <= ctrl(ctrl_spi_cs1_c);
data_o(ctrl_spi_cs2_c) <= ctrl(ctrl_spi_cs2_c);
data_o(ctrl_spi_cs3_c) <= ctrl(ctrl_spi_cs3_c);
data_o(ctrl_spi_cs4_c) <= ctrl(ctrl_spi_cs4_c);
data_o(ctrl_spi_cs5_c) <= ctrl(ctrl_spi_cs5_c);
data_o(ctrl_spi_cs6_c) <= ctrl(ctrl_spi_cs6_c);
data_o(ctrl_spi_cs7_c) <= ctrl(ctrl_spi_cs7_c);
if (addr = spi_ctrl_addr_c) then -- control register
data_o(ctrl_spi_cs0_c) <= ctrl(ctrl_spi_cs0_c);
data_o(ctrl_spi_cs1_c) <= ctrl(ctrl_spi_cs1_c);
data_o(ctrl_spi_cs2_c) <= ctrl(ctrl_spi_cs2_c);
data_o(ctrl_spi_cs3_c) <= ctrl(ctrl_spi_cs3_c);
data_o(ctrl_spi_cs4_c) <= ctrl(ctrl_spi_cs4_c);
data_o(ctrl_spi_cs5_c) <= ctrl(ctrl_spi_cs5_c);
data_o(ctrl_spi_cs6_c) <= ctrl(ctrl_spi_cs6_c);
data_o(ctrl_spi_cs7_c) <= ctrl(ctrl_spi_cs7_c);
--
data_o(ctrl_spi_en_c) <= ctrl(ctrl_spi_en_c);
data_o(ctrl_spi_cpha_c) <= ctrl(ctrl_spi_cpha_c);
data_o(ctrl_spi_prsc0_c) <= ctrl(ctrl_spi_prsc0_c);
data_o(ctrl_spi_prsc1_c) <= ctrl(ctrl_spi_prsc1_c);
data_o(ctrl_spi_prsc2_c) <= ctrl(ctrl_spi_prsc2_c);
data_o(ctrl_spi_size0_c) <= ctrl(ctrl_spi_size0_c);
data_o(ctrl_spi_size1_c) <= ctrl(ctrl_spi_size1_c);
data_o(ctrl_spi_en_c) <= ctrl(ctrl_spi_en_c);
data_o(ctrl_spi_cpha_c) <= ctrl(ctrl_spi_cpha_c);
data_o(ctrl_spi_prsc0_c) <= ctrl(ctrl_spi_prsc0_c);
data_o(ctrl_spi_prsc1_c) <= ctrl(ctrl_spi_prsc1_c);
data_o(ctrl_spi_prsc2_c) <= ctrl(ctrl_spi_prsc2_c);
data_o(ctrl_spi_size0_c) <= ctrl(ctrl_spi_size0_c);
data_o(ctrl_spi_size1_c) <= ctrl(ctrl_spi_size1_c);
data_o(ctrl_spi_cpol_c) <= ctrl(ctrl_spi_cpol_c);
--
data_o(ctrl_spi_busy_c) <= spi_busy;
else -- spi_rtx_addr_c
data_o <= rx_data;
data_o(ctrl_spi_busy_c) <= rtx_engine.busy;
else -- data register (spi_rtx_addr_c)
data_o <= rtx_engine.rtx_sreg;
end if;
end if;
end if;
end process rw_access;
 
-- direct chip-select (CS) (output is low-active) --
-- direct chip-select (CS), output is low-active --
spi_csn_o(7 downto 0) <= not ctrl(ctrl_spi_cs7_c downto ctrl_spi_cs0_c);
 
 
-- Transmission Data Size -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
data_size: process(ctrl)
begin
case ctrl(ctrl_spi_size1_c downto ctrl_spi_size0_c) is
when "00" => rtx_engine.bytecnt <= "001"; -- 1-byte mode
when "01" => rtx_engine.bytecnt <= "010"; -- 2-byte mode
when "10" => rtx_engine.bytecnt <= "011"; -- 3-byte mode
when others => rtx_engine.bytecnt <= "100"; -- 4-byte mode
end case;
end process data_size;
 
 
-- Clock Selection ------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- clock generator enable --
clkgen_en_o <= ctrl(ctrl_spi_en_c);
clkgen_en_o <= ctrl(ctrl_spi_en_c); -- clock generator enable
spi_clk_en <= clkgen_i(to_integer(unsigned(ctrl(ctrl_spi_prsc2_c downto ctrl_spi_prsc0_c)))); -- clock select
 
-- spi clock select --
spi_clk <= clkgen_i(to_integer(unsigned(ctrl(ctrl_spi_prsc2_c downto ctrl_spi_prsc0_c))));
 
 
-- SPI Transceiver ------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
spi_rtx_unit: process(clk_i)
193,61 → 217,60
begin
if rising_edge(clk_i) then
-- input (sdi) synchronizer --
spi_sdi_ff0 <= spi_sdi_i;
spi_sdi_ff1 <= spi_sdi_ff0;
rtx_engine.sdi_ff0 <= spi_sdi_i;
rtx_engine.sdi_ff1 <= rtx_engine.sdi_ff0;
 
-- serial engine --
irq_o <= '0';
if (spi_state0 = '0') or (ctrl(ctrl_spi_en_c) = '0') then -- idle or disabled
if (rtx_engine.state0 = '0') or (ctrl(ctrl_spi_en_c) = '0') then -- idle or disabled
-- --------------------------------------------------------------
spi_bitcnt <= (others => '0');
spi_state1 <= '0';
spi_sdo_o <= '0';
spi_sck_o <= '0';
spi_sck_o <= ctrl(ctrl_spi_cpol_c);
rtx_engine.bitcnt <= (others => '0');
rtx_engine.state1 <= '0';
if (ctrl(ctrl_spi_en_c) = '0') then -- disabled
spi_busy <= '0';
elsif (spi_start = '1') then -- start new transmission
spi_rtx_sreg <= tx_data_reg;
spi_busy <= '1';
rtx_engine.busy <= '0';
elsif (wren = '1') and (addr = spi_rtx_addr_c) then -- start new transmission
rtx_engine.rtx_sreg <= data_i;
rtx_engine.busy <= '1';
end if;
spi_state0 <= spi_busy and spi_clk; -- start with next new clock pulse
rtx_engine.state0 <= rtx_engine.busy and spi_clk_en; -- start with next new clock pulse
 
else -- transmission in progress
-- --------------------------------------------------------------
if (spi_state1 = '0') then -- first half of transmission
 
if (rtx_engine.state1 = '0') then -- first half of bit transmission
-- --------------------------------------------------------------
spi_sck_o <= ctrl(ctrl_spi_cpha_c);
 
spi_sck_o <= ctrl(ctrl_spi_cpha_c) xor ctrl(ctrl_spi_cpol_c);
--
case ctrl(ctrl_spi_size1_c downto ctrl_spi_size0_c) is
when "00" => spi_sdo_o <= spi_rtx_sreg(07); -- 8-bit mode
when "01" => spi_sdo_o <= spi_rtx_sreg(15); -- 16-bit mode
when "10" => spi_sdo_o <= spi_rtx_sreg(23); -- 24-bit mode
when others => spi_sdo_o <= spi_rtx_sreg(31); -- 32-bit mode
when "00" => spi_sdo_o <= rtx_engine.rtx_sreg(07); -- 8-bit mode
when "01" => spi_sdo_o <= rtx_engine.rtx_sreg(15); -- 16-bit mode
when "10" => spi_sdo_o <= rtx_engine.rtx_sreg(23); -- 24-bit mode
when others => spi_sdo_o <= rtx_engine.rtx_sreg(31); -- 32-bit mode
end case;
 
if (spi_clk = '1') then
spi_state1 <= '1';
--
if (spi_clk_en = '1') then
if (ctrl(ctrl_spi_cpha_c) = '0') then
spi_rtx_sreg <= spi_rtx_sreg(30 downto 0) & spi_sdi_ff1;
rtx_engine.rtx_sreg <= rtx_engine.rtx_sreg(30 downto 0) & rtx_engine.sdi_ff1;
end if;
spi_bitcnt <= std_ulogic_vector(unsigned(spi_bitcnt) + 1);
rtx_engine.bitcnt <= std_ulogic_vector(unsigned(rtx_engine.bitcnt) + 1);
rtx_engine.state1 <= '1';
end if;
 
else -- second half of transmission
else -- second half of bit transmission
-- --------------------------------------------------------------
spi_sck_o <= not ctrl(ctrl_spi_cpha_c);
 
if (spi_clk = '1') then
spi_state1 <= '0';
spi_sck_o <= ctrl(ctrl_spi_cpha_c) xnor ctrl(ctrl_spi_cpol_c);
--
if (spi_clk_en = '1') then
if (ctrl(ctrl_spi_cpha_c) = '1') then
spi_rtx_sreg <= spi_rtx_sreg(30 downto 0) & spi_sdi_ff1;
rtx_engine.rtx_sreg <= rtx_engine.rtx_sreg(30 downto 0) & rtx_engine.sdi_ff1;
end if;
if (spi_bitcnt = spi_bitcnt_max) then
spi_state0 <= '0';
spi_busy <= '0';
irq_o <= '1';
if (rtx_engine.bitcnt(5 downto 3) = rtx_engine.bytecnt) then
rtx_engine.state0 <= '0';
rtx_engine.busy <= '0';
end if;
rtx_engine.state1 <= '0';
end if;
 
end if;
end if;
end if;
254,30 → 277,9
end process spi_rtx_unit;
 
 
-- RTX Data size ------------------------------------------------------------------------
-- Interrupt ------------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
data_size: process(ctrl)
begin
case ctrl(ctrl_spi_size1_c downto ctrl_spi_size0_c) is
when "00" => spi_bitcnt_max <= "001000"; -- 8-bit mode
when "01" => spi_bitcnt_max <= "010000"; -- 16-bit mode
when "10" => spi_bitcnt_max <= "011000"; -- 24-bit mode
when others => spi_bitcnt_max <= "100000"; -- 32-bit mode
end case;
end process data_size;
irq_o <= ctrl(ctrl_spi_en_c) and (not rtx_engine.busy); -- fire IRQ if transceiver idle
 
 
-- RX-Data Masking ------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
rx_mapping: process(ctrl, spi_rtx_sreg)
begin
case ctrl(ctrl_spi_size1_c downto ctrl_spi_size0_c) is
when "00" => rx_data <= x"000000" & spi_rtx_sreg(07 downto 0); -- 8-bit mode
when "01" => rx_data <= x"0000" & spi_rtx_sreg(15 downto 0); -- 16-bit mode
when "10" => rx_data <= x"00" & spi_rtx_sreg(23 downto 0); -- 24-bit mode
when others => rx_data <= spi_rtx_sreg(31 downto 0); -- 32-bit mode
end case;
end process rx_mapping;
 
 
end neorv32_spi_rtl;
/neorv32/trunk/rtl/core/neorv32_top.vhd
120,7 → 120,11
IO_GPIO_EN : boolean := false; -- implement general purpose input/output port unit (GPIO)?
IO_MTIME_EN : boolean := false; -- implement machine system timer (MTIME)?
IO_UART0_EN : boolean := false; -- implement primary universal asynchronous receiver/transmitter (UART0)?
IO_UART0_RX_FIFO : natural := 1; -- RX fifo depth, has to be a power of two, min 1
IO_UART0_TX_FIFO : natural := 1; -- TX fifo depth, has to be a power of two, min 1
IO_UART1_EN : boolean := false; -- implement secondary universal asynchronous receiver/transmitter (UART1)?
IO_UART1_RX_FIFO : natural := 1; -- RX fifo depth, has to be a power of two, min 1
IO_UART1_TX_FIFO : natural := 1; -- TX fifo depth, has to be a power of two, min 1
IO_SPI_EN : boolean := false; -- implement serial peripheral interface (SPI)?
IO_TWI_EN : boolean := false; -- implement two-wire interface (TWI)?
IO_PWM_NUM_CH : natural := 0; -- number of PWM channels to implement (0..60); 0 = disabled
330,7 → 334,6
 
-- misc --
signal mtime_time : std_ulogic_vector(63 downto 0); -- current system time from MTIME
signal cpu_sleep : std_ulogic; -- CPU is in sleep mode when set
signal bus_keeper_err : std_ulogic; -- bus keeper: bus access timeout
 
begin
479,7 → 482,7
-- global control --
clk_i => clk_i, -- global clock, rising edge
rstn_i => sys_rstn, -- global reset, low-active, async
sleep_o => cpu_sleep, -- cpu is in sleep mode when set
sleep_o => open, -- cpu is in sleep mode when set
-- instruction bus interface --
i_bus_addr_o => cpu_i.addr, -- bus access address
i_bus_rdata_i => cpu_i.rdata, -- bus read data
868,8 → 871,6
-- clock generator --
clkgen_en_o => cfs_cg_en, -- enable clock generator
clkgen_i => clk_gen, -- "clock" inputs
-- CPU state --
sleep_i => cpu_sleep, -- set if cpu is in sleep mode
-- interrupt --
irq_o => cfs_irq, -- interrupt request
-- custom io (conduit) --
1006,7 → 1007,9
if (IO_UART0_EN = true) generate
neorv32_uart0_inst: neorv32_uart
generic map (
UART_PRIMARY => true -- true = primary UART (UART0), false = secondary UART (UART1)
UART_PRIMARY => true, -- true = primary UART (UART0), false = secondary UART (UART1)
UART_RX_FIFO => IO_UART0_RX_FIFO, -- RX fifo depth, has to be a power of two, min 1
UART_TX_FIFO => IO_UART0_TX_FIFO -- TX fifo depth, has to be a power of two, min 1
)
port map (
-- host access --
1050,7 → 1053,9
if (IO_UART1_EN = true) generate
neorv32_uart1_inst: neorv32_uart
generic map (
UART_PRIMARY => false -- true = primary UART (UART0), false = secondary UART (UART1)
UART_PRIMARY => false, -- true = primary UART (UART0), false = secondary UART (UART1)
UART_RX_FIFO => IO_UART1_RX_FIFO, -- RX fifo depth, has to be a power of two, min 1
UART_TX_FIFO => IO_UART1_TX_FIFO -- TX fifo depth, has to be a power of two, min 1
)
port map (
-- host access --
1156,8 → 1161,8
neorv32_twi_inst_false:
if (IO_TWI_EN = false) generate
resp_bus(RESP_TWI) <= resp_bus_entry_terminate_c;
-- twi_sda_io <= 'Z'; -- FIXME?
-- twi_scl_io <= 'Z'; -- FIXME?
twi_sda_io <= 'Z';
twi_scl_io <= 'Z';
twi_cg_en <= '0';
twi_irq <= '0';
end generate;
/neorv32/trunk/rtl/core/neorv32_twi.vhd
190,8 → 190,14
twi_scl_i_ff0 <= twi_scl_i;
twi_scl_i_ff1 <= twi_scl_i_ff0;
 
-- interrupt --
if (arbiter = "100") then -- fire IRQ if enabled transceiver is idle
irq_o <= '1';
else
irq_o <= '0';
end if;
 
-- defaults --
irq_o <= '0';
arbiter(2) <= ctrl(ctrl_twi_en_c); -- still activated?
 
-- serial engine --
257,7 → 263,6
 
if (twi_bitcnt = "1010") then -- 8 data bits + 1 bit for ACK + 1 tick delay
arbiter(1 downto 0) <= "00"; -- go back to IDLE
irq_o <= '1'; -- fire IRQ
end if;
 
when others => -- "0--" OFFLINE: TWI deactivated
/neorv32/trunk/rtl/core/neorv32_uart.vhd
2,21 → 2,22
-- # << NEORV32 - Universal Asynchronous Receiver and Transmitter (UART0/1) >> #
-- # ********************************************************************************************* #
-- # Frame configuration: 1 start bit, 8 bit data, parity bit (none/even/odd), 1 stop bit, #
-- # programmable BAUD rate via clock pre-scaler and 12-bit BAUD value config register. RX engine #
-- # a simple 2-entry data buffer (for double-buffering). #
-- # Interrupts: UART_RX_available, UART_TX_done #
-- # programmable BAUD rate via clock pre-scaler and 12-bit BAUD value configuration register, #
-- # optional configurable RX and TX FIFOs. #
-- # #
-- # Interrupts: Configurable RX and TX interrupt (both triggered by specific FIFO fill-levels) #
-- # #
-- # Support for RTS("RTR")/CTS hardware flow control: #
-- # * uart_rts_o = 0: RX is ready to receive a new char, enabled via CTRL.ctrl_uart_rts_en_c #
-- # * uart_cts_i = 0: TX is allowed to send a new char, enabled via CTRL.ctrl_uart_cts_en_c #
-- # * uart_rts_o = 0: RX is ready to receive a new char, enabled via CTRL.ctrl_rts_en_c #
-- # * uart_cts_i = 0: TX is allowed to send a new char, enabled via CTRL.ctrl_cts_en_c #
-- # #
-- # UART0 / UART1: #
-- # This module is used for implementing UART0 and UART1. The UART_PRIMARY generic configures the #
-- # interface register addresses and simulation output setting for UART0 (UART_PRIMARY = true) #
-- # or UART1 (UART_PRIMARY = false). #
-- # interface register addresses and simulation outputs for UART0 (UART_PRIMARY = true) or UART1 #
-- # (UART_PRIMARY = false). #
-- # #
-- # SIMULATION MODE: #
-- # When the simulation mode is enabled (setting the ctrl.ctrl_uart_sim_en_c bit) any write #
-- # When the simulation mode is enabled (setting the ctrl.ctrl_sim_en_c bit) any write #
-- # access to the TX register will not trigger any UART activity. Instead, the written data is #
-- # output to the simulation environment. The lowest 8 bits of the written data are printed as #
-- # ASCII char to the simulator console. #
62,11 → 63,13
 
library neorv32;
use neorv32.neorv32_package.all;
use std.textio.all; -- obviously only for simulation
use std.textio.all;
 
entity neorv32_uart is
generic (
UART_PRIMARY : boolean -- true = primary UART (UART0), false = secondary UART (UART1)
UART_PRIMARY : boolean; -- true = primary UART (UART0), false = secondary UART (UART1)
UART_RX_FIFO : natural; -- RX fifo depth, has to be a power of two, min 1
UART_TX_FIFO : natural -- TX fifo depth, has to be a power of two, min 1
);
port (
-- host access --
108,46 → 111,54
constant sim_screen_output_en_c : boolean := true; -- output lowest byte as char to simulator console when enabled
constant sim_text_output_en_c : boolean := true; -- output lowest byte as char to text file when enabled
constant sim_data_output_en_c : boolean := true; -- dump 32-word to file when enabled
constant sim_uart_text_file_c : string := cond_sel_string_f(UART_PRIMARY, "neorv32.uart0.sim_mode.text.out", "neorv32.uart1.sim_mode.text.out");
constant sim_uart_data_file_c : string := cond_sel_string_f(UART_PRIMARY, "neorv32.uart0.sim_mode.data.out", "neorv32.uart1.sim_mode.data.out");
 
-- simulation output file configuration --
constant sim_uart_text_file_c : string := cond_sel_string_f(UART_PRIMARY, "neorv32.uart0.sim_mode.text.out", "neorv32.uart1.sim_mode.text.out");
constant sim_uart_data_file_c : string := cond_sel_string_f(UART_PRIMARY, "neorv32.uart0.sim_mode.data.out", "neorv32.uart1.sim_mode.data.out");
 
-- control register --
signal ctrl : std_ulogic_vector(31 downto 0);
 
-- control register bits --
constant ctrl_uart_baud00_c : natural := 0; -- r/w: UART baud config bit 0
constant ctrl_uart_baud01_c : natural := 1; -- r/w: UART baud config bit 1
constant ctrl_uart_baud02_c : natural := 2; -- r/w: UART baud config bit 2
constant ctrl_uart_baud03_c : natural := 3; -- r/w: UART baud config bit 3
constant ctrl_uart_baud04_c : natural := 4; -- r/w: UART baud config bit 4
constant ctrl_uart_baud05_c : natural := 5; -- r/w: UART baud config bit 5
constant ctrl_uart_baud06_c : natural := 6; -- r/w: UART baud config bit 6
constant ctrl_uart_baud07_c : natural := 7; -- r/w: UART baud config bit 7
constant ctrl_uart_baud08_c : natural := 8; -- r/w: UART baud config bit 8
constant ctrl_uart_baud09_c : natural := 9; -- r/w: UART baud config bit 9
constant ctrl_uart_baud10_c : natural := 10; -- r/w: UART baud config bit 10
constant ctrl_uart_baud11_c : natural := 11; -- r/w: UART baud config bit 11
constant ctrl_uart_sim_en_c : natural := 12; -- r/w: UART <<SIMULATION MODE>> enable
constant ctrl_baud00_c : natural := 0; -- r/w: baud config bit 0
constant ctrl_baud01_c : natural := 1; -- r/w: baud config bit 1
constant ctrl_baud02_c : natural := 2; -- r/w: baud config bit 2
constant ctrl_baud03_c : natural := 3; -- r/w: baud config bit 3
constant ctrl_baud04_c : natural := 4; -- r/w: baud config bit 4
constant ctrl_baud05_c : natural := 5; -- r/w: baud config bit 5
constant ctrl_baud06_c : natural := 6; -- r/w: baud config bit 6
constant ctrl_baud07_c : natural := 7; -- r/w: baud config bit 7
constant ctrl_baud08_c : natural := 8; -- r/w: baud config bit 8
constant ctrl_baud09_c : natural := 9; -- r/w: baud config bit 9
constant ctrl_baud10_c : natural := 10; -- r/w: baud config bit 10
constant ctrl_baud11_c : natural := 11; -- r/w: baud config bit 11
constant ctrl_sim_en_c : natural := 12; -- r/w: UART <<SIMULATION MODE>> enable
constant ctrl_rx_empty_c : natural := 13; -- r/-: RX FIFO is empty
constant ctrl_rx_half_c : natural := 14; -- r/-: RX FIFO is at least half-full
constant ctrl_rx_full_c : natural := 15; -- r/-: RX FIFO is full
constant ctrl_tx_empty_c : natural := 16; -- r/-: TX FIFO is empty
constant ctrl_tx_half_c : natural := 17; -- r/-: TX FIFO is at least half-full
constant ctrl_tx_full_c : natural := 18; -- r/-: TX FIFO is full
-- ...
constant ctrl_uart_rts_en_c : natural := 20; -- r/w: enable hardware flow control: assert rts_o if ready to receive
constant ctrl_uart_cts_en_c : natural := 21; -- r/w: enable hardware flow control: send only if cts_i is asserted
constant ctrl_uart_pmode0_c : natural := 22; -- r/w: Parity config (0=even; 1=odd)
constant ctrl_uart_pmode1_c : natural := 23; -- r/w: Enable parity bit
constant ctrl_uart_prsc0_c : natural := 24; -- r/w: UART baud prsc bit 0
constant ctrl_uart_prsc1_c : natural := 25; -- r/w: UART baud prsc bit 1
constant ctrl_uart_prsc2_c : natural := 26; -- r/w: UART baud prsc bit 2
constant ctrl_uart_cts_c : natural := 27; -- r/-: current state of CTS input
constant ctrl_uart_en_c : natural := 28; -- r/w: UART enable
-- ...
constant ctrl_uart_tx_busy_c : natural := 31; -- r/-: UART transmitter is busy
constant ctrl_rts_en_c : natural := 20; -- r/w: enable hardware flow control: assert rts_o if ready to receive
constant ctrl_cts_en_c : natural := 21; -- r/w: enable hardware flow control: send only if cts_i is asserted
constant ctrl_pmode0_c : natural := 22; -- r/w: Parity config (0=even; 1=odd)
constant ctrl_pmode1_c : natural := 23; -- r/w: Enable parity bit
constant ctrl_prsc0_c : natural := 24; -- r/w: baud prsc bit 0
constant ctrl_prsc1_c : natural := 25; -- r/w: baud prsc bit 1
constant ctrl_prsc2_c : natural := 26; -- r/w: baud prsc bit 2
constant ctrl_cts_c : natural := 27; -- r/-: current state of CTS input
constant ctrl_en_c : natural := 28; -- r/w: UART enable
constant ctrl_rx_irq_c : natural := 29; -- r/w: RX IRQ mode: 1=FIFO at least half-full; 0=FIFO not empty
constant ctrl_tx_irq_c : natural := 30; -- r/w: TX IRQ mode: 1=FIFO less than half-full; 0=FIFO not full
constant ctrl_tx_busy_c : natural := 31; -- r/-: UART transmitter is busy
 
-- data register flags --
constant data_rx_perr_c : natural := 28; -- r/-: Rx parity error
constant data_rx_ferr_c : natural := 29; -- r/-: Rx frame error
constant data_rx_overr_c : natural := 30; -- r/-: Rx data overrun
constant data_rx_avail_c : natural := 31; -- r/-: Rx data available
constant data_lsb_c : natural := 0; -- r/-: received char LSB
constant data_msb_c : natural := 7; -- r/-: received char MSB
-- ...
constant data_rx_perr_c : natural := 28; -- r/-: RX parity error
constant data_rx_ferr_c : natural := 29; -- r/-: RX frame error
constant data_rx_overr_c : natural := 30; -- r/-: RX data overrun
constant data_rx_avail_c : natural := 31; -- r/-: RX data available
 
-- access control --
signal acc_en : std_ulogic; -- module access enable
165,41 → 176,67
signal uart_cts_ff : std_ulogic_vector(1 downto 0);
signal uart_rts : std_ulogic;
 
-- uart tx unit --
type uart_tx_t is record
busy : std_ulogic;
done : std_ulogic;
bitcnt : std_ulogic_vector(03 downto 0);
sreg : std_ulogic_vector(10 downto 0);
baud_cnt : std_ulogic_vector(11 downto 0);
tx_granted : std_ulogic; -- allowed to start sending when 1
cts : std_ulogic; -- allow new transmission when 1
-- UART transmitter --
type tx_state_t is (S_TX_IDLE, S_TX_GET, S_TX_CHECK, S_TX_TRANSMIT, S_TX_SIM);
type tx_engine_t is record
state : tx_state_t;
busy : std_ulogic;
bitcnt : std_ulogic_vector(03 downto 0);
sreg : std_ulogic_vector(10 downto 0);
baud_cnt : std_ulogic_vector(11 downto 0);
cts : std_ulogic; -- allow new transmission when 1
end record;
signal uart_tx : uart_tx_t;
signal tx_engine : tx_engine_t;
 
-- uart rx unit --
type ry_data_buf_t is array (0 to 1) of std_ulogic_vector(07 downto 0);
type uart_rx_t is record
-- UART receiver --
type rx_state_t is (S_RX_IDLE, S_RX_RECEIVE);
type rx_engine_t is record
state : rx_state_t;
sync : std_ulogic_vector(04 downto 0);
busy : std_ulogic;
busy_ff : std_ulogic;
bitcnt : std_ulogic_vector(03 downto 0);
sreg : std_ulogic_vector(09 downto 0);
baud_cnt : std_ulogic_vector(11 downto 0);
overr : std_ulogic;
rtr : std_ulogic; -- ready to receive when 1
--
avail : std_ulogic_vector(02 downto 0);
data : ry_data_buf_t;
data_rd : std_ulogic_vector(07 downto 0);
ferr : std_ulogic_vector(01 downto 0); -- frame error (stop bit not set)
ferr_rd : std_ulogic;
perr : std_ulogic_vector(01 downto 0); -- parity error
perr_rd : std_ulogic;
end record;
signal uart_rx : uart_rx_t;
signal rx_engine : rx_engine_t;
 
-- TX FIFO --
type tx_buffer_t is record
we : std_ulogic; -- write enable
re : std_ulogic; -- read enable
clear : std_ulogic; -- sync reset, high-active
wdata : std_ulogic_vector(31 downto 0); -- write data
rdata : std_ulogic_vector(31 downto 0); -- read data
avail : std_ulogic; -- data available?
free : std_ulogic; -- free entry available?
half : std_ulogic; -- half full
end record;
signal tx_buffer : tx_buffer_t;
 
-- RX FIFO --
type rx_buffer_t is record
we : std_ulogic; -- write enable
re : std_ulogic; -- read enable
clear : std_ulogic; -- sync reset, high-active
wdata : std_ulogic_vector(9 downto 0); -- write data
rdata : std_ulogic_vector(9 downto 0); -- read data
avail : std_ulogic; -- data available?
free : std_ulogic; -- free entry available?
half : std_ulogic; -- half full
end record;
signal rx_buffer : rx_buffer_t;
 
begin
 
-- Sanity Checks --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
assert not (is_power_of_two_f(UART_RX_FIFO) = false) report "NEORV32 PROCESSOR CONFIG ERROR: UART" &
cond_sel_string_f(UART_PRIMARY, "0", "1") & " <UART_RX_FIFO> has to be a power of two." severity error;
assert not (is_power_of_two_f(UART_TX_FIFO) = false) report "NEORV32 PROCESSOR CONFIG ERROR: UART" &
cond_sel_string_f(UART_PRIMARY, "0", "1") & " <UART_TX_FIFO> has to be a power of two." severity error;
 
 
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = uart_id_base_c(hi_abb_c downto lo_abb_c)) else '0';
213,39 → 250,52
rw_access: process(clk_i)
begin
if rising_edge(clk_i) then
ack_o <= acc_en and (rden_i or wren_i);
-- bus access acknowledge --
ack_o <= wr_en or rd_en;
 
-- write access --
if (wr_en = '1') then
if (addr = uart_id_ctrl_addr_c) then
ctrl <= (others => '0');
ctrl(ctrl_uart_baud11_c downto ctrl_uart_baud00_c) <= data_i(ctrl_uart_baud11_c downto ctrl_uart_baud00_c);
ctrl(ctrl_uart_sim_en_c) <= data_i(ctrl_uart_sim_en_c);
ctrl(ctrl_uart_pmode1_c downto ctrl_uart_pmode0_c) <= data_i(ctrl_uart_pmode1_c downto ctrl_uart_pmode0_c);
ctrl(ctrl_uart_prsc2_c downto ctrl_uart_prsc0_c) <= data_i(ctrl_uart_prsc2_c downto ctrl_uart_prsc0_c);
ctrl(ctrl_uart_rts_en_c) <= data_i(ctrl_uart_rts_en_c);
ctrl(ctrl_uart_cts_en_c) <= data_i(ctrl_uart_cts_en_c);
ctrl(ctrl_uart_en_c) <= data_i(ctrl_uart_en_c);
ctrl(ctrl_baud11_c downto ctrl_baud00_c) <= data_i(ctrl_baud11_c downto ctrl_baud00_c);
ctrl(ctrl_sim_en_c) <= data_i(ctrl_sim_en_c);
ctrl(ctrl_pmode1_c downto ctrl_pmode0_c) <= data_i(ctrl_pmode1_c downto ctrl_pmode0_c);
ctrl(ctrl_prsc2_c downto ctrl_prsc0_c) <= data_i(ctrl_prsc2_c downto ctrl_prsc0_c);
ctrl(ctrl_rts_en_c) <= data_i(ctrl_rts_en_c);
ctrl(ctrl_cts_en_c) <= data_i(ctrl_cts_en_c);
ctrl(ctrl_rx_irq_c) <= data_i(ctrl_rx_irq_c);
ctrl(ctrl_tx_irq_c) <= data_i(ctrl_tx_irq_c);
ctrl(ctrl_en_c) <= data_i(ctrl_en_c);
end if;
end if;
 
-- read access --
data_o <= (others => '0');
if (rd_en = '1') then
if (addr = uart_id_ctrl_addr_c) then
data_o(ctrl_uart_baud11_c downto ctrl_uart_baud00_c) <= ctrl(ctrl_uart_baud11_c downto ctrl_uart_baud00_c);
data_o(ctrl_uart_sim_en_c) <= ctrl(ctrl_uart_sim_en_c);
data_o(ctrl_uart_pmode1_c downto ctrl_uart_pmode0_c) <= ctrl(ctrl_uart_pmode1_c downto ctrl_uart_pmode0_c);
data_o(ctrl_uart_prsc2_c downto ctrl_uart_prsc0_c) <= ctrl(ctrl_uart_prsc2_c downto ctrl_uart_prsc0_c);
data_o(ctrl_uart_rts_en_c) <= ctrl(ctrl_uart_rts_en_c);
data_o(ctrl_uart_cts_en_c) <= ctrl(ctrl_uart_cts_en_c);
data_o(ctrl_uart_en_c) <= ctrl(ctrl_uart_en_c);
data_o(ctrl_uart_tx_busy_c) <= uart_tx.busy;
data_o(ctrl_uart_cts_c) <= uart_cts_ff(1);
data_o(ctrl_baud11_c downto ctrl_baud00_c) <= ctrl(ctrl_baud11_c downto ctrl_baud00_c);
data_o(ctrl_sim_en_c) <= ctrl(ctrl_sim_en_c);
data_o(ctrl_pmode1_c downto ctrl_pmode0_c) <= ctrl(ctrl_pmode1_c downto ctrl_pmode0_c);
data_o(ctrl_prsc2_c downto ctrl_prsc0_c) <= ctrl(ctrl_prsc2_c downto ctrl_prsc0_c);
data_o(ctrl_rts_en_c) <= ctrl(ctrl_rts_en_c);
data_o(ctrl_cts_en_c) <= ctrl(ctrl_cts_en_c);
data_o(ctrl_rx_empty_c) <= not rx_buffer.avail;
data_o(ctrl_rx_half_c) <= rx_buffer.half;
data_o(ctrl_rx_full_c) <= not rx_buffer.free;
data_o(ctrl_tx_empty_c) <= not tx_buffer.avail;
data_o(ctrl_tx_half_c) <= tx_buffer.half;
data_o(ctrl_tx_full_c) <= not tx_buffer.free;
data_o(ctrl_en_c) <= ctrl(ctrl_en_c);
data_o(ctrl_rx_irq_c) <= ctrl(ctrl_rx_irq_c) and bool_to_ulogic_f(boolean(UART_RX_FIFO > 1)); -- tie to zero if UART_RX_FIFO = 1
data_o(ctrl_tx_irq_c) <= ctrl(ctrl_tx_irq_c) and bool_to_ulogic_f(boolean(UART_TX_FIFO > 1)); -- tie to zero if UART_TX_FIFO = 1
data_o(ctrl_tx_busy_c) <= tx_engine.busy;
data_o(ctrl_cts_c) <= uart_cts_ff(1);
else -- uart_id_rtx_addr_c
data_o(data_rx_avail_c) <= or_reduce_f(uart_rx.avail);
data_o(data_rx_overr_c) <= and_reduce_f(uart_rx.avail);
data_o(data_rx_ferr_c) <= uart_rx.ferr_rd;
data_o(data_rx_perr_c) <= uart_rx.perr_rd;
data_o(7 downto 0) <= uart_rx.data_rd;
data_o(data_msb_c downto data_lsb_c) <= rx_buffer.rdata(7 downto 0);
data_o(data_rx_perr_c) <= rx_buffer.rdata(8);
data_o(data_rx_ferr_c) <= rx_buffer.rdata(9);
data_o(data_rx_overr_c) <= rx_engine.overr;
data_o(data_rx_avail_c) <= rx_buffer.avail; -- data available (valid?)
end if;
end if;
end if;
254,134 → 304,229
-- number of bits to be sampled --
-- if parity flag is ENABLED: 11 bit -> "1011" (1 start bit + 8 data bits + 1 parity bit + 1 stop bit)
-- if parity flag is DISABLED: 10 bit -> "1010" (1 start bit + 8 data bits + 1 stop bit)
num_bits <= "1011" when (ctrl(ctrl_uart_pmode1_c) = '1') else "1010";
num_bits <= "1011" when (ctrl(ctrl_pmode1_c) = '1') else "1010";
 
 
-- Clock Selection ------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- clock enable --
clkgen_en_o <= ctrl(ctrl_uart_en_c);
clkgen_en_o <= ctrl(ctrl_en_c);
 
-- uart clock select --
uart_clk <= clkgen_i(to_integer(unsigned(ctrl(ctrl_uart_prsc2_c downto ctrl_uart_prsc0_c))));
uart_clk <= clkgen_i(to_integer(unsigned(ctrl(ctrl_prsc2_c downto ctrl_prsc0_c))));
 
 
-- UART Transmitter -----------------------------------------------------------------------
-- TX FIFO --------------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
uart_tx_unit: process(clk_i)
tx_engine_fifo_inst: neorv32_fifo
generic map (
FIFO_DEPTH => UART_TX_FIFO, -- number of fifo entries; has to be a power of two; min 1
FIFO_WIDTH => 32, -- size of data elements in fifo (32-bit only for simulation)
FIFO_RSYNC => false, -- async read
FIFO_SAFE => true -- safe access
)
port map (
-- control --
clk_i => clk_i, -- clock, rising edge
rstn_i => '1', -- async reset, low-active
clear_i => tx_buffer.clear, -- sync reset, high-active
level_o => open,
half_o => tx_buffer.half, -- FIFO at least half-full
-- write port --
wdata_i => tx_buffer.wdata, -- write data
we_i => tx_buffer.we, -- write enable
free_o => tx_buffer.free, -- at least one entry is free when set
-- read port --
re_i => tx_buffer.re, -- read enable
rdata_o => tx_buffer.rdata, -- read data
avail_o => tx_buffer.avail -- data available when set
);
 
-- control --
tx_buffer.clear <= not ctrl(ctrl_en_c);
 
-- write access --
tx_buffer.we <= '1' when (wr_en = '1') and (addr = uart_id_rtx_addr_c) else '0';
tx_buffer.wdata <= data_i;
 
 
-- UART Transmitter Engine ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
uart_tx_engine: process(clk_i)
begin
if rising_edge(clk_i) then
-- serial engine --
uart_tx.done <= '0';
if (uart_tx.busy = '0') or (ctrl(ctrl_uart_en_c) = '0') or (ctrl(ctrl_uart_sim_en_c) = '1') then -- idle or disabled or in SIM mode
uart_tx.busy <= '0';
uart_tx.baud_cnt <= ctrl(ctrl_uart_baud11_c downto ctrl_uart_baud00_c);
uart_tx.bitcnt <= num_bits;
uart_tx.sreg(0) <= '1';
if (wr_en = '1') and (ctrl(ctrl_uart_en_c) = '1') and (addr = uart_id_rtx_addr_c) and (ctrl(ctrl_uart_sim_en_c) = '0') then -- write trigger and not in SIM mode
if (ctrl(ctrl_uart_pmode1_c) = '1') then -- add parity flag
uart_tx.sreg <= '1' & (xor_reduce_f(data_i(7 downto 0)) xor ctrl(ctrl_uart_pmode0_c)) & data_i(7 downto 0) & '0'; -- stopbit & parity bit & data & startbit
else
uart_tx.sreg <= '1' & '1' & data_i(7 downto 0) & '0'; -- (dummy fill-bit &) stopbit & data & startbit
end if;
uart_tx.busy <= '1';
end if;
elsif (uart_clk = '1') and (uart_tx.tx_granted = '1') then
if (uart_tx.baud_cnt = x"000") then
uart_tx.baud_cnt <= ctrl(ctrl_uart_baud11_c downto ctrl_uart_baud00_c);
uart_tx.bitcnt <= std_ulogic_vector(unsigned(uart_tx.bitcnt) - 1);
uart_tx.sreg <= '1' & uart_tx.sreg(uart_tx.sreg'left downto 1);
else
uart_tx.baud_cnt <= std_ulogic_vector(unsigned(uart_tx.baud_cnt) - 1);
end if;
if (uart_tx.bitcnt = "0000") then
uart_tx.busy <= '0'; -- done
uart_tx.done <= '1';
end if;
-- defaults --
uart_txd_o <= '1'; -- keep TX line idle (=high) if waiting for permission to start sending (->CTS)
tx_buffer.re <= '0';
 
-- FSM --
if (ctrl(ctrl_en_c) = '0') then -- disabled
tx_engine.state <= S_TX_IDLE;
else
case tx_engine.state is
 
when S_TX_IDLE => -- wait for new data to send
-- ------------------------------------------------------------
if (tx_buffer.avail = '1') then -- new data available
if (ctrl(ctrl_sim_en_c) = '0') then -- normal mode
tx_engine.state <= S_TX_GET;
else -- simulation mode
tx_engine.state <= S_TX_SIM;
end if;
tx_buffer.re <= '1';
end if;
 
when S_TX_GET => -- get new data from buffer and prepare transmission
-- ------------------------------------------------------------
tx_engine.baud_cnt <= ctrl(ctrl_baud11_c downto ctrl_baud00_c);
tx_engine.bitcnt <= num_bits;
if (ctrl(ctrl_pmode1_c) = '1') then -- add parity flag
-- stop bit & parity bit & data (8-bit) & start bit
tx_engine.sreg <= '1' & (xor_reduce_f(tx_buffer.rdata(7 downto 0)) xor ctrl(ctrl_pmode0_c)) & tx_buffer.rdata(7 downto 0) & '0';
else
-- (dummy fill-bit &) stop bit & data (8-bit) & start bit
tx_engine.sreg <= '1' & '1' & tx_buffer.rdata(7 downto 0) & '0';
end if;
tx_engine.state <= S_TX_CHECK;
 
when S_TX_CHECK => -- check if allowed to send
-- ------------------------------------------------------------
if (tx_engine.cts = '1') then -- clear to send
tx_engine.state <= S_TX_TRANSMIT;
end if;
 
when S_TX_TRANSMIT => -- transmit data
-- ------------------------------------------------------------
if (uart_clk = '1') then
if (tx_engine.baud_cnt = x"000") then
tx_engine.baud_cnt <= ctrl(ctrl_baud11_c downto ctrl_baud00_c);
tx_engine.bitcnt <= std_ulogic_vector(unsigned(tx_engine.bitcnt) - 1);
tx_engine.sreg <= '1' & tx_engine.sreg(tx_engine.sreg'left downto 1);
else
tx_engine.baud_cnt <= std_ulogic_vector(unsigned(tx_engine.baud_cnt) - 1);
end if;
end if;
uart_txd_o <= tx_engine.sreg(0);
if (tx_engine.bitcnt = "0000") then -- all bits send?
tx_engine.state <= S_TX_IDLE;
end if;
 
when S_TX_SIM => -- simulation mode output
-- ------------------------------------------------------------
tx_engine.state <= S_TX_IDLE;
 
when others => -- undefined
-- ------------------------------------------------------------
tx_engine.state <= S_TX_IDLE;
 
end case;
end if;
-- transmission granted --
if (ctrl(ctrl_uart_en_c) = '0') then -- disabled
uart_tx.tx_granted <= '0';
elsif (uart_tx.done = '1') then
uart_tx.tx_granted <= '0';
elsif (uart_tx.cts = '1') then
uart_tx.tx_granted <= '1';
end if;
-- transmitter output --
uart_txd_o <= uart_tx.sreg(0) or (not uart_tx.tx_granted); -- keep TX line idle (=high) if waiting for permission to start sending (->CTS)
end if;
end process uart_tx_unit;
end process uart_tx_engine;
 
-- transmitter busy --
tx_engine.busy <= '0' when (tx_engine.state = S_TX_IDLE) else '1';
 
-- UART Receiver --------------------------------------------------------------------------
 
-- UART Receiver Engine -------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
uart_rx_unit: process(clk_i)
uart_rx_engine: process(clk_i)
begin
if rising_edge(clk_i) then
-- input synchronizer --
uart_rx.sync <= uart_rxd_i & uart_rx.sync(4 downto 1);
rx_engine.sync <= uart_rxd_i & rx_engine.sync(4 downto 1);
 
-- serial engine --
if (uart_rx.busy = '0') or (ctrl(ctrl_uart_en_c) = '0') or (ctrl(ctrl_uart_sim_en_c) = '1') then -- idle or disabled or in SIM mode
uart_rx.busy <= '0';
uart_rx.baud_cnt <= '0' & ctrl(ctrl_uart_baud11_c downto ctrl_uart_baud01_c); -- half baud delay at the beginning to sample in the middle of each bit
uart_rx.bitcnt <= num_bits;
if (ctrl(ctrl_uart_en_c) = '0') then -- to ensure defined state when reading
uart_rx.perr <= (others => '0');
uart_rx.ferr <= (others => '0');
uart_rx.data <= (others => (others => '0'));
elsif (uart_rx.sync(2 downto 0) = "001") then -- start bit? (falling edge)
uart_rx.busy <= '1';
-- FSM --
if (ctrl(ctrl_en_c) = '0') then -- disabled
rx_engine.overr <= '0';
rx_engine.state <= S_RX_IDLE;
else
case rx_engine.state is
 
when S_RX_IDLE => -- idle; prepare receive
-- ------------------------------------------------------------
rx_engine.baud_cnt <= '0' & ctrl(ctrl_baud11_c downto ctrl_baud01_c); -- half baud delay at the beginning to sample in the middle of each bit
rx_engine.bitcnt <= num_bits;
if (rx_engine.sync(2 downto 0) = "001") then -- start bit? (falling edge)
rx_engine.state <= S_RX_RECEIVE;
end if;
 
when S_RX_RECEIVE => -- receive data
-- ------------------------------------------------------------
if (uart_clk = '1') then
if (rx_engine.baud_cnt = x"000") then
rx_engine.baud_cnt <= ctrl(ctrl_baud11_c downto ctrl_baud00_c);
rx_engine.bitcnt <= std_ulogic_vector(unsigned(rx_engine.bitcnt) - 1);
rx_engine.sreg <= rx_engine.sync(0) & rx_engine.sreg(rx_engine.sreg'left downto 1);
else
rx_engine.baud_cnt <= std_ulogic_vector(unsigned(rx_engine.baud_cnt) - 1);
end if;
end if;
if (rx_engine.bitcnt = "0000") then -- all bits received?
rx_engine.state <= S_RX_IDLE;
end if;
 
when others => -- undefined
-- ------------------------------------------------------------
rx_engine.state <= S_RX_IDLE;
 
end case;
 
-- overrun flag --
if (rd_en = '1') and (addr = uart_id_rtx_addr_c) then -- clear when reading data register
rx_engine.overr <= '1';
elsif (rx_buffer.we = '1') and (rx_buffer.free = '0') then -- write to full FIFO
rx_engine.overr <= '0';
end if;
elsif (uart_clk = '1') then
if (uart_rx.baud_cnt = x"000") then
uart_rx.baud_cnt <= ctrl(ctrl_uart_baud11_c downto ctrl_uart_baud00_c);
uart_rx.bitcnt <= std_ulogic_vector(unsigned(uart_rx.bitcnt) - 1);
uart_rx.sreg <= uart_rx.sync(0) & uart_rx.sreg(uart_rx.sreg'left downto 1);
else
uart_rx.baud_cnt <= std_ulogic_vector(unsigned(uart_rx.baud_cnt) - 1);
end if;
if (uart_rx.bitcnt = "0000") then
uart_rx.busy <= '0'; -- done
-- data buffer (double buffering) --
uart_rx.perr(0) <= ctrl(ctrl_uart_pmode1_c) and (xor_reduce_f(uart_rx.sreg(8 downto 0)) xor ctrl(ctrl_uart_pmode0_c));
uart_rx.ferr(0) <= not uart_rx.sreg(9); -- check stop bit (error if not set)
if (ctrl(ctrl_uart_pmode1_c) = '1') then -- add parity flag
uart_rx.data(0) <= uart_rx.sreg(7 downto 0);
else
uart_rx.data(0) <= uart_rx.sreg(8 downto 1);
end if;
uart_rx.perr(1) <= uart_rx.perr(0);
uart_rx.ferr(1) <= uart_rx.ferr(0);
uart_rx.data(1) <= uart_rx.data(0);
end if;
end if;
 
-- RX available flag --
uart_rx.busy_ff <= uart_rx.busy;
if (ctrl(ctrl_uart_en_c) = '0') then -- disabled
uart_rx.avail <= "000";
elsif ((uart_rx.avail(0) = '1') or (uart_rx.avail(1) = '1')) and (rd_en = '1') and (addr = uart_id_rtx_addr_c) then -- RX read access
uart_rx.avail <= '0' & '0' & uart_rx.avail(1);
elsif (uart_rx.busy_ff = '1') and (uart_rx.busy = '0') then -- RX done
uart_rx.avail <= uart_rx.avail(1 downto 0) & '1';
end if;
end if;
end process uart_rx_unit;
end process uart_rx_engine;
 
-- Receiver double-buffering - buffer read --
uart_rx.perr_rd <= uart_rx.perr(1) when (uart_rx.avail(1) = '1') else uart_rx.perr(0);
uart_rx.ferr_rd <= uart_rx.ferr(1) when (uart_rx.avail(1) = '1') else uart_rx.ferr(0);
uart_rx.data_rd <= uart_rx.data(1) when (uart_rx.avail(1) = '1') else uart_rx.data(0);
 
-- RX engine ready for a new char? --
uart_rx.rtr <= '1' when (uart_rx.avail(2 downto 0) = "000") and (uart_rx.busy = '0') and (uart_rx.busy_ff = '0') and (ctrl(ctrl_uart_en_c) = '1') else '0';
rx_engine.rtr <= '1' when (rx_engine.state = S_RX_IDLE) and (ctrl(ctrl_en_c) = '1') else '0';
 
 
-- RX FIFO --------------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
rx_engine_fifo_inst: neorv32_fifo
generic map (
FIFO_DEPTH => UART_RX_FIFO, -- number of fifo entries; has to be a power of two; min 1
FIFO_WIDTH => 10, -- size of data elements in fifo
FIFO_RSYNC => false, -- async read
FIFO_SAFE => true -- safe access
)
port map (
-- control --
clk_i => clk_i, -- clock, rising edge
rstn_i => '1', -- async reset, low-active
clear_i => rx_buffer.clear, -- sync reset, high-active
level_o => open,
half_o => rx_buffer.half, -- FIFO at least half-full
-- write port --
wdata_i => rx_buffer.wdata, -- write data
we_i => rx_buffer.we, -- write enable
free_o => rx_buffer.free, -- at least one entry is free when set
-- read port --
re_i => rx_buffer.re, -- read enable
rdata_o => rx_buffer.rdata, -- read data
avail_o => rx_buffer.avail -- data available when set
);
 
-- control --
rx_buffer.clear <= not ctrl(ctrl_en_c);
 
-- read/write access --
rx_buffer.wdata(7 downto 0) <= rx_engine.sreg(7 downto 0) when (ctrl(ctrl_pmode1_c) = '1') else rx_engine.sreg(8 downto 1); -- RX data
rx_buffer.wdata(8) <= ctrl(ctrl_pmode1_c) and (xor_reduce_f(rx_engine.sreg(8 downto 0)) xor ctrl(ctrl_pmode0_c)); -- parity error flag
rx_buffer.wdata(9) <= not rx_engine.sreg(9); -- frame error flag: check stop bit (error if not set)
rx_buffer.we <= '1' when (rx_engine.bitcnt = "0000") and (rx_engine.state = S_RX_RECEIVE) else '0'; -- RX complete
rx_buffer.re <= '1' when (rd_en = '1') and (addr = uart_id_rtx_addr_c) else '0';
 
 
-- Hardware Flow Control ------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
uart_tx.cts <= (not uart_cts_ff(1)) when (ctrl(ctrl_uart_cts_en_c) = '1') else '1'; -- input is low-active, internal signal is high-active
uart_rts <= (not uart_rx.rtr) when (ctrl(ctrl_uart_rts_en_c) = '1') else '0'; -- output is low-active
tx_engine.cts <= (not uart_cts_ff(1)) when (ctrl(ctrl_cts_en_c) = '1') else '1'; -- input is low-active, internal signal is high-active
uart_rts <= (not rx_engine.rtr) when (ctrl(ctrl_rts_en_c) = '1') else '0'; -- output is low-active
 
-- flow-control input/output synchronizer --
flow_control_buffer: process(clk_i)
395,13 → 540,40
 
-- Interrupts -----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- UART RX data available
irq_rxd_o <= uart_rx.busy_ff and (not uart_rx.busy);
-- UART TX complete
irq_txd_o <= uart_tx.done;
irq_generator: process(clk_i)
begin
if rising_edge(clk_i) then
if (ctrl(ctrl_en_c) = '0') then -- no interrupts when disabled
irq_txd_o <= '0';
irq_rxd_o <= '0';
else
-- TX interrupt --
if (UART_TX_FIFO = 1) then
irq_txd_o <= tx_buffer.free; -- fire IRQ if FIFO is not full
else
if (ctrl(ctrl_tx_irq_c) = '1') then
irq_txd_o <= not tx_buffer.half; -- fire IRQ if FIFO is less than half-full
else
irq_txd_o <= tx_buffer.free; -- fire IRQ if FIFO is not full
end if;
end if;
 
-- RX interrupt --
if (UART_RX_FIFO = 1) then
irq_rxd_o <= rx_buffer.avail; -- fire IRQ if FIFO is not empty
else
if (ctrl(ctrl_rx_irq_c) = '1') then
irq_rxd_o <= rx_buffer.half; -- fire IRQ if FIFO is at least half-full
else
irq_rxd_o <= rx_buffer.avail; -- fire IRQ is FIFO is not empty
end if;
end if;
end if;
end if;
end process irq_generator;
 
-- SIMULATION Output ----------------------------------------------------------------------
 
-- SIMULATION Transmitter -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- pragma translate_off
-- synthesis translate_off
415,42 → 587,40
variable line_data_v : line;
begin
if rising_edge(clk_i) then
if (ctrl(ctrl_uart_en_c) = '1') and (ctrl(ctrl_uart_sim_en_c) = '1') then -- UART enabled and simulation output selected?
if (wr_en = '1') and (addr = uart_id_rtx_addr_c) then -- write access to tx register
if (tx_engine.state = S_TX_SIM) then -- UART simulation mode
-- print lowest byte to ASCII char --
char_v := to_integer(unsigned(data_i(7 downto 0)));
if (char_v >= 128) then -- out of range?
char_v := 0;
end if;
-- print lowest byte as ASCII char --
char_v := to_integer(unsigned(tx_buffer.rdata(7 downto 0)));
if (char_v >= 128) then -- out of range?
char_v := 0;
end if;
 
if (char_v /= 10) and (char_v /= 13) then -- skip line breaks - they are issued via "writeline"
if (sim_screen_output_en_c = true) then
write(line_screen_v, character'val(char_v));
end if;
if (sim_text_output_en_c = true) then
write(line_text_v, character'val(char_v));
end if;
if (char_v /= 10) and (char_v /= 13) then -- skip line breaks - they are issued via "writeline"
if (sim_screen_output_en_c = true) then
write(line_screen_v, character'val(char_v));
end if;
 
if (char_v = 10) then -- line break: write to screen and text file
if (sim_screen_output_en_c = true) then
writeline(output, line_screen_v);
end if;
if (sim_text_output_en_c = true) then
writeline(file_uart_text_out, line_text_v);
end if;
if (sim_text_output_en_c = true) then
write(line_text_v, character'val(char_v));
end if;
end if;
 
-- dump raw data as 8 hex char text to file --
if (sim_data_output_en_c = true) then
for x in 7 downto 0 loop
write(line_data_v, to_hexchar_f(data_i(3+x*4 downto 0+x*4))); -- write in hex form
end loop; -- x
writeline(file_uart_data_out, line_data_v);
if (char_v = 10) then -- line break: write to screen and text file
if (sim_screen_output_en_c = true) then
writeline(output, line_screen_v);
end if;
if (sim_text_output_en_c = true) then
writeline(file_uart_text_out, line_text_v);
end if;
end if;
 
-- dump raw data as 8 hex chars to file --
if (sim_data_output_en_c = true) then
for x in 7 downto 0 loop
write(line_data_v, to_hexchar_f(tx_buffer.rdata(3+x*4 downto 0+x*4))); -- write in hex form
end loop; -- x
writeline(file_uart_data_out, line_data_v);
end if;
 
end if;
end if;
end process sim_output;
/neorv32/trunk/rtl/core/neorv32_wdt.vhd
112,6 → 112,14
-- internal reset (sync, low-active) --
signal rstn_sync : std_ulogic;
 
-- cpu interrupt --
type cpu_irq_t is record
pending : std_ulogic;
set : std_ulogic;
clr : std_ulogic;
end record;
signal cpu_irq : cpu_irq_t;
 
begin
 
-- Access Control -------------------------------------------------------------------------
132,7 → 140,10
ctrl_reg.mode <= '0'; -- trigger interrupt on WDT overflow
ctrl_reg.clk_sel <= (others => '1'); -- slowest clock source
ctrl_reg.lock <= '0';
cpu_irq.clr <= '-';
elsif rising_edge(clk_i) then
-- acknowledge interrupt when resetting WDT --
cpu_irq.clr <= ctrl_reg.reset;
if (rstn_sync = '0') then -- internal reset
ctrl_reg.reset <= '0';
ctrl_reg.enforce <= '0';
178,10 → 189,33
end process wdt_counter;
 
-- action trigger --
irq_o <= ctrl_reg.enable and (wdt_cnt(wdt_cnt'left) or ctrl_reg.enforce) and (not ctrl_reg.mode); -- mode 0: IRQ
hw_rst <= ctrl_reg.enable and (wdt_cnt(wdt_cnt'left) or ctrl_reg.enforce) and ( ctrl_reg.mode); -- mode 1: RESET
cpu_irq.set <= ctrl_reg.enable and (wdt_cnt(wdt_cnt'left) or ctrl_reg.enforce) and (not ctrl_reg.mode); -- mode 0: IRQ
hw_rst <= ctrl_reg.enable and (wdt_cnt(wdt_cnt'left) or ctrl_reg.enforce) and ( ctrl_reg.mode); -- mode 1: RESET
 
 
-- Interrupt ------------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
irq_gen: process(clk_i)
begin
if rising_edge(clk_i) then
if (ctrl_reg.enable = '0') then
cpu_irq.pending <= '0';
else
if (cpu_irq.set = '1') then
cpu_irq.pending <= '1';
elsif(cpu_irq.clr = '1') then
cpu_irq.pending <= '0';
else
cpu_irq.pending <= cpu_irq.pending;
end if;
end if;
end if;
end process irq_gen;
 
-- CPU IRQ --
irq_o <= cpu_irq.pending;
 
 
-- Reset Generator & Action Cause Indicator -----------------------------------------------
-- -------------------------------------------------------------------------------------------
reset_generator: process(rstn_i, clk_i)
/neorv32/trunk/rtl/core/neorv32_xirq.vhd
212,12 → 212,10
irq_arbiter: process(clk_i)
begin
if rising_edge(clk_i) then
cpu_irq_o <= '0';
if (irq_run = '0') then -- no active IRQ
if (irq_fire = '1') then
cpu_irq_o <= '1';
irq_run <= '1';
irq_src <= irq_src_nxt;
irq_run <= '1';
irq_src <= irq_src_nxt;
end if;
else -- active IRQ, wait for CPU to acknowledge
if (host_ack = '1') then
227,5 → 225,8
end if;
end process irq_arbiter;
 
-- interrupt request --
cpu_irq_o <= irq_run;
 
 
end neorv32_xirq_rtl;
/neorv32/trunk/rtl/system_integration/neorv32_ProcessorTop_stdlogic.vhd
97,7 → 97,11
IO_GPIO_EN : boolean := true; -- implement general purpose input/output port unit (GPIO)?
IO_MTIME_EN : boolean := true; -- implement machine system timer (MTIME)?
IO_UART0_EN : boolean := true; -- implement primary universal asynchronous receiver/transmitter (UART0)?
IO_UART0_RX_FIFO : natural := 1; -- RX fifo depth, has to be a power of two, min 1
IO_UART0_TX_FIFO : natural := 1; -- TX fifo depth, has to be a power of two, min 1
IO_UART1_EN : boolean := true; -- implement secondary universal asynchronous receiver/transmitter (UART1)?
IO_UART1_RX_FIFO : natural := 1; -- RX fifo depth, has to be a power of two, min 1
IO_UART1_TX_FIFO : natural := 1; -- TX fifo depth, has to be a power of two, min 1
IO_SPI_EN : boolean := true; -- implement serial peripheral interface (SPI)?
IO_TWI_EN : boolean := true; -- implement two-wire interface (TWI)?
IO_PWM_NUM_CH : natural := 4; -- number of PWM channels to implement (0..60); 0 = disabled
316,7 → 320,11
IO_GPIO_EN => IO_GPIO_EN, -- implement general purpose input/output port unit (GPIO)?
IO_MTIME_EN => IO_MTIME_EN, -- implement machine system timer (MTIME)?
IO_UART0_EN => IO_UART0_EN, -- implement primary universal asynchronous receiver/transmitter (UART0)?
IO_UART0_RX_FIFO => IO_UART0_RX_FIFO, -- RX fifo depth, has to be a power of two, min 1
IO_UART0_TX_FIFO => IO_UART0_TX_FIFO, -- TX fifo depth, has to be a power of two, min 1
IO_UART1_EN => IO_UART1_EN, -- implement secondary universal asynchronous receiver/transmitter (UART1)?
IO_UART1_RX_FIFO => IO_UART1_RX_FIFO, -- RX fifo depth, has to be a power of two, min 1
IO_UART1_TX_FIFO => IO_UART1_TX_FIFO, -- TX fifo depth, has to be a power of two, min 1
IO_SPI_EN => IO_SPI_EN, -- implement serial peripheral interface (SPI)?
IO_TWI_EN => IO_TWI_EN, -- implement two-wire interface (TWI)?
IO_PWM_NUM_CH => IO_PWM_NUM_CH, -- number of PWM channels to implement (0..60); 0 = disabled
441,8 → 449,12
 
uart0_txd_o <= std_logic(uart0_txd_o_int);
uart0_rxd_i_int <= std_ulogic(uart0_rxd_i);
uart0_rts_o <= std_logic(uart0_rts_o_int);
uart0_cts_i_int <= std_ulogic(uart0_cts_i);
uart1_txd_o <= std_logic(uart1_txd_o_int);
uart1_rxd_i_int <= std_ulogic(uart1_rxd_i);
uart1_rts_o <= std_logic(uart1_rts_o_int);
uart1_cts_i_int <= std_ulogic(uart1_cts_i);
 
spi_sck_o <= std_logic(spi_sck_o_int);
spi_sdo_o <= std_logic(spi_sdo_o_int);
/neorv32/trunk/rtl/system_integration/neorv32_SystemTop_AvalonMM.vhd
107,7 → 107,11
IO_GPIO_EN : boolean := false; -- implement general purpose input/output port unit (GPIO)?
IO_MTIME_EN : boolean := false; -- implement machine system timer (MTIME)?
IO_UART0_EN : boolean := false; -- implement primary universal asynchronous receiver/transmitter (UART0)?
IO_UART0_RX_FIFO : natural := 1; -- RX fifo depth, has to be a power of two, min 1
IO_UART0_TX_FIFO : natural := 1; -- TX fifo depth, has to be a power of two, min 1
IO_UART1_EN : boolean := false; -- implement secondary universal asynchronous receiver/transmitter (UART1)?
IO_UART1_RX_FIFO : natural := 1; -- RX fifo depth, has to be a power of two, min 1
IO_UART1_TX_FIFO : natural := 1; -- TX fifo depth, has to be a power of two, min 1
IO_SPI_EN : boolean := false; -- implement serial peripheral interface (SPI)?
IO_TWI_EN : boolean := false; -- implement two-wire interface (TWI)?
IO_PWM_NUM_CH : natural := 0; -- number of PWM channels to implement (0..60); 0 = disabled
207,18 → 211,18
 
architecture neorv32_top_avalonmm_rtl of neorv32_top_avalonmm is
 
-- Wishbone bus interface (available if MEM_EXT_EN = true) --
signal wb_tag_o : std_ulogic_vector(02 downto 0); -- request tag
signal wb_adr_o : std_ulogic_vector(31 downto 0); -- address
signal wb_dat_i : std_ulogic_vector(31 downto 0) := (others => 'U'); -- read data
signal wb_dat_o : std_ulogic_vector(31 downto 0); -- write data
signal wb_we_o : std_ulogic; -- read/write
signal wb_sel_o : std_ulogic_vector(03 downto 0); -- byte enable
signal wb_stb_o : std_ulogic; -- strobe
signal wb_cyc_o : std_ulogic; -- valid cycle
signal wb_lock_o : std_ulogic; -- exclusive access request
signal wb_ack_i : std_ulogic := 'L'; -- transfer acknowledge
signal wb_err_i : std_ulogic := 'L'; -- transfer error
-- Wishbone bus interface (available if MEM_EXT_EN = true) --
signal wb_tag_o : std_ulogic_vector(02 downto 0); -- request tag
signal wb_adr_o : std_ulogic_vector(31 downto 0); -- address
signal wb_dat_i : std_ulogic_vector(31 downto 0) := (others => 'U'); -- read data
signal wb_dat_o : std_ulogic_vector(31 downto 0); -- write data
signal wb_we_o : std_ulogic; -- read/write
signal wb_sel_o : std_ulogic_vector(03 downto 0); -- byte enable
signal wb_stb_o : std_ulogic; -- strobe
signal wb_cyc_o : std_ulogic; -- valid cycle
signal wb_lock_o : std_ulogic; -- exclusive access request
signal wb_ack_i : std_ulogic := 'L'; -- transfer acknowledge
signal wb_err_i : std_ulogic := 'L'; -- transfer error
 
begin
 
294,7 → 298,11
IO_GPIO_EN => IO_GPIO_EN,
IO_MTIME_EN => IO_MTIME_EN,
IO_UART0_EN => IO_UART0_EN,
IO_UART0_RX_FIFO => IO_UART0_RX_FIFO,
IO_UART0_TX_FIFO => IO_UART0_TX_FIFO,
IO_UART1_EN => IO_UART1_EN,
IO_UART1_RX_FIFO => IO_UART1_RX_FIFO,
IO_UART1_TX_FIFO => IO_UART1_TX_FIFO,
IO_SPI_EN => IO_SPI_EN,
IO_TWI_EN => IO_TWI_EN,
IO_PWM_NUM_CH => IO_PWM_NUM_CH,
391,9 → 399,10
-- CPU interrupts --
mtime_irq_i => mtime_irq_i,
msw_irq_i => msw_irq_i,
mext_irq_i => mext_irq_i);
mext_irq_i => mext_irq_i
);
-- Wishbone to AvalonMM brdige
-- Wishbone to AvalonMM bridge
read_o <= '1' when (wb_stb_o = '1' and wb_we_o = '0') else '0';
write_o <= '1' when (wb_stb_o = '1' and wb_we_o = '1') else '0';
address_o <= std_logic_vector(wb_adr_o);
/neorv32/trunk/rtl/system_integration/neorv32_SystemTop_axi4lite.vhd
92,7 → 92,11
IO_GPIO_EN : boolean := true; -- implement general purpose input/output port unit (GPIO)?
IO_MTIME_EN : boolean := true; -- implement machine system timer (MTIME)?
IO_UART0_EN : boolean := true; -- implement primary universal asynchronous receiver/transmitter (UART0)?
IO_UART0_RX_FIFO : natural := 1; -- RX fifo depth, has to be a power of two, min 1
IO_UART0_TX_FIFO : natural := 1; -- TX fifo depth, has to be a power of two, min 1
IO_UART1_EN : boolean := true; -- implement secondary universal asynchronous receiver/transmitter (UART1)?
IO_UART1_RX_FIFO : natural := 1; -- RX fifo depth, has to be a power of two, min 1
IO_UART1_TX_FIFO : natural := 1; -- TX fifo depth, has to be a power of two, min 1
IO_SPI_EN : boolean := true; -- implement serial peripheral interface (SPI)?
IO_TWI_EN : boolean := true; -- implement two-wire interface (TWI)?
IO_PWM_NUM_CH : natural := 4; -- number of PWM channels to implement (0..60); 0 = disabled
102,7 → 106,8
IO_CFS_CONFIG : std_logic_vector(31 downto 0) := x"00000000"; -- custom CFS configuration generic
IO_CFS_IN_SIZE : positive := 32; -- size of CFS input conduit in bits
IO_CFS_OUT_SIZE : positive := 32; -- size of CFS output conduit in bits
IO_NEOLED_EN : boolean := true -- implement NeoPixel-compatible smart LED interface (NEOLED)?
IO_NEOLED_EN : boolean := true; -- implement NeoPixel-compatible smart LED interface (NEOLED)?
IO_NEOLED_TX_FIFO : natural := 1 -- NEOLED TX FIFO depth, 1..32k, has to be a power of two
);
port (
-- ------------------------------------------------------------
317,7 → 322,11
IO_GPIO_EN => IO_GPIO_EN, -- implement general purpose input/output port unit (GPIO)?
IO_MTIME_EN => IO_MTIME_EN, -- implement machine system timer (MTIME)?
IO_UART0_EN => IO_UART0_EN, -- implement primary universal asynchronous receiver/transmitter (UART0)?
IO_UART0_RX_FIFO => IO_UART0_RX_FIFO, -- RX fifo depth, has to be a power of two, min 1
IO_UART0_TX_FIFO => IO_UART0_TX_FIFO, -- TX fifo depth, has to be a power of two, min 1
IO_UART1_EN => IO_UART1_EN, -- implement secondary universal asynchronous receiver/transmitter (UART1)?
IO_UART1_RX_FIFO => IO_UART1_RX_FIFO, -- RX fifo depth, has to be a power of two, min 1
IO_UART1_TX_FIFO => IO_UART1_TX_FIFO, -- TX fifo depth, has to be a power of two, min 1
IO_SPI_EN => IO_SPI_EN, -- implement serial peripheral interface (SPI)?
IO_TWI_EN => IO_TWI_EN, -- implement two-wire interface (TWI)?
IO_PWM_NUM_CH => IO_PWM_NUM_CH, -- number of PWM channels to implement (0..60); 0 = disabled
327,7 → 336,8
IO_CFS_CONFIG => IO_CFS_CONFIG_INT, -- custom CFS configuration generic
IO_CFS_IN_SIZE => IO_CFS_IN_SIZE, -- size of CFS input conduit in bits
IO_CFS_OUT_SIZE => IO_CFS_OUT_SIZE, -- size of CFS output conduit in bits
IO_NEOLED_EN => IO_NEOLED_EN -- implement NeoPixel-compatible smart LED interface (NEOLED)?
IO_NEOLED_EN => IO_NEOLED_EN, -- implement NeoPixel-compatible smart LED interface (NEOLED)?
IO_NEOLED_TX_FIFO => IO_NEOLED_TX_FIFO -- NEOLED TX FIFO depth, 1..32k, has to be a power of two
)
port map (
-- Global control --
405,8 → 415,12
 
uart0_txd_o <= std_logic(uart0_txd_o_int);
uart0_rxd_i_int <= std_ulogic(uart0_rxd_i);
uart1_txd_o <= std_logic(uart0_txd_o_int);
uart1_rxd_i_int <= std_ulogic(uart0_rxd_i);
uart0_rts_o <= std_logic(uart0_rts_o_int);
uart0_cts_i_int <= std_ulogic(uart0_cts_i);
uart1_txd_o <= std_logic(uart1_txd_o_int);
uart1_rxd_i_int <= std_ulogic(uart1_rxd_i);
uart1_rts_o <= std_logic(uart1_rts_o_int);
uart1_cts_i_int <= std_ulogic(uart1_cts_i);
 
spi_sck_o <= std_logic(spi_sck_o_int);
spi_sdo_o <= std_logic(spi_sdo_o_int);
/neorv32/trunk/setups/radiant/UPduino_v3/README.md
2,29 → 2,32
 
 
This example setup turns the UPduino v3.0 board, which features a Lattice iCE40 UltraPlus FPGA, into a medium-scale NEORV32 *microcontroller*.
The processor setup provides 64kB of data and instruction memory, an RTOS-capable CPU (privileged architecture) and a set of standard peripherals like UART, TWI and SPI.
The processor setup provides 64kB of data and instruction memory, an RTOS-capable CPU (privileged architecture)
and a set of standard peripherals like UART, TWI and SPI.
 
 
* FPGA Board: :books: [tinyVision.ai Inc. UPduino v3 FPGA Board (GitHub)](https://github.com/tinyvision-ai-inc/UPduino-v3.0/), :credit_card: buy on [Tindie](https://www.tindie.com/products/tinyvision_ai/upduino-v30-low-cost-lattice-ice40-fpga-board/)
* FPGA Board: :books: [tinyVision.ai Inc. UPduino v3 FPGA Board (GitHub)](https://github.com/tinyvision-ai-inc/UPduino-v3.0/),
:credit_card: buy on [Tindie](https://www.tindie.com/products/tinyvision_ai/upduino-v30-low-cost-lattice-ice40-fpga-board/)
* FPGA: Lattice iCE40 UltraPlus 5k `iCE40UP5K-SG48I`
* Toolchain: Lattice Radiant (tested with Radiant version 2.1.0), using *Lattice Synthesis Engine (LSE)*
* Toolchain: Lattice Radiant (tested with Radiant version 3.0.0), using *Lattice Synthesis Engine (LSE)*
* Top entity: [`neorv32_upduino_v3_top.vhd`](https://github.com/stnolting/neorv32/blob/master/boards/UPduino_v3/neorv32_upduino_v3_top.vhd) (instantiates NEORV32 top entity)
 
 
### Processor Configuration
 
* CPU: `rv32imac_Zicsr` (reduced CPU `[m]instret` & `[m]cycle` counter width!)
* Memory: 64 kB instruction memory (internal IMEM), 64 kB data memory (internal DMEM), 4 kB bootloader ROM
* Peripherals: `GPIO`, `MTIME`, `UART0`, `SPI`, `TWI`, `PWM`, `WDT`, `TRNG`
* Clock: 24 MHz from on-chip HF oscillator (via PLL)
* Reset: via PLL "locked" signal; "external reset" via FPGA reconfiguration (`creset_n`)
* Tested with version [`1.5.7.6`](https://github.com/stnolting/neorv32/blob/master/CHANGELOG.md)
* On-board FPGA bitstream flash storage can also be used to store/load NEORV32 application software (via the bootloader)
- [x] CPU: `rv32imac_Zicsr` (reduced CPU `[m]instret` & `[m]cycle` counter width!)
- [x] Memory: 64 kB instruction memory (internal IMEM), 64 kB data memory (internal DMEM), 4 kB bootloader ROM
- [x] Peripherals: `GPIO`, `MTIME`, `UART0`, `SPI`, `TWI`, `PWM`, `WDT`, `TRNG`
- [x] Clock: 24 MHz from on-chip HF oscillator (via PLL)
- [x] Reset: via PLL "locked" signal; external "reset" via FPGA re-reconfiguration pin (`creset_n`)
- [x] Tested with processor version [`1.6.1.6`](https://github.com/stnolting/neorv32/blob/master/CHANGELOG.md)
- [x] On-board FPGA bitstream flash storage can also be used to store/load NEORV32 application software (via the bootloader)
 
:information_source: This setup uses optimized platform-specific memory modules for the internal data and instruction memories (DMEM & IMEM). Each memory uses two
UltraPlus SPRAM primitives (total memory size per memory = 2 x 32kB = 64kB). VHDL source file for platform-specific IMEM: [`neorv32_imem.ice40up_spram.vhd`](https://github.com/stnolting/neorv32/blob/master/boards/UPduino_v3/neorv32_imem.ice40up_spram.vhd);
UltraPlus SPRAM primitives (total memory size per memory = 2 x 32kB = 64kB). VHDL source file for platform-specific IMEM:
[`neorv32_imem.ice40up_spram.vhd`](https://github.com/stnolting/neorv32/blob/master/boards/UPduino_v3/neorv32_imem.ice40up_spram.vhd);
VHDL source file for platform-specific DMEM: [`neorv32_dmem.ice40up_spram.vhd`](https://github.com/stnolting/neorv32/blob/master/boards/UPduino_v3/neorv32_dmem.ice40up_spram.vhd).
These platform-specific memories are used *instead* of the default platform-agnostic modules from the core's `rtl/core` folder.
These platform-specific memories are used *instead* of the default platform-agnostic modules from the core's `rtl/core/mem` folder.
 
 
### Interface Signals
48,7 → 51,7
| `gpio_o(3)` | IOB_6A | 2 | J3-16 |
| - | - | - | - |
| **reconfigure FPGA** ("_reset_") | CRESET | 8 | J2-3 |
| `pwm_o(0)` (red) | RGB2 | 41 | J2-5 |
| `pwm_o(0)` | `gpio_i(0)` (red)| RGB2 | 41 | J2-5 |
| `pwm_o(1)` (green) | RGB0 | 39 | J2-6 |
| `pwm_o(2)` (blue) | RGB1 | 40 | J2-7 |
| `twi_sda_io` | IOT_42B | 31 | J2-9 |
60,15 → 63,17
| `uart_txd_o` (UART0) | IOT_50B | 38 | J2-15 |
| `uart_rxd_i` (UART0) | IOT_41A | 28 | J2-16 |
 
:information_source: The TWI signals (`twi_sda_io` and `twi_scl_io`) and the reset input (`rstn_i`) require an external pull-up resistor. GPIO output 0 (`gpio_o(0)`) is used as output for a high-active status LED driven by the bootloader.
:information_source: The TWI signals (`twi_sda_io` and `twi_scl_io`) and the reset input (`rstn_i`) require an external pull-up resistor.
GPIO output 0 (`gpio_o(0)`, also connected to the RGB drive) is used as output for a high-active **status LED** driven by the bootloader.
 
 
### FPGA Utilization
 
```
Number of slice registers: 1676 out of 5280 (32%)
Number of I/O registers: 8 out of 117 (7%)
Number of LUT4s: 4560 out of 5280 (86%)
Number of slice registers: 1768 out of 5280 (33%)
Number of I/O registers: 7 out of 117 (6%)
Number of LUT4s: 4850 out of 5280 (92%)
Number of IO sites used: 23 out of 39 (59%)
Number of DSPs: 0 out of 8 (0%)
Number of I2Cs: 0 out of 2 (0%)
Number of High Speed OSCs: 1 out of 1 (100%)
80,13 → 85,11
Number of WARMBOOTs: 0 out of 1 (0%)
Number of SPIs: 0 out of 2 (0%)
Number of EBRs: 15 out of 30 (50%)
Number of PLLs: 1 out of 1 (100%)
Number of PLLs: 1 out of 1 (100%
```
 
## How To Run
### FPGA Setup
 
#### FPGA Setup
 
1. start Lattice Radiant (in GUI mode)
2. click on "open project" and select `neorv32_upduino_v3.rdf` from this folder
3. click the :arrow_forward: button to synthesize, map, place and route the design and to generate a programming file
/neorv32/trunk/setups/radiant/UPduino_v3/neorv32_upduino_v3_top.vhd
103,6 → 103,8
signal con_spi_sdi : std_ulogic;
signal con_spi_sdo : std_ulogic;
signal con_spi_csn : std_ulogic_vector(07 downto 0);
signal con_gpio_i : std_ulogic_vector(63 downto 0);
signal con_gpio_o : std_ulogic_vector(63 downto 0);
 
-- Misc --
signal pwm_drive : std_logic_vector(2 downto 0);
145,9 → 147,10
-- General --
CLOCK_FREQUENCY => f_clock_c, -- clock frequency of clk_i in Hz
HW_THREAD_ID => 0, -- hardware thread id (32-bit)
INT_BOOTLOADER_EN => true, -- boot configuration: true = boot explicit bootloader; false = boot from int/ext (I)MEM
 
-- On-Chip Debugger (OCD) --
ON_CHIP_DEBUGGER_EN => false, -- implement on-chip debugger
ON_CHIP_DEBUGGER_EN => false, -- implement on-chip debugger?
 
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A => true, -- implement atomic extension?
180,12 → 183,6
MEM_INT_DMEM_EN => true, -- implement processor-internal data memory
MEM_INT_DMEM_SIZE => 64*1024, -- size of processor-internal data memory in bytes
 
-- Internal Cache memory --
ICACHE_EN => false, -- implement instruction cache
ICACHE_NUM_BLOCKS => 4, -- i-cache: number of blocks (min 1), has to be a power of 2
ICACHE_BLOCK_SIZE => 64, -- i-cache: block size in bytes (min 4), has to be a power of 2
ICACHE_ASSOCIATIVITY => 1, -- i-cache: associativity / number of sets (1=direct_mapped), has to be a power of 2
 
-- Processor peripherals --
IO_GPIO_EN => true, -- implement general purpose input/output port unit (GPIO)?
IO_MTIME_EN => true, -- implement machine system timer (MTIME)?
193,7 → 190,8
IO_SPI_EN => true, -- implement serial peripheral interface (SPI)?
IO_TWI_EN => true, -- implement two-wire interface (TWI)?
IO_PWM_NUM_CH => 3, -- number of PWM channels to implement (0..60); 0 = disabled
IO_WDT_EN => true -- implement watch dog timer (WDT)?
IO_WDT_EN => true, -- implement watch dog timer (WDT)?
IO_TRNG_EN => true -- implement true random number generator (TRNG)?
)
port map (
-- Global control --
201,8 → 199,8
rstn_i => cpu_rstn, -- global reset, low-active, async
 
-- GPIO (available if IO_GPIO_EN = true) --
gpio_o => gpio_o, -- parallel output
gpio_i => gpio_i, -- parallel input
gpio_o => con_gpio_o, -- parallel output
gpio_i => con_gpio_i, -- parallel input
 
-- primary UART0 (available if IO_UART0_EN = true) --
uart0_txd_o => uart_txd_o, -- UART0 send data
222,6 → 220,10
pwm_o => con_pwm -- pwm channels
);
 
-- GPIO --
con_gpio_i <= x"000000000000000" & gpio_i(3 downto 0);
gpio_o(3 downto 0) <= con_gpio_o(3 downto 0);
 
-- SPI --
flash_sck_o <= con_spi_sck;
flash_sdo_o <= con_spi_sdo;
232,10 → 234,9
con_spi_sdi <= flash_sdi_i when (con_spi_csn(0) = '0') else spi_sdi_i;
 
-- RGB --
-- bit 0: red - pwm channel 0
-- bit 1: green - pwm channel 1
-- bit 2: blue - pwm channel 2
pwm_drive <= std_logic_vector(con_pwm(2 downto 0));
pwm_drive(0) <= std_logic(con_pwm(0) or con_gpio_o(0)); -- bit 0: red - pwm channel 0 OR gpio_o(0) [status LED]
pwm_drive(1) <= std_logic(con_pwm(1)); -- bit 1: green - pwm channel 1
pwm_drive(2) <= std_logic(con_pwm(2)); -- bit 2: blue - pwm channel 2
 
RGB_inst: RGB
generic map (
/neorv32/trunk/setups/vivado/arty-a7-test-setup/create_project.tcl
39,14 → 39,10
set fileset_constraints [glob ./*.xdc]
 
## Simulation-only sources
set fileset_sim [list ./../../../sim/neorv32_tb.simple.vhd ./../../../sim/uart_rx.simple.vhd]
set fileset_sim [list ./../../../sim/simple/neorv32_tb.simple.vhd ./../../../sim/simple/uart_rx.simple.vhd]
 
# Add source files
 
## Core
add_files $fileset_neorv32
set_property library neorv32 [get_files $fileset_neorv32]
 
## Design
add_files $fileset_design
 
/neorv32/trunk/setups/vivado/nexys-a7-test-setup/create_project.tcl
35,7 → 35,7
add_files [glob ./../../../rtl/test_setups/neorv32_test_setup_bootloader.vhd]
 
# add source files: simulation-only
add_files -fileset sim_1 [list ./../../../sim/neorv32_tb.simple.vhd ./../../../sim/uart_rx.simple.vhd]
add_files -fileset sim_1 [list ./../../../sim/simple/neorv32_tb.simple.vhd ./../../../sim/simple/uart_rx.simple.vhd]
 
# add source files: constraints
add_files -fileset constrs_1 [glob ./*.xdc]
/neorv32/trunk/setups/vivado/README.md
5,6 → 5,8
The `create_project.tcl` TCL script in the board subdirectories can be used for creating a complete Vivado project and for running the implementation.
If not already available, this script will create a `work` folder in those subdirectories.
 
Note that you may need to install support for your particular development board through "XHub Stores" menu item within Vivado prior to sourcing the `create_project.tcl` script.
 
### Batch mode
 
Execute `vivado -mode batch -nojournal -nolog -source create_project.tcl` from the board subdir.
/neorv32/trunk/setups/README.md
1,6 → 1,11
# Exemplary FPGA Board Setups
 
This folder provides exemplary NEORV32 SoC setups for different FPGA platforms/boards.
* [Setups using Commercial Toolchains](#Setups-using-Commercial-Toolchains)
* [Setups using Open-Source Toolchains](#Setups-using-Open-Source-Toolchains)
* [Adding Your Project Setup](#Adding-Your-Project-Setup)
* [Setup-Specific NEORV32 Software Framework Modification](#Setup-Specific-NEORV32-Software-Framework-Modification)
 
This folder provides exemplary NEORV32 SoC setups and projects for different FPGA platforms/boards.
You can directly use one of the provided setups or use them as starting point to build your own setup.
Project maintainers may make pull requests against this repository to [add or link their setups](#Adding-Your-Project-Setup).
 
17,6 → 22,7
| :file_folder: [`arty-a7-35-test-setup`](https://github.com/stnolting/neorv32/tree/master/setups/vivado/arty-a7-test-setup) | Xilinx Vivado | [Digilent Arty A7-35](https://reference.digilentinc.com/reference/programmable-logic/arty-a7/start) | Xilinx Artix-7 `XC7A35TICSG324-1L` | [stnolting](https://github.com/stnolting) |
| :file_folder: [`nexys-a7-test-setup`](https://github.com/stnolting/neorv32/tree/master/setups/vivado/nexys-a7-test-setup) | Xilinx Vivado | [Digilent Nexys A7](https://reference.digilentinc.com/reference/programmable-logic/nexys-a7/start) | Xilinx Artix-7 `XC7A50TCSG324-1` | [AWenzel83](https://github.com/AWenzel83) |
| :file_folder: [`nexys-a7-test-setup`](https://github.com/stnolting/neorv32/tree/master/setups/vivado/nexys-a7-test-setup) | Xilinx Vivado | [Digilent Nexys 4 DDR](https://reference.digilentinc.com/reference/programmable-logic/nexys-4-ddr/start) | Xilinx Artix-7 `XC7A100TCSG324-1` | [AWenzel83](https://github.com/AWenzel83) |
| :earth_africa: [custom CRC32 processor module for the nexys-a7 boards (**tutorial**)](https://github.com/motius/neorv32/tree/add-custom-crc32-module) | Xilinx Vivado | [Digilent Nexys A7](https://reference.digilentinc.com/reference/programmable-logic/nexys-a7/start) | Xilinx Artix-7 `XC7A50TCSG324-1` | [motius](https://github.com/motius) ([ikstvn](https://github.com/ikstvn), [turbinenreiter](https://github.com/turbinenreiter)) |
 
 
## Setups using Open-Source Toolchains
35,17 → 41,19
See the README there for more information how to run a specific setup / configuration.
 
 
### Adding Your Project Setup
## Adding Your Project Setup
 
Please respect the following guidelines if you'd like to add (or link) your setup to the list.
 
* check out the project's [code of conduct](https://github.com/stnolting/neorv32/tree/master/CODE_OF_CONDUCT.md)
* add a link if the board you are using provides online documentation (and/or can be purchased somewhere)
* use the :file_folder: emoji (`:file_folder:`) if the setup is located *in this* folder; use the :earth_africa: emoji (`:earth_africa:`) if it is a link to your local project
* please add a `README` to give some brief information about the setup and a `.gitignore` to keep things clean; take a look at [`arty-a7-35-test-setup`](https://github.com/stnolting/neorv32/setups/boards/arty-a7-35-test-setup) to get some ideas what a project setup might look like
* use the :file_folder: emoji (`:file_folder:`) if the setup is located *in this* folder; use the :earth_africa:
emoji (`:earth_africa:`) if it is a link to your local project
* please add a `README` to give some brief information about the setup and a `.gitignore` to keep things clean;
take a look at [`UPduino_v3`](https://github.com/stnolting/neorv32/tree/master/setups/radiant/UPduino_v3) to get some ideas what a project setup might look like
 
 
### Setup-Specifc NEORV32 Software Framework Modification
## Setup-Specific NEORV32 Software Framework Modification
 
In order to use the features provided by the setups, minor *optional* changes can be made to the default NEORV32 setup.
 
/neorv32/trunk/sim/simple/neorv32_tb.simple.vhd
222,7 → 222,11
IO_GPIO_EN => true, -- implement general purpose input/output port unit (GPIO)?
IO_MTIME_EN => true, -- implement machine system timer (MTIME)?
IO_UART0_EN => true, -- implement primary universal asynchronous receiver/transmitter (UART0)?
IO_UART0_RX_FIFO => 32, -- RX fifo depth, has to be a power of two, min 1
IO_UART0_TX_FIFO => 32, -- TX fifo depth, has to be a power of two, min 1
IO_UART1_EN => true, -- implement secondary universal asynchronous receiver/transmitter (UART1)?
IO_UART1_RX_FIFO => 1, -- RX fifo depth, has to be a power of two, min 1
IO_UART1_TX_FIFO => 1, -- TX fifo depth, has to be a power of two, min 1
IO_SPI_EN => true, -- implement serial peripheral interface (SPI)?
IO_TWI_EN => true, -- implement two-wire interface (TWI)?
IO_PWM_NUM_CH => 30, -- number of PWM channels to implement (0..60); 0 = disabled
232,7 → 236,8
IO_CFS_CONFIG => (others => '0'), -- custom CFS configuration generic
IO_CFS_IN_SIZE => 32, -- size of CFS input conduit in bits
IO_CFS_OUT_SIZE => 32, -- size of CFS output conduit in bits
IO_NEOLED_EN => true -- implement NeoPixel-compatible smart LED interface (NEOLED)?
IO_NEOLED_EN => true, -- implement NeoPixel-compatible smart LED interface (NEOLED)?
IO_NEOLED_TX_FIFO => 8 -- NEOLED TX FIFO depth, 1..32k, has to be a power of two
)
port map (
-- Global control --
/neorv32/trunk/sim/neorv32_tb.vhd
329,7 → 329,11
IO_GPIO_EN => true, -- implement general purpose input/output port unit (GPIO)?
IO_MTIME_EN => true, -- implement machine system timer (MTIME)?
IO_UART0_EN => true, -- implement primary universal asynchronous receiver/transmitter (UART0)?
IO_UART0_RX_FIFO => 32, -- RX fifo depth, has to be a power of two, min 1
IO_UART0_TX_FIFO => 32, -- TX fifo depth, has to be a power of two, min 1
IO_UART1_EN => true, -- implement secondary universal asynchronous receiver/transmitter (UART1)?
IO_UART1_RX_FIFO => 1, -- RX fifo depth, has to be a power of two, min 1
IO_UART1_TX_FIFO => 1, -- TX fifo depth, has to be a power of two, min 1
IO_SPI_EN => true, -- implement serial peripheral interface (SPI)?
IO_TWI_EN => true, -- implement two-wire interface (TWI)?
IO_PWM_NUM_CH => 30, -- number of PWM channels to implement (0..60); 0 = disabled
339,7 → 343,8
IO_CFS_CONFIG => (others => '0'), -- custom CFS configuration generic
IO_CFS_IN_SIZE => 32, -- size of CFS input conduit in bits
IO_CFS_OUT_SIZE => 32, -- size of CFS output conduit in bits
IO_NEOLED_EN => true -- implement NeoPixel-compatible smart LED interface (NEOLED)?
IO_NEOLED_EN => true, -- implement NeoPixel-compatible smart LED interface (NEOLED)?
IO_NEOLED_TX_FIFO => 8 -- NEOLED TX FIFO depth, 1..32k, has to be a power of two
)
port map (
-- Global control --
/neorv32/trunk/sw/bootloader/bootloader.c
288,7 → 288,7
// setup UART0 (primary UART, no parity bit, no hardware flow control)
neorv32_uart0_setup(UART_BAUD, PARITY_NONE, FLOW_CONTROL_NONE);
// SPI setup
neorv32_spi_setup(SPI_FLASH_CLK_PRSC, 0, 0);
neorv32_spi_setup(SPI_FLASH_CLK_PRSC, 0, 0, 0);
 
PRINT_TEXT("\nNEORV32 bootloader\nLoading from SPI flash at ");
PRINT_XNUM((uint32_t)SPI_BOOT_BASE_ADDR);
316,7 → 316,7
 
#if (SPI_EN != 0)
// setup SPI for 8-bit, clock-mode 0
neorv32_spi_setup(SPI_FLASH_CLK_PRSC, 0, 0);
neorv32_spi_setup(SPI_FLASH_CLK_PRSC, 0, 0, 0);
#endif
 
#if (STATUS_LED_EN != 0)
333,7 → 333,7
 
// Configure machine system timer interrupt for ~2Hz
if (neorv32_mtime_available()) {
neorv32_mtime_set_timecmp(neorv32_mtime_get_time() + (NEORV32_SYSINFO.CLK/4));
neorv32_mtime_set_timecmp(neorv32_cpu_get_systime() + (NEORV32_SYSINFO.CLK/4));
// active timer IRQ
neorv32_cpu_csr_write(CSR_MIE, 1 << CSR_MIE_MTIE); // activate MTIME IRQ source only!
neorv32_cpu_eint(); // enable global interrupts
372,7 → 372,7
if (neorv32_mtime_available()) {
 
PRINT_TEXT("\n\nAutoboot in "xstr(AUTO_BOOT_TIMEOUT)"s. Press key to abort.\n");
uint64_t timeout_time = neorv32_mtime_get_time() + (uint64_t)(AUTO_BOOT_TIMEOUT * NEORV32_SYSINFO.CLK);
uint64_t timeout_time = neorv32_cpu_get_systime() + (uint64_t)(AUTO_BOOT_TIMEOUT * NEORV32_SYSINFO.CLK);
 
while(1){
 
382,7 → 382,7
}
}
 
if (neorv32_mtime_get_time() >= timeout_time) { // timeout? start auto boot sequence
if (neorv32_cpu_get_systime() >= timeout_time) { // timeout? start auto boot sequence
get_exe(EXE_STREAM_FLASH); // try booting from flash
PRINT_TEXT("\n");
start_app();
503,7 → 503,7
#endif
// set time for next IRQ
if (neorv32_mtime_available()) {
neorv32_mtime_set_timecmp(neorv32_mtime_get_time() + (NEORV32_SYSINFO.CLK/4));
neorv32_mtime_set_timecmp(neorv32_cpu_get_systime() + (NEORV32_SYSINFO.CLK/4));
}
}
 
/neorv32/trunk/sw/common/common.mk
16,8 → 16,8
RISCV_PREFIX ?= riscv32-unknown-elf-
 
# CPU architecture and ABI
MARCH ?= -march=rv32i
MABI ?= -mabi=ilp32
MARCH ?= rv32i
MABI ?= ilp32
 
# User flags for additional configuration (will be added to compiler flags)
USER_FLAGS ?=
87,7 → 87,7
IMAGE_GEN = $(NEORV32_EXG_PATH)/image_gen
 
# Compiler & linker flags
CC_OPTS = $(MARCH) $(MABI) $(EFFORT) -Wall -ffunction-sections -fdata-sections -nostartfiles -mno-fdiv
CC_OPTS = -march=$(MARCH) -mabi=$(MABI) $(EFFORT) -Wall -ffunction-sections -fdata-sections -nostartfiles -mno-fdiv
CC_OPTS += -Wl,--gc-sections -lm -lc -lgcc -lc
# This accelerates instruction fetch after branches when C extension is enabled (irrelevant when C extension is disabled)
CC_OPTS += -falign-functions=4 -falign-labels=4 -falign-loops=4 -falign-jumps=4
104,13 → 104,15
exe: $(APP_ASM) $(APP_EXE)
hex: $(APP_ASM) $(APP_HEX)
compile: $(APP_ASM) $(APP_EXE)
install: $(APP_ASM) $(APP_IMG)
all: $(APP_ASM) $(APP_EXE) $(APP_IMG) $(APP_HEX)
image: $(APP_ASM) $(APP_IMG)
install: image install-$(APP_IMG)
all: $(APP_ASM) $(APP_EXE) $(APP_IMG) $(APP_HEX) install
 
# Check if making bootloader
# Use different base address and legth for instruction memory/"rom" (BOOTMEM instead of IMEM)
# Also define "make_bootloader" for crt0.S
# Use different base address and length for instruction memory/"rom" (BOOTROM instead of IMEM)
# Also define "make_bootloader" symbol for crt0.S
target bootloader: CC_OPTS += -Wl,--defsym=make_bootloader=1 -Dmake_bootloader
target bl_image: CC_OPTS += -Wl,--defsym=make_bootloader=1 -Dmake_bootloader
 
 
# -----------------------------------------------------------------------------
174,6 → 176,9
$(APP_IMG): main.bin $(IMAGE_GEN)
@set -e
@$(IMAGE_GEN) -app_img $< $@ $(shell basename $(CURDIR))
 
install-$(APP_IMG): $(APP_IMG)
@set -e
@echo "Installing application image to $(NEORV32_RTL_PATH)/$(APP_IMG)"
@cp $(APP_IMG) $(NEORV32_RTL_PATH)/.
 
190,11 → 195,15
$(BOOT_IMG): main.bin $(IMAGE_GEN)
@set -e
@$(IMAGE_GEN) -bld_img $< $(BOOT_IMG) $(shell basename $(CURDIR))
 
install-$(BOOT_IMG): $(BOOT_IMG)
@set -e
@echo "Installing bootloader image to $(NEORV32_RTL_PATH)/$(BOOT_IMG)"
@cp $(BOOT_IMG) $(NEORV32_RTL_PATH)/.
 
# Just an alias that
bootloader: $(BOOT_IMG)
# Just an alias
bl_image: $(BOOT_IMG)
bootloader: bl_image install-$(BOOT_IMG)
 
 
# -----------------------------------------------------------------------------
267,7 → 276,7
# -----------------------------------------------------------------------------
# In-console simulation using default/simple testbench and GHDL
# -----------------------------------------------------------------------------
sim: $(APP_IMG)
sim: $(APP_IMG) install
@echo "Simulating $(APP_IMG)..."
@sh $(NEORV32_SIM_PATH)/simple/ghdl.sh
 
290,6 → 299,7
@echo " info - show makefile/toolchain configuration"
@echo " exe - compile and generate <neorv32_exe.bin> executable for upload via bootloader"
@echo " hex - compile and generate <neorv32_exe.hex> executable raw file"
@echo " image - compile and generate VHDL IMEM boot image (for application) in local folder"
@echo " install - compile, generate and install VHDL IMEM boot image (for application)"
@echo " sim - in-console simulation using default/simple testbench and GHDL"
@echo " all - exe + hex + install"
296,6 → 306,7
@echo " elf_info - show ELF layout info"
@echo " clean - clean up project"
@echo " clean_all - clean up project, core libraries and image generator"
@echo " bl_image - compile and generate VHDL BOOTROM boot image (for bootloader only!) in local folder"
@echo " bootloader - compile, generate and install VHDL BOOTROM boot image (for bootloader only!)"
 
 
/neorv32/trunk/sw/example/bitmanip_test/main.c
78,7 → 78,7
neorv32_rte_setup();
 
// init UART at default baud rate, no parity bits, ho hw flow control
neorv32_uart_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
neorv32_uart0_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
 
// Disable compilation by default
#ifndef RUN_CHECK
85,13 → 85,13
#warning Program HAS NOT BEEN COMPILED! Use >>make USER_FLAGS+=-DRUN_CHECK clean_all exe<< to compile it.
 
// inform the user if you are actually executing this
neorv32_uart_printf("ERROR! Program has not been compiled. Use >>make USER_FLAGS+=-DRUN_CHECK clean_all exe<< to compile it.\n");
neorv32_uart0_printf("ERROR! Program has not been compiled. Use >>make USER_FLAGS+=-DRUN_CHECK clean_all exe<< to compile it.\n");
 
return 1;
#endif
 
// intro
neorv32_uart_printf("NEORV32 'Zbb' Bit-Manipulation Extension Test\n\n");
neorv32_uart0_printf("NEORV32 'Zbb' Bit-Manipulation Extension Test\n\n");
 
// check available hardware extensions and compare with compiler flags
neorv32_rte_check_isa(0); // silent = 0 -> show message if isa mismatch
98,14 → 98,14
 
// check if Zbb extension is implemented at all
if ((NEORV32_SYSINFO.CPU & (1<<SYSINFO_CPU_ZBB)) == 0) {
neorv32_uart_print("Error! <Zbb> extension not synthesized!\n");
neorv32_uart0_print("Error! <Zbb> extension not synthesized!\n");
return 1;
}
 
neorv32_uart_printf("Starting Zbb bit-manipulation extension tests (%i test cases per instruction)...\n", num_tests);
neorv32_uart0_printf("Starting Zbb bit-manipulation extension tests (%i test cases per instruction)...\n", num_tests);
 
// ANDN
neorv32_uart_printf("\nANDN:\n");
neorv32_uart0_printf("\nANDN:\n");
err_cnt = 0;
for (i=0;i<num_tests; i++) {
opa = xorshift32();
117,7 → 117,7
print_report(err_cnt, num_tests);
 
// ORN
neorv32_uart_printf("\nORN:\n");
neorv32_uart0_printf("\nORN:\n");
err_cnt = 0;
for (i=0;i<num_tests; i++) {
opa = xorshift32();
129,7 → 129,7
print_report(err_cnt, num_tests);
 
// XNOR
neorv32_uart_printf("\nXNOR:\n");
neorv32_uart0_printf("\nXNOR:\n");
err_cnt = 0;
for (i=0;i<num_tests; i++) {
opa = xorshift32();
143,7 → 143,7
 
 
// CLZ
neorv32_uart_printf("\nCLZ:\n");
neorv32_uart0_printf("\nCLZ:\n");
err_cnt = 0;
for (i=0;i<num_tests; i++) {
opa = xorshift32();
154,7 → 154,7
print_report(err_cnt, num_tests);
 
// CTZ
neorv32_uart_printf("\nCTZ:\n");
neorv32_uart0_printf("\nCTZ:\n");
err_cnt = 0;
for (i=0;i<num_tests; i++) {
opa = xorshift32();
167,7 → 167,7
 
 
// CPOP
neorv32_uart_printf("\nCPOP:\n");
neorv32_uart0_printf("\nCPOP:\n");
err_cnt = 0;
for (i=0;i<num_tests; i++) {
opa = xorshift32();
180,7 → 180,7
 
 
// MAX
neorv32_uart_printf("\nMAX:\n");
neorv32_uart0_printf("\nMAX:\n");
err_cnt = 0;
for (i=0;i<num_tests; i++) {
opa = xorshift32();
192,7 → 192,7
print_report(err_cnt, num_tests);
 
// MAXU
neorv32_uart_printf("\nMAXU:\n");
neorv32_uart0_printf("\nMAXU:\n");
err_cnt = 0;
for (i=0;i<num_tests; i++) {
opa = xorshift32();
204,7 → 204,7
print_report(err_cnt, num_tests);
 
// MIN
neorv32_uart_printf("\nMIN:\n");
neorv32_uart0_printf("\nMIN:\n");
err_cnt = 0;
for (i=0;i<num_tests; i++) {
opa = xorshift32();
216,7 → 216,7
print_report(err_cnt, num_tests);
 
// MINU
neorv32_uart_printf("\nMINU:\n");
neorv32_uart0_printf("\nMINU:\n");
err_cnt = 0;
for (i=0;i<num_tests; i++) {
opa = xorshift32();
230,7 → 230,7
 
 
// SEXT.B
neorv32_uart_printf("\nSEXT.B:\n");
neorv32_uart0_printf("\nSEXT.B:\n");
err_cnt = 0;
for (i=0;i<num_tests; i++) {
opa = xorshift32();
241,7 → 241,7
print_report(err_cnt, num_tests);
 
// SEXT.H
neorv32_uart_printf("\nSEXT.H:\n");
neorv32_uart0_printf("\nSEXT.H:\n");
err_cnt = 0;
for (i=0;i<num_tests; i++) {
opa = xorshift32();
252,7 → 252,7
print_report(err_cnt, num_tests);
 
// ZEXT.H
neorv32_uart_printf("\nZEXT.H:\n");
neorv32_uart0_printf("\nZEXT.H:\n");
err_cnt = 0;
for (i=0;i<num_tests; i++) {
opa = xorshift32();
265,7 → 265,7
 
 
// ROL
neorv32_uart_printf("\nROL:\n");
neorv32_uart0_printf("\nROL:\n");
err_cnt = 0;
for (i=0;i<num_tests; i++) {
opa = xorshift32();
277,7 → 277,7
print_report(err_cnt, num_tests);
 
// ROR
neorv32_uart_printf("\nROR:\n");
neorv32_uart0_printf("\nROR:\n");
err_cnt = 0;
for (i=0;i<num_tests; i++) {
opa = xorshift32();
289,7 → 289,7
print_report(err_cnt, num_tests);
 
// RORI
neorv32_uart_printf("\nRORI (imm=20):\n"); // FIXME: static immediate
neorv32_uart0_printf("\nRORI (imm=20):\n"); // FIXME: static immediate
err_cnt = 0;
for (i=0;i<num_tests; i++) {
opa = xorshift32();
302,7 → 302,7
 
 
// ORC.B
neorv32_uart_printf("\nORCB:\n");
neorv32_uart0_printf("\nORCB:\n");
err_cnt = 0;
for (i=0;i<num_tests; i++) {
opa = xorshift32();
315,7 → 315,7
 
 
// REV8
neorv32_uart_printf("\nREV8:\n");
neorv32_uart0_printf("\nREV8:\n");
err_cnt = 0;
for (i=0;i<num_tests; i++) {
opa = xorshift32();
326,7 → 326,7
print_report(err_cnt, num_tests);
 
 
neorv32_uart_printf("\nBit manipulation extension tests done.\n");
neorv32_uart0_printf("\nBit manipulation extension tests done.\n");
 
return 0;
}
362,8 → 362,8
uint32_t check_result(uint32_t num, uint32_t opa, uint32_t opb, uint32_t ref, uint32_t res) {
 
if (ref != res) {
neorv32_uart_printf("%u: opa = 0x%x, opb = 0x%x : ref = 0x%x vs res = 0x%x ", num, opa, opb, ref, res);
neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
neorv32_uart0_printf("%u: opa = 0x%x, opb = 0x%x : ref = 0x%x vs res = 0x%x ", num, opa, opb, ref, res);
neorv32_uart0_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
return 1;
}
else {
380,12 → 380,12
**************************************************************************/
void print_report(int num_err, int num_tests) {
 
neorv32_uart_printf("Errors: %i/%i ", num_err, num_tests);
neorv32_uart0_printf("Errors: %i/%i ", num_err, num_tests);
 
if (num_err == 0) {
neorv32_uart_printf("%c[1m[ok]%c[0m\n", 27, 27);
neorv32_uart0_printf("%c[1m[ok]%c[0m\n", 27, 27);
}
else {
neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
neorv32_uart0_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
}
}
/neorv32/trunk/sw/example/blink_led/main.c
74,11 → 74,11
int main() {
 
// init UART (primary UART = UART0; if no id number is specified the primary UART is used) at default baud rate, no parity bits, ho hw flow control
neorv32_uart_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
neorv32_uart0_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
 
// check if GPIO unit is implemented at all
if (neorv32_gpio_available() == 0) {
neorv32_uart_print("Error! No GPIO unit synthesized!\n");
neorv32_uart0_print("Error! No GPIO unit synthesized!\n");
return 1; // nope, no GPIO unit synthesized
}
 
87,7 → 87,7
neorv32_rte_setup();
 
// say hello
neorv32_uart_print("Blinking LED demo program\n");
neorv32_uart0_print("Blinking LED demo program\n");
 
 
// use ASM version of LED blinking (file: blink_led_in_asm.S)
/neorv32/trunk/sw/example/coremark/README.md
17,7 → 17,7
 
To build the executable for a certain CPU configuration and a certain optimization level of the benchmark, type (`rv32imc` and `O3` in this example):
 
`> make USER_FLAGS+=-DRUN_COREMARK MARCH=-march=rv32imc EFFORT=-O3 clean_all exe`
`> make USER_FLAGS+=-DRUN_COREMARK MARCH=rv32imc EFFORT=-O3 clean_all exe`
 
 
# Running
/neorv32/trunk/sw/example/coremark/core_portme.c
151,7 → 151,7
/* NEORV32-specific */
neorv32_cpu_dint(); // no interrupt, thanks
neorv32_rte_setup(); // capture all exceptions and give debug information, ho hw flow control
neorv32_uart_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
neorv32_uart0_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
 
 
// Disable coremark compilation by default
159,7 → 159,7
#warning COREMARK HAS NOT BEEN COMPILED! Use >>make USER_FLAGS+=-DRUN_COREMARK clean_all exe<< to compile it.
 
// inform the user if you are actually executing this
neorv32_uart_printf("ERROR! CoreMark has not been compiled. Use >>make USER_FLAGS+=-DRUN_COREMARK clean_all exe<< to compile it.\n");
neorv32_uart0_printf("ERROR! CoreMark has not been compiled. Use >>make USER_FLAGS+=-DRUN_COREMARK clean_all exe<< to compile it.\n");
 
while(1);
#endif
183,8 → 183,8
neorv32_cpu_csr_write(CSR_MHPMCOUNTER13, 0); neorv32_cpu_csr_write(CSR_MHPMEVENT13, 1 << HPMCNT_EVENT_TRAP);
neorv32_cpu_csr_write(CSR_MHPMCOUNTER14, 0); neorv32_cpu_csr_write(CSR_MHPMEVENT14, 1 << HPMCNT_EVENT_ILLEGAL);
 
neorv32_uart_printf("NEORV32: Processor running at %u Hz\n", (uint32_t)NEORV32_SYSINFO.CLK);
neorv32_uart_printf("NEORV32: Executing coremark (%u iterations). This may take some time...\n\n", (uint32_t)ITERATIONS);
neorv32_uart0_printf("NEORV32: Processor running at %u Hz\n", (uint32_t)NEORV32_SYSINFO.CLK);
neorv32_uart0_printf("NEORV32: Executing coremark (%u iterations). This may take some time...\n\n", (uint32_t)ITERATIONS);
 
// clear cycle counter
neorv32_cpu_set_mcycle(0);
231,28 → 231,28
exe_time.uint64 = (uint64_t)get_time();
exe_instructions.uint64 = neorv32_cpu_get_instret();
 
neorv32_uart_printf("\nNEORV32: All reported numbers only show the integer part.\n\n");
neorv32_uart0_printf("\nNEORV32: All reported numbers only show the integer part.\n\n");
 
neorv32_uart_printf("NEORV32: HPM results\n");
if (num_hpm_cnts_global == 0) {neorv32_uart_printf("no HPMs available\n"); }
if (num_hpm_cnts_global > 0) {neorv32_uart_printf("# Retired compr. instructions: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER3)); }
if (num_hpm_cnts_global > 1) {neorv32_uart_printf("# I-fetch wait cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER4)); }
if (num_hpm_cnts_global > 2) {neorv32_uart_printf("# I-issue wait cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER5)); }
if (num_hpm_cnts_global > 3) {neorv32_uart_printf("# Multi-cycle ALU wait cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER6)); }
if (num_hpm_cnts_global > 4) {neorv32_uart_printf("# Load operations: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER7)); }
if (num_hpm_cnts_global > 5) {neorv32_uart_printf("# Store operations: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER8)); }
if (num_hpm_cnts_global > 6) {neorv32_uart_printf("# Load/store wait cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER9)); }
if (num_hpm_cnts_global > 7) {neorv32_uart_printf("# Unconditional jumps: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER10)); }
if (num_hpm_cnts_global > 8) {neorv32_uart_printf("# Conditional branches (all): %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER11)); }
if (num_hpm_cnts_global > 9) {neorv32_uart_printf("# Conditional branches (taken): %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER12)); }
if (num_hpm_cnts_global > 10) {neorv32_uart_printf("# Entered traps: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER13)); }
if (num_hpm_cnts_global > 11) {neorv32_uart_printf("# Illegal operations: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER14)); }
neorv32_uart_printf("\n");
neorv32_uart0_printf("NEORV32: HPM results\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)); }
neorv32_uart0_printf("\n");
 
neorv32_uart_printf("NEORV32: Executed instructions 0x%x_%x\n", (uint32_t)exe_instructions.uint32[1], (uint32_t)exe_instructions.uint32[0]);
neorv32_uart_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_uart_printf("NEORV32: Average CPI (integer part only): %u cycles/instruction\n", (uint32_t)average_cpi_int);
neorv32_uart0_printf("NEORV32: Average CPI (integer part only): %u cycles/instruction\n", (uint32_t)average_cpi_int);
 
}
/neorv32/trunk/sw/example/coremark/core_portme.h
87,7 → 87,7
FLAGS_STR /* "Please put compiler flags here (e.g. -o3)" */
#endif
#ifndef MEM_LOCATION
#define MEM_LOCATION "STACK"
#define MEM_LOCATION "STATIC"
#endif
 
/* Data Types :
142,7 → 142,7
MEM_STACK - to allocate the data block on the stack (NYI).
*/
#ifndef MEM_METHOD
#define MEM_METHOD MEM_STACK
#define MEM_METHOD MEM_STATIC
#endif
 
/* Configuration : MULTITHREAD
/neorv32/trunk/sw/example/coremark/ee_printf.c
683,9 → 683,9
 
/* NEORV32-specific */
if (c == '\n') {
neorv32_uart_putc('\r');
neorv32_uart0_putc('\r');
}
neorv32_uart_putc(c);
neorv32_uart0_putc(c);
}
 
int
/neorv32/trunk/sw/example/demo_freeRTOS/main.c
106,7 → 106,7
prvSetupHardware();
 
/* say hi */
neorv32_uart_printf("FreeRTOS %s on NEORV32 Demo\n\n", tskKERNEL_VERSION_NUMBER);
neorv32_uart0_printf("FreeRTOS %s on NEORV32 Demo\n\n", tskKERNEL_VERSION_NUMBER);
 
/* The mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is described at the top
of this file. */
128,7 → 128,7
neorv32_gpio_port_set(0);
 
// init UART at default baud rate, no parity bits, ho hw flow control
neorv32_uart_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
neorv32_uart0_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
 
// check available hardware extensions and compare with compiler flags
neorv32_rte_check_isa(0); // silent = 0 -> show message if isa mismatch
145,7 → 145,7
 
void vSendString( const char * pcString )
{
neorv32_uart_print( ( const char * ) pcString );
neorv32_uart0_print( ( const char * ) pcString );
}
 
/*-----------------------------------------------------------*/
163,7 → 163,7
to query the size of free heap space that remains (although it does not
provide information on how the remaining heap might be fragmented). */
taskDISABLE_INTERRUPTS();
neorv32_uart_print("FreeRTOS_FAULT: vApplicationMallocFailedHook (solution: increase 'configTOTAL_HEAP_SIZE' in FreeRTOSConfig.h)\n");
neorv32_uart0_print("FreeRTOS_FAULT: vApplicationMallocFailedHook (solution: increase 'configTOTAL_HEAP_SIZE' in FreeRTOSConfig.h)\n");
__asm volatile( "ebreak" );
for( ;; );
}
194,7 → 194,7
configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook
function is called if a stack overflow is detected. */
taskDISABLE_INTERRUPTS();
neorv32_uart_print("FreeRTOS_FAULT: vApplicationStackOverflowHook\n");
neorv32_uart0_print("FreeRTOS_FAULT: vApplicationStackOverflowHook\n");
__asm volatile( "ebreak" );
for( ;; );
}
217,7 → 217,7
/* This handler is responsible for handling all interrupts. Only the machine timer interrupt is handled by the kernel. */
void SystemIrqHandler( uint32_t mcause )
{
neorv32_uart_printf("freeRTOS: Unknown interrupt (0x%x)\n", mcause);
neorv32_uart0_printf("freeRTOS: Unknown interrupt (0x%x)\n", mcause);
}
 
 
232,8 → 232,8
int main() {
 
// init UART at default baud rate, no parity bits, ho hw flow control
neorv32_uart_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
neorv32_uart_print("ERROR! FreeRTOS has not been compiled. Use >>make USER_FLAGS+=-DRUN_FREERTOS_DEMO clean_all exe<< to compile it.\n");
neorv32_uart0_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
neorv32_uart0_print("ERROR! FreeRTOS has not been compiled. Use >>make USER_FLAGS+=-DRUN_FREERTOS_DEMO clean_all exe<< to compile it.\n");
return 1;
}
#endif
/neorv32/trunk/sw/example/demo_freeRTOS/makefile
53,8 → 53,8
RISCV_PREFIX ?= riscv32-unknown-elf-
 
# CPU architecture and ABI
MARCH ?= -march=rv32i
MABI ?= -mabi=ilp32
MARCH ?= rv32i
MABI ?= ilp32
 
# User flags for additional configuration (will be added to compiler flags)
USER_FLAGS ?=
/neorv32/trunk/sw/example/demo_neopixel/main.c
75,12 → 75,12
 
 
// setup UART0 at default baud rate, no parity bits, no hw flow control
neorv32_uart_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
neorv32_uart0_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
 
 
// check if NEOLED unit is implemented at all, abort if not
if (neorv32_neoled_available() == 0) {
neorv32_uart_printf("Error! No NEOLED unit synthesized!\n");
neorv32_uart0_printf("Error! No NEOLED unit synthesized!\n");
return 1;
}
 
/neorv32/trunk/sw/example/demo_trng/main.c
66,7 → 66,7
int main(void) {
 
// check if UART unit is implemented at all
if (neorv32_uart_available() == 0) {
if (neorv32_uart0_available() == 0) {
return 1;
}
 
76,17 → 76,17
 
 
// init UART at default baud rate, no parity bits, ho hw flow control
neorv32_uart_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
neorv32_uart0_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
 
// check available hardware extensions and compare with compiler flags
neorv32_rte_check_isa(0); // silent = 0 -> show message if isa mismatch
 
// intro
neorv32_uart_printf("\n--- TRNG Demo ---\n\n");
neorv32_uart0_printf("\n--- TRNG Demo ---\n\n");
 
// check if TRNG unit is implemented at all
if (neorv32_trng_available() == 0) {
neorv32_uart_printf("No TRNG implemented.");
neorv32_uart0_printf("No TRNG implemented.");
return 1;
}
 
96,14 → 96,14
while(1) {
 
// main menu
neorv32_uart_printf("\nCommands:\n"
neorv32_uart0_printf("\nCommands:\n"
" n: Print 8-bit random numbers (abort by pressing any key)\n"
" h: Generate and print histogram\n");
 
neorv32_uart_printf("CMD:> ");
char cmd = neorv32_uart_getc();
neorv32_uart_putc(cmd); // echo
neorv32_uart_printf("\n");
neorv32_uart0_printf("CMD:> ");
char cmd = neorv32_uart0_getc();
neorv32_uart0_putc(cmd); // echo
neorv32_uart0_printf("\n");
 
if (cmd == 'n') {
print_random_data();
112,7 → 112,7
generate_histogram();
}
else {
neorv32_uart_printf("Invalid command.\n");
neorv32_uart0_printf("Invalid command.\n");
}
}
 
132,16 → 132,16
while(1) {
err = neorv32_trng_get(&trng_data);
if (err) {
neorv32_uart_printf("\nTRNG error!\n");
neorv32_uart0_printf("\nTRNG error!\n");
break;
}
neorv32_uart_printf("%u ", (uint32_t)(trng_data));
neorv32_uart0_printf("%u ", (uint32_t)(trng_data));
num_samples++;
if (neorv32_uart_char_received()) { // abort when key pressed
if (neorv32_uart0_char_received()) { // abort when key pressed
break;
}
}
neorv32_uart_printf("\nPrinted samples: %u\n", num_samples);
neorv32_uart0_printf("\nPrinted samples: %u\n", num_samples);
}
 
 
156,10 → 156,10
int err = 0;
uint8_t trng_data;
 
neorv32_uart_printf("Press any key to start.\n");
neorv32_uart0_printf("Press any key to start.\n");
 
while(neorv32_uart_char_received() == 0);
neorv32_uart_printf("Sampling... Press any key to stop.\n");
while(neorv32_uart0_char_received() == 0);
neorv32_uart0_printf("Sampling... Press any key to stop.\n");
 
// clear histogram
for (i=0; i<256; i++) {
174,11 → 174,11
cnt++;
 
if (err) {
neorv32_uart_printf("\nTRNG error!\n");
neorv32_uart0_printf("\nTRNG error!\n");
break;
}
 
if (neorv32_uart_char_received()) { // abort when key pressed
if (neorv32_uart0_char_received()) { // abort when key pressed
break;
}
 
188,12 → 188,12
}
 
// print histogram
neorv32_uart_printf("Histogram [random data value] : [# occurences]\n");
neorv32_uart0_printf("Histogram [random data value] : [# occurences]\n");
for (i=0; i<256; i++) {
neorv32_uart_printf("%u: %u\n", (uint32_t)i, hist[i]);
neorv32_uart0_printf("%u: %u\n", (uint32_t)i, hist[i]);
}
 
neorv32_uart_printf("\nSamples: %u\n", cnt);
neorv32_uart0_printf("\nSamples: %u\n", cnt);
 
// average
uint64_t average = 0;
201,5 → 201,13
average += (uint64_t)hist[i] * i;
}
average = average / ((uint64_t)cnt);
neorv32_uart_printf("Average value: %u\n", (uint32_t)average);
neorv32_uart0_printf("Average value: %u ", (uint32_t)average);
 
if (((uint8_t)average) == ((uint8_t)(255/2))) {
neorv32_uart0_printf("%c[1m[TEST OK]%c[0m\n", 27, 27);
}
else {
neorv32_uart0_printf("%c[1m[TEST FAILED]%c[0m\n", 27, 27);
}
 
}
/neorv32/trunk/sw/example/demo_twi/main.c
73,7 → 73,7
int bus_claimed = 0;
 
// check if UART unit is implemented at all
if (neorv32_uart_available() == 0) {
if (neorv32_uart0_available() == 0) {
return 1;
}
 
84,24 → 84,24
 
 
// init UART at default baud rate, no parity bits, ho hw flow control
neorv32_uart_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
neorv32_uart0_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
 
// check available hardware extensions and compare with compiler flags
neorv32_rte_check_isa(0); // silent = 0 -> show message if isa mismatch
 
// intro
neorv32_uart_printf("\n--- TWI Bus Explorer ---\n\n");
neorv32_uart0_printf("\n--- TWI Bus Explorer ---\n\n");
 
 
// check if TWI unit is implemented at all
if (neorv32_twi_available() == 0) {
neorv32_uart_printf("No TWI unit implemented.");
neorv32_uart0_printf("No TWI unit implemented.");
return 1;
}
 
 
// info
neorv32_uart_printf("This program allows to create TWI transfers by hand.\n"
neorv32_uart0_printf("This program allows to create TWI transfers by hand.\n"
"Type 'help' to see the help menu.\n\n");
 
// configure TWI, second slowest clock, no clock-stretching
112,9 → 112,9
 
// Main menu
for (;;) {
neorv32_uart_printf("TWI_EXPLORER:> ");
length = neorv32_uart_scan(buffer, 8, 1);
neorv32_uart_printf("\n");
neorv32_uart0_printf("TWI_EXPLORER:> ");
length = neorv32_uart0_scan(buffer, 8, 1);
neorv32_uart0_printf("\n");
 
if (!length) // nothing to be done
continue;
121,7 → 121,7
 
// decode input and execute command
if (!strcmp(buffer, "help")) {
neorv32_uart_printf("Available commands:\n"
neorv32_uart0_printf("Available commands:\n"
" help - show this text\n"
" scan - scan bus for devices\n"
" start - generate START condition\n"
138,7 → 138,7
}
else if (!strcmp(buffer, "stop")) {
if (bus_claimed == 0) {
neorv32_uart_printf("No active I2C transmission.\n");
neorv32_uart0_printf("No active I2C transmission.\n");
continue;
}
neorv32_twi_generate_stop(); // generate STOP condition
152,7 → 152,7
}
else if (!strcmp(buffer, "send")) {
if (bus_claimed == 0) {
neorv32_uart_printf("No active I2C transmission. Generate a START condition first.\n");
neorv32_uart0_printf("No active I2C transmission. Generate a START condition first.\n");
continue;
}
else {
160,7 → 160,7
}
}
else {
neorv32_uart_printf("Invalid command. Type 'help' to see all commands.\n");
neorv32_uart0_printf("Invalid command. Type 'help' to see all commands.\n");
}
}
 
175,17 → 175,17
 
char terminal_buffer[2];
 
neorv32_uart_printf("Select new clock prescaler (0..7): ");
neorv32_uart_scan(terminal_buffer, 2, 1); // 1 hex char plus '\0'
neorv32_uart0_printf("Select new clock prescaler (0..7): ");
neorv32_uart0_scan(terminal_buffer, 2, 1); // 1 hex char plus '\0'
uint8_t prsc = (uint8_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
 
if ((prsc >= 0) && (prsc < 8)) { // valid?
NEORV32_TWI.CTRL = 0; // reset
NEORV32_TWI.CTRL = (1 << TWI_CTRL_EN) | (prsc << TWI_CTRL_PRSC0);
neorv32_uart_printf("\nDone.\n");
neorv32_uart0_printf("\nDone.\n");
}
else {
neorv32_uart_printf("\nInvalid selection!\n");
neorv32_uart0_printf("\nInvalid selection!\n");
return;
}
 
203,7 → 203,7
default: div = 0; break;
}
uint32_t clock = NEORV32_SYSINFO.CLK / div;
neorv32_uart_printf("New I2C clock: %u Hz\n", clock);
neorv32_uart0_printf("New I2C clock: %u Hz\n", clock);
}
 
 
212,7 → 212,7
**************************************************************************/
void scan_twi(void) {
 
neorv32_uart_printf("Scanning TWI bus...\n");
neorv32_uart0_printf("Scanning TWI bus...\n");
uint8_t i, num_devices = 0;
for (i=0; i<128; i++) {
uint8_t twi_ack = neorv32_twi_start_trans((uint8_t)(2*i+1));
219,13 → 219,13
neorv32_twi_generate_stop();
 
if (twi_ack == 0) {
neorv32_uart_printf("+ Found device at write-address 0x%x\n", (uint32_t)(2*i));
neorv32_uart0_printf("+ Found device at write-address 0x%x\n", (uint32_t)(2*i));
num_devices++;
}
}
 
if (!num_devices) {
neorv32_uart_printf("No devices found.\n");
neorv32_uart0_printf("No devices found.\n");
}
}
 
238,16 → 238,16
char terminal_buffer[4];
 
// enter data
neorv32_uart_printf("Enter TX data (2 hex chars): ");
neorv32_uart_scan(terminal_buffer, 3, 1); // 2 hex chars for address plus '\0'
neorv32_uart0_printf("Enter TX data (2 hex chars): ");
neorv32_uart0_scan(terminal_buffer, 3, 1); // 2 hex chars for address plus '\0'
uint8_t tmp = (uint8_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
uint8_t res = neorv32_twi_trans(tmp);
neorv32_uart_printf("\nRX data: 0x%x\n", (uint32_t)neorv32_twi_get_data());
neorv32_uart_printf("Response: ");
neorv32_uart0_printf("\nRX data: 0x%x\n", (uint32_t)neorv32_twi_get_data());
neorv32_uart0_printf("Response: ");
if (res == 0)
neorv32_uart_printf("ACK\n");
neorv32_uart0_printf("ACK\n");
else
neorv32_uart_printf("NACK\n");
neorv32_uart0_printf("NACK\n");
 
}
 
/neorv32/trunk/sw/example/demo_wdt/main.c
66,7 → 66,7
}
 
// check if UART unit is implemented at all
if (neorv32_uart_available() == 0) {
if (neorv32_uart0_available() == 0) {
return 1; // nope, no UART unit synthesized
}
 
76,27 → 76,27
neorv32_rte_setup();
 
// init UART at default baud rate, no parity bits, ho hw flow control
neorv32_uart_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
neorv32_uart0_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
 
// check available hardware extensions and compare with compiler flags
neorv32_rte_check_isa(0); // silent = 0 -> show message if isa mismatch
 
// simple text output via UART (strings only)
neorv32_uart_print("\nWatchdog system reset demo program\n\n");
neorv32_uart0_print("\nWatchdog system reset demo program\n\n");
 
 
// show the cause of the last processor reset
neorv32_uart_print("Cause of last processor reset: ");
neorv32_uart0_print("Cause of last processor reset: ");
uint8_t wdt_cause = neorv32_wdt_get_cause();
 
if (wdt_cause == 0) {
neorv32_uart_print("External reset\n");
neorv32_uart0_print("External reset\n");
}
else if (wdt_cause == 1) {
neorv32_uart_print("Watchdog\n");
neorv32_uart0_print("Watchdog\n");
}
else {
neorv32_uart_print("Undefined\n");
neorv32_uart0_print("Undefined\n");
}
 
 
109,7 → 109,7
 
 
 
neorv32_uart_print("\n\nWill reset WDT 64 times.\n"
neorv32_uart0_print("\n\nWill reset WDT 64 times.\n"
"A system reset will be executed in the following time out.\n"
"Press any key to trigger manual WDT hardware reset by WDT access with wrong password.\n"
"Restart this program after reset to check for the reset cause.\n\n"
117,18 → 117,18
 
uint8_t i;
for (i=0; i<64; i++) {
neorv32_uart_putc('.');
neorv32_uart0_putc('.');
neorv32_wdt_reset(); // reset watchdog
neorv32_cpu_delay_ms(80); // wait some time
 
// trigger manual reset if key pressed
if (neorv32_uart_char_received()) { // just check, if a char has been received
if (neorv32_uart0_char_received()) { // just check, if a char has been received
neorv32_wdt_force(); // access wdt with wrong password
}
}
 
while (1) { // wait for the watchdog time-out or trigger manual reset if key pressed
if (neorv32_uart_char_received()) { // just check, if a char has been received
if (neorv32_uart0_char_received()) { // just check, if a char has been received
neorv32_wdt_force(); // access wdt with wrong password
}
}
/neorv32/trunk/sw/example/dhrystone/dhry_1.c
28,7 → 28,7
 
 
#ifndef DHRY_ITERS
#define DHRY_ITERS 2000
#define DHRY_ITERS 10000
#endif
 
/* Global Variables: */
104,12 → 104,12
{ /* ***** NEORV32-SPECIFIC ***** */
neorv32_cpu_dint(); // no interrupt, thanks
neorv32_rte_setup(); // capture all exceptions and give debug information, ho hw flow control
neorv32_uart_setup(19200, PARITY_NONE, FLOW_CONTROL_NONE);
neorv32_uart0_setup(19200, PARITY_NONE, FLOW_CONTROL_NONE);
// check available hardware extensions and compare with compiler flags
neorv32_rte_check_isa(0); // silent = 0 -> show message if isa mismatch
 
neorv32_uart_printf("NEORV32: Processor running at %u Hz\n", (uint32_t)NEORV32_SYSINFO.CLK);
neorv32_uart_printf("NEORV32: Executing Dhrystone (%u iterations). This may take some time...\n\n", (uint32_t)DHRY_ITERS);
neorv32_uart0_printf("NEORV32: Processor running at %u Hz\n", (uint32_t)NEORV32_SYSINFO.CLK);
neorv32_uart0_printf("NEORV32: Executing Dhrystone (%u iterations). This may take some time...\n\n", (uint32_t)DHRY_ITERS);
 
// clear cycle counter
neorv32_cpu_set_mcycle(0);
118,7 → 118,7
#warning DHRYSTONE HAS NOT BEEN COMPILED! Use >>make USER_FLAGS+=-DRUN_DHRYSTONE clean_all exe<< to compile it.
 
// inform the user if you are actually executing this
neorv32_uart_printf("ERROR! CoreMark has not been compiled. Use >>make USER_FLAGS+=-DRUN_COREMARK clean_all exe<< to compile it.\n");
neorv32_uart0_printf("ERROR! CoreMark has not been compiled. Use >>make USER_FLAGS+=-DRUN_COREMARK clean_all exe<< to compile it.\n");
 
while(1);
#endif
150,32 → 150,32
/* Warning: With 16-Bit processors and Number_Of_Runs > 32000, */
/* overflow may occur for this array element. */
 
neorv32_uart_printf ("\n");
neorv32_uart_printf ("Dhrystone Benchmark, Version 2.1 (Language: C)\n");
neorv32_uart_printf ("\n");
neorv32_uart0_printf ("\n");
neorv32_uart0_printf ("Dhrystone Benchmark, Version 2.1 (Language: C)\n");
neorv32_uart0_printf ("\n");
if (Reg)
{
neorv32_uart_printf ("Program compiled with 'register' attribute\n");
neorv32_uart_printf ("\n");
neorv32_uart0_printf ("Program compiled with 'register' attribute\n");
neorv32_uart0_printf ("\n");
}
else
{
neorv32_uart_printf ("Program compiled without 'register' attribute\n");
neorv32_uart_printf ("\n");
neorv32_uart0_printf ("Program compiled without 'register' attribute\n");
neorv32_uart0_printf ("\n");
}
#ifdef DHRY_ITERS
Number_Of_Runs = DHRY_ITERS;
#else
neorv32_uart_printf ("Please give the number of runs through the benchmark: ");
neorv32_uart0_printf ("Please give the number of runs through the benchmark: ");
{
int n;
scanf ("%d", &n);
Number_Of_Runs = n;
}
neorv32_uart_printf ("\n");
neorv32_uart0_printf ("\n");
#endif
 
neorv32_uart_printf ("Execution starts, %u runs through Dhrystone\n", (uint32_t)Number_Of_Runs);
neorv32_uart0_printf ("Execution starts, %u runs through Dhrystone\n", (uint32_t)Number_Of_Runs);
 
/***************/
/* Start timer */
266,66 → 266,66
} /* ***** /NEORV32-SPECIFIC ***** */
 
neorv32_uart_printf ("Execution ends\n");
neorv32_uart_printf ("\n");
neorv32_uart_printf ("Final values of the variables used in the benchmark:\n");
neorv32_uart_printf ("\n");
neorv32_uart_printf ("Int_Glob: %u\n", (uint32_t)Int_Glob);
neorv32_uart_printf (" should be: %u\n", 5);
neorv32_uart_printf ("Bool_Glob: %u\n", (uint32_t)Bool_Glob);
neorv32_uart_printf (" should be: %u\n", 1);
neorv32_uart_printf ("Ch_1_Glob: %c\n", (uint32_t)Ch_1_Glob);
neorv32_uart_printf (" should be: %c\n", 'A');
neorv32_uart_printf ("Ch_2_Glob: %c\n", (uint32_t)Ch_2_Glob);
neorv32_uart_printf (" should be: %c\n", 'B');
neorv32_uart_printf ("Arr_1_Glob[8]: %u\n", (uint32_t)Arr_1_Glob[8]);
neorv32_uart_printf (" should be: %u\n", 7);
neorv32_uart_printf ("Arr_2_Glob[8][7]: %u\n", (uint32_t)Arr_2_Glob[8][7]);
neorv32_uart_printf (" should be: Number_Of_Runs + 10\n");
neorv32_uart_printf ("Ptr_Glob->\n");
neorv32_uart_printf (" Ptr_Comp: %u\n", (uint32_t) Ptr_Glob->Ptr_Comp);
neorv32_uart_printf (" should be: (implementation-dependent)\n");
neorv32_uart_printf (" Discr: %u\n", (uint32_t)Ptr_Glob->Discr);
neorv32_uart_printf (" should be: %u\n", 0);
neorv32_uart_printf (" Enum_Comp: %u\n", (uint32_t)Ptr_Glob->variant.var_1.Enum_Comp);
neorv32_uart_printf (" should be: %u\n", 2);
neorv32_uart_printf (" Int_Comp: %u\n", (uint32_t)Ptr_Glob->variant.var_1.Int_Comp);
neorv32_uart_printf (" should be: %u\n", 17);
neorv32_uart_printf (" Str_Comp: %s\n", Ptr_Glob->variant.var_1.Str_Comp);
neorv32_uart_printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n");
neorv32_uart_printf ("Next_Ptr_Glob->\n");
neorv32_uart_printf (" Ptr_Comp: %u\n", (uint32_t) Next_Ptr_Glob->Ptr_Comp);
neorv32_uart_printf (" should be: (implementation-dependent), same as above\n");
neorv32_uart_printf (" Discr: %u\n", (uint32_t)Next_Ptr_Glob->Discr);
neorv32_uart_printf (" should be: %u\n", 0);
neorv32_uart_printf (" Enum_Comp: %u\n", (uint32_t)Next_Ptr_Glob->variant.var_1.Enum_Comp);
neorv32_uart_printf (" should be: %u\n", 1);
neorv32_uart_printf (" Int_Comp: %u\n", (uint32_t)Next_Ptr_Glob->variant.var_1.Int_Comp);
neorv32_uart_printf (" should be: %u\n", 18);
neorv32_uart_printf (" Str_Comp: %s\n",
neorv32_uart0_printf ("Execution ends\n");
neorv32_uart0_printf ("\n");
neorv32_uart0_printf ("Final values of the variables used in the benchmark:\n");
neorv32_uart0_printf ("\n");
neorv32_uart0_printf ("Int_Glob: %u\n", (uint32_t)Int_Glob);
neorv32_uart0_printf (" should be: %u\n", 5);
neorv32_uart0_printf ("Bool_Glob: %u\n", (uint32_t)Bool_Glob);
neorv32_uart0_printf (" should be: %u\n", 1);
neorv32_uart0_printf ("Ch_1_Glob: %c\n", (uint32_t)Ch_1_Glob);
neorv32_uart0_printf (" should be: %c\n", 'A');
neorv32_uart0_printf ("Ch_2_Glob: %c\n", (uint32_t)Ch_2_Glob);
neorv32_uart0_printf (" should be: %c\n", 'B');
neorv32_uart0_printf ("Arr_1_Glob[8]: %u\n", (uint32_t)Arr_1_Glob[8]);
neorv32_uart0_printf (" should be: %u\n", 7);
neorv32_uart0_printf ("Arr_2_Glob[8][7]: %u\n", (uint32_t)Arr_2_Glob[8][7]);
neorv32_uart0_printf (" should be: Number_Of_Runs + 10\n");
neorv32_uart0_printf ("Ptr_Glob->\n");
neorv32_uart0_printf (" Ptr_Comp: %u\n", (uint32_t) Ptr_Glob->Ptr_Comp);
neorv32_uart0_printf (" should be: (implementation-dependent)\n");
neorv32_uart0_printf (" Discr: %u\n", (uint32_t)Ptr_Glob->Discr);
neorv32_uart0_printf (" should be: %u\n", 0);
neorv32_uart0_printf (" Enum_Comp: %u\n", (uint32_t)Ptr_Glob->variant.var_1.Enum_Comp);
neorv32_uart0_printf (" should be: %u\n", 2);
neorv32_uart0_printf (" Int_Comp: %u\n", (uint32_t)Ptr_Glob->variant.var_1.Int_Comp);
neorv32_uart0_printf (" should be: %u\n", 17);
neorv32_uart0_printf (" Str_Comp: %s\n", Ptr_Glob->variant.var_1.Str_Comp);
neorv32_uart0_printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n");
neorv32_uart0_printf ("Next_Ptr_Glob->\n");
neorv32_uart0_printf (" Ptr_Comp: %u\n", (uint32_t) Next_Ptr_Glob->Ptr_Comp);
neorv32_uart0_printf (" should be: (implementation-dependent), same as above\n");
neorv32_uart0_printf (" Discr: %u\n", (uint32_t)Next_Ptr_Glob->Discr);
neorv32_uart0_printf (" should be: %u\n", 0);
neorv32_uart0_printf (" Enum_Comp: %u\n", (uint32_t)Next_Ptr_Glob->variant.var_1.Enum_Comp);
neorv32_uart0_printf (" should be: %u\n", 1);
neorv32_uart0_printf (" Int_Comp: %u\n", (uint32_t)Next_Ptr_Glob->variant.var_1.Int_Comp);
neorv32_uart0_printf (" should be: %u\n", 18);
neorv32_uart0_printf (" Str_Comp: %s\n",
Next_Ptr_Glob->variant.var_1.Str_Comp);
neorv32_uart_printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n");
neorv32_uart_printf ("Int_1_Loc: %u\n", (uint32_t)Int_1_Loc);
neorv32_uart_printf (" should be: %u\n", 5);
neorv32_uart_printf ("Int_2_Loc: %u\n", (uint32_t)Int_2_Loc);
neorv32_uart_printf (" should be: %u\n", 13);
neorv32_uart_printf ("Int_3_Loc: %u\n", (uint32_t)Int_3_Loc);
neorv32_uart_printf (" should be: %u\n", 7);
neorv32_uart_printf ("Enum_Loc: %u\n", (uint32_t)Enum_Loc);
neorv32_uart_printf (" should be: %u\n", 1);
neorv32_uart_printf ("Str_1_Loc: %s\n", Str_1_Loc);
neorv32_uart_printf (" should be: DHRYSTONE PROGRAM, 1'ST STRING\n");
neorv32_uart_printf ("Str_2_Loc: %s\n", Str_2_Loc);
neorv32_uart_printf (" should be: DHRYSTONE PROGRAM, 2'ND STRING\n");
neorv32_uart_printf ("\n");
neorv32_uart0_printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n");
neorv32_uart0_printf ("Int_1_Loc: %u\n", (uint32_t)Int_1_Loc);
neorv32_uart0_printf (" should be: %u\n", 5);
neorv32_uart0_printf ("Int_2_Loc: %u\n", (uint32_t)Int_2_Loc);
neorv32_uart0_printf (" should be: %u\n", 13);
neorv32_uart0_printf ("Int_3_Loc: %u\n", (uint32_t)Int_3_Loc);
neorv32_uart0_printf (" should be: %u\n", 7);
neorv32_uart0_printf ("Enum_Loc: %u\n", (uint32_t)Enum_Loc);
neorv32_uart0_printf (" should be: %u\n", 1);
neorv32_uart0_printf ("Str_1_Loc: %s\n", Str_1_Loc);
neorv32_uart0_printf (" should be: DHRYSTONE PROGRAM, 1'ST STRING\n");
neorv32_uart0_printf ("Str_2_Loc: %s\n", Str_2_Loc);
neorv32_uart0_printf (" should be: DHRYSTONE PROGRAM, 2'ND STRING\n");
neorv32_uart0_printf ("\n");
 
User_Time = End_Time - Begin_Time;
 
// if (User_Time < Too_Small_Time)
// {
// neorv32_uart_printf ("Measured time too small to obtain meaningful results\n");
// neorv32_uart_printf ("Please increase number of runs\n");
// neorv32_uart_printf ("\n");
// neorv32_uart0_printf ("Measured time too small to obtain meaningful results\n");
// neorv32_uart0_printf ("Please increase number of runs\n");
// neorv32_uart0_printf ("\n");
// }
// else
{
341,38 → 341,35
/ (float) User_Time;
#endif
*/
{ /* ***** NEORV32-SPECIFIC ***** */
neorv32_uart_printf ("Microseconds for one run through Dhrystone: ");
neorv32_uart_printf ("%u \n", (uint32_t)(((User_Time/NEORV32_SYSINFO.CLK) * Mic_secs_Per_Second) / Number_Of_Runs));
neorv32_uart_printf ("Dhrystones per Second: ");
neorv32_uart_printf ("%u \n", (uint32_t)(Number_Of_Runs / (User_Time/NEORV32_SYSINFO.CLK)));
neorv32_uart_printf ("\n");
{ /* ***** NEORV32-SPECIFIC ***** */
neorv32_uart0_printf ("Microseconds for one run through Dhrystone: %u \n", (uint32_t)((User_Time * (Mic_secs_Per_Second / Number_Of_Runs)) / NEORV32_SYSINFO.CLK));
 
uint32_t dhry_per_sec = (uint32_t)(Number_Of_Runs / (User_Time/NEORV32_SYSINFO.CLK));
uint32_t vax_per_sec = dhry_per_sec / 1757;
uint32_t dhry_per_sec = (uint32_t)(NEORV32_SYSINFO.CLK / (User_Time / Number_Of_Runs));
 
neorv32_uart_printf("NEORV32: << DETAILED RESULTS (integer parts only) >>\n");
neorv32_uart_printf("NEORV32: Total cycles: %u\n", (uint32_t)User_Time);
neorv32_uart_printf("NEORV32: Cycles per second: %u\n", (uint32_t)NEORV32_SYSINFO.CLK);
neorv32_uart_printf("NEORV32: Total runs: %u\n", (uint32_t)Number_Of_Runs);
neorv32_uart0_printf ("Dhrystones per Second: %u \n\n", (uint32_t)dhry_per_sec);
 
neorv32_uart_printf("\n");
neorv32_uart_printf("NEORV32: DMIPS/s: %u\n", (uint32_t)dhry_per_sec);
neorv32_uart_printf("NEORV32: DMIPS/MHz: %u\n", (uint32_t)(dhry_per_sec / (NEORV32_SYSINFO.CLK / 1000000)));
neorv32_uart0_printf("NEORV32: << DETAILED RESULTS (integer parts only) >>\n");
neorv32_uart0_printf("NEORV32: Total cycles: %u\n", (uint32_t)User_Time);
neorv32_uart0_printf("NEORV32: Cycles per second: %u\n", (uint32_t)NEORV32_SYSINFO.CLK);
neorv32_uart0_printf("NEORV32: Total runs: %u\n", (uint32_t)Number_Of_Runs);
 
neorv32_uart_printf("\n");
neorv32_uart_printf("NEORV32: VAX DMIPS/s: %u\n", (uint32_t)vax_per_sec);
neorv32_uart_printf("NEORV32: VAX DMIPS/MHz: %u/%u\n", (uint32_t)vax_per_sec, (uint32_t)(NEORV32_SYSINFO.CLK / 1000000));
} /* ***** /NEORV32-SPECIFIC ***** */
/*
neorv32_uart_printf ("Microseconds for one run through Dhrystone: ");
//neorv32_uart_printf ("%6.1f \n", Microseconds);
neorv32_uart_printf ("%d \n", (int)Microseconds);
neorv32_uart_printf ("Dhrystones per Second: ");
//neorv32_uart_printf ("%6.1f \n", Dhrystones_Per_Second);
neorv32_uart_printf ("%d \n", (int)Dhrystones_Per_Second);
neorv32_uart_printf ("\n");
*/
neorv32_uart0_printf("\n");
neorv32_uart0_printf("NEORV32: DMIPS/s: %u\n", (uint32_t)dhry_per_sec);
neorv32_uart0_printf("NEORV32: DMIPS/s/MHz: %u\n", (uint32_t)(dhry_per_sec / (NEORV32_SYSINFO.CLK / 1000000)));
 
neorv32_uart0_printf("\n");
neorv32_uart0_printf("NEORV32: VAX DMIPS/s: %u\n", (uint32_t)dhry_per_sec/1757);
neorv32_uart0_printf("NEORV32: VAX DMIPS/s/MHz: %u/1757\n", (uint32_t)(dhry_per_sec / (NEORV32_SYSINFO.CLK / 1000000)));
} /* ***** /NEORV32-SPECIFIC ***** */
/*
neorv32_uart0_printf ("Microseconds for one run through Dhrystone: ");
//neorv32_uart0_printf ("%6.1f \n", Microseconds);
neorv32_uart0_printf ("%d \n", (int)Microseconds);
neorv32_uart0_printf ("Dhrystones per Second: ");
//neorv32_uart0_printf ("%6.1f \n", Dhrystones_Per_Second);
neorv32_uart0_printf ("%d \n", (int)Dhrystones_Per_Second);
neorv32_uart0_printf ("\n");
*/
}
 
return 0;
/neorv32/trunk/sw/example/dhrystone/dhrystone.sh
1,38 → 341,35
make USER_FLAGS+=-DRUN_DHRYSTONE USER_FLAGS+=-DDHRY_ITERS=2000000 USER_FLAGS+=-DNOENUM MARCH=-march=rv32imc EFFORT=-O3 clean_all exe
make USER_FLAGS+=-DRUN_DHRYSTONE USER_FLAGS+=-DDHRY_ITERS=2000000 USER_FLAGS+=-DNOENUM MARCH=rv32imc EFFORT=-O3 clean_all exe
/neorv32/trunk/sw/example/floating_point_test/README.md
8,11 → 8,11
* floating-point load/store operations (`FLW`, `FSW`) and their compressed versions
* integer register file `x` <-> floating point register file `f` move operations (`FMV.W.X`, `FMV.X.W`)
 
:information_source: More information regarding the RISC-V `Zfinx` single-precision floating-point extension can be found in the officail GitHub repo:
:information_source: More information regarding the RISC-V `Zfinx` single-precision floating-point extension can be found in the official GitHub repo:
[`github.com/riscv/riscv-zfinx`](https://github.com/riscv/riscv-zfinx).
 
:warning: The RISC-V `Zfinx` extension is not officially ratified yet, but it is assumed to remain unchanged. Hence, it is not supported by the upstream RISC-V GCC port.
Make sure you **do not** use the `f` ISA attribute when compiling applications that use floating-point arithmetic (`-march=rv32i*f*` is **NOT ALLOWED!**).
Make sure you **do not** use the `f` ISA attribute when compiling applications that use floating-point arithmetic (`MARCH=rv32i*f*` is **NOT ALLOWED!**).
 
 
### :warning: FPU Limitations
32,7 → 32,7
float riscv_intrinsic_fadds(float rs1, float rs2)
```
 
The pure-software emulation instruction, which uses the standard builtin functions to execute all floating-point operations, is available via wrapper function. The
The pure-software emulation instruction, which uses the standard built-in functions to execute all floating-point operations, is available via wrapper function. The
emulation function for the `FADD.S` instruction is:
 
```c
47,6 → 47,6
 
## Resources
 
* Great page with online calculators for floating-point artihmetic: [http://www.ecs.umass.edu/ece/koren/arith/simulator/](http://www.ecs.umass.edu/ece/koren/arith/simulator/)
* Great page with online calculators for floating-point arithmetic: [http://www.ecs.umass.edu/ece/koren/arith/simulator/](http://www.ecs.umass.edu/ece/koren/arith/simulator/)
* A handy tool for visualizing floating-point numbers in their binary representation: [https://www.h-schmidt.net/FloatConverter/IEEE754.html](https://www.h-schmidt.net/FloatConverter/IEEE754.html)
* This helped me to understand what results the different FPU operation generate when having "special" inputs like NaN: [https://techdocs.altium.com/display/FPGA/IEEE+754+Standard+-+Overview](https://techdocs.altium.com/display/FPGA/IEEE+754+Standard+-+Overview)
/neorv32/trunk/sw/example/floating_point_test/main.c
114,7 → 114,7
 
 
// init primary UART
neorv32_uart_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
neorv32_uart0_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
 
// capture all exceptions and give debug info via UART
neorv32_rte_setup();
124,7 → 124,7
 
// check if Zfinx extension is implemented at all
if ((NEORV32_SYSINFO.CPU & (1<<SYSINFO_CPU_ZFINX)) == 0) {
neorv32_uart_print("Error! <Zfinx> extension not synthesized!\n");
neorv32_uart0_print("Error! <Zfinx> extension not synthesized!\n");
return 1;
}
 
134,7 → 134,7
#warning Program HAS NOT BEEN COMPILED! Use >>make USER_FLAGS+=-DRUN_CHECK clean_all exe<< to compile it.
 
// inform the user if you are actually executing this
neorv32_uart_printf("ERROR! Program has not been compiled. Use >>make USER_FLAGS+=-DRUN_CHECK clean_all exe<< to compile it.\n");
neorv32_uart0_printf("ERROR! Program has not been compiled. Use >>make USER_FLAGS+=-DRUN_CHECK clean_all exe<< to compile it.\n");
 
return 1;
#endif
141,12 → 141,12
 
 
// intro
neorv32_uart_printf("<<< Zfinx extension test >>>\n");
neorv32_uart0_printf("<<< Zfinx extension test >>>\n");
#if (SILENT_MODE != 0)
neorv32_uart_printf("SILENT_MODE enabled (only showing actual errors)\n");
neorv32_uart0_printf("SILENT_MODE enabled (only showing actual errors)\n");
#endif
neorv32_uart_printf("Test cases per instruction: %u\n", (uint32_t)NUM_TEST_CASES);
neorv32_uart_printf("NOTE: The NEORV32 FPU does not support subnormal numbers yet. Subnormal numbers are flushed to zero.\n\n");
neorv32_uart0_printf("Test cases per instruction: %u\n", (uint32_t)NUM_TEST_CASES);
neorv32_uart0_printf("NOTE: The NEORV32 FPU does not support subnormal numbers yet. Subnormal numbers are flushed to zero.\n\n");
 
// clear exception status word
neorv32_cpu_csr_write(CSR_FFLAGS, 0); // real hardware
158,7 → 158,7
// ----------------------------------------------------------------------------
 
#if (RUN_CONV_TESTS != 0)
neorv32_uart_printf("\n#%u: FCVT.S.WU (unsigned integer to float)...\n", test_cnt);
neorv32_uart0_printf("\n#%u: FCVT.S.WU (unsigned integer to float)...\n", test_cnt);
err_cnt = 0;
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
opa.binary_value = get_test_vector();
170,7 → 170,7
err_cnt_total += err_cnt;
test_cnt++;
 
neorv32_uart_printf("\n#%u: FCVT.S.W (signed integer to float)...\n", test_cnt);
neorv32_uart0_printf("\n#%u: FCVT.S.W (signed integer to float)...\n", test_cnt);
err_cnt = 0;
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
opa.binary_value = get_test_vector();
182,7 → 182,7
err_cnt_total += err_cnt;
test_cnt++;
 
neorv32_uart_printf("\n#%u: FCVT.WU.S (float to unsigned integer)...\n", test_cnt);
neorv32_uart0_printf("\n#%u: FCVT.WU.S (float to unsigned integer)...\n", test_cnt);
err_cnt = 0;
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
opa.binary_value = get_test_vector();
194,7 → 194,7
err_cnt_total += err_cnt;
test_cnt++;
 
neorv32_uart_printf("\n#%u: FCVT.W.S (float to signed integer)...\n", test_cnt);
neorv32_uart0_printf("\n#%u: FCVT.W.S (float to signed integer)...\n", test_cnt);
err_cnt = 0;
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
opa.binary_value = get_test_vector();
213,7 → 213,7
// ----------------------------------------------------------------------------
 
#if (RUN_ADDSUB_TESTS != 0)
neorv32_uart_printf("\n#%u: FADD.S (addition)...\n", test_cnt);
neorv32_uart0_printf("\n#%u: FADD.S (addition)...\n", test_cnt);
err_cnt = 0;
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
opa.binary_value = get_test_vector();
226,7 → 226,7
err_cnt_total += err_cnt;
test_cnt++;
 
neorv32_uart_printf("\n#%u: FSUB.S (subtraction)...\n", test_cnt);
neorv32_uart0_printf("\n#%u: FSUB.S (subtraction)...\n", test_cnt);
err_cnt = 0;
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
opa.binary_value = get_test_vector();
246,7 → 246,7
// ----------------------------------------------------------------------------
 
#if (RUN_MUL_TESTS != 0)
neorv32_uart_printf("\n#%u: FMUL.S (multiplication)...\n", test_cnt);
neorv32_uart0_printf("\n#%u: FMUL.S (multiplication)...\n", test_cnt);
err_cnt = 0;
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
opa.binary_value = get_test_vector();
266,7 → 266,7
// ----------------------------------------------------------------------------
 
#if (RUN_MINMAX_TESTS != 0)
neorv32_uart_printf("\n#%u: FMIN.S (select minimum)...\n", test_cnt);
neorv32_uart0_printf("\n#%u: FMIN.S (select minimum)...\n", test_cnt);
err_cnt = 0;
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
opa.binary_value = get_test_vector();
279,7 → 279,7
err_cnt_total += err_cnt;
test_cnt++;
 
neorv32_uart_printf("\n#%u: FMAX.S (select maximum)...\n", test_cnt);
neorv32_uart0_printf("\n#%u: FMAX.S (select maximum)...\n", test_cnt);
err_cnt = 0;
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
opa.binary_value = get_test_vector();
299,7 → 299,7
// ----------------------------------------------------------------------------
 
#if (RUN_COMPARE_TESTS != 0)
neorv32_uart_printf("\n#%u: FEQ.S (compare if equal)...\n", test_cnt);
neorv32_uart0_printf("\n#%u: FEQ.S (compare if equal)...\n", test_cnt);
err_cnt = 0;
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
opa.binary_value = get_test_vector();
312,7 → 312,7
err_cnt_total += err_cnt;
test_cnt++;
 
neorv32_uart_printf("\n#%u: FLT.S (compare if less-than)...\n", test_cnt);
neorv32_uart0_printf("\n#%u: FLT.S (compare if less-than)...\n", test_cnt);
err_cnt = 0;
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
opa.binary_value = get_test_vector();
325,7 → 325,7
err_cnt_total += err_cnt;
test_cnt++;
 
neorv32_uart_printf("\n#%u: FLE.S (compare if less-than-or-equal)...\n", test_cnt);
neorv32_uart0_printf("\n#%u: FLE.S (compare if less-than-or-equal)...\n", test_cnt);
err_cnt = 0;
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
opa.binary_value = get_test_vector();
345,7 → 345,7
// ----------------------------------------------------------------------------
 
#if (RUN_SGNINJ_TESTS != 0)
neorv32_uart_printf("\n#%u: FSGNJ.S (sign-injection)...\n", test_cnt);
neorv32_uart0_printf("\n#%u: FSGNJ.S (sign-injection)...\n", test_cnt);
err_cnt = 0;
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
opa.binary_value = get_test_vector();
358,7 → 358,7
err_cnt_total += err_cnt;
test_cnt++;
 
neorv32_uart_printf("\n#%u: FSGNJN.S (sign-injection NOT)...\n", test_cnt);
neorv32_uart0_printf("\n#%u: FSGNJN.S (sign-injection NOT)...\n", test_cnt);
err_cnt = 0;
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
opa.binary_value = get_test_vector();
371,7 → 371,7
err_cnt_total += err_cnt;
test_cnt++;
 
neorv32_uart_printf("\n#%u: FSGNJX.S (sign-injection XOR)...\n", test_cnt);
neorv32_uart0_printf("\n#%u: FSGNJX.S (sign-injection XOR)...\n", test_cnt);
err_cnt = 0;
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
opa.binary_value = get_test_vector();
391,7 → 391,7
// ----------------------------------------------------------------------------
 
#if (RUN_CLASSIFY_TESTS != 0)
neorv32_uart_printf("\n#%u: FCLASS.S (classify)...\n", test_cnt);
neorv32_uart0_printf("\n#%u: FCLASS.S (classify)...\n", test_cnt);
err_cnt = 0;
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
opa.binary_value = get_test_vector();
410,82 → 410,82
// ----------------------------------------------------------------------------
 
#if (RUN_UNAVAIL_TESTS != 0)
neorv32_uart_printf("\n# unsupported FDIV.S (division) [illegal instruction]...\n");
neorv32_uart0_printf("\n# unsupported FDIV.S (division) [illegal instruction]...\n");
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
opa.binary_value = get_test_vector();
opb.binary_value = get_test_vector();
riscv_intrinsic_fdivs(opa.float_value, opb.float_value);
if (neorv32_cpu_csr_read(CSR_MCAUSE) != TRAP_CODE_I_ILLEGAL) {
neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
neorv32_uart0_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
err_cnt_total++;
}
else {
neorv32_uart_printf("%c[1m[ok]%c[0m\n", 27, 27);
neorv32_uart0_printf("%c[1m[ok]%c[0m\n", 27, 27);
}
 
neorv32_uart_printf("\n# unsupported FSQRT.S (square root) [illegal instruction]...\n");
neorv32_uart0_printf("\n# unsupported FSQRT.S (square root) [illegal instruction]...\n");
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
opa.binary_value = get_test_vector();
opb.binary_value = get_test_vector();
riscv_intrinsic_fsqrts(opa.float_value);
if (neorv32_cpu_csr_read(CSR_MCAUSE) != TRAP_CODE_I_ILLEGAL) {
neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
neorv32_uart0_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
err_cnt_total++;
}
else {
neorv32_uart_printf("%c[1m[ok]%c[0m\n", 27, 27);
neorv32_uart0_printf("%c[1m[ok]%c[0m\n", 27, 27);
}
 
neorv32_uart_printf("\n# unsupported FMADD.S (fused multiply-add) [illegal instruction]...\n");
neorv32_uart0_printf("\n# unsupported FMADD.S (fused multiply-add) [illegal instruction]...\n");
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
opa.binary_value = get_test_vector();
opb.binary_value = get_test_vector();
riscv_intrinsic_fmadds(opa.float_value, opb.float_value, -opa.float_value);
if (neorv32_cpu_csr_read(CSR_MCAUSE) != TRAP_CODE_I_ILLEGAL) {
neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
neorv32_uart0_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
err_cnt_total++;
}
else {
neorv32_uart_printf("%c[1m[ok]%c[0m\n", 27, 27);
neorv32_uart0_printf("%c[1m[ok]%c[0m\n", 27, 27);
}
 
neorv32_uart_printf("\n# unsupported FMSUB.S (fused multiply-sub) [illegal instruction]...\n");
neorv32_uart0_printf("\n# unsupported FMSUB.S (fused multiply-sub) [illegal instruction]...\n");
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
opa.binary_value = get_test_vector();
opb.binary_value = get_test_vector();
riscv_intrinsic_fmsubs(opa.float_value, opb.float_value, -opa.float_value);
if (neorv32_cpu_csr_read(CSR_MCAUSE) != TRAP_CODE_I_ILLEGAL) {
neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
neorv32_uart0_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
err_cnt_total++;
}
else {
neorv32_uart_printf("%c[1m[ok]%c[0m\n", 27, 27);
neorv32_uart0_printf("%c[1m[ok]%c[0m\n", 27, 27);
}
 
neorv32_uart_printf("\n# unsupported FNMSUB.S (fused negated multiply-sub) [illegal instruction]...\n");
neorv32_uart0_printf("\n# unsupported FNMSUB.S (fused negated multiply-sub) [illegal instruction]...\n");
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
opa.binary_value = get_test_vector();
opb.binary_value = get_test_vector();
riscv_intrinsic_fnmadds(opa.float_value, opb.float_value, -opa.float_value);
if (neorv32_cpu_csr_read(CSR_MCAUSE) != TRAP_CODE_I_ILLEGAL) {
neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
neorv32_uart0_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
err_cnt_total++;
}
else {
neorv32_uart_printf("%c[1m[ok]%c[0m\n", 27, 27);
neorv32_uart0_printf("%c[1m[ok]%c[0m\n", 27, 27);
}
 
neorv32_uart_printf("\n# unsupported FNMADD.S (fused negated multiply-add) [illegal instruction]...\n");
neorv32_uart0_printf("\n# unsupported FNMADD.S (fused negated multiply-add) [illegal instruction]...\n");
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
opa.binary_value = get_test_vector();
opb.binary_value = get_test_vector();
riscv_intrinsic_fnmadds(opa.float_value, opb.float_value, -opa.float_value);
if (neorv32_cpu_csr_read(CSR_MCAUSE) != TRAP_CODE_I_ILLEGAL) {
neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
neorv32_uart0_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
err_cnt_total++;
}
else {
neorv32_uart_printf("%c[1m[ok]%c[0m\n", 27, 27);
neorv32_uart0_printf("%c[1m[ok]%c[0m\n", 27, 27);
}
#endif
 
499,11 → 499,11
uint32_t time_start, time_sw, time_hw;
const uint32_t num_runs = 4096;
 
neorv32_uart_printf("\nAverage execution time tests (%u runs)\n", num_runs);
neorv32_uart0_printf("\nAverage execution time tests (%u runs)\n", num_runs);
 
 
// signed integer to float
neorv32_uart_printf("FCVT.S.W: ");
neorv32_uart0_printf("FCVT.S.W: ");
time_sw = 0;
time_hw = 0;
err_cnt = 0;
531,16 → 531,16
}
 
if (err_cnt == 0) {
neorv32_uart_printf("cycles[SW] = %u vs. cycles[HW] = %u\n", time_sw/num_runs, time_hw/num_runs);
neorv32_uart0_printf("cycles[SW] = %u vs. cycles[HW] = %u\n", time_sw/num_runs, time_hw/num_runs);
}
else {
neorv32_uart_printf("%c[1m[TEST FAILED!]%c[0m\n", 27, 27);
neorv32_uart0_printf("%c[1m[TEST FAILED!]%c[0m\n", 27, 27);
err_cnt_total++;
}
 
 
// float to signed integer
neorv32_uart_printf("FCVT.W.S: ");
neorv32_uart0_printf("FCVT.W.S: ");
time_sw = 0;
time_hw = 0;
err_cnt = 0;
568,16 → 568,16
}
 
if (err_cnt == 0) {
neorv32_uart_printf("cycles[SW] = %u vs. cycles[HW] = %u\n", time_sw/num_runs, time_hw/num_runs);
neorv32_uart0_printf("cycles[SW] = %u vs. cycles[HW] = %u\n", time_sw/num_runs, time_hw/num_runs);
}
else {
neorv32_uart_printf("%c[1m[TEST FAILED!]%c[0m\n", 27, 27);
neorv32_uart0_printf("%c[1m[TEST FAILED!]%c[0m\n", 27, 27);
err_cnt_total++;
}
 
 
// addition
neorv32_uart_printf("FADD.S: ");
neorv32_uart0_printf("FADD.S: ");
time_sw = 0;
time_hw = 0;
err_cnt = 0;
606,16 → 606,16
}
 
if (err_cnt == 0) {
neorv32_uart_printf("cycles[SW] = %u vs. cycles[HW] = %u\n", time_sw/num_runs, time_hw/num_runs);
neorv32_uart0_printf("cycles[SW] = %u vs. cycles[HW] = %u\n", time_sw/num_runs, time_hw/num_runs);
}
else {
neorv32_uart_printf("%c[1m[TEST FAILED!]%c[0m\n", 27, 27);
neorv32_uart0_printf("%c[1m[TEST FAILED!]%c[0m\n", 27, 27);
err_cnt_total++;
}
 
 
// subtraction
neorv32_uart_printf("FSUB.S: ");
neorv32_uart0_printf("FSUB.S: ");
time_sw = 0;
time_hw = 0;
err_cnt = 0;
644,16 → 644,16
}
 
if (err_cnt == 0) {
neorv32_uart_printf("cycles[SW] = %u vs. cycles[HW] = %u\n", time_sw/num_runs, time_hw/num_runs);
neorv32_uart0_printf("cycles[SW] = %u vs. cycles[HW] = %u\n", time_sw/num_runs, time_hw/num_runs);
}
else {
neorv32_uart_printf("%c[1m[TEST FAILED!]%c[0m\n", 27, 27);
neorv32_uart0_printf("%c[1m[TEST FAILED!]%c[0m\n", 27, 27);
err_cnt_total++;
}
 
 
// multiplication
neorv32_uart_printf("FMUL.S: ");
neorv32_uart0_printf("FMUL.S: ");
time_sw = 0;
time_hw = 0;
err_cnt = 0;
682,16 → 682,16
}
 
if (err_cnt == 0) {
neorv32_uart_printf("cycles[SW] = %u vs. cycles[HW] = %u\n", time_sw/num_runs, time_hw/num_runs);
neorv32_uart0_printf("cycles[SW] = %u vs. cycles[HW] = %u\n", time_sw/num_runs, time_hw/num_runs);
}
else {
neorv32_uart_printf("%c[1m[TEST FAILED!]%c[0m\n", 27, 27);
neorv32_uart0_printf("%c[1m[TEST FAILED!]%c[0m\n", 27, 27);
err_cnt_total++;
}
 
 
// Max
neorv32_uart_printf("FMAX.S: ");
neorv32_uart0_printf("FMAX.S: ");
time_sw = 0;
time_hw = 0;
err_cnt = 0;
720,16 → 720,16
}
 
if (err_cnt == 0) {
neorv32_uart_printf("cycles[SW] = %u vs. cycles[HW] = %u\n", time_sw/num_runs, time_hw/num_runs);
neorv32_uart0_printf("cycles[SW] = %u vs. cycles[HW] = %u\n", time_sw/num_runs, time_hw/num_runs);
}
else {
neorv32_uart_printf("%c[1m[TEST FAILED!]%c[0m\n", 27, 27);
neorv32_uart0_printf("%c[1m[TEST FAILED!]%c[0m\n", 27, 27);
err_cnt_total++;
}
 
 
// Comparison
neorv32_uart_printf("FLE.S: ");
neorv32_uart0_printf("FLE.S: ");
time_sw = 0;
time_hw = 0;
err_cnt = 0;
758,16 → 758,16
}
 
if (err_cnt == 0) {
neorv32_uart_printf("cycles[SW] = %u vs. cycles[HW] = %u\n", time_sw/num_runs, time_hw/num_runs);
neorv32_uart0_printf("cycles[SW] = %u vs. cycles[HW] = %u\n", time_sw/num_runs, time_hw/num_runs);
}
else {
neorv32_uart_printf("%c[1m[TEST FAILED!]%c[0m\n", 27, 27);
neorv32_uart0_printf("%c[1m[TEST FAILED!]%c[0m\n", 27, 27);
err_cnt_total++;
}
 
 
// Sign-injection
neorv32_uart_printf("FSGNJX.S: ");
neorv32_uart0_printf("FSGNJX.S: ");
time_sw = 0;
time_hw = 0;
err_cnt = 0;
796,10 → 796,10
}
 
if (err_cnt == 0) {
neorv32_uart_printf("cycles[SW] = %u vs. cycles[HW] = %u\n", time_sw/num_runs, time_hw/num_runs);
neorv32_uart0_printf("cycles[SW] = %u vs. cycles[HW] = %u\n", time_sw/num_runs, time_hw/num_runs);
}
else {
neorv32_uart_printf("%c[1m[TEST FAILED!]%c[0m\n", 27, 27);
neorv32_uart0_printf("%c[1m[TEST FAILED!]%c[0m\n", 27, 27);
err_cnt_total++;
}
#endif
810,12 → 810,12
// ----------------------------------------------------------------------------
 
if (err_cnt_total != 0) {
neorv32_uart_printf("\n%c[1m[ZFINX EXTENSION VERIFICATION FAILED!]%c[0m\n", 27, 27);
neorv32_uart_printf("%u errors in %u test cases\n", err_cnt_total, test_cnt*(uint32_t)NUM_TEST_CASES);
neorv32_uart0_printf("\n%c[1m[ZFINX EXTENSION VERIFICATION FAILED!]%c[0m\n", 27, 27);
neorv32_uart0_printf("%u errors in %u test cases\n", err_cnt_total, test_cnt*(uint32_t)NUM_TEST_CASES);
return 1;
}
else {
neorv32_uart_printf("\n%c[1m[Zfinx extension verification successful!]%c[0m\n", 27, 27);
neorv32_uart0_printf("\n%c[1m[Zfinx extension verification successful!]%c[0m\n", 27, 27);
return 0;
}
 
884,19 → 884,19
uint32_t verify_result(uint32_t num, uint32_t opa, uint32_t opb, uint32_t ref, uint32_t res) {
 
#if (SILENT_MODE == 0)
neorv32_uart_printf("%u: opa = 0x%x, opb = 0x%x : ref[SW] = 0x%x vs. res[HW] = 0x%x ", num, opa, opb, ref, res);
neorv32_uart0_printf("%u: opa = 0x%x, opb = 0x%x : ref[SW] = 0x%x vs. res[HW] = 0x%x ", num, opa, opb, ref, res);
#endif
 
if (ref != res) {
#if (SILENT_MODE != 0)
neorv32_uart_printf("%u: opa = 0x%x, opb = 0x%x : ref[SW] = 0x%x vs. res[HW] = 0x%x ", num, opa, opb, ref, res);
neorv32_uart0_printf("%u: opa = 0x%x, opb = 0x%x : ref[SW] = 0x%x vs. res[HW] = 0x%x ", num, opa, opb, ref, res);
#endif
neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
neorv32_uart0_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
return 1;
}
else {
#if (SILENT_MODE == 0)
neorv32_uart_printf("%c[1m[ok]%c[0m\n", 27, 27);
neorv32_uart0_printf("%c[1m[ok]%c[0m\n", 27, 27);
#endif
return 0;
}
910,12 → 910,12
**************************************************************************/
void print_report(uint32_t num_err) {
 
neorv32_uart_printf("Errors: %u/%u ", num_err, (uint32_t)NUM_TEST_CASES);
neorv32_uart0_printf("Errors: %u/%u ", num_err, (uint32_t)NUM_TEST_CASES);
 
if (num_err == 0) {
neorv32_uart_printf("%c[1m[ok]%c[0m\n", 27, 27);
neorv32_uart0_printf("%c[1m[ok]%c[0m\n", 27, 27);
}
else {
neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
neorv32_uart0_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
}
}
/neorv32/trunk/sw/example/game_of_life/main.c
87,7 → 87,7
int main(void) {
 
// check if UART unit is implemented at all
if (neorv32_uart_available() == 0) {
if (neorv32_uart0_available() == 0) {
return 1;
}
 
98,7 → 98,7
 
 
// init UART at default baud rate, no parity bits, ho hw flow control
neorv32_uart_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
neorv32_uart0_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
 
// check available hardware extensions and compare with compiler flags
neorv32_rte_check_isa(0); // silent = 0 -> show message if isa mismatch
118,15 → 118,15
clear_universe(1);
 
// intro
neorv32_uart_printf("\n\n<<< Conways's Game of Life >>>\n\n");
neorv32_uart_printf("This program requires a terminal resolution of at least %ux%u characters.\n", NUM_CELLS_X+2, NUM_CELLS_Y+3);
neorv32_uart_printf("Press any key to start a random-initialized torus-style universe of %ux%u cells.\n", NUM_CELLS_X, NUM_CELLS_Y);
neorv32_uart_printf("You can pause/restart the simulation by pressing any key.\n");
neorv32_uart0_printf("\n\n<<< Conways's Game of Life >>>\n\n");
neorv32_uart0_printf("This program requires a terminal resolution of at least %ux%u characters.\n", NUM_CELLS_X+2, NUM_CELLS_Y+3);
neorv32_uart0_printf("Press any key to start a random-initialized torus-style universe of %ux%u cells.\n", NUM_CELLS_X, NUM_CELLS_Y);
neorv32_uart0_printf("You can pause/restart the simulation by pressing any key.\n");
 
 
// check if TRNG was synthesized
if (neorv32_trng_available()) {
neorv32_uart_printf("\nTRNG detected. Using TRNG for universe initialization.\n");
neorv32_uart0_printf("\nTRNG detected. Using TRNG for universe initialization.\n");
neorv32_trng_enable();
trng_available = 1;
}
133,7 → 133,7
 
 
// randomize until key pressed
while (neorv32_uart_char_received() == 0) {
while (neorv32_uart0_char_received() == 0) {
xorshift32();
}
 
145,7 → 145,7
while (1) {
int err = neorv32_trng_get(&trng_data);
if (err) {
neorv32_uart_printf("TRNG error (%i)! Restarting TRNG...\n", err);
neorv32_uart0_printf("TRNG error (%i)! Restarting TRNG...\n", err);
continue;
}
else {
164,15 → 164,15
while(1) {
 
// user abort?
if (neorv32_uart_char_received()) {
neorv32_uart_printf("\nRestart (y/n)?");
if (neorv32_uart_getc() == 'y') {
if (neorv32_uart0_char_received()) {
neorv32_uart0_printf("\nRestart (y/n)?");
if (neorv32_uart0_getc() == 'y') {
break;
}
}
 
// print generation, population count and the current universe
neorv32_uart_printf("\n\nGeneration %u: %u/%u living cells\n", (uint32_t)generation, (uint32_t)pop_count(u), NUM_CELLS_X*NUM_CELLS_Y);
neorv32_uart0_printf("\n\nGeneration %u: %u/%u living cells\n", (uint32_t)generation, (uint32_t)pop_count(u), NUM_CELLS_X*NUM_CELLS_Y);
print_universe(u);
 
// compute next generation
216,35 → 216,35
 
int16_t x, y;
 
neorv32_uart_putc('+');
neorv32_uart0_putc('+');
for (x=0; x<NUM_CELLS_X; x++) {
neorv32_uart_putc('-');
neorv32_uart0_putc('-');
}
neorv32_uart_putc('+');
neorv32_uart_putc('\r');
neorv32_uart_putc('\n');
neorv32_uart0_putc('+');
neorv32_uart0_putc('\r');
neorv32_uart0_putc('\n');
 
for (y=0; y<NUM_CELLS_Y; y++) {
neorv32_uart_putc('|');
neorv32_uart0_putc('|');
for (x=0; x<NUM_CELLS_X; x++) {
if (get_cell(u, x, y))
neorv32_uart_putc((char)CELL_ALIVE);
neorv32_uart0_putc((char)CELL_ALIVE);
else
neorv32_uart_putc((char)CELL_DEAD);
neorv32_uart0_putc((char)CELL_DEAD);
}
 
// end of line
neorv32_uart_putc('|');
neorv32_uart_putc('\r');
neorv32_uart_putc('\n');
neorv32_uart0_putc('|');
neorv32_uart0_putc('\r');
neorv32_uart0_putc('\n');
}
 
neorv32_uart_putc('+');
neorv32_uart0_putc('+');
for (x=0; x<NUM_CELLS_X; x++) {
neorv32_uart_putc('-');
neorv32_uart0_putc('-');
}
neorv32_uart_putc('+');
neorv32_uart0_putc('+');
}
 
 
/neorv32/trunk/sw/example/hello_world/main.c
66,7 → 66,7
neorv32_rte_setup();
 
// init UART at default baud rate, no parity bits, ho hw flow control
neorv32_uart_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
neorv32_uart0_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
 
// check available hardware extensions and compare with compiler flags
neorv32_rte_check_isa(0); // silent = 0 -> show message if isa mismatch
75,7 → 75,7
neorv32_rte_print_logo();
 
// say hello
neorv32_uart_print("Hello world! :)\n");
neorv32_uart0_print("Hello world! :)\n");
 
 
return 0;
/neorv32/trunk/sw/example/hex_viewer/main.c
73,7 → 73,7
int length = 0;
 
// check if UART unit is implemented at all
if (neorv32_uart_available() == 0) {
if (neorv32_uart0_available() == 0) {
return 1;
}
 
85,23 → 85,23
neorv32_cpu_dint();
 
// init UART at default baud rate, no parity bits, ho hw flow control
neorv32_uart_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
neorv32_uart0_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
 
// check available hardware extensions and compare with compiler flags
neorv32_rte_check_isa(0); // silent = 0 -> show message if isa mismatch
 
// intro
neorv32_uart_printf("\n--- Hex Viewer ---\n\n");
neorv32_uart0_printf("\n--- Hex Viewer ---\n\n");
 
// info
neorv32_uart_printf("This program allows to read/write/dump memory locations by hand.\n"
neorv32_uart0_printf("This program allows to read/write/dump memory locations by hand.\n"
"Type 'help' to see the help menu.\n\n");
 
// Main menu
for (;;) {
neorv32_uart_printf("HEX_VIEWER:> ");
length = neorv32_uart_scan(buffer, 8, 1);
neorv32_uart_printf("\n");
neorv32_uart0_printf("HEX_VIEWER:> ");
length = neorv32_uart0_scan(buffer, 8, 1);
neorv32_uart0_printf("\n");
 
if (!length) // nothing to be done
continue;
108,7 → 108,7
 
// decode input and execute command
if (!strcmp(buffer, "help")) {
neorv32_uart_printf("Available commands:\n"
neorv32_uart0_printf("Available commands:\n"
" help - show this text\n"
" read - read single word from address\n"
" write - write single word to address\n"
133,7 → 133,7
}
 
else {
neorv32_uart_printf("Invalid command. Type 'help' to see all commands.\n");
neorv32_uart0_printf("Invalid command. Type 'help' to see all commands.\n");
}
}
 
149,12 → 149,12
char terminal_buffer[16];
 
// enter address
neorv32_uart_printf("Enter address (8 hex chars): 0x");
neorv32_uart_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0'
neorv32_uart0_printf("Enter address (8 hex chars): 0x");
neorv32_uart0_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0'
register uint32_t mem_address = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
 
// perform read access
neorv32_uart_printf("\n[0x%x] = ", mem_address);
neorv32_uart0_printf("\n[0x%x] = ", mem_address);
 
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
 
162,10 → 162,10
 
// show memory content if there was no exception
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
neorv32_uart_printf("0x%x", mem_data);
neorv32_uart0_printf("0x%x", mem_data);
}
 
neorv32_uart_printf("\n");
neorv32_uart0_printf("\n");
}
 
 
177,17 → 177,17
char terminal_buffer[16];
 
// enter address
neorv32_uart_printf("Enter address (8 hex chars): 0x");
neorv32_uart_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0'
neorv32_uart0_printf("Enter address (8 hex chars): 0x");
neorv32_uart0_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0'
uint32_t mem_address = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
 
// enter data
neorv32_uart_printf("\nEnter data (8 hex chars): 0x");
neorv32_uart_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0'
neorv32_uart0_printf("\nEnter data (8 hex chars): 0x");
neorv32_uart0_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0'
uint32_t mem_data = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
 
// perform write access
neorv32_uart_printf("\n[0x%x] = ", mem_address);
neorv32_uart0_printf("\n[0x%x] = ", mem_address);
 
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
 
195,10 → 195,10
 
// show memory content if there was no exception
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
neorv32_uart_printf("0x%x", mem_data);
neorv32_uart0_printf("0x%x", mem_data);
}
 
neorv32_uart_printf("\n");
neorv32_uart0_printf("\n");
}
 
 
213,13 → 213,13
if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_A)) != 0) {
 
// enter memory address
neorv32_uart_printf("Enter memory address (8 hex chars): 0x");
neorv32_uart_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0'
neorv32_uart0_printf("Enter memory address (8 hex chars): 0x");
neorv32_uart0_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0'
mem_address = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
 
// enter desired value
neorv32_uart_printf("\nEnter new value @0x%x (8 hex chars): 0x", mem_address);
neorv32_uart_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0'
neorv32_uart0_printf("\nEnter new value @0x%x (8 hex chars): 0x", mem_address);
neorv32_uart0_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0'
wdata = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
 
rdata = neorv32_cpu_load_reservate_word(mem_address); // make reservation
226,17 → 226,17
status = neorv32_cpu_store_conditional(mem_address, wdata);
 
// status
neorv32_uart_printf("\nOld data: 0x%x\n", rdata);
neorv32_uart0_printf("\nOld data: 0x%x\n", rdata);
if (status == 0) {
neorv32_uart_printf("Atomic access successful!\n");
neorv32_uart_printf("New data: 0x%x\n", neorv32_cpu_load_unsigned_word(mem_address));
neorv32_uart0_printf("Atomic access successful!\n");
neorv32_uart0_printf("New data: 0x%x\n", neorv32_cpu_load_unsigned_word(mem_address));
}
else {
neorv32_uart_printf("Atomic access failed!\n");
neorv32_uart0_printf("Atomic access failed!\n");
}
}
else {
neorv32_uart_printf("Atomic operations not implemented/enabled!\n");
neorv32_uart0_printf("Atomic operations not implemented/enabled!\n");
}
}
 
249,19 → 249,19
char terminal_buffer[16];
 
// enter base address
neorv32_uart_printf("Enter base address (8 hex chars): 0x");
neorv32_uart_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0'
neorv32_uart0_printf("Enter base address (8 hex chars): 0x");
neorv32_uart0_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0'
uint32_t mem_address = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
 
neorv32_uart_printf("\nPress key to start dumping. Press any key to abort.\n");
neorv32_uart0_printf("\nPress key to start dumping. Press any key to abort.\n");
 
neorv32_uart_getc(); // wait for key
neorv32_uart0_getc(); // wait for key
 
// perform read accesses
uint32_t mem_data = 0;
while(neorv32_uart_char_received() == 0) {
while(neorv32_uart0_char_received() == 0) {
 
neorv32_uart_printf("[0x%x] = ", mem_address);
neorv32_uart0_printf("[0x%x] = ", mem_address);
 
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
 
269,7 → 269,7
 
// show memory content if there was no exception
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
neorv32_uart_printf("0x%x\n", mem_data);
neorv32_uart0_printf("0x%x\n", mem_data);
}
else {
break;
278,8 → 278,8
mem_address = mem_address + 4;
 
}
neorv32_uart_char_received_get(); // clear UART rx buffer
neorv32_uart_printf("\n");
neorv32_uart0_char_received_get(); // clear UART rx buffer
neorv32_uart0_printf("\n");
}
 
 
/neorv32/trunk/sw/example/processor_check/main.c
351,15 → 351,23
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
 
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
neorv32_cpu_goto_user_mode();
{
// access to cycle CSR is no longer allowed
tmp_a = neorv32_cpu_csr_read(CSR_CYCLE);
asm volatile (" mv %[result], zero \n" // initialize with zero
" rdcycle %[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) {
if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) && (tmp_a == 0)) {
test_ok();
}
else {
750,7 → 758,7
// Machine timer interrupt (MTIME)
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] MTI (via MTIME): ", cnt_test);
PRINT_STANDARD("[%i] MTI (MTIME): ", cnt_test);
 
cnt_test++;
 
785,7 → 793,7
// Machine software interrupt (MSI) via testbench
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] MSI (via testbench): ", cnt_test);
PRINT_STANDARD("[%i] MSI (testbench): ", cnt_test);
 
cnt_test++;
 
814,7 → 822,7
// Machine external interrupt (MEI) via testbench
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] MEI (via testbench): ", cnt_test);
PRINT_STANDARD("[%i] MEI (testbench): ", cnt_test);
 
cnt_test++;
 
873,7 → 881,7
// Test pending interrupt
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] Pending IRQ test (MTIME): ", cnt_test);
PRINT_STANDARD("[%i] Pending IRQ (MTIME): ", cnt_test);
 
cnt_test++;
 
922,7 → 930,7
// ----------------------------------------------------------
if (neorv32_wdt_available()) {
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] FIRQ0 test (via WDT): ", cnt_test);
PRINT_STANDARD("[%i] FIRQ0 (WDT): ", cnt_test);
 
cnt_test++;
 
936,7 → 944,7
 
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
asm volatile("nop");
neorv32_cpu_irq_disable(CSR_MIE_FIRQ0E);
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_0) {
test_ok();
945,9 → 953,6
test_fail();
}
 
// disable fast interrupt
neorv32_cpu_irq_disable(CSR_MIE_FIRQ0E);
 
// no more WDT interrupts
neorv32_wdt_disable();
}
956,7 → 961,7
// ----------------------------------------------------------
// Fast interrupt channel 1 (CFS)
// ----------------------------------------------------------
PRINT_STANDARD("[%i] FIRQ1 test (via CFS): ", cnt_test);
PRINT_STANDARD("[%i] FIRQ1 (CFS): ", cnt_test);
PRINT_STANDARD("skipped \n");
 
 
965,13 → 970,10
// ----------------------------------------------------------
if (neorv32_uart1_available()) {
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] FIRQ2 test (via UART0.RX): ", cnt_test);
PRINT_STANDARD("[%i] FIRQ2 (UART0.RX): ", cnt_test);
 
cnt_test++;
 
// enable fast interrupt
neorv32_cpu_irq_enable(CSR_MIE_FIRQ2E);
 
// wait for UART0 to finish transmitting
while(neorv32_uart0_tx_busy());
 
985,20 → 987,19
 
// trigger UART0 RX IRQ
neorv32_uart0_putc(0);
 
// wait for UART0 to finish transmitting
while(neorv32_uart0_tx_busy());
 
// enable fast interrupt
neorv32_cpu_irq_enable(CSR_MIE_FIRQ2E);
 
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
asm volatile("nop");
neorv32_cpu_irq_disable(CSR_MIE_FIRQ2E);
 
// restore original configuration
NEORV32_UART0.CTRL = tmp_a;
 
// disable fast interrupt
neorv32_cpu_irq_disable(CSR_MIE_FIRQ2E);
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_2) {
test_ok();
}
1013,13 → 1014,10
// ----------------------------------------------------------
if (neorv32_uart0_available()) {
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] FIRQ3 test (via UART0.TX): ", cnt_test);
PRINT_STANDARD("[%i] FIRQ3 (UART0.TX): ", cnt_test);
 
cnt_test++;
 
// UART0 TX interrupt enable
neorv32_cpu_irq_enable(CSR_MIE_FIRQ3E);
 
// wait for UART0 to finish transmitting
while(neorv32_uart0_tx_busy());
 
1033,19 → 1031,18
 
// trigger UART0 TX IRQ
neorv32_uart0_putc(0);
 
// UART0 TX interrupt enable
neorv32_cpu_irq_enable(CSR_MIE_FIRQ3E);
// wait for UART to finish transmitting
while(neorv32_uart0_tx_busy());
 
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
asm volatile("nop");
neorv32_cpu_irq_disable(CSR_MIE_FIRQ3E);
 
// restore original configuration
NEORV32_UART0.CTRL = tmp_a;
 
neorv32_cpu_irq_disable(CSR_MIE_FIRQ3E);
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_3) {
test_ok();
}
1060,13 → 1057,10
// ----------------------------------------------------------
if (neorv32_uart1_available()) {
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] FIRQ4 test (via UART1.RX): ", cnt_test);
PRINT_STANDARD("[%i] FIRQ4 (UART1.RX): ", cnt_test);
 
cnt_test++;
 
// UART1 RX interrupt enable
neorv32_cpu_irq_enable(CSR_MIE_FIRQ4E);
 
// backup current UART1 configuration
tmp_a = NEORV32_UART1.CTRL;
 
1077,20 → 1071,18
 
// trigger UART1 RX IRQ
neorv32_uart1_putc(0);
 
// wait for UART1 to finish transmitting
while(neorv32_uart1_tx_busy());
// UART1 RX interrupt enable
neorv32_cpu_irq_enable(CSR_MIE_FIRQ4E);
 
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
asm volatile("nop");
neorv32_cpu_irq_disable(CSR_MIE_FIRQ4E);
 
// restore original configuration
NEORV32_UART1.CTRL = tmp_a;
 
// disable fast interrupt
neorv32_cpu_irq_disable(CSR_MIE_FIRQ4E);
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_4) {
test_ok();
}
1105,13 → 1097,10
// ----------------------------------------------------------
if (neorv32_uart1_available()) {
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] FIRQ5 test (via UART1.TX): ", cnt_test);
PRINT_STANDARD("[%i] FIRQ5 (UART1.TX): ", cnt_test);
 
cnt_test++;
 
// UART1 RX interrupt enable
neorv32_cpu_irq_enable(CSR_MIE_FIRQ5E);
 
// backup current UART1 configuration
tmp_a = NEORV32_UART1.CTRL;
 
1122,20 → 1111,18
 
// trigger UART1 TX IRQ
neorv32_uart1_putc(0);
 
// UART1 RX interrupt enable
neorv32_cpu_irq_enable(CSR_MIE_FIRQ5E);
// wait for UART1 to finish transmitting
while(neorv32_uart1_tx_busy());
 
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
asm volatile("nop");
neorv32_cpu_irq_disable(CSR_MIE_FIRQ5E);
 
// restore original configuration
NEORV32_UART1.CTRL = tmp_a;
 
// disable fast interrupt
neorv32_cpu_irq_disable(CSR_MIE_FIRQ5E);
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_5) {
test_ok();
}
1150,23 → 1137,22
// ----------------------------------------------------------
if (neorv32_spi_available()) {
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] FIRQ6 test (via SPI): ", cnt_test);
PRINT_STANDARD("[%i] FIRQ6 (SPI): ", cnt_test);
 
cnt_test++;
 
// enable fast interrupt
neorv32_cpu_irq_enable(CSR_MIE_FIRQ6E);
 
// configure SPI
neorv32_spi_setup(CLK_PRSC_2, 0, 0);
neorv32_spi_setup(CLK_PRSC_2, 0, 0, 0);
 
// trigger SPI IRQ
neorv32_spi_trans(0);
// enable fast interrupt
neorv32_cpu_irq_enable(CSR_MIE_FIRQ6E);
while(neorv32_spi_busy()); // wait for current transfer to finish
 
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
asm volatile("nop");
neorv32_cpu_irq_disable(CSR_MIE_FIRQ6E);
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_6) {
test_ok();
1177,9 → 1163,6
 
// disable SPI
neorv32_spi_disable();
 
// disable fast interrupt
neorv32_cpu_irq_disable(CSR_MIE_FIRQ6E);
}
 
 
1188,7 → 1171,7
// ----------------------------------------------------------
if (neorv32_twi_available()) {
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] FIRQ7 test (via TWI): ", cnt_test);
PRINT_STANDARD("[%i] FIRQ7 (TWI): ", cnt_test);
 
cnt_test++;
 
1195,16 → 1178,15
// configure TWI, fastest clock, no peripheral clock stretching
neorv32_twi_setup(CLK_PRSC_2, 0);
 
neorv32_cpu_irq_enable(CSR_MIE_FIRQ7E);
 
// trigger TWI IRQ
neorv32_twi_generate_start();
neorv32_twi_trans(0);
neorv32_twi_generate_stop();
neorv32_cpu_irq_enable(CSR_MIE_FIRQ7E);
 
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
asm volatile("nop");
neorv32_cpu_irq_disable(CSR_MIE_FIRQ7E);
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_7) {
test_ok();
1215,7 → 1197,6
 
// disable TWI
neorv32_twi_disable();
neorv32_cpu_irq_disable(CSR_MIE_FIRQ7E);
}
 
 
1223,7 → 1204,7
// Fast interrupt channel 8 (XIRQ)
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] FIRQ8 test (via XIRQ): ", cnt_test);
PRINT_STANDARD("[%i] FIRQ8 (XIRQ): ", cnt_test);
if (neorv32_xirq_available()) {
 
cnt_test++;
1244,7 → 1225,7
// wait for IRQs to arrive CPU
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
neorv32_cpu_irq_disable(CSR_MIE_FIRQ8E);
 
if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_8) && // FIRQ8 IRQ
(xirq_err_cnt == 0) && // no errors during XIRQ configuration
1255,7 → 1236,6
test_fail();
}
 
neorv32_cpu_irq_disable(CSR_MIE_FIRQ8E);
NEORV32_XIRQ.IER = 0;
NEORV32_XIRQ.IPR = -1;
}
1274,13 → 1254,15
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] FIRQ10 & 11 (SLINK): ", cnt_test);
 
// NOTE: this test requires FIFO sizes = 1
 
cnt_test++;
 
// enable SLINK
neorv32_slink_enable();
 
// configure SLINK IRQs
neorv32_slink_tx_irq_config(0, SLINK_IRQ_ENABLE, SLINK_IRQ_TX_NOT_FULL);
neorv32_slink_rx_irq_config(0, SLINK_IRQ_ENABLE, SLINK_IRQ_RX_NOT_EMPTY);
 
// enable SLINK FIRQs
neorv32_cpu_irq_enable(CSR_MIE_FIRQ10E);
neorv32_cpu_irq_enable(CSR_MIE_FIRQ11E);
1287,24 → 1269,39
 
tmp_a = 0; // error counter
 
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
 
// check if TX FIFO fires IRQ
if (neorv32_cpu_csr_read(CSR_MCAUSE) != TRAP_CODE_FIRQ_11) {
tmp_a += 1;
}
neorv32_slink_tx_irq_config(0, SLINK_IRQ_DISABLE, SLINK_IRQ_TX_NOT_FULL);
 
// send single data word via link 0
if (neorv32_slink_tx0_nonblocking(0xA1B2C3D4)) {
tmp_a++; // sending failed
tmp_a += 2; // sending failed
}
 
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
 
// check if RX FIFO fires IRQ
if (neorv32_cpu_csr_read(CSR_MCAUSE) != TRAP_CODE_FIRQ_10) {
tmp_a += 4;
}
neorv32_slink_rx_irq_config(0, SLINK_IRQ_DISABLE, SLINK_IRQ_RX_NOT_EMPTY);
 
// get single data word from link 0
uint32_t slink_rx_data;
if (neorv32_slink_rx0_nonblocking(&slink_rx_data)) {
tmp_a++; // receiving failed
tmp_a += 8; // receiving failed
}
 
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
asm volatile("nop");
neorv32_cpu_irq_disable(CSR_MIE_FIRQ10E);
neorv32_cpu_irq_disable(CSR_MIE_FIRQ11E);
 
tmp_b = neorv32_cpu_csr_read(CSR_MCAUSE);
if (((tmp_b == TRAP_CODE_FIRQ_10) || (tmp_b == TRAP_CODE_FIRQ_11)) && // right trap code
(tmp_a == 0) && // local error counter = 0
if ((tmp_a == 0) && // local error counter = 0
(slink_rx_data == 0xA1B2C3D4)) { // correct data read-back
test_ok();
}
1314,8 → 1311,6
 
// shutdown SLINK
neorv32_slink_disable();
neorv32_cpu_irq_disable(CSR_MIE_FIRQ10E);
neorv32_cpu_irq_disable(CSR_MIE_FIRQ11E);
}
 
 
1330,27 → 1325,18
// Test WFI ("sleep") instructions, wakeup via MTIME
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] WFI (sleep instruction) test (wake-up via MTIME): ", cnt_test);
PRINT_STANDARD("[%i] WFI (sleep instruction, wake-up via MTIME): ", cnt_test);
 
cnt_test++;
 
// clear timeout wait flag
tmp_a = neorv32_cpu_csr_read(CSR_MSTATUS);
tmp_a &= ~(1 << CSR_MSTATUS_TW);
neorv32_cpu_csr_write(CSR_MSTATUS, tmp_a);
 
// program wake-up timer
neorv32_mtime_set_timecmp(neorv32_mtime_get_time() + 500);
 
// enable interrupt
// enable mtime interrupt
neorv32_cpu_irq_enable(CSR_MIE_MTIE);
 
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
neorv32_cpu_goto_user_mode();
{
// only when mstatus.TW = 0 executing WFI in user mode is allowed
asm volatile ("wfi"); // put CPU into sleep mode
}
// put CPU into sleep mode
asm volatile ("wfi");
 
// no more mtime interrupts
neorv32_cpu_irq_disable(CSR_MIE_MTIE);
1440,6 → 1426,9
test_ok();
}
else {
if (neorv32_cpu_csr_read(CSR_PMPCFG0) & 0x80) {
PRINT_CRITICAL("%c[1m<Entry LOCKED!> %c[0m\n", 27, 27);
}
test_fail();
}
 
1604,12 → 1593,13
 
// atomic access
tmp_a = neorv32_cpu_load_reservate_word((uint32_t)&atomic_access_addr); // make reservation
neorv32_cpu_store_unsigned_word((uint32_t)&atomic_access_addr, 0xDEADDEAD); // destroy reservation
// neorv32_cpu_store_unsigned_word((uint32_t)&atomic_access_addr, 0xDEADDEAD); // destroy reservation
neorv32_cpu_load_unsigned_word((uint32_t)&atomic_access_addr); // destroy reservation
tmp_b = neorv32_cpu_store_conditional((uint32_t)&atomic_access_addr, 0x22446688);
 
if ((tmp_b != 0) && // status: fail
(tmp_a == 0xAABBCCDD) && // correct data read
(neorv32_cpu_load_unsigned_word((uint32_t)&atomic_access_addr) == 0xDEADDEAD)) { // correct data write
(neorv32_cpu_load_unsigned_word((uint32_t)&atomic_access_addr) == 0xAABBCCDD)) { // correct data write
test_ok();
}
else {
/neorv32/trunk/sw/lib/include/neorv32.h
283,8 → 283,7
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_TW = 21, /**< CPU mstatus CSR (21): TW - timeout wait (trigger illegal instruction exception if WFI is executed outside of m-mode when set) (r/w) */
CSR_MSTATUS_MPP_H = 12 /**< CPU mstatus CSR (12): MPP_H - Machine previous privilege mode bit high (r/w) */
};
 
 
471,7 → 470,7
 
 
/**********************************************************************//**
* Processor clock prescalers select
* Processor clock prescaler select
**************************************************************************/
enum NEORV32_CLOCK_PRSC_enum {
CLK_PRSC_2 = 0, /**< CPU_CLK (from clk_i top signal) / 2 */
502,12 → 501,44
// -> configured via dspace_base_c constant in neorv32_package.vhd and available to SW via SYSCONFIG entry
/** bootloader memory base address (r/-/x) */
#define BOOTLOADER_BASE_ADDRESS (0xFFFF0000UL)
/** peripheral/IO devices memory base address (r/w/x) */
/** on-chip debugger complex base address (r/w/x) */
#define OCD_BASE_ADDRESS (0XFFFFF800UL)
/** peripheral/IO devices memory base address (r/w/-) */
#define IO_BASE_ADDRESS (0xFFFFFE00UL)
/**@}*/
 
 
// ############################################################################################################################
// On-Chip Debugger (should NOT be used by application software)
// ############################################################################################################################
/**@{*/
/** on-chip debugger - debug module prototype */
typedef struct __attribute__((packed,aligned(4))) {
const uint32_t CODE[32]; /**< offset 0: park loop code ROM (r/-) */
const uint32_t PBUF[4]; /**< offset 128: program buffer (r/-) */
const uint32_t reserved1[28]; /**< offset 144..252: reserved */
uint32_t DATA; /**< offset 256: data exchange register (r/w) */
const uint32_t reserved2[31]; /**< offset 260..380: reserved */
uint32_t SREG; /**< offset 384: control and status register (r/w) (#NEORV32_OCD_DM_SREG_enum) */
const uint32_t reserved3[31]; /**< offset 388..508: reserved */
} neorv32_dm_t;
 
/** on-chip debugger debug module hardware access (#neorv32_dm_t) */
#define NEORV32_DM (*((volatile neorv32_dm_t*) (0XFFFFF800UL)))
 
/** on-chip debugger debug module control and status register bits */
enum NEORV32_OCD_DM_SREG_enum {
OCD_DM_SREG_HALT_ACK = 0, /**< OCD.DM control and status register(0) (-/w): CPU is halted in debug mode and waits in park loop */
OCD_DM_SREG_RESUME_REQ = 1, /**< OCD.DM control and status register(1) (r/-): DM requests CPU to resume */
OCD_DM_SREG_RESUME_ACK = 2, /**< OCD.DM control and status register(2) (-/w): CPU starts resuming */
OCD_DM_SREG_EXECUTE_REQ = 3, /**< OCD.DM control and status register(3) (r/-): DM requests to execute program buffer */
OCD_DM_SREG_EXECUTE_ACK = 4, /**< OCD.DM control and status register(4) (-/w): CPU starts to execute program buffer */
OCD_DM_SREG_EXCEPTION_ACK = 5 /**< OCD.DM control and status register(5) (-/w): CPU has detected an exception */
};
/**@}*/
 
 
// ############################################################################################################################
// Peripheral/IO Devices - IO Address Space
// ############################################################################################################################
 
579,8 → 610,10
/** SLINK module prototype */
typedef struct __attribute__((packed,aligned(4))) {
uint32_t CTRL; /**< offset 0: control register (#NEORV32_SLINK_CTRL_enum) */
const uint32_t reserved[3]; /**< offset 4..12: reserved */
uint32_t STATUS; /**< offset 16: status register (#NEORV32_SLINK_STATUS_enum) */
const uint32_t reserved0; /**< offset 4: reserved */
uint32_t IRQ; /**< offset 8: interrupt configuration register (#NEORV32_SLINK_IRQ_enum) */
const uint32_t reserved1; /**< offset 12: reserved */
const uint32_t STATUS; /**< offset 16: status register (#NEORV32_SLINK_STATUS_enum) */
const uint32_t reserved2[3]; /**< offset 20..28: reserved */
uint32_t DATA[8]; /**< offset 32..60: stream link data channel 0..7 */
} neorv32_slink_t;
613,25 → 646,56
SLINK_CTRL_EN = 31, /**< SLINK control register(0) (r/w): SLINK controller enable */
};
 
/** SLINK interrupt control register bits */
enum NEORV32_SLINK_IRQ_enum {
SLINK_IRQ_RX_EN_LSB = 0, /**< SLINK IRQ configuration register( 0) (r/w): RX IRQ enable LSB (link 0) (#NEORV32_SLINK_IRQ_EN_enum) */
SLINK_IRQ_RX_EN_MSB = 7, /**< SLINK IRQ configuration register( 7) (r/w): RX IRQ enable MSB (link 7) (#NEORV32_SLINK_IRQ_EN_enum) */
SLINK_IRQ_RX_MODE_LSB = 8, /**< SLINK IRQ configuration register( 8) (r/w): RX IRQ mode LSB (link 0) */
SLINK_IRQ_RX_MODE_MSB = 15, /**< SLINK IRQ configuration register(15) (r/w): RX IRQ mode MSB (link 7) */
 
SLINK_IRQ_TX_EN_LSB = 16, /**< SLINK IRQ configuration register(16) (r/w): TX IRQ enable LSB (link 0) (#NEORV32_SLINK_IRQ_EN_enum) */
SLINK_IRQ_TX_EN_MSB = 23, /**< SLINK IRQ configuration register(23) (r/w): TX IRQ enable MSB (link 7) (#NEORV32_SLINK_IRQ_EN_enum) */
SLINK_IRQ_TX_MODE_LSB = 24, /**< SLINK IRQ configuration register(24) (r/w): TX IRQ mode LSB (link 0) */
SLINK_IRQ_TX_MODE_MSB = 31 /**< SLINK IRQ configuration register(31) (r/w): TX IRQ mode MSB (link 7) */
};
 
/** SLINK interrupt configuration enable (per link) */
enum NEORV32_SLINK_IRQ_EN_enum {
SLINK_IRQ_DISABLE = 0, /**< '1': IRQ disabled */
SLINK_IRQ_ENABLE = 1 /**< '0': IRQ enabled */
};
 
/** SLINK RX interrupt configuration type (per link) */
enum NEORV32_SLINK_IRQ_RX_TYPE_enum {
SLINK_IRQ_RX_FIFO_HALF = 0, /**< '0': RX FIFO is at least half-full */
SLINK_IRQ_RX_NOT_EMPTY = 1 /**< '1': RX FIFO is not empty */
};
 
/** SLINK TX interrupt configuration type (per link) */
enum NEORV32_SLINK_IRQ_TX_TYPE_enum {
SLINK_IRQ_TX_FIFO_HALF = 0, /**< '0': TX FIFO is less than half-full */
SLINK_IRQ_TX_NOT_FULL = 1 /**< '1': TX FIFO is not FULL */
};
 
/** SLINK status register bits */
enum NEORV32_SLINK_STATUS_enum {
SLINK_STATUS_RX0_AVAIL = 0, /**< SLINK status register(0) (r/-): RX link 0 data available */
SLINK_STATUS_RX1_AVAIL = 1, /**< SLINK status register(1) (r/-): RX link 1 data available */
SLINK_STATUS_RX2_AVAIL = 2, /**< SLINK status register(2) (r/-): RX link 2 data available */
SLINK_STATUS_RX3_AVAIL = 3, /**< SLINK status register(3) (r/-): RX link 3 data available */
SLINK_STATUS_RX4_AVAIL = 4, /**< SLINK status register(4) (r/-): RX link 4 data available */
SLINK_STATUS_RX5_AVAIL = 5, /**< SLINK status register(5) (r/-): RX link 5 data available */
SLINK_STATUS_RX6_AVAIL = 6, /**< SLINK status register(6) (r/-): RX link 6 data available */
SLINK_STATUS_RX7_AVAIL = 7, /**< SLINK status register(7) (r/-): RX link 7 data available */
SLINK_STATUS_RX0_AVAIL = 0, /**< SLINK status register(0) (r/-): RX link 0 FIFO is NOT empty (data available) */
SLINK_STATUS_RX1_AVAIL = 1, /**< SLINK status register(1) (r/-): RX link 1 FIFO is NOT empty (data available) */
SLINK_STATUS_RX2_AVAIL = 2, /**< SLINK status register(2) (r/-): RX link 2 FIFO is NOT empty (data available) */
SLINK_STATUS_RX3_AVAIL = 3, /**< SLINK status register(3) (r/-): RX link 3 FIFO is NOT empty (data available) */
SLINK_STATUS_RX4_AVAIL = 4, /**< SLINK status register(4) (r/-): RX link 4 FIFO is NOT empty (data available) */
SLINK_STATUS_RX5_AVAIL = 5, /**< SLINK status register(5) (r/-): RX link 5 FIFO is NOT empty (data available) */
SLINK_STATUS_RX6_AVAIL = 6, /**< SLINK status register(6) (r/-): RX link 6 FIFO is NOT empty (data available) */
SLINK_STATUS_RX7_AVAIL = 7, /**< SLINK status register(7) (r/-): RX link 7 FIFO is NOT empty (data available) */
 
SLINK_STATUS_TX0_FREE = 8, /**< SLINK status register(8) (r/-): TX link 0 ready to send */
SLINK_STATUS_TX1_FREE = 9, /**< SLINK status register(9) (r/-): TX link 1 ready to send */
SLINK_STATUS_TX2_FREE = 10, /**< SLINK status register(10) (r/-): TX link 2 ready to send */
SLINK_STATUS_TX3_FREE = 11, /**< SLINK status register(11) (r/-): TX link 3 ready to send */
SLINK_STATUS_TX4_FREE = 12, /**< SLINK status register(12) (r/-): TX link 4 ready to send */
SLINK_STATUS_TX5_FREE = 13, /**< SLINK status register(13) (r/-): TX link 5 ready to send */
SLINK_STATUS_TX6_FREE = 14, /**< SLINK status register(14) (r/-): TX link 6 ready to send */
SLINK_STATUS_TX7_FREE = 15, /**< SLINK status register(15) (r/-): TX link 7 ready to send */
SLINK_STATUS_TX0_FREE = 8, /**< SLINK status register(8) (r/-): TX link 0 FIFO is NOT full (ready to send) */
SLINK_STATUS_TX1_FREE = 9, /**< SLINK status register(9) (r/-): TX link 1 FIFO is NOT full (ready to send) */
SLINK_STATUS_TX2_FREE = 10, /**< SLINK status register(10) (r/-): TX link 2 FIFO is NOT full (ready to send) */
SLINK_STATUS_TX3_FREE = 11, /**< SLINK status register(11) (r/-): TX link 3 FIFO is NOT full (ready to send) */
SLINK_STATUS_TX4_FREE = 12, /**< SLINK status register(12) (r/-): TX link 4 FIFO is NOT full (ready to send) */
SLINK_STATUS_TX5_FREE = 13, /**< SLINK status register(13) (r/-): TX link 5 FIFO is NOT full (ready to send) */
SLINK_STATUS_TX6_FREE = 14, /**< SLINK status register(14) (r/-): TX link 6 FIFO is NOT full (ready to send) */
SLINK_STATUS_TX7_FREE = 15, /**< SLINK status register(15) (r/-): TX link 7 FIFO is NOT full (ready to send) */
 
SLINK_STATUS_RX0_HALF = 16, /**< SLINK status register(16) (r/-): RX link 0 FIFO fill level is >= half-full */
SLINK_STATUS_RX1_HALF = 17, /**< SLINK status register(17) (r/-): RX link 1 FIFO fill level is >= half-full */
725,7 → 789,13
UART_CTRL_BAUD10 = 10, /**< UART control register(10) (r/w): BAUD rate config value (12-bit, bit 9) */
UART_CTRL_BAUD11 = 11, /**< UART control register(11) (r/w): BAUD rate config value msb (12-bit, bit 0) */
UART_CTRL_SIM_MODE = 12, /**< UART control register(12) (r/w): Simulation output override enable, for use in simulation only */
 
UART_CTRL_RX_EMPTY = 13, /**< UART control register(13) (r/-): RX FIFO is empty */
UART_CTRL_RX_HALF = 14, /**< UART control register(14) (r/-): RX FIFO is at least half-full */
UART_CTRL_RX_FULL = 15, /**< UART control register(15) (r/-): RX FIFO is full */
UART_CTRL_TX_EMPTY = 16, /**< UART control register(16) (r/-): TX FIFO is empty */
UART_CTRL_TX_HALF = 17, /**< UART control register(17) (r/-): TX FIFO is at least half-full */
UART_CTRL_TX_FULL = 18, /**< UART control register(18) (r/-): TX FIFO is full */
UART_CTRL_RTS_EN = 20, /**< UART control register(20) (r/w): Enable hardware flow control: Assert RTS output if UART.RX is ready to receive */
UART_CTRL_CTS_EN = 21, /**< UART control register(21) (r/w): Enable hardware flow control: UART.TX starts sending only if CTS input is asserted */
UART_CTRL_PMODE0 = 22, /**< UART control register(22) (r/w): Parity configuration (0=even; 1=odd) */
735,7 → 805,8
UART_CTRL_PRSC2 = 26, /**< UART control register(26) (r/w): BAUD rate clock prescaler select bit 2 */
UART_CTRL_CTS = 27, /**< UART control register(27) (r/-): current state of CTS input */
UART_CTRL_EN = 28, /**< UART control register(28) (r/w): UART global enable */
 
UART_CTRL_RX_IRQ = 29, /**< UART control register(29) (r/w: RX IRQ mode: 1=FIFO at least half-full; 0=FIFO not empty */
UART_CTRL_TX_IRQ = 30, /**< UART control register(30) (r/w: TX IRQ mode: 1=FIFO less than half-full; 0=FIFO not full */
UART_CTRL_TX_BUSY = 31 /**< UART control register(31) (r/-): Transmitter is busy when set */
};
 
760,7 → 831,7
UART_DATA_MSB = 7, /**< UART receive/transmit data register(7) (r/w): Receive/transmit data MSB (bit 7) */
 
UART_DATA_PERR = 28, /**< UART receive/transmit data register(18) (r/-): RX parity error detected when set */
UART_DATA_FERR = 29, /**< UART receive/transmit data register(29) (r/-): RX frame error (not valid stop bit) wdetected when set */
UART_DATA_FERR = 29, /**< UART receive/transmit data register(29) (r/-): RX frame error (no valid stop bit) detected when set */
UART_DATA_OVERR = 30, /**< UART receive/transmit data register(30) (r/-): RX data overrun when set */
UART_DATA_AVAIL = 31 /**< UART receive/transmit data register(31) (r/-): RX data available when set */
};
782,23 → 853,24
 
/** SPI control register bits */
enum NEORV32_SPI_CTRL_enum {
SPI_CTRL_CS0 = 0, /**< UART control register(0) (r/w): Direct chip select line 0 (output is low when set) */
SPI_CTRL_CS1 = 1, /**< UART control register(1) (r/w): Direct chip select line 1 (output is low when set) */
SPI_CTRL_CS2 = 2, /**< UART control register(2) (r/w): Direct chip select line 2 (output is low when set) */
SPI_CTRL_CS3 = 3, /**< UART control register(3) (r/w): Direct chip select line 3 (output is low when set) */
SPI_CTRL_CS4 = 4, /**< UART control register(4) (r/w): Direct chip select line 4 (output is low when set) */
SPI_CTRL_CS5 = 5, /**< UART control register(5) (r/w): Direct chip select line 5 (output is low when set) */
SPI_CTRL_CS6 = 6, /**< UART control register(6) (r/w): Direct chip select line 6 (output is low when set) */
SPI_CTRL_CS7 = 7, /**< UART control register(7) (r/w): Direct chip select line 7 (output is low when set) */
SPI_CTRL_EN = 8, /**< UART control register(8) (r/w): SPI unit enable */
SPI_CTRL_CPHA = 9, /**< UART control register(9) (r/w): Clock polarity (idle polarity) */
SPI_CTRL_PRSC0 = 10, /**< UART control register(10) (r/w): Clock prescaler select bit 0 */
SPI_CTRL_PRSC1 = 11, /**< UART control register(11) (r/w): Clock prescaler select bit 1 */
SPI_CTRL_PRSC2 = 12, /**< UART control register(12) (r/w): Clock prescaler select bit 2 */
SPI_CTRL_SIZE0 = 13, /**< UART control register(13) (r/w): Transfer data size lsb (00: 8-bit, 01: 16-bit, 10: 24-bit, 11: 32-bit) */
SPI_CTRL_SIZE1 = 14, /**< UART control register(14) (r/w): Transfer data size msb (00: 8-bit, 01: 16-bit, 10: 24-bit, 11: 32-bit) */
SPI_CTRL_CS0 = 0, /**< SPI control register(0) (r/w): Direct chip select line 0 (output is low when set) */
SPI_CTRL_CS1 = 1, /**< SPI control register(1) (r/w): Direct chip select line 1 (output is low when set) */
SPI_CTRL_CS2 = 2, /**< SPI control register(2) (r/w): Direct chip select line 2 (output is low when set) */
SPI_CTRL_CS3 = 3, /**< SPI control register(3) (r/w): Direct chip select line 3 (output is low when set) */
SPI_CTRL_CS4 = 4, /**< SPI control register(4) (r/w): Direct chip select line 4 (output is low when set) */
SPI_CTRL_CS5 = 5, /**< SPI control register(5) (r/w): Direct chip select line 5 (output is low when set) */
SPI_CTRL_CS6 = 6, /**< SPI control register(6) (r/w): Direct chip select line 6 (output is low when set) */
SPI_CTRL_CS7 = 7, /**< SPI control register(7) (r/w): Direct chip select line 7 (output is low when set) */
SPI_CTRL_EN = 8, /**< SPI control register(8) (r/w): SPI unit enable */
SPI_CTRL_CPHA = 9, /**< SPI control register(9) (r/w): Clock phase */
SPI_CTRL_PRSC0 = 10, /**< SPI control register(10) (r/w): Clock prescaler select bit 0 */
SPI_CTRL_PRSC1 = 11, /**< SPI control register(11) (r/w): Clock prescaler select bit 1 */
SPI_CTRL_PRSC2 = 12, /**< SPI control register(12) (r/w): Clock prescaler select bit 2 */
SPI_CTRL_SIZE0 = 13, /**< SPI control register(13) (r/w): Transfer data size lsb (00: 8-bit, 01: 16-bit, 10: 24-bit, 11: 32-bit) */
SPI_CTRL_SIZE1 = 14, /**< SPI control register(14) (r/w): Transfer data size msb (00: 8-bit, 01: 16-bit, 10: 24-bit, 11: 32-bit) */
SPI_CTRL_CPOL = 15, /**< SPI control register(15) (r/w): Clock polarity */
 
SPI_CTRL_BUSY = 31 /**< UART control register(31) (r/-): SPI busy flag */
SPI_CTRL_BUSY = 31 /**< SPI control register(31) (r/-): SPI busy flag */
};
/**@}*/
 
951,6 → 1023,7
NEOLED_CTRL_T_ONE_H_3 = 23, /**< NEOLED control register(23) (r/w): pulse-clock ticks per ONE high-time bit 3 */
NEOLED_CTRL_T_ONE_H_4 = 24, /**< NEOLED control register(24) (r/w): pulse-clock ticks per ONE high-time bit 4 */
//
NEOLED_CTRL_IRQ_CONF = 27, /**< NEOLED control register(27) (r/w): TX FIFO interrupt: 0=IRQ if FIFO is less than half-full, 1=IRQ if FIFO is empty */
NEOLED_CTRL_TX_EMPTY = 28, /**< NEOLED control register(28) (r/-): TX FIFO is empty */
NEOLED_CTRL_TX_HALF = 29, /**< NEOLED control register(29) (r/-): TX FIFO is at least half-full */
NEOLED_CTRL_TX_FULL = 30, /**< NEOLED control register(30) (r/-): TX FIFO is full */
/neorv32/trunk/sw/lib/include/neorv32_cpu.h
69,13 → 69,13
 
 
/**********************************************************************//**
* Store unsigned word to address space.
* Store unsigned word to address space if atomic access reservation is still valid.
*
* @note An unaligned access address will raise an alignment exception.
*
* @param[in] addr Address (32-bit).
* @param[in] wdata Data word (32-bit) to store.
* @return Operation status (32-bit).
* @return Operation status (32-bit, zero if success).
**************************************************************************/
inline uint32_t __attribute__ ((always_inline)) neorv32_cpu_store_conditional(uint32_t addr, uint32_t wdata) {
 
94,7 → 94,7
 
 
/**********************************************************************//**
* Conditional store unsigned word to address space if atomic access reservation is valid.
* Conditional store unsigned word to address space.
*
* @note An unaligned access address will raise an alignment exception.
*
254,9 → 254,9
/**********************************************************************//**
* Put CPU into "sleep" mode.
*
* @note This function executes the WFI insstruction.
* @note This function executes the WFI instruction.
* The WFI (wait for interrupt) instruction will make the CPU stall until
* an interupt request is detected. Interrupts have to be globally enabled
* an interrupt request is detected. Interrupts have to be globally enabled
* and at least one external source must be enabled (like the MTI machine
* timer interrupt) to allow the CPU to wake up again. If 'Zicsr' CPU extension is disabled,
* this will permanently stall the CPU.
/neorv32/trunk/sw/lib/include/neorv32_slink.h
46,6 → 46,8
int neorv32_slink_available(void);
void neorv32_slink_enable(void);
void neorv32_slink_disable(void);
void neorv32_slink_rx_irq_config(int link_id, int irq_en, int irq_type);
void neorv32_slink_tx_irq_config(int link_id, int irq_en, int irq_type);
int neorv32_slink_get_rx_num(void);
int neorv32_slink_get_tx_num(void);
int neorv32_slink_get_rx_depth(void);
/neorv32/trunk/sw/lib/include/neorv32_spi.h
46,7 → 46,7
 
// prototypes
int neorv32_spi_available(void);
void neorv32_spi_setup(uint8_t prsc, uint8_t clk_polarity, uint8_t data_size);
void neorv32_spi_setup(uint8_t prsc, uint8_t clk_phase, uint8_t clk_polarity, uint8_t data_size);
void neorv32_spi_disable(void);
void neorv32_spi_enable(void);
void neorv32_spi_cs_en(uint8_t cs);
/neorv32/trunk/sw/lib/include/neorv32_uart.h
49,7 → 49,7
// Libs required by functions
#include <stdarg.h>
 
// compatibility wrappers (mapping to primary UART -> UART0)
// compatibility wrappers (mapping to primary UART -> UART0) (OBSOLETE, do not use for new designs!)
int neorv32_uart_available(void);
void neorv32_uart_setup(uint32_t baudrate, uint8_t parity, uint8_t flow_con);
void neorv32_uart_disable(void);
/neorv32/trunk/sw/lib/source/neorv32_cpu.c
354,9 → 354,9
uint32_t i = 0;
 
// try setting R bit in all PMPCFG CSRs
const uint32_t tmp = 0x01010101;
const uint32_t mask = 0x01010101;
for (i=0; i<16; i++) {
__neorv32_cpu_pmp_cfg_write(i, tmp);
__neorv32_cpu_pmp_cfg_write(i, mask);
}
 
// sum up all written ones (only available PMPCFG* CSRs/entries will return =! 0)
367,7 → 367,7
 
cnt.uint32 = 0;
for (i=0; i<16; i++) {
cnt.uint32 += __neorv32_cpu_pmp_cfg_read(i);
cnt.uint32 += __neorv32_cpu_pmp_cfg_read(i) & mask;
}
 
// sum up bytes
/neorv32/trunk/sw/lib/source/neorv32_rte.c
51,6 → 51,7
static void __attribute__((__interrupt__)) __neorv32_rte_core(void) __attribute__((aligned(16)));
static void __neorv32_rte_debug_exc_handler(void);
static void __neorv32_rte_print_true_false(int state);
static void __neorv32_rte_print_checkbox(int state);
static void __neorv32_rte_print_hex_word(uint32_t num);
 
 
204,7 → 205,7
char tmp;
 
// intro
neorv32_uart_print("<RTE> ");
neorv32_uart0_print("<RTE> ");
 
// cause
register uint32_t trap_cause = neorv32_cpu_csr_read(CSR_MCAUSE);
216,19 → 217,19
tmp = '0' + tmp;
}
switch (trap_cause) {
case TRAP_CODE_I_MISALIGNED: neorv32_uart_print("Instruction address misaligned"); break;
case TRAP_CODE_I_ACCESS: neorv32_uart_print("Instruction access fault"); break;
case TRAP_CODE_I_ILLEGAL: neorv32_uart_print("Illegal instruction"); break;
case TRAP_CODE_BREAKPOINT: neorv32_uart_print("Breakpoint"); break;
case TRAP_CODE_L_MISALIGNED: neorv32_uart_print("Load address misaligned"); break;
case TRAP_CODE_L_ACCESS: neorv32_uart_print("Load access fault"); break;
case TRAP_CODE_S_MISALIGNED: neorv32_uart_print("Store address misaligned"); break;
case TRAP_CODE_S_ACCESS: neorv32_uart_print("Store access fault"); break;
case TRAP_CODE_UENV_CALL: neorv32_uart_print("Environment call from U-mode"); break;
case TRAP_CODE_MENV_CALL: neorv32_uart_print("Environment call from M-mode"); break;
case TRAP_CODE_MSI: neorv32_uart_print("Machine software interrupt"); break;
case TRAP_CODE_MTI: neorv32_uart_print("Machine timer interrupt"); break;
case TRAP_CODE_MEI: neorv32_uart_print("Machine external interrupt"); break;
case TRAP_CODE_I_MISALIGNED: neorv32_uart0_print("Instruction address misaligned"); break;
case TRAP_CODE_I_ACCESS: neorv32_uart0_print("Instruction access fault"); break;
case TRAP_CODE_I_ILLEGAL: neorv32_uart0_print("Illegal instruction"); break;
case TRAP_CODE_BREAKPOINT: neorv32_uart0_print("Breakpoint"); break;
case TRAP_CODE_L_MISALIGNED: neorv32_uart0_print("Load address misaligned"); break;
case TRAP_CODE_L_ACCESS: neorv32_uart0_print("Load access fault"); break;
case TRAP_CODE_S_MISALIGNED: neorv32_uart0_print("Store address misaligned"); break;
case TRAP_CODE_S_ACCESS: neorv32_uart0_print("Store access fault"); break;
case TRAP_CODE_UENV_CALL: neorv32_uart0_print("Environment call from U-mode"); break;
case TRAP_CODE_MENV_CALL: neorv32_uart0_print("Environment call from M-mode"); break;
case TRAP_CODE_MSI: neorv32_uart0_print("Machine software interrupt"); break;
case TRAP_CODE_MTI: neorv32_uart0_print("Machine timer interrupt"); break;
case TRAP_CODE_MEI: neorv32_uart0_print("Machine external interrupt"); break;
case TRAP_CODE_FIRQ_0:
case TRAP_CODE_FIRQ_1:
case TRAP_CODE_FIRQ_2:
244,18 → 245,18
case TRAP_CODE_FIRQ_12:
case TRAP_CODE_FIRQ_13:
case TRAP_CODE_FIRQ_14:
case TRAP_CODE_FIRQ_15: neorv32_uart_print("Fast interrupt "); neorv32_uart_putc(tmp); break;
default: neorv32_uart_print("Unknown trap cause: "); __neorv32_rte_print_hex_word(trap_cause); break;
case TRAP_CODE_FIRQ_15: neorv32_uart0_print("Fast interrupt "); neorv32_uart0_putc(tmp); break;
default: neorv32_uart0_print("Unknown trap cause: "); __neorv32_rte_print_hex_word(trap_cause); break;
}
 
// instruction address
neorv32_uart_print(" @ PC=");
neorv32_uart0_print(" @ PC=");
__neorv32_rte_print_hex_word(neorv32_cpu_csr_read(CSR_MSCRATCH)); // rte core stores actual mepc to mscratch
 
// additional info
neorv32_uart_print(", MTVAL=");
neorv32_uart0_print(", MTVAL=");
__neorv32_rte_print_hex_word(neorv32_cpu_csr_read(CSR_MTVAL));
neorv32_uart_print(" </RTE>");
neorv32_uart0_print(" </RTE>");
}
 
 
272,25 → 273,15
int i;
char c;
 
neorv32_uart_printf("\n\n<<< Processor Configuration Overview >>>\n");
neorv32_uart0_printf("\n\n<<< Processor Configuration Overview >>>\n");
 
// Processor - general stuff
neorv32_uart0_printf("\n=== << General >> ===\n"
"Clock speed: %u Hz\n", NEORV32_SYSINFO.CLK);
neorv32_uart0_printf("Full HW reset: "); __neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_HW_RESET));
neorv32_uart0_printf("Boot Config.: Boot ");
if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_BOOTLOADER)) {
neorv32_uart0_printf("via Bootloader\n");
}
else {
neorv32_uart0_printf("from memory (@ 0x%x)\n", NEORV32_SYSINFO.ISPACE_BASE);
}
neorv32_uart0_printf("On-chip debug: "); __neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_OCD));
 
 
// CPU configuration
neorv32_uart0_printf("\n=== << CPU >> ===\n");
 
// general
neorv32_uart0_printf("Clock speed: %u Hz\n", NEORV32_SYSINFO.CLK);
neorv32_uart0_printf("Full HW reset: "); __neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_HW_RESET));
neorv32_uart0_printf("On-chip debugger: "); __neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_OCD));
// ID
neorv32_uart0_printf("Hart ID: 0x%x\n"
"Vendor ID: 0x%x\n", neorv32_cpu_csr_read(CSR_MHARTID), neorv32_cpu_csr_read(CSR_MVENDORID));
378,8 → 369,16
 
 
// Memory configuration
neorv32_uart0_printf("\n=== << Memory Configuration >> ===\n");
neorv32_uart0_printf("\n=== << Memory System >> ===\n");
 
neorv32_uart0_printf("Boot Config.: Boot ");
if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_BOOTLOADER)) {
neorv32_uart0_printf("via Bootloader\n");
}
else {
neorv32_uart0_printf("from memory (@ 0x%x)\n", NEORV32_SYSINFO.ISPACE_BASE);
}
 
neorv32_uart0_printf("Instr. base address: 0x%x\n", NEORV32_SYSINFO.ISPACE_BASE);
 
// IMEM
394,14 → 393,17
// DMEM
neorv32_uart0_printf("Data base address: 0x%x\n", NEORV32_SYSINFO.DSPACE_BASE);
neorv32_uart0_printf("Internal DMEM: ");
if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_INT_DMEM)) { neorv32_uart0_printf("yes, %u bytes\n", NEORV32_SYSINFO.DMEM_SIZE); }
else { neorv32_uart0_printf("no\n"); }
if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_INT_DMEM)) {
neorv32_uart0_printf("yes, %u bytes\n", NEORV32_SYSINFO.DMEM_SIZE);
}
else {
neorv32_uart0_printf("no\n");
}
 
// i-cache
neorv32_uart0_printf("Internal i-cache: ");
__neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_ICACHE));
if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_ICACHE)) {
neorv32_uart0_printf("- ");
neorv32_uart0_printf("yes, ");
 
uint32_t ic_block_size = (NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_BLOCK_SIZE_0) & 0x0F;
if (ic_block_size) {
422,7 → 424,7
uint32_t ic_associativity = (NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_ASSOCIATIVITY_0) & 0x0F;
ic_associativity = 1 << ic_associativity;
 
neorv32_uart0_printf("%u bytes: %u set(s), %u block(s) per set, %u bytes per block", ic_associativity*ic_num_blocks*ic_block_size, ic_associativity, ic_num_blocks, ic_block_size);
neorv32_uart0_printf("%u bytes, %u set(s), %u block(s) per set, %u bytes per block", ic_associativity*ic_num_blocks*ic_block_size, ic_associativity, ic_num_blocks, ic_block_size);
if (ic_associativity == 1) {
neorv32_uart0_printf(" (direct-mapped)\n");
}
433,6 → 435,9
neorv32_uart0_printf("\n");
}
}
else {
neorv32_uart0_printf("no\n");
}
 
neorv32_uart0_printf("Ext. bus interface: ");
__neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_EXT));
448,19 → 453,19
neorv32_uart0_printf("\n=== << Peripherals >> ===\n");
 
tmp = NEORV32_SYSINFO.SOC;
neorv32_uart0_printf("GPIO - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_GPIO));
neorv32_uart0_printf("MTIME - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_MTIME));
neorv32_uart0_printf("UART0 - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_UART0));
neorv32_uart0_printf("UART1 - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_UART1));
neorv32_uart0_printf("SPI - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_SPI));
neorv32_uart0_printf("TWI - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_TWI));
neorv32_uart0_printf("PWM - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_PWM));
neorv32_uart0_printf("WDT - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_WDT));
neorv32_uart0_printf("TRNG - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_TRNG));
neorv32_uart0_printf("CFS - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_CFS));
neorv32_uart0_printf("SLINK - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_SLINK));
neorv32_uart0_printf("NEOLED - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_NEOLED));
neorv32_uart0_printf("XIRQ - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_XIRQ));
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_GPIO)); neorv32_uart0_printf(" GPIO\n");
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_MTIME)); neorv32_uart0_printf(" MTIME\n");
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_UART0)); neorv32_uart0_printf(" UART0\n");
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_UART1)); neorv32_uart0_printf(" UART1\n");
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_SPI)); neorv32_uart0_printf(" SPI\n");
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_TWI)); neorv32_uart0_printf(" TWI\n");
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_PWM)); neorv32_uart0_printf(" PWM\n");
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_WDT)); neorv32_uart0_printf(" WDT\n");
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_TRNG)); neorv32_uart0_printf(" TRNG\n");
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_CFS)); neorv32_uart0_printf(" CFS\n");
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_SLINK)); neorv32_uart0_printf(" SLINK\n");
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_NEOLED)); neorv32_uart0_printf(" NEOLED\n");
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_XIRQ)); neorv32_uart0_printf(" XIRQ\n");
}
 
 
468,7 → 473,7
* NEORV32 runtime environment: Private function to print yes or no.
* @note This function is used by neorv32_rte_print_hw_config(void) only.
*
* @param[in] state Print 'yes' when !=0, print '0' when 0
* @param[in] state Print 'yes' when !=0, print 'no' when 0
**************************************************************************/
static void __neorv32_rte_print_true_false(int state) {
 
482,6 → 487,25
 
 
/**********************************************************************//**
* NEORV32 runtime environment: Private function to print [x] or [ ].
* @note This function is used by neorv32_rte_print_hw_config(void) only.
*
* @param[in] state Print '[x]' when !=0, print '[ ]' when 0
**************************************************************************/
static void __neorv32_rte_print_checkbox(int state) {
 
neorv32_uart0_putc('[');
if (state) {
neorv32_uart0_putc('x');
}
else {
neorv32_uart0_putc(' ');
}
neorv32_uart0_putc(']');
}
 
 
/**********************************************************************//**
* NEORV32 runtime environment: Private function to print 32-bit number
* as 8-digit hexadecimal value (with "0x" suffix).
*
606,7 → 630,7
return; // cannot output anything if UART0 is not implemented
}
 
neorv32_uart_print(
neorv32_uart0_print(
"\n"
"BSD 3-Clause License\n"
"\n"
712,7 → 736,7
}
else {
if ((silent == 0) || (neorv32_uart0_available() == 0)) {
neorv32_uart_printf("\nWARNING! SW_ISA (features required) vs HW_ISA (features available) mismatch!\n"
neorv32_uart0_printf("\nWARNING! SW_ISA (features required) vs HW_ISA (features available) mismatch!\n"
"SW_ISA = 0x%x (compiler flags)\n"
"HW_ISA = 0x%x (misa csr)\n\n", misa_sw, misa_hw);
}
/neorv32/trunk/sw/lib/source/neorv32_slink.c
80,6 → 80,72
 
 
/**********************************************************************//**
* Configure SLINK RX interrupt.
*
* @param[in] link_id Link id (0..7).
* @param[in] irq_en Link's IRQ enable (#NEORV32_SLINK_IRQ_EN_enum)
* @param[in] irq_type Link's IRQ type (#NEORV32_SLINK_IRQ_RX_TYPE_enum)
**************************************************************************/
void neorv32_slink_rx_irq_config(int link_id, int irq_en, int irq_type) {
 
link_id = link_id & 7;
 
uint32_t slink_irq_conf = NEORV32_SLINK.IRQ;
 
// enable IRQ
if (irq_en) {
slink_irq_conf |= (1 << (SLINK_IRQ_RX_EN_LSB + link_id));
}
else {
slink_irq_conf &= ~(1 << (SLINK_IRQ_RX_EN_LSB + link_id));
}
 
// configure type
if (irq_type) {
slink_irq_conf |= (1 << (SLINK_IRQ_RX_MODE_LSB + link_id));
}
else {
slink_irq_conf &= ~(1 << (SLINK_IRQ_RX_MODE_LSB + link_id));
}
 
NEORV32_SLINK.IRQ = slink_irq_conf;
}
 
 
/**********************************************************************//**
* Configure SLINK TX interrupt.
*
* @param[in] link_id Link id (0..7).
* @param[in] irq_en Link's IRQ enable (#NEORV32_SLINK_IRQ_EN_enum)
* @param[in] irq_type Link's IRQ type (#NEORV32_SLINK_IRQ_TX_TYPE_enum)
**************************************************************************/
void neorv32_slink_tx_irq_config(int link_id, int irq_en, int irq_type) {
 
link_id = link_id & 7;
 
uint32_t slink_irq_conf = NEORV32_SLINK.IRQ;
 
// enable IRQ
if (irq_en) {
slink_irq_conf |= (1 << (SLINK_IRQ_TX_EN_LSB + link_id));
}
else {
slink_irq_conf &= ~(1 << (SLINK_IRQ_TX_EN_LSB + link_id));
}
 
// configure type
if (irq_type) {
slink_irq_conf |= (1 << (SLINK_IRQ_TX_MODE_LSB + link_id));
}
else {
slink_irq_conf &= ~(1 << (SLINK_IRQ_TX_MODE_LSB + link_id));
}
 
NEORV32_SLINK.IRQ = slink_irq_conf;
}
 
 
/**********************************************************************//**
* Get number of implemented RX links
*
* @return Number of implemented RX link (0..8).
/neorv32/trunk/sw/lib/source/neorv32_spi.c
65,10 → 65,11
* Enable and configure SPI controller. The SPI control register bits are listed in #NEORV32_SPI_CTRL_enum.
*
* @param[in] prsc Clock prescaler select (0..7). See #NEORV32_CLOCK_PRSC_enum.
* @param[in] clk_polarity Idle clock polarity (0, 1).
* @param[in] clk_phase Clock phase (0=sample on rising edge, 1=sample on falling edge).
* @param[in] clk_polarity Clock polarity (when idle).
* @param[in] data_size Data transfer size (0: 8-bit, 1: 16-bit, 2: 24-bit, 3: 32-bit).
**************************************************************************/
void neorv32_spi_setup(uint8_t prsc, uint8_t clk_polarity, uint8_t data_size) {
void neorv32_spi_setup(uint8_t prsc, uint8_t clk_phase, uint8_t clk_polarity, uint8_t data_size) {
 
NEORV32_SPI.CTRL = 0; // reset
 
78,13 → 79,16
uint32_t ct_prsc = (uint32_t)(prsc & 0x07);
ct_prsc = ct_prsc << SPI_CTRL_PRSC0;
 
uint32_t ct_phase = (uint32_t)(clk_phase & 0x01);
ct_phase = ct_phase << SPI_CTRL_CPHA;
 
uint32_t ct_polarity = (uint32_t)(clk_polarity & 0x01);
ct_polarity = ct_polarity << SPI_CTRL_CPHA;
ct_polarity = ct_polarity << SPI_CTRL_CPOL;
 
uint32_t ct_size = (uint32_t)(data_size & 0x03);
ct_size = ct_size << SPI_CTRL_SIZE0;
 
NEORV32_SPI.CTRL = ct_enable | ct_prsc | ct_polarity | ct_size;
NEORV32_SPI.CTRL = ct_enable | ct_prsc | ct_phase | ct_polarity | ct_size;
}
 
 
158,8 → 162,6
/**********************************************************************//**
* Check if SPI transceiver is busy.
*
* @note This function is blocking.
*
* @return 0 if idle, 1 if busy
**************************************************************************/
int neorv32_spi_busy(void) {
167,5 → 169,7
if ((NEORV32_SPI.CTRL & (1<<SPI_CTRL_BUSY)) != 0) {
return 1;
}
return 0;
else {
return 0;
}
}
/neorv32/trunk/sw/lib/source/neorv32_uart.c
50,8 → 50,8
 
/// \cond
// Private functions
static void __neorv32_uart_itoa(uint32_t x, char *res) __attribute__((unused)); // GCC: do not ouput a warning when this variable is unused
static void __neorv32_uart_tohex(uint32_t x, char *res) __attribute__((unused)); // GCC: do not ouput a warning when this variable is unused
static void __neorv32_uart_itoa(uint32_t x, char *res) __attribute__((unused)); // GCC: do not output a warning when this variable is unused
static void __neorv32_uart_tohex(uint32_t x, char *res) __attribute__((unused)); // GCC: do not output a warning when this variable is unused
/// \endcond
 
 
336,13 → 336,13
void neorv32_uart0_putc(char c) {
 
// wait for previous transfer to finish
while ((NEORV32_UART0.CTRL & (1<<UART_CTRL_TX_BUSY)) != 0);
while ((NEORV32_UART0.CTRL & (1<<UART_CTRL_TX_FULL)) != 0); // wait for space in TX FIFO
NEORV32_UART0.DATA = ((uint32_t)c) << UART_DATA_LSB;
}
 
 
/**********************************************************************//**
* Check if UART0 TX is busy.
* Check if UART0 TX is busy (transmitter busy or data left in TX buffer).
*
* @note This function is blocking.
*
350,7 → 350,10
**************************************************************************/
int neorv32_uart0_tx_busy(void) {
 
if ((NEORV32_UART0.CTRL & (1<<UART_CTRL_TX_BUSY)) != 0) {
uint32_t ctrl = NEORV32_UART0.CTRL;
 
if (((ctrl & (1<<UART_CTRL_TX_BUSY)) != 0) || // TX engine busy
((ctrl & (1<<UART_CTRL_TX_EMPTY)) == 0)) { // TX buffer not empty
return 1;
}
return 0;
382,37 → 385,41
* @note This function is non-blocking and checks for frame and parity errors.
*
* @param[in,out] data Received char.
* @return Status code (0=nothing received, 1: char received without errors; -1: char received with frame error; -2: char received with parity error; -3 char received with frame & parity error).
* @return Status code:
* 0 = char received without errors
* -1 = nothing received
* -2 = char received with frame error
* -3 = char received with parity error
* -4 = char received with overrun error.
**************************************************************************/
int neorv32_uart0_getc_safe(char *data) {
 
uint32_t uart_rx = NEORV32_UART0.DATA;
if (uart_rx & (1<<UART_DATA_AVAIL)) { // char available at all?
 
int status = 0;
// get received byte (if there is any)
*data = (char)uart_rx;
 
// check for frame error
if (uart_rx & (1<<UART_DATA_FERR)) {
status -= 1;
}
// check if no data available at all
if ((uart_rx & (1<<UART_DATA_AVAIL)) == 0) {
return -1;
}
 
// check for parity error
if (uart_rx & (1<<UART_DATA_PERR)) {
status -= 2;
}
// check for frame error
if (uart_rx & (1<<UART_DATA_FERR)) {
return -2;
}
 
if (status == 0) {
status = 1;
}
// check for parity error
if (uart_rx & (1<<UART_DATA_PERR)) {
return -3;
}
 
// get received byte
*data = (char)uart_rx;
// check for overrun error
if (uart_rx & (1<<UART_DATA_OVERR)) {
return -4;
}
 
return status;
}
else {
return 0;
}
return 0; // all fine
}
 
 
696,13 → 703,13
void neorv32_uart1_putc(char c) {
 
// wait for previous transfer to finish
while ((NEORV32_UART1.CTRL & (1<<UART_CTRL_TX_BUSY)) != 0);
while ((NEORV32_UART1.CTRL & (1<<UART_CTRL_TX_FULL)) != 0); // wait for space in TX FIFO
NEORV32_UART1.DATA = ((uint32_t)c) << UART_DATA_LSB;
}
 
 
/**********************************************************************//**
* Check if UART1 TX is busy.
* Check if UART1 TX is busy (transmitter busy or data left in TX buffer).
*
* @note This function is blocking.
*
710,7 → 717,10
**************************************************************************/
int neorv32_uart1_tx_busy(void) {
 
if ((NEORV32_UART1.CTRL & (1<<UART_CTRL_TX_BUSY)) != 0) {
uint32_t ctrl = NEORV32_UART1.CTRL;
 
if (((ctrl & (1<<UART_CTRL_TX_BUSY)) != 0) || // TX engine busy
((ctrl & (1<<UART_CTRL_TX_EMPTY)) == 0)) { // TX buffer not empty
return 1;
}
return 0;
742,37 → 752,41
* @note This function is non-blocking and checks for frame and parity errors.
*
* @param[in,out] data Received char.
* @return Status code (0=nothing received, 1: char received without errors; -1: char received with frame error; -2: char received with parity error; -3 char received with frame & parity error).
* @return Status code:
* 0 = char received without errors
* -1 = nothing received
* -2 = char received with frame error
* -3 = char received with parity error
* -4 = char received with overrun error.
**************************************************************************/
int neorv32_uart1_getc_safe(char *data) {
 
uint32_t uart_rx = NEORV32_UART1.DATA;
if (uart_rx & (1<<UART_DATA_AVAIL)) { // char available at all?
 
int status = 0;
// get received byte (if there is any)
*data = (char)uart_rx;
 
// check for frame error
if (uart_rx & (1<<UART_DATA_FERR)) {
status -= 1;
}
// check if no data available at all
if ((uart_rx & (1<<UART_DATA_AVAIL)) == 0) {
return -1;
}
 
// check for parity error
if (uart_rx & (1<<UART_DATA_PERR)) {
status -= 2;
}
// check for frame error
if (uart_rx & (1<<UART_DATA_FERR)) {
return -2;
}
 
if (status == 0) {
status = 1;
}
// check for parity error
if (uart_rx & (1<<UART_DATA_PERR)) {
return -3;
}
 
// get received byte
*data = (char)uart_rx;
// check for overrun error
if (uart_rx & (1<<UART_DATA_OVERR)) {
return -4;
}
 
return status;
}
else {
return 0;
}
return 0; // all fine
}
 
 
/neorv32/trunk/sw/ocd-firmware/makefile
55,8 → 55,8
RISCV_PREFIX ?= riscv32-unknown-elf-
 
# CPU architecture and ABI
MARCH = -march=rv32i
MABI = -mabi=ilp32
MARCH = rv32i
MABI = ilp32
 
# User flags for additional configuration (will be added to compiler flags)
USER_FLAGS ?=
117,7 → 117,7
IMAGE_GEN = $(NEORV32_EXG_PATH)/image_gen
 
# Compiler & linker flags
CC_OPTS = $(MARCH) $(MABI) $(EFFORT) -Wall -ffunction-sections -fdata-sections -nostartfiles -mno-fdiv
CC_OPTS = -march=$(MARCH) -mabi=$(MABI) $(EFFORT) -Wall -ffunction-sections -fdata-sections -nostartfiles -mno-fdiv
CC_OPTS += -Wl,--gc-sections -lm -lc -lgcc -lc
# This accelerates instruction fetch after branches when C extension is enabled (irrelevant when C extension is disabled)
CC_OPTS += -falign-functions=4 -falign-labels=4 -falign-loops=4 -falign-jumps=4
/neorv32/trunk/.gitmodules
1,3 → 1,4
[submodule "riscv-arch-test/work/riscv-arch-test"]
path = sw/isa-test/riscv-arch-test
url = https://github.com/riscv/riscv-arch-test.git
url = https://github.com/riscv-non-isa/riscv-arch-test.git
ignore = dirty
/neorv32/trunk/CHANGELOG.md
26,8 → 26,24
 
| Date (*dd.mm.yyyy*) | Version | Comment |
|:----------:|:-------:|:--------|
| 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 | 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)) |
| 14.10.2021 | 1.6.1.10 | :sparkles: SLINK: added fine-grained, per-link interrupt configuration (see [PR #182](https://github.com/stnolting/neorv32/pull/182)) |
| 13.10.2021 | 1.6.1.9 | :sparkles: NEOLED: added new control register bit _NEOLED_CTRL_IRQ_CONF_ to configure IRQ condition: `0` = IRQ if FIFO is less than half-full, `1` = IRQ if FIFO is empty; :information_source: IRQ behavior is fully backwards compatible if _NEOLED_CTRL_IRQ_CONF_ is ignored (kept zero) |
| 12.10.2021 | 1.6.1.8 | added dedicated `half_o` signal to FIFO component (FIFO _at least_ half-full), simplifies half-full test logic in FIFO-utilizing modules (area footprint and critical path); minor logic/hardware optimization of NEOLED module |
| 09.10.2021 | 1.6.1.7 | :warning: reworked _fast interrupt requests_ (FIRQ) CPU interrupt system: fast interrupt requests are now also high-level-triggered (like the RISC-V standard interrupts) and stay asserted until explicitly acknowledged by software ([PR #176](https://github.com/stnolting/neorv32/pull/176)) |
| 06.10.2021 | 1.6.1.6 | :bug: fixed bugs in signal assignments and processor configuration of `setups/radiant/UPduino_v3` setup; minor CPU HPM counter fix (architecture condition for "multi-cycle ALU wait cycle" HPM event) |
| 05.10.2021 | 1.6.1.5 | :sparkles: :lock: the CPU now ensures that _all_ illegal instructions _do not commit_ any potential architecture state changes (like writing registers or triggering memory accesses); CPU logic optimization (smaller footprint) |
| 04.10.2021 | 1.6.1.4 | moved CPU's comparator logic from register file unit to ALU unit (to allow easier replacement of register file design unit by technology-optimized one) |
| 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 | 1.6.0.13 | :bug: fixed _stupid_ bug in MTIME comparator logic (interrupt condition `mtime >= mtimecmp` was not always evaluated correctly) |
| 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 |
| 22.09.2021 | 1.6.0.10 | reworked CPU/software handshake of external interrupt controller `XIRQ` to avoid "external IRQ -> CPU IRQ" race conditions |
34,7 → 50,7
| 22.09.2021 | 1.6.0.9 | if `CPU_CNT_WIDTH` generic (actual width of `[m]cycle` and `[m]instret` counters) is less than 64 the remaining bits are now just hardwired to zero ignoring any write access instead of causing an exception; minor CPU hardware optimizations |
| 22.09.2021 | 1.6.0.8 | :bug: fixed bug introduced in previous version: misaligned instruction address - PC and all instruction address-related registers need to have bit 0 hardwired to zero, misaligned instructions can only appear if NOT using `C` ISA extension |
| 21.09.2021 | 1.6.0.7 | :warning: **reworked CPU trap/exception system** (in order to comply with RISC-V specs.): removed non-maskable interrupt (`NMI`, top signal `nm_irq_i`); reworked CPU trap prioritization (sync before async); RISC-V interrupts (`MTI`, `MSI`, `MEI`) are now high-level-triggered and require to stay asserted until they are explicitly acknowledged; fixed minor bug in misaligned instruction check logic (PC(0) = '1' will always cause a misalignment exception); updated trap/interrupt-related documentation |
| 20.09.2021 | 1.6.0.6 | the NEORV32's `misa`, `mip` and `mtval` CSRs are _read-only_; however, write accesses to these CSRs _do not raise an illegal instruction exception_ (anymore) to be compatibility to the RISC-V specs. |
| 20.09.2021 | 1.6.0.6 | the NEORV32's `misa`, `mip` and `mtval` CSRs are _read-only_; however, write accesses to these CSRs _do not raise an illegal instruction exception_ (anymore) to be compatible to the RISC-V specs. |
| 19.09.2021 | 1.6.0.5 | added `menvcfg[h]` CSRs (only available if `U` ISA extension is enabled; not used yet - hardwired to zero, but required by RISC-V spec.) |
| 18.09.2021 | 1.6.0.4 | :warning: :warning: **major change** modified low-level hardware access (memory-mapped registers) [PR #158](https://github.com/stnolting/neorv32/pull/158): now using `struct`-based access concept (IO module = `struct`, interface registers = members of struct) instead of `#define` single-pointers (inspired by https://blog.feabhas.com/2019/01/peripheral-register-access-using-c-structs-part-1/), format: `NEORV32_<module_name>.<register_name>`; renamed all control registers and bits from `*CT*` to `*CTRL*`; added `sw/lib/include/neorv32_legacy.h` compatibility layer (maps deprecated "defines" to according struct registers, provides old control register/bit names, _do not use for new designs!_) |
| 16.09.2021 | 1.6.0.3 | :bug: fixed another missing IRQ signal connection (NMI) in `system_integration` wrappers |
57,7 → 73,7
| 07.08.2021 | 1.5.8.8 | :bug: fixed bug in execution (trapping) of `xRET` instructions: `dret` (return from debug-mode handler) has to raise an illegal instruction exception if executed outside of debug-mode, `mret` (return from machine-mode handler) has to raise an illegal instruction exception if executed in lower-privileged modes (lower than machine-mode) |
| 05.08.2021 | 1.5.8.7 | :sparkles: added `mstatus.FS` and `mstatus.SD` CSR bits: control the state of the FPU (`Zfinx`) extension; supported states for `mstatus.FS`: `00` = _off_, `11` = _dirty_; writing other states will always set _dirty_ state; note that all FPU instructions including FPU CSR access instructions will raise an illegal instruction exception if `mstatus.FS` = _off_ |
| 03.08.2021 | 1.5.8.6 | :bug: fixed bug in linker script [#134](https://github.com/stnolting/neorv32/issues/134): `.rodata.*` "sub"-sections were missing, caused wrong linking of implicit constants (like strings); added `mconfigptr` CSR (RISC-V priv. ISA spec. v1.12-draft ;read-only): holds a pointer to a platform/system configuration structure - not actually used yet |
| 30.07.2021 | 1.5.8.5 | fixed minor bug in top entity / AXI4 wrapper (Vivado "issue": generic defaults need a _fixed-size_ intialization value) [#113](https://github.com/stnolting/neorv32/issues/133) |
| 30.07.2021 | 1.5.8.5 | fixed minor bug in top entity / AXI4 wrapper (Vivado "issue": generic defaults need a _fixed-size_ initialization value) [#113](https://github.com/stnolting/neorv32/issues/133) |
| 26.07.2021 | 1.5.8.4 | :bug: **fixed major bug in CPU interrupt system**: interrupts during memory accesses (load/store instruction) terminated those memory accesses violating the crucial "instruction atomicity" concept: traps (interrupts and exceptions) must only intervene _between_ instructions |
| 25.07.2021 | 1.5.8.3 | :sparkles: added `mstauts.TW` CSR flag (when set executing `wfi` instruction outside of machine-mode will raise an illegal instruction exception); flag is hardwired to zero if user mode is not implemented |
| 25.07.2021 | 1.5.8.2 | :bug: fixed bug in `E` ISA extension: extension could not be enabled due to missing generic propagation; clean-up of generic defaults: only the processor top entity provides defaults for the configuration generics |
88,10 → 104,10
| 13.06.2021 | 1.5.6.9 | :warning: reworked boot configuration: removed `MEM_INT_IMEM_ROM` and `BOOTLOADER_EN` generics, replaced by single `INT_BOOTLOADER_EN` generic (type boolean): _true_ = implement processor-internal (default) bootloader, implement processor-internal IMEM (if implemented) as RAM; _false_ = boot from processor-internal IMEM implemented (if enabled) as pre-intialized ROM; reworked IMEM, DMEM and BOOTROM memory architecture; reworked image generator and generated application image files (now using unconstrained array as init images + unified array/memory types) |
| 12.06.2021 | 1.5.6.8 | :bug: fixed bug in instruction cache (cache controller might have missed resync/"clear-and-reload" requests from `fence.i` instructions); minor project/repo clean-ups |
| 08.06.2021 | 1.5.6.7 | clean-up of Wishbone interface module (dead code removal); added new package constant `wb_rx_buffer_c` to configure SYNC (default) or ASYNC Wishbone RX path (allows trade-off between performance/latency and timing closure) |
| 06.06.2021 | 1.5.6.6 | :bug: fixed bug in PWM base address configuration; :warning: removed user-access HPM counter access via `hpmcounter3[h]`:`hpmcounter3[h]` CSRs, hardwaired according `mcounteren` bits to zero: HPM can only be used in machine mode; reworded 64-bit counters (`cycle`, `instret`, `hpmcounter` + `mtime`) overflow logic: now using dedicated CARRY chain instead of overflow detector (can improve timing); |
| 06.06.2021 | 1.5.6.6 | :bug: fixed bug in PWM base address configuration; :warning: removed user-access HPM counter access via `hpmcounter3[h]`:`hpmcounter3[h]` CSRs, hardwired according `mcounteren` bits to zero: HPM can only be used in machine mode; reworded 64-bit counters (`cycle`, `instret`, `hpmcounter` + `mtime`) overflow logic: now using dedicated CARRY chain instead of overflow detector (can improve timing); |
| 05.06.2021 | 1.5.6.5 | removed debug mode's `stepie` flag (used to allow interrupts during single-stepping) as the debugger can emulate interrupts |
| 04.06.2021 | 1.5.6.4 | :warning: removed `IO_PWM_EN` generic, replaced by `IO_PWM_NUM_CH` generic - PWM controller now supports implementation of up to 60 channels via `IO_PWM_NUM_CH` (`IO_PWM_NUM_CH` = 0 will omit the PWM controller); :bug: fixed minor bug in `minstreth` counter logic |
| 04.06.2021 | 1.5.6.3 | :warning: increased processor-internal IO size from 256 bytes to 512 bytes; relocated base adress of CFS |
| 04.06.2021 | 1.5.6.3 | :warning: increased processor-internal IO size from 256 bytes to 512 bytes; relocated base address of CFS |
| 03.06.2021 | 1.5.6.2 | :warning: The `B` ISA extension (bit manipulation) has been (temporarily) removed from the project. See [B ISA Extension](https://github.com/stnolting/neorv32/projects/7) project board. |
| 03.06.2021 | 1.5.6.1 | CPU/HPM counter size configuration (`CPU_CNT_WIDTH` and `HPM_CNT_WIDTH` generics) can now be 0-bit (no counters implemented at all) to 64-bit (full-scale / RISC-V standard) wide |
| 01.06.2021 | [**:rocket:1.5.6.0**](https://github.com/stnolting/neorv32/releases/tag/v1.5.6.0) | **New release** |
199,7 → 215,7
| 07.11.2020 | 1.4.6.7 | Updated bootloader (size optimization) and changed processor version output; added project logo; minor data sheet edits |
| 03.11.2020 | 1.4.6.6 | Removed SPI module's *buggy* "LSB-first mode", SPI module now always sends data MSB-first; removed SPI.CTRL `SPI_CT_DIR` bit; modfied bit order in SPI CTRL register; updated SPI SW library |
| 02.11.2020 | 1.4.6.5 | :warning: Fixed bug in CPU's illegal instruction detection logic; CPU rtl code optimizations - further reduced hardware footprint; rtl code clean-ups |
| 01.11.2020 | 1.4.6.4 | :warning: Fixed bug in `[m]instret[h]` and `[m]cycle[h]` carry logic; CPU hardware optimizations (area reduction, shortend critical path) |
| 01.11.2020 | 1.4.6.4 | :warning: Fixed bug in `[m]instret[h]` and `[m]cycle[h]` carry logic; CPU hardware optimizations (area reduction, shortened critical path) |
| 29.10.2020 | 1.4.6.3 | rtl code clean-up; made preparations for additional co-processors |
| 25.10.2020 | 1.4.6.2 | Added tag signal (`wb_tag_o`) to processor's Wishbone bus; removed processor's `priv_o` - privilege level is now encoded in Wishbone *tag* signal; added a more sophisticated **FreeRTOS** example ("full_demo") |
| 24.10.2020 | [**:rocket:1.4.6.0**](https://github.com/stnolting/neorv32/releases/tag/v1.4.6.0) | Completely reworked external memory interface (WISHBONE), removed now-obsolete processor generic `MEM_EXT_REG_STAGES`; added processor wrapper with **AXI4-Lite master interface** |
212,9 → 228,9
| 17.10.2020 | 1.4.5.4 | Added new CPU/Processor generic `FAST_SHIFT_EN` (default = *false*) to enable implementation of a fast (but large) barrel shifter for accelerating CPU shift instructions; updated CoreMark performance results |
| 16.10.2020 | 1.4.5.2 | Added read-only flag to custom `mzext` CSR to check if physical memory protection (PMP) is implemented; added [C] `mzext` CSR name aliases to neorv32.h |
| 15.10.2020 | 1.4.5.1 | Fixed "unprecise exceptions": `mtval` did not always reflect the correct value according to the instruction that caused the exceptions; fixed bug in RTE: Debug trap handler was not showing the correct `mepc` value |
| 13.10.2020 | [**:rocket:1.4.5.0**](https://github.com/stnolting/neorv32/releases/tag/v1.4.5.0) | An official *open-soucre RISC-V architecture ID* was assigned to the project: decimal = `19`, 32-bit hexadecimal = `0x00000013` - software can retrieve the ID from the `marchid` CSR |
| 13.10.2020 | [**:rocket:1.4.5.0**](https://github.com/stnolting/neorv32/releases/tag/v1.4.5.0) | An official *open-source RISC-V architecture ID* was assigned to the project: decimal = `19`, 32-bit hexadecimal = `0x00000013` - software can retrieve the ID from the `marchid` CSR |
| 12.10.2020 | 1.4.4.9 | Added *alignment flags* to makefiles: branch/jump/call targets are forced to be 32-bit aligned -> increases performance when using the `C` extension; added makefile flag listing to NEORV32.pdf; updated performance results for CPUs with `C` extension; `crt0.S` will initialize *all* registers with zero if not using `E` extension and not compiling bootloader |
| 11.10.2020 | 1.4.4.8 | Reworked pipeline frontend: Optimized fetch enginge, added issue engine, faster instruction fetch after taken branches + reduced hardware requirements; updated synthesis and performance results |
| 11.10.2020 | 1.4.4.8 | Reworked pipeline frontend: Optimized fetch engine, added issue engine, faster instruction fetch after taken branches + reduced hardware requirements; updated synthesis and performance results |
| 11.10.2020 | 1.4.4.6 | Added option to configure external memory interface (Wishbone) to either use *standard/classic protocol* (default) or *pipelined protocol* (for better timing): via `wb_pipe_mode_c` constant in VHDL package file (`rtl/core/neorv32_package.vhd`); added help text to NEORV32.pdf section "3.4.4. Processor-External Memory Interface (WISHBONE)" |
| 08.10.2020 | 1.4.4.5 | Removed CPU's `BUS_TIMEOUT` and processor's `MEM_EXT_TIMEOUT` generics; instead, a global configuration `bus_timeout_c` in the VHDL package file is used now |
| 08.10.2020 | 1.4.4.4 | Removed `DEVNULL` device; all simulation output options from this device are now available as `SIM_MODE` in the `UART`; `mcause` CSR can now also be written; FIXED: trying to write a read-only CSR will cause an illegal instruction exception; for compatibility reasons any write access to the misa CSR will be ignored and will NOT cause an exception |
242,7 → 258,7
| 25.07.2020 | 1.3.0.0 | `mcause` CSR is read-only now!; removed `CLIC`, added 4 fast IRQ channels to CPU with according flags in `mie` and `mip` and trap IDs; updated core libraries; updated NEORV32 RTE; highly reworked data sheet; updated synthesis and performance results |
| 21.07.2020 | 1.2.0.6 | Added doc section regarding the CPU's data and instruction interfaces; optimized CPU fetch engine; updated iCE40 synthesis results |
| 20.07.2020 | 1.2.0.5 | Less penalty for taken branches and jumps (2 cycles faster) |
| 19.07.2020 | 1.2.0.0 | CPU bus unit now has independent busses for instruction fetch and data access – merged into single processor bus via new bus switch unit; doubled speed of ALU shifter unit again; all bits of `mcause` CSR can now be modified by application program (full RISC-V-compliant); performance counters CSRs `[m]cycleh` and `[m]instreth` are only 20-bit wide; removed NEORV32-specific custom CSRs – all processor-related information can be obtained from the new `SYSINFO` IO module (CPU is now more independent from processor configuration); changed IO address of `DEVNULL`; fixed bug in bootloader's trap handler; added `USER_CODE` generic to assign a custom user code that can be read by software (from `SYSINFO`) |
| 19.07.2020 | 1.2.0.0 | CPU bus unit now has independent buses for instruction fetch and data access – merged into single processor bus via new bus switch unit; doubled speed of ALU shifter unit again; all bits of `mcause` CSR can now be modified by application program (full RISC-V-compliant); performance counters CSRs `[m]cycleh` and `[m]instreth` are only 20-bit wide; removed NEORV32-specific custom CSRs – all processor-related information can be obtained from the new `SYSINFO` IO module (CPU is now more independent from processor configuration); changed IO address of `DEVNULL`; fixed bug in bootloader's trap handler; added `USER_CODE` generic to assign a custom user code that can be read by software (from `SYSINFO`) |
| 14.07.2020 | 1.1.0.0 | Added `fence_o` and `fencei_o` signals to top entity to show if a `fence` or `fencei` instruction is executed; added `mvendorid` and `marchid` CSRs (both are always zero); ALU shift unit is faster now; two lowest bits of `mtvec` are always zero; fixed wrong instruction exception priority; removed `HART_ID` generic – `mhartid` CSR is always read as zero; performance counters (`[m]cycle[h]`, `[m]instret[h]` and `time[h]`) are also available in embedded mode – but can be explicitly disabled via the `CSR_COUNTERS_USE` generic; mcause CSR only allows write access to bit 31 and bits 3:0; updated synthesis reports |
| 10.07.2020 | 1.0.6.0 | Non-taken branches are now 1 cycle faster; the `time[h]` CSR now correctly reflects the system time from the MTIME unit; fixed WFI instruction permanently stalling the CPU; `[m]cycle[h]` counters now stop counting when CPU is in sleep mode; `minstret[h]` and `mcycle[h]` now also allow write-access |
| 09.07.2020 | 1.0.5.0 | `X` flag of `misa` CSR is zero now; the default SPI flash boot address of the bootloader is now `0x0080000`; new exemplary FPGA utilization results for Intel, Lattice and Xilinx; `misa` CSR is read-only again, switching compressed extension on/off is pretty bad for the fetch engine; `mtval` and `mcause` CSRs now allow write accesses and are finally RISC-V-compliant; time low and high registers of `MTIME` peripheral can now also be written by user; `MTIME` registers only allow full-word write accesses |
/neorv32/trunk/README.md
12,7 → 12,7
 
[![license](https://img.shields.io/github/license/stnolting/neorv32?longCache=true&style=flat-square)](https://github.com/stnolting/neorv32/blob/master/LICENSE)
[![release](https://img.shields.io/github/v/release/stnolting/neorv32?longCache=true&style=flat-square&logo=GitHub)](https://github.com/stnolting/neorv32/releases)
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.5121427.svg)](https://doi.org/10.5281/zenodo.5121427)
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.5018888.svg)](https://doi.org/10.5281/zenodo.5018888)
 
[![datasheet (pdf)](https://img.shields.io/badge/data%20sheet-PDF-ffbd00?longCache=true&style=flat-square&logo=asciidoctor)](https://github.com/stnolting/neorv32/releases/tag/nightly)
[![datasheet (html)](https://img.shields.io/badge/-HTML-ffbd00?longCache=true&style=flat-square)](https://stnolting.github.io/neorv32)
51,9 → 51,11
To see the changes between *official* releases visit the project's [release page](https://github.com/stnolting/neorv32/releases).
 
:package: The [`setups`](https://github.com/stnolting/neorv32/tree/master/setups) folder provides exemplary setups targeting
various FPGA boards and toolchains to get you started. Several example programs to be run on your setup can be found in
[`sw/example`](https://github.com/stnolting/neorv32/tree/master/sw/example).
various FPGA boards and toolchains to get you started. Several example programs (including a FreeRTOS port) to be run on your setup
can be found in [`sw/example`](https://github.com/stnolting/neorv32/tree/master/sw/example).
 
:kite: Upstream [**Zephyr RTOS**](https://docs.zephyrproject.org/latest/boards/riscv/neorv32/doc/index.html) support.
 
:spiral_notepad: Check out the [project boards](https://github.com/stnolting/neorv32/projects) for a list of current **ideas**,
**TODOs**, features being **planned** and **work-in-progress**.
 
72,8 → 74,8
- [x] all-in-one: [CPU](#NEORV32-CPU-Features) plus [Processor/SoC](#NEORV32-Processor-Features) plus [Software Framework & Tooling](#Software-Framework-and-Tooling)
- [x] completely described in behavioral, platform-independent VHDL - no primitives, macros, etc.
- [x] fully synchronous design, no latches, no gated clocks
- [x] be as small as possible (while being as RISC-V-compliant as possible) – but with a reasonable size-performance trade-off
(the processor has to fit in a Lattice iCE40 UltraPlus 5k low-power FPGA running at 22+ MHz)
- [x] be as small as possible while being as RISC-V-compliant as possible – but with a reasonable size-performance trade-off:
the processor (CPU _including_ privileged architecture) fits into a Lattice iCE40 UltraPlus 5k low-power FPGA running at 24 MHz
- [x] from zero to `printf("hello world!");` - completely open source and documented
- [x] easy to use even for FPGA/RISC-V starters – intended to work *out of the box*
 
117,6 → 119,7
* 32-bit external bus interface, Wishbone b4 compatible
([WISHBONE](https://stnolting.github.io/neorv32/#_processor_external_memory_interface_wishbone_axi4_lite))
* [wrapper](https://github.com/stnolting/neorv32/blob/master/rtl/system_integration/neorv32_SystemTop_axi4lite.vhd) for AXI4-Lite master interface
* [wrapper](https://github.com/stnolting/neorv32/blob/master/rtl/system_integration/neorv32_SystemTop_AvalonMM.vhd) for Avalon-MM master interface
* 32-bit stream link interface with up to 8 independent RX and TX links
([SLINK](https://stnolting.github.io/neorv32/#_stream_link_interface_slink))
* AXI4-Stream compatible
274,11 → 277,14
* gcc-based toolchain ([pre-compiled toolchains available](https://github.com/stnolting/riscv-gcc-prebuilt))
* bootloader with UART interface console
* runtime environment for handling traps
* several [example programs](https://github.com/stnolting/neorv32/tree/master/sw/example) to get started including CoreMark, FreeRTOS and *Conway's Game of Life*
* `doxygen`-based documentation, available on [GitHub pages](https://stnolting.github.io/neorv32/sw/files.html)
* several [example programs](https://github.com/stnolting/neorv32/tree/master/sw/example) to get started including
[CoreMark](https://github.com/stnolting/neorv32/tree/master/sw/example/coremark),
[FreeRTOS](https://github.com/stnolting/neorv32/tree/master/sw/example/demo_freeRTOS) and
[Conway's Game of Life](https://github.com/stnolting/neorv32/tree/master/sw/example/game_of_life)
* `doxygen`-based documentation, available on :books: [GitHub pages](https://stnolting.github.io/neorv32/sw/files.html)
* supports implementation using open source tooling (GHDL, Yosys and nextpnr; in the future Verilog-to-Routing); both, software and hardware can be
developed and debugged with open source tooling
* continuous Integration is available for:
* [continuous integration](https://github.com/stnolting/neorv32/actions) :octocat: is available for:
* allowing users to see the expected execution/output of the tools
* ensuring specification compliance
* catching regressions
/neorv32/trunk/do.py
27,7 → 27,7
# Compile and install test application
# Redirect UART0 TX to text.io simulation output via <UART0_SIM_MODE> user flag
"echo 'Compiling and installing CPU (/Processor) test application'",
"make -C sw/example/processor_check clean_all USER_FLAGS+=-DRUN_CHECK USER_FLAGS+=-DUART0_SIM_MODE USER_FLAGS+=-DUART1_SIM_MODE MARCH=-march=rv32imac info all",
"make -C sw/example/processor_check clean_all USER_FLAGS+=-DRUN_CHECK USER_FLAGS+=-DUART0_SIM_MODE USER_FLAGS+=-DUART1_SIM_MODE MARCH=rv32imac info all",
],
"doc": "Build all sw/example/*; install bootloader and processor check",
}

powered by: WebSVN 2.1.0

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