Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework TRNG module #212

Merged
merged 6 commits into from
Nov 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ defined by the `hw_version_c` constant in the main VHDL package file [`rtl/core/

| Date (*dd.mm.yyyy*) | Version | Comment |
|:----------:|:-------:|:--------|
| 22.11.2021 | 1.6.3.10 | reworked **TRNG** (less hardware requirements, improved quality), see [PR #212](https://github.com/stnolting/neorv32/pull/212) and [stnolting/neoTRNG](https://github.com/stnolting/neoTRNG) |
| 21.11.2021 | 1.6.3.9 | minor rtl edits: configuring an IMEM or DMEM size (`MEM_INT_IMEM_SIZE` / `MEM_INT_DMEM_SIZE` generic) of 0 will now exclude the according memory from synthesis (and also clears the according `NEORV32_SYSINFO.SOC` flags) |
| 18.11.2021 | 1.6.3.8 | TWI: removed TWI_CTRL_CKSTEN flag (enable clock stretching) from control registers, clock-stretching is now _always_ enabled |
| 14.11.2021 | 1.6.3.7 | major control unit and ALU logic optimizations, reduced hardware footprint; :lock: closed further illegal instruction encoding holes (system environment instructions, ALU and ALU-immediate instructions, FENCE instructions); [PR #204](https://github.com/stnolting/neorv32/pull/204) |
Expand Down
67 changes: 19 additions & 48 deletions docs/datasheet/soc_trng.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -13,72 +13,43 @@
| 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.

**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.
attributes so it can be synthesized for _any_ FPGA.

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"]
[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
|=======================
2 changes: 1 addition & 1 deletion rtl/core/neorv32_package.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ package neorv32_package is
-- 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"01060309"; -- no touchy!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01060310"; -- no touchy!
constant archid_c : natural := 19; -- official NEORV32 architecture ID - hands off!

-- External Interface Types ---------------------------------------------------------------
Expand Down
Loading