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

Subversion Repositories neorv32

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /neorv32/trunk/docs/datasheet
    from Rev 67 to Rev 68
    Reverse comparison

Rev 67 → Rev 68

/cpu.adoc
611,28 → 611,31
 
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_.
 
[IMPORTANT]
If the `Zicsr` extension is disabled the CPU does not provide any _privileged architecture_ features at all!
In order to provide the full set of privileged functions that are required to run more complex tasks like
operating system and to allow a secure execution environment the `Zicsr` extension should always be enabled.
 
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 _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]
If `rd=x0` for the `csrrw[i]` instructions there will be no actual read access to the according CSR.
However, access privileges are still enforced so these instruction variants _do_ cause side-effects
(the RISC-V spec. state that these combinations "_shall_ not cause any side-effects").
 
[NOTE]
The "wait for interrupt instruction" `wfi` works like a sleep command. When executed, the CPU is
The "wait for interrupt instruction" `wfi` acts like a sleep command. When executed, the CPU is
halted until a valid interrupt request occurs. To wake up again, the according interrupt source has to
be enabled via the `mie` CSR and the global interrupt enable flag in `mstatus` has to be 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.
`TW` (timeout wait) is _hardwired_ to zero.
 
 
 
 
==== **`Zicntr`** CPU Base Counters
 
The `Zicntr` ISA extension adds the basic cycle `[m]cycle[h]`), instruction-retired (`[m]instret[h]`) and time (`time[h]`)
/on_chip_debugger.adoc
87,13 → 87,11
| `jtag_tms_i` | 1 | in | mode select
|=======================
 
.JTAG Clock
.Maximum JTAG Clock
[IMPORTANT]
The actual JTAG clock signal is **not** used as primary clock. Instead it is used to synchronize
JTGA accesses, while all internal operations trigger on the system clock. Hence, no additional clock domain is required
for integration of this module.
However, this constraints the maximal JTAG clock (`jtag_tck_i`) frequency to be less than or equal to
1/4 of the system clock (`clk_i`) frequency.
All JTAG signals are synchronized to the processor clock domain by oversampling them in DTM. Hence, no additional
clock domain is required for the DTM. However, this constraints the maximal JTAG clock frequency (`jtag_tck_i`) to be less
than or equal to **1/5** of the processor clock frequency (`clk_i`).
 
[NOTE]
If the on-chip debugger is disabled (_ON_CHIP_DEBUGGER_EN_ = false) the JTAG serial input `jtag_tdi_i` is directly
127,10 → 125,24
| others | `BYPASS` | 1 | default JTAG bypass register
|=======================
 
.`DTMCS` - DTM Control and Status Register
[cols="^2,^3,^1,<8"]
[options="header",grid="rows"]
|=======================
| Bit(s) | Name | r/w | Description
| 31:18 | - | r/- | _reserved_, hardwired to zero
| 17 | `dmihardreset` | r/w | setting this bit will reset the DM interface; this bit auto-clears
| 16 | `dmireset` | r/w | setting this bit will clear ste sticky error state; this bit auto-clears
| 15 | - | r/- | _reserved_, hardwired to zero
| 14:12 | `idle` | r/- | recommended idle states (= 0, no idle states required)
| 11:10 | `dmistat` | r/- | DMI statu: `00` = no error, `01` = reserved, `10` = operation failed, `11` = failed operation during pending DMI operation
| 9:4 | `abits` | r/- | number of DMI address bits (= 7)
| 3:0 | `version` | r/- | `0001` = spec version 0.13
|=======================
 
[INFO]
See the https://github.com/riscv/riscv-debug-spec[RISC-V debug specification] for more information regarding the data
registers and operations.
A local copy can be found in `docs/references`.
registers and operations. A local copy can be found in `docs/references`.
 
 
 
