
This project implements a fully digital True Random Number Generator (TRNG) designed to fit within a single Tiny Tapeout tile. Since analog components are not available in a standard cell digital flow, this design harvests entropy from the phase noise (jitter) of free-running, unconstrained ring oscillators.
The raw, asynchronous bitstream is sampled by the synchronous system clock, whitened to remove systemic 0 or 1 biases, and shifted into a complete 8-bit word.
The module communicates using a standard valid/ready handshake protocol to ensure the receiving system only reads fully assembled, valid random bytes.
input logic [7:0] ui_in, // ui_in[0] is used for ready_i signal, rest is UNUSED
output logic [7:0] uo_out, // 8-bit Random Byte payload
input logic [7:0] uio_in, // UNUSED
output logic [7:0] uio_out, // uio_out[0] is used for valid_o signal, rest is UNUSED
output logic [7:0] uio_oe, // uio_oe[0] is 1'b1, rest is UNUSED
input logic ena, // always 1 when the design is powered, so you can ignore it
input logic clk, // clock
input logic rst_n // reset_n - low to reset
To guarantee entropy, the source consists of multiple mutually prime length ring oscillators (e.g., lengths of 3, 5, and 7).
Each ring oscillator is built with 2*DEPTH + 1 standard IHP 130nm (sg13g2_inv_1) inverter cells. These standard cells are manually instantiated with (* keep = "true" *) attributes to prevent the synthesis tool (Yosys) from optimizing away the combinatorial loops.
The asynchronous outputs from these rings are XOR'd together into a single raw bitstream which is captured by D-Flip-Flops clocked by clk_i.
Raw ring oscillators often exhibit a slight bias (e.g., naturally preferring 1s over 0s due to microscopic process variations). The Von Neumann extractor eliminates this bias by reading the raw bits in non-overlapping pairs.
Extraction Logic:
The whitener generates a bit according to the following truth table. Discarded bits yield no output (valid_o remains LOW).
| Bit 1 (Cycle N) | Bit 2 (Cycle N+1) | bit_o |
valid_o |
Action |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | Discard (No entropy) |
| 0 | 1 | 1 | 1 | Keep 1 |
| 1 | 0 | 0 | 1 | Keep 0 |
| 1 | 1 | 0 | 0 | Discard (No entropy) |
Because the Von Neumann extractor drops 00 and 11 pairs, there is a statistical possibility (especially if the oscillators lock up) that the process suffers from "entropy starvation" and fails to converge on a full 8-bit byte in a reasonable timeframe.
To prevent the system from hanging indefinitely:
clk_i cycle.0 every time the whitener successfully outputs a valid bit.Testing the physical silicon requires observing the handshake protocol.
rst_ni LOW, then HIGH to reset the module.ena_i HIGH to enable the oscillators and sampling logic.ready_i HIGH from your receiving device to indicate you are ready to receive data.valid_o to go HIGH.valid_o is HIGH, read the 8-bit value on byte_o. This is your true random byte.Pre-silicon verification is handled via a Python-based Cocotb testbench. Because digital simulators cannot natively process analog phase noise, the RTL leverages a \ifdef SIM`block to model the oscillators using fractional#` delays.
The DV suite verifies the digital plumbing using two main tests:
ready_i signal HIGH and loops 100 times, waiting for the valid_o edge to capture sequential random bytes and confirming the handshake can operate continuously.Note: Simulating this design at the gate level (GLS) presents a fundamental EDA challenge. Synthesis tools generate a physical netlist for the combinatorial inverter loops without an initial value. Digital simulators evaluate this unknown initial state as X.
Because a pure combinatorial loop has no reset pin, the X state remains permanently locked, propagating through the synchronizer flip-flops and crashing the Von Neumann logic. Consequently, our Cocotb testbench actively monitors the output bus for unresolvable X states. If an X state is detected (indicating a GLS environment where the oscillator failed to initialize), the testbench logs the limitation and gracefully skips the remainder of the simulation to prevent CI pipeline failures.
valid/ready handshake protocol and quickly stream the generated random bytes over USB to a host PC for statistical validation.| # | Input | Output | Bidirectional |
|---|---|---|---|
| 0 | ready_i | bit0_o | valid_o |
| 1 | bit1_o | ||
| 2 | bit2_o | ||
| 3 | bit3_o | ||
| 4 | bit4_o | ||
| 5 | bit5_o | ||
| 6 | bit6_o | ||
| 7 | bit7_o |