80 lines
4.5 KiB
Markdown
80 lines
4.5 KiB
Markdown
# STRIX
|
||
### Satellite True Random Information eXtractor
|
||
|
||
[](https://docs.arduino.cc/hardware/mkr-vidor-4000/)
|
||
[](https://github.com/jetify-com/devbox/)
|
||
[](LICENSE)
|
||
[](https://ai-declaration.md)
|
||
|
||
A portable wireless True Random Number Generator built on an Arduino MKR Vidor 4000.
|
||
|
||
## Design
|
||
|
||
Entropy comes from FPGA ring oscillators whose sampled timing jitter is XOR-combined into output bits, with no pseudo-random post-processing. A SAMD21 serves the results over USB, over HTTP on its own WiFi access point (stationary mode, on a charger), or over Bluetooth LE (mobile mode, on battery).
|
||
|
||
- 4 independent generators × 90 ring oscillators. Each generator XORs its rings every 120 MHz clock (spatial) and then several consecutive bits (temporal, default 5): about 24 Mbps per generator.
|
||
- Separate stream per generator, plus a combined stream of all healthy generators
|
||
- On-device health tests per generator: NIST SP 800-90B repetition count and adaptive proportion, plus a dead-ring monitor
|
||
- Live statistics per trial: bias, z-score, random walk and lag-1 autocorrelation, with rolling and cumulative windows
|
||
- Configurable random-walk / majority-vote bias amplifier on a bias path and an autocorrelation path, with sub-trial voting
|
||
- Von Neumann extractor that can be toggled on the stream, statistics and amplifier paths
|
||
- Per-second trials in Global Consciousness Project format (200-bit XOR-masked sums per generator, plus full-rate sums), with Stouffer Z and network variance
|
||
- Raw ring captures and frequency measurement for characterization
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
subgraph FPGA["FPGA: Cyclone 10 LP, 120 MHz from a PLL on the SAMD21's 48 MHz clock"]
|
||
direction LR
|
||
subgraph GEN["4 generators"]
|
||
direction TB
|
||
RO["90 ring oscillators<br/>3 taps XORed per ring"] --> SMP["2-flip-flop sampling"]
|
||
SMP --> SX["spatial XOR<br/>of all rings"]
|
||
SX --> TX["temporal XOR<br/>of 1-8 bits"]
|
||
end
|
||
SMP --> HM["health monitors<br/>repetition count, adaptive<br/>proportion, dead rings"]
|
||
SX --> HM
|
||
TX --> SEL["healthy generators<br/>g0-g3 and combined XOR"]
|
||
HM -->|healthy| SEL
|
||
SEL --> ST["entropy stream<br/>4 KB FIFO"]
|
||
SEL --> STATS["statistics<br/>per-trial counts"]
|
||
SEL --> AMP["bias amplifier<br/>2 paths, 3 stages"]
|
||
SEL --> GCP["GCP trials<br/>per second"]
|
||
GEN -.-> CAP["raw capture,<br/>frequency counter"]
|
||
ST & STATS & AMP & GCP & CAP & HM --> REG["SPI registers"]
|
||
PT["WiFi module<br/>pin pass-through"]
|
||
end
|
||
REG <-->|SPI 8 MHz| MCU["SAMD21 firmware"]
|
||
MCU <--> PT
|
||
PT <--> NINA["NINA-W102<br/>WiFi and BLE"]
|
||
MCU --> USB["USB serial"]
|
||
NINA --> HTTP["HTTP on its own<br/>access point"]
|
||
NINA --> BLE["BLE GATT service"]
|
||
```
|
||
|
||
The USB, HTTP and BLE API is documented in [arduino/strix/API.md](arduino/strix/API.md).
|
||
|
||
## Command-line client
|
||
|
||
`tools/strix.py` talks to the device over USB; run it with `devbox run strix <command>` or `uv run tools/strix.py <command>`. It finds the board by its USB ID (override with `--port` or `STRIX_PORT`).
|
||
|
||
| Command | Does |
|
||
|---|---|
|
||
| `id`, `health`, `amp`, `get` | Prints the device's reply |
|
||
| `stats [--reset]` | Prints the statistics, or restarts them |
|
||
| `set KEY VALUE` | Changes a setting (keys in the API documentation) |
|
||
| `entropy N [--out FILE]` | N entropy bytes as hex, or binary into a file |
|
||
| `watch stats\|amp` | Prints every new trial until Ctrl-C |
|
||
| `gcp [--log FILE] [--full] [--seconds N]` | Follows the per-second GCP-format trials |
|
||
| `send LINE` | Sends any command line and prints the reply |
|
||
|
||
`gcp` prints one line per second: UTC time, second number, the four 200-bit sums, Stouffer Z, Z², and the cumulative Z² − 1 with its p = 0.05 envelope (`*` when outside). `--full` tracks the full-rate trials instead. It reconnects after USB dropouts and fills missed seconds from the device's 60-second history. `--log` appends GCP-style CSV rows, `13,<unix time>,<UTC date-time>,<g0>,<g1>,<g2>,<g3>` (empty for unhealthy generators), after a `12,gmtime,Date/Time,g0,g1,g2,g3` header.
|
||
|
||
## TODO
|
||
|
||
- WiFi credentials stored on the device instead of compile-time defaults
|
||
- Battery pack
|
||
- 3D case
|
||
|
||
---
|
||
|
||
## [Development Notes](NOTES.md)
|