/overview.adoc
107,7 → 107,13
vs. size trade-off and a different focus: _embrace_ concepts like documentation, platform-independence / portability,
RISC-V compatibility, _customization_ and _ease of use_. See the <<_project_key_features>> below.
 
Furthermore, the NEORV32 pays special focus on _execution safety_ using <<_full_virtualization>>. The CPU aims to
provide fall-backs for _everything that could go wrong_. This includes malformed instruction words, privilege escalations
and even memory accesses that are checked for address space holes and deterministic response times from memory-mapped
devices. Precise exceptions allow a defined and fully-synchronized state of the CPU at every time.
 
 
 
// ####################################################################################################################
:sectnums:
=== Project Key Features
193,7 → 199,7
:sectnums:
=== VHDL File Hierarchy
 
All necessary VHDL hardware description files are located in the project's `rtl/core folder`. The top entity
All necessary VHDL hardware description files are located in the project's `rtl/core` folder. The top entity
of the entire processor including all the required configuration generics is **`neorv32_top.vhd`**.
 
[IMPORTANT]
243,14 → 249,14
├neorv32_wishbone.vhd - External (Wishbone) bus interface
├neorv32_xirq.vhd - External interrupt controller
│
├mem/neorv32_dmem.default.vhd - _Default_ data memory (architecture-only!)
â””mem/neorv32_imem.default.vhd - _Default_ instruction memory (architecture-only!)
├mem/neorv32_dmem.default.vhd - _Default_ data memory (architecture-only)
â””mem/neorv32_imem.default.vhd - _Default_ instruction memory (architecture-only)
...................................
 
[NOTE]
The processor-internal instruction and data memories (IMEM and DMEM) are split into two design files each:
a plain entity definition (`neorv32_*mem.entity.vhd`) and the actual architecture definition
(`mem/neorv32_*mem.default.vhd`). The **default** architecture definitions from `rtl/core/mem` provide a _generic_ and
(`mem/neorv32_*mem.default.vhd`). The `*.default.vhd` architecture definitions from `rtl/core/mem` provide a _generic_ and
_platform independent_ memory design that (should) infers embedded memory blocks. You can replace/modify the architecture
source file in order to use platform-specific features (like advanced memory resources) or to improve technology mapping
and/or timing.
/soc.adoc
1321,32 → 1321,35
:sectnums!:
===== Indirect Boot
 
The _indirect_ boot scenarios **1a** and **1b** use the processor-internal <<_bootloader>>. This general setup is enabled
by setting the <<_int_bootloader_en>> generic to true, which will implement the processor-internal <<_bootloader_rom_bootrom>>.
The _indirect_ boot scenarios **1a** and **1b** use the processor-internal <<_bootloader>>. This boot setup is enabled
by setting the <<_int_bootloader_en>> generic to _true_, which will implement the processor-internal <<_bootloader_rom_bootrom>>.
This read-only memory is pre-initialized during synthesis with the default bootloader firmware.
The bootloader provides several options to upload an executable (via UART or from external SPI flash) and copies it to
the beginning of the _instruction address space_ so the CPU can execute it.
 
The bootloader provides several options to upload an executable (via UART or from external SPI flash) and store it to
the _instruction address space_ so the CPU can execute it. Boot scenario **1a** uses the processor-internal IMEM
Boot scenario **1a** uses the processor-internal IMEM
(<<_mem_int_imem_en>> = _true_). This scenario implements the internal <<_instruction_memory_imem>> as non-initialized
RAM so the bootloader can write the actual executable to it.
RAM so the bootloader can copy the actual executable to it.
 
Boot scenario **1b** uses a processor-external IMEM (<<_mem_int_imem_en>> = _false_) that is connected via the processor's
bus interface. In this scenario the internal <<_instruction_memory_imem>> is not implemented at all and the bootloader will
write the executable to the processor-external memory.
copy the executable to the processor-external memory. Hence, the external memory has to be implemented as RAM.
 
:sectnums!:
===== Direct Boot
 
