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", |
} |