The _direct_ boot scenarios **2a** and **2b** do not use the processor-internal bootloader. Hence, the <<_int_bootloader_en>>
The _direct_ boot scenarios **2a** and **2b** do not use the processor-internal bootloader since the <<_int_bootloader_en>>
generic is set _false_. In this configuration the <<_bootloader_rom_bootrom>> is not implemented at all and the CPU will
directly begin executing code from the instruction address space after reset. A "pre-initialization mechanism is required
in order to provide an executable _in_ memory.
directly begin executing code from the beginning of the instruction address space after reset. An application-specific
"pre-initialization" mechanism is required in order to provide an executable _in_ memory.
 
Boot scenario **2a** uses the processor-internal IMEM (<<_mem_int_imem_en>> = _true_) that is implemented as _read-only memory_
in this scenario. It is pre-initialized (by the bitstream) with the actual application executable.
in this scenario. It is pre-initialized (by the bitstream) with the actual application executable during synthesis.
 
In contrast, boot scenario **2b** uses a processor-external IMEM (<<_mem_int_imem_en>> = _false_). In this scenario the
system designer is responsible for providing a initialized external memory that contains the actual application to be executed.
system designer is responsible for providing an initialized external memory that contains the actual application to be executed.
If the external is not already initialized after reset, a simple ROM containing a "polling loop" can be implemented that is
exited as soon as the application logic has finished initializing the memory with the acutal application code.
 
 
 
/soc_buskeeper.adoc
13,6 → 13,7
| CPU interrupts: | none |
|=======================
 
 
**Theory of Operation**
 
The Bus Keeper is a fundamental component of the processor's internal bus system that ensures correct bus operations
30,35 → 31,25
 
In case of a bus access fault exception application software can evaluate the Bus Keeper's control register
`NEORV32_BUSKEEPER.CTRL` to retrieve further details of the bus exception. The _BUSKEEPER_ERR_FLAG_ bit indicates
that an actual bus access fault has occurred. The bit is sticky once set is automatically cleared when reading the
`NEORV32_BUSKEEPER.CTRL` register. The _BUSKEEPER_ERR_TYPE_ indicated the tape or bus fault:
that an actual bus access fault has occurred. The bit is sticky once set and is automatically cleared when reading or
writing the `NEORV32_BUSKEEPER.CTRL` register. The _BUSKEEPER_ERR_TYPE_ indicated the tape of the bus fault:
 
* _BUSKEEPER_ERR_TYPE_ = `0` - "Device Error": The bus access exception was cause by the memory-mapped device that
has been accessed (the device asserted it's `err_o`).
* _BUSKEEPER_ERR_TYPE_ = `1` - "Timeout Error": The bus access exception was caused by the Bus Keeper because the
accessed memory-mapped device did not respond within the access time window.
accessed memory-mapped device did not respond within the access time window. Note that this error type can also be raised
by the optional timeout feature of the <<_processor_external_memory_interface_wishbone_axi4_lite>>).
 
[NOTE]
Bus access fault exceptions are also raised if a physical memory protection rule is violated. In this case
the _BUSKEEPER_ERR_FLAG_ bit remains zero.
 
Furthermore, application software can determine the source of the bus access fault via the _BUSKEEPER_ERR_SRC_ bit:
 
* _BUSKEEPER_ERR_SRC_ = `0`: The error was cause during access via the <<_processor_external_memory_interface_wishbone_axi4_lite>>).
* _BUSKEEPER_ERR_SRC_ = `1`: The error was cause during access to an processor-internal module.
 
[NOTE]
The Bus Keeper does not track **timeout errors** of processor-external accesses via the external memory bus interface.
However, the external memory bus interface also provides an _optional_ and independent bus timeout feature
(see section <<_processor_external_memory_interface_wishbone_axi4_lite>>).
 
 
.BUSKEEPER register map (`struct NEORV32_BUSKEEPER`)
[cols="<2,<2,<4,^1,<4"]
[options="header",grid="all"]
|=======================
| Address | Name [C] | Bit(s), Name [C] | R/W | Function
.3+<| `0xffffff7C` .3+<| `NEORV32_BUSKEEPER.CTRL` <|`0` _BUSKEEPER_ERR_TYPE_ ^| r/- <| Bus error type, valid if _BUSKEEPER_ERR_FLAG_ is set: `0`=device error, `1`=access timeout
<|`1` _BUSKEEPER_ERR_SRC_ ^| r/- <| Error source: `0`=processor-internal, `1`=processor-external (via Wishbone bus interface)
<|`31` _BUSKEEPER_ERR_FLAG_ ^| r/- <| Sticky error flag, clears after read
.2+<| `0xffffff7C` .2+<| `NEORV32_BUSKEEPER.CTRL` <|`0` _BUSKEEPER_ERR_TYPE_ ^| r/- <| Bus error type, valid if _BUSKEEPER_ERR_FLAG_ is set: `0`=device error, `1`=access timeout
<|`31` _BUSKEEPER_ERR_FLAG_ ^| r/- <| Sticky error flag, clears after read or write access
|=======================
/soc_neoled.adoc
163,19 → 163,20
data word being written to the TX buffer making busy wait concepts obsolete and allowing maximum refresh rates.
 
 
**Interrupt**
**NEOLED Interrupt**
 
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`.
is configured via the _NEOLED_CTRL_IRQ_CONF_ bit in the unit's control register.
 
If _NEOLED_CTRL_IRQ_CONF_ is cleared, an interrupt is generated whenever the TX FIFO is _less than half-full_.
If _NEOLED_CTRL_IRQ_CONF_ is cleared, an interrupt is generated whenever the TX FIFO _becomes_ 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.
status flags. If _NEOLED_CTRL_IRQ_CONF_ is set, an interrupt is generated whenever the TX FIFO _becomes_ empty.
 
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.
A pending interrupt request is cleared is cleared by any of the following operations:
* write access to `NEORV32_NEOLED.DATA` (for example to send more LED data)
* write access to `NEORV32_NEOLED.CTRL`
* disabling the NEOLED module
 
[NOTE]
The _NEOLED_CTRL_IRQ_CONF_ is hardwired to one if _IO_NEOLED_TX_FIFO_ = 1 (-> IRQ if FIFO is empty).
/soc_slink.adoc
79,11 → 79,14
The NEORV32 processor ensures that _any_ CPU access to memory-mapped devices (including the SLINK module)
will **time out** after a certain number of cycles (see section <<_bus_interface>>).
Hence, blocking access to a stream link that does not complete within a certain amount of cycles will
raise a _store bus access exception_ when writing a _full_ TX link or a _load bus access exception_ when reading
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.
raise a _store bus access exception_ when writing to a _full_ TX link's FIFO or a _load bus access exception_
when reading from an _empty_ RX 's FIFO. Hence, this concept should only be used when evaluating the half-full
FIFO condition (for example via the SLINK interrupts) before actual accessing links.
 
[NOTE]
There is no RX FIFO overflow mechanism available yet.
 
 
**Non-Blocking Link Access**
 
For a non-blocking link access concept, the FIFO status flags in `STATUS` need to be checked _before_
118,43 → 121,52
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**
**SLINK 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.
specific FIFO 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.
 
[NOTE]
There is no RX FIFO overflow mechanism available yet.
 
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").
* If a link's interrupt mode flag is `1` an IRQ is generated when the link's FIFO _becomes_ not empty ("RX data available").
* If a link's interrupt mode flag is `0` an IRQ is generated when the link's FIFO _becomes_ 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").
* If a link's interrupt mode flag is `1` an IRQ is generated when the link's FIFO _becomes_ not full ("space left in FIFO for new TX data").
* If a link's interrupt mode flag is `0` an IRQ is generated when the link's FIFO _becomes_ less than half-full ("SW can send _SLINK_TX_FIFO_/2 data words without checking any flags").
 
[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.
[IMPORTANT]
The interrupt configuration register `NEORV32_SLINK.IRQ` should we written _before_ the SLINK
module is actually enabled.
 
[NOTE]
There is no RX FIFO overflow mechanism available yet.
If _SLINK_RX_FIFO_ is 1 all _SLINK_IRQ_RX_MODE_ bits are hardwired to one.
If _SLINK_TX_FIFO_ is 1 all _SLINK_IRQ_TX_MODE_ bits are hardwired to one.
 
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.
A **pending RX interrupt** request is cleared by any of the following operations:
* read access to any `NEORV32_SLINK.DATA` (for example to read incoming data)
* write access to `NEORV32_SLINK.CTRL`
* disabling the SLINK module
 
[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).
A **pending TX interrupt** request is cleared by any of the following operations:
* write access any `NEORV32_SLINK.DATA` (for example to send more data)
* write access to `NEORV32_SLINK.CTRL`
* disabling the SLINK module
 
[TIP]
A dummy write to to the control register (i.e. `NEORV32_SLINK.DATA = NEORV32_SLINK.DATA`)
can be executed to acknowledge any interrupt.
 
 
.SLINK register map (`struct NEORV32_SLINK`)
[cols="^4,<5,^2,^2,<14"]
[options="header",grid="all"]
168,9 → 180,9
<| `3:0` _SLINK_CTRL_RX_NUM3_ : _SLINK_CTRL_RX_NUM0_ ^| r/- <| Number of implemented RX links
| `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
<|`23:16` _SLINK_IRQ_RX_MODE_MSB_ : _SLINK_IRQ_RX_MODE_LSB_ ^| r/w <| RX IRQ mode for link 7..0: `0` = FIFO rises above 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
<|`7:0` _SLINK_IRQ_TX_MODE_MSB_ : _SLINK_IRQ_TX_MODE_LSB_ ^| r/w <| TX IRQ mode for link 7..0: `0` = FIFO falls below 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
/soc_spi.adoc
107,11 → 107,18
 
**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.
The SPI module provides a single interrupt to signal "transmission done" to the CPU. Whenever the SPI
module completes the current transfer operation, the interrupt request is set. A pending interrupt request
is cleared by any of the following operations:
* read or write access to `NEORV32_SPI.DATA` (for example to trigger a new transmission)
* write access to `NEORV32_SPI.CTRL`
* disabling the SPI module
 
[TIP]
A dummy read from `NEORV32_SPI.DATA` can be executed to acknowledge the interrupt without affecting data
or the state of the SPI module.
 
 
.SPI register map (`struct NEORV32_SPI`)
[cols="<2,<2,<4,^1,<7"]
[options="header",grid="all"]
/soc_trng.adoc
13,65 → 13,36
| CPU interrupts: | none |
|=======================
 
 
**Theory of Operation**
 
The NEORV32 true random number generator provides _physical true random numbers_ for your application.
Instead of using a pseudo RNG like a LFSR, the TRNG of the processor uses a simple, straight-forward ring
oscillator as physical entropy source. Hence, voltage and thermal fluctuations are used to provide true
physical random data.
The NEORV32 true random number generator provides _physical_ true random numbers.
Instead of using a pseudo RNG like a LFSR, the TRNG uses a simple, straight-forward ring
oscillator concept as physical entropy source. Hence, voltage, thermal and also semiconductor manufacturing
fluctuations are used to provide a true physical entropy source.
 
The TRNG is based on the neoTRNG[https://github.com/stnolting/neoTRNG], which is a "spin-off project" of the
NEORV32 processor. The TRNG uses the default neoTRNG configuration, which showed very good results in the
`dieharder` battery of random number tests. More detailed information about the neoTRNG, it's architecture and a
detailed evaluation of the random number quality can be found it it's repository: https://github.com/stnolting/neoTRNG
 
[NOTE]
The TRNG features a platform independent architecture without FPGA-specific primitives, macros or
attributes.
attributes so it can be synthesized for _any_ FPGA.
 
**Architecture**
 
The NEORV32 TRNG is based on simple ring oscillators, which are implemented as an inverter chain with
an odd number of inverters. A **latch** is used to decouple each individual inverter. Basically, this architecture
is some king of asynchronous LFSR.
 
The output of several ring oscillators are synchronized using two registers and are XORed together. The
resulting output is de-biased using a von-Neumann randomness extractor. This de-biased output is further
processed by a simple 8-bit Fibonacci LFSR to improve whitening. After at least 8 clock cycles the state of
the LFSR is sampled and provided as final data output.
 
To prevent the synthesis tool from doing logic optimization and thus, removing all but one inverter, the
TRNG uses simple latches to decouple an inverter and its actual output. The latches are reset when the
TRNG is disabled and are enabled one by one by a "real" shift register when the TRNG is activated. This
construct can be synthesized for any FPGA platform. Thus, the NEORV32 TRNG provides a platform
independent architecture.
 
**TRNG Configuration**
 
The TRNG uses several ring-oscillators, where the next oscillator provides a slightly longer chain (more
inverters) than the one before. This increment is constant for all implemented oscillators. This setup can be
customized by modifying the "Advanced Configuration" constants in the TRNG's VHDL file:
 
* The `num_roscs_c` constant defines the total number of ring oscillators in the system. num_inv_start_c
defines the number of inverters used by the first ring oscillators (has to be an odd number). Each additional
ring oscillator provides `num_inv_inc_c` more inverters that the one before (has to be an even number).
* The LFSR-based post-processing can be deactivated using the `lfsr_en_c` constant. The polynomial tap
mask of the LFSR can be customized using `lfsr_taps_c`.
 
**Using the TRNG**
 
The TRNG features a single register for status and data access. When the _TRNG_CTRL_EN_ control register (`CTRL`)
bit is set, the TRNG is enabled and starts operation. As soon as the _TRNG_CTRL_VALID_ bit is set, the currently
sampled 8-bit random data byte can be obtained from the lowest 8 bits of the `CTRL` register
(_TRNG_CTRL_DATA_MSB_ : _TRNG_CTRL_DATA_LSB_). The _TRNG_CTRL_VALID_ bit is automatically cleared
when reading the control register.
(_TRNG_CTRL_DATA_MSB_ : _TRNG_CTRL_DATA_LSB_). These bits always keep the latest valid data obtained from the TRNG
entropy source. The _TRNG_CTRL_VALID_ bit is automatically cleared when reading the control register.
 
[IMPORTANT]
The TRNG needs at least 8 clock cycles to generate a new random byte. During this sampling time
the current output random data is kept stable in the output register until a valid sampling of the new byte has
completed.
[NOTE]
The TRNG core does not provide a dedicated reset. In order to ensure correct operations, the TRNG should be
disabled (=reset) by clearing the _TRNG_CTRL_EN_ and waiting some milliseconds before re-enabling it.
 
Randomness "Quality"
I have not verified the quality of the generated random numbers (for example using NIST test suites). The
quality is highly effected by the actual configuration of the TRNG and the resulting FPGA mapping/routing.
However, generating larger histograms of the generated random number shows an equal distribution (binary
average of the random numbers = 127). A simple evaluation test/demo program can be found in
`sw/example/demo_trng`.
 
.TRNG register map (`struct NEORV32_TRNG`)
[cols="<2,<2,<4,^1,<7"]
78,7 → 49,7
[options="header",grid="all"]
|=======================
| Address | Name [C] | Bit(s), Name [C] | R/W | Function
.3+<| `0xffffffb8` .3+<| `NEORV32_TRNG.CTRL` <|`7:0` _TRNG_CTRL_DATA_MSB_ : _TRNG_CTRL_DATA_MSB_ ^| r/- <| 8-bit random data output
<|`30` _TRNG_CTRL_EN_ ^| r/w <| TRNG enable
<|`31` _TRNG_CTRL_VALID_ ^| r/- <| random data output is valid when set
.3+<| `0xffffffb8` .3+<| `NEORV32_TRNG.CTRL` <|`7:0` _TRNG_CTRL_DATA_MSB_ : _TRNG_CTRL_DATA_MSB_ ^| r/- <| 8-bit random data
<|`30` _TRNG_CTRL_EN_ ^| r/w <| TRNG enable
<|`31` _TRNG_CTRL_VALID_ ^| r/- <| random data is valid when set
|=======================
/soc_twi.adoc
21,8 → 21,8
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
register), so a slow peripheral can halt the transmission by pulling the SCL line low. Currently, **no multi-controller
The NEORV32 TWI implements a **TWI controller**. It supports "clock so a slow peripheral can halt
the transmission by pulling the SCL line low. Currently, **no multi-controller
support** is available. Also, the NEORV32 TWI unit cannot operate in peripheral mode.
 
The TWI is enabled via the _TWI_CTRL_EN_ bit in the `CTRL` control register. The user program can start / stop a
70,27 → 70,34
_**f~SCL~**_ = _f~main~[Hz]_ / (4 * `clock_prescaler`)
 
 
**Interrupt**
**TWI Interrupt**
 
The TWI module provides a single interrupt to signal _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.
The SPI module provides a single interrupt to signal "operation done" to the CPU. Whenever the TWI
module completes the current operation (generate stop condition, generate start conditions or transfer byte),
the interrupt request is set. A pending interrupt request is cleared is cleared by any of
the following operations:
* read or write access to `NEORV32_TWI.DATA` (for example to trigger a new transmission)
* write access to `NEORV32_TWI.CTRL`
* disabling the TWI module
 
[TIP]
A dummy read from `NEORV32_TWI.DATA` can be executed to acknowledge the interrupt without affecting data
or the state of the TWI module.
 
 
.TWI register map (`struct NEORV32_TWI`)
[cols="<2,<2,<4,^1,<7"]
[options="header",grid="all"]
|=======================
| Address | Name [C] | Bit(s), Name [C] | R/W | Function
.10+<| `0xffffffb0` .10+<| `NEORV32_TWI.CTRL` <|`0` _TWI_CTRL_EN_ ^| r/w <| TWI enable
<|`1` _TWI_CTRL_START_ ^| r/w <| generate START condition
<|`2` _TWI_CTRL_STOP_ ^| r/w <| generate STOP condition
<|`3` _TWI_CTRL_PRSC0_ ^| r/w .3+<| 3-bit clock prescaler select
<|`4` _TWI_CTRL_PRSC1_ ^| r/w
<|`5` _TWI_CTRL_PRSC2_ ^| r/w
<|`6` _TWI_CTRL_MACK_ ^| r/w <| generate controller ACK for each transmission ("MACK")
<|`7` _TWI_CTRL_CKSTEN_ ^| r/w <| allow clock-stretching by peripherals when set
<|`30` _TWI_CTRL_ACK_ ^| r/- <| ACK received when set
<|`31` _TWI_CTRL_BUSY_ ^| r/- <| transfer/START/STOP in progress when set
.9+<| `0xffffffb0` .9+<| `NEORV32_TWI.CTRL` <|`0` _TWI_CTRL_EN_ ^| r/w <| TWI enable
<|`1` _TWI_CTRL_START_ ^| r/w <| generate START condition
<|`2` _TWI_CTRL_STOP_ ^| r/w <| generate STOP condition
<|`3` _TWI_CTRL_PRSC0_ ^| r/w .3+<| 3-bit clock prescaler select
<|`4` _TWI_CTRL_PRSC1_ ^| r/w
<|`5` _TWI_CTRL_PRSC2_ ^| r/w
<|`6` _TWI_CTRL_MACK_ ^| r/w <| generate controller ACK for each transmission ("MACK")
<|`30` _TWI_CTRL_ACK_ ^| r/- <| ACK received when set
<|`31` _TWI_CTRL_BUSY_ ^| r/- <| transfer/START/STOP in progress when set
| `0xffffffb4` | `NEORV32_TWI.DATA` |`7:0` _TWI_DATA_MSB_ : TWI_DATA_LSB_ | r/w | receive/transmit data
|=======================
/soc_uart.adoc
108,29 → 108,40
received character and is cleared by reading the `DATA` register.
 
 
**Interrupts**
**UART Interrupts**
 
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.
UART0 features two independent interrupt for signaling certain RX and TX conditions. The behavior of these conditions differs
based on the configured FIFO sizes. 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. An interrupt can only become pending if the according interrupt
condition is fulfilled and the UART is enabled at all.
 
* 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 exactly 1, the RX interrupt goes pending when data _becomes_ available in the RX FIFO
(-> _UART_CTRL_RX_EMPTY_ clears). _UART_CTRL_RX_IRQ_ is hardwired to `0` in this case.
* If _UART0_TX_FIFO_ is exactly 1, the TX interrupt goes pending when at least one entry in the TX FIFO _becomes_ free
(-> _UART_CTRL_TX_FULL_ clears). _UART_CTRL_TX_IRQ_ is hardwired to `0` in this case.
 
* 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).
* If _UART0_RX_FIFO_ is greater than 1: If _UART_CTRL_RX_IRQ_ is `0` the RX interrupt goes pending when data _becomes_
available in the RX FIFO (-> _UART_CTRL_RX_EMPTY_ clears). If _UART_CTRL_RX_IRQ_ is `1` the RX interrupt becomes pending
the RX FIFO _becomes_ 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 goes pending when at least one entry
in the TX FIFO _becomes_ free (-> _UART_CTRL_TX_FULL_ clears). If _UART_CTRL_TX_IRQ_ is `1` the TX interrupt goes pending
when the RX FIFO _becomes_ less than half-full (-> _UART_CTRL_TX_HALF_ clears).
 
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).
A **pending RX interrupt** request is cleared by any of the following operations:
* read access to `NEORV32_UART0.DATA` (for example to read incoming data)
* write access to `NEORV32_UART0.CTRL`
* disabling the UART module
 
A **pending TX interrupt** request is cleared by any of the following operations:
* write access to `NEORV32_UART0.DATA` (for example to send more data)
* write access to `NEORV32_UART0.CTRL`
* disabling the UART module
 
[TIP]
A dummy write to to the control register (i.e. `NEORV32_UART0.DATA = NEORV32_UART0.DATA`)
can be executed to acknowledge any interrupt.
 
 
**Simulation Mode**
 
The default UART0 operation will transmit any data written to the `DATA` register via the serial TX line at
/software.adoc
588,9 → 588,18
 
[source]
----
<RTE> Illegal instruction @0x000002d6, MTVAL=0x00001537 </RTE>
<RTE> Illegal instruction @ PC=0x000002d6, MTVAL=0x00001537 </RTE>
----
 
For bus access faults the RTE also outputs the error code from the <<_internal_bus_monitor_buskeeper>>
to show the cause of the access fault. Two example are shown below.
 
[source]
----
<RTE> Load access fault [TIMEOUT_ERR] @ PC=0x00000150, MTVAL=0xFFFFFF70 </RTE>
<RTE> Store access fault [DEVICE_ERR] @ PC=0x00000162, MTVAL=0xF0000000 </RTE>
----
 
To install the **actual application's trap handlers** the NEORV32 RTE provides functions for installing and
un-installing trap handler for each implemented exception/interrupt source.
 

powered by: WebSVN 2.1.0

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