{"id":28124631,"url":"https://github.com/stnolting/neotrng","last_synced_at":"2026-04-02T20:49:15.519Z","repository":{"id":49743234,"uuid":"430418414","full_name":"stnolting/neoTRNG","owner":"stnolting","description":"🎲 A Tiny and Platform-Independent True Random Number Generator for any FPGA (and ASIC).","archived":false,"fork":false,"pushed_at":"2026-04-01T01:09:40.000Z","size":646,"stargazers_count":217,"open_issues_count":0,"forks_count":28,"subscribers_count":6,"default_branch":"main","last_synced_at":"2026-04-01T03:50:50.776Z","etag":null,"topics":["asic","cryptography","entropy","entropy-source","fpga","hdl","random","random-number-generators","ring-oscillator","rng","trng","vhdl"],"latest_commit_sha":null,"homepage":"","language":"VHDL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stnolting.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-11-21T16:23:45.000Z","updated_at":"2026-04-01T01:05:20.000Z","dependencies_parsed_at":"2025-06-27T05:22:30.960Z","dependency_job_id":"e850ce51-0939-424b-8824-4ed152ea690c","html_url":"https://github.com/stnolting/neoTRNG","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/stnolting/neoTRNG","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stnolting%2FneoTRNG","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stnolting%2FneoTRNG/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stnolting%2FneoTRNG/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stnolting%2FneoTRNG/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stnolting","download_url":"https://codeload.github.com/stnolting/neoTRNG/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stnolting%2FneoTRNG/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31316007,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T12:59:32.332Z","status":"ssl_error","status_checked_at":"2026-04-02T12:54:48.875Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asic","cryptography","entropy","entropy-source","fpga","hdl","random","random-number-generators","ring-oscillator","rng","trng","vhdl"],"created_at":"2025-05-14T09:18:41.981Z","updated_at":"2026-04-02T20:49:15.508Z","avatar_url":"https://github.com/stnolting.png","language":"VHDL","funding_links":[],"categories":[],"sub_categories":[],"readme":"# The neoTRNG True Random Number Generator\n\n**A Tiny and Platform-Independent True Random Number Generator for _any_ FPGA (and even ASICs).**\n\n[![neoTRNG simulation](https://github.com/stnolting/neoTRNG/actions/workflows/main.yml/badge.svg)](https://github.com/stnolting/neoTRNG/actions/workflows/main.yml)\n[![Release](https://img.shields.io/github/v/release/stnolting/neoTRNG)](https://github.com/stnolting/neoTRNG/releases)\n[![License](https://img.shields.io/github/license/stnolting/neoTRNG)](https://github.com/stnolting/neoTRNG/blob/main/LICENSE)\n[![DOI](https://zenodo.org/badge/430418414.svg)](https://zenodo.org/badge/latestdoi/430418414)\n\n* [Introduction](#introduction)\n* [Top Entity, Integration and Interface](#top-entity)\n* [Theory of Operation / Architecture](#architecture)\n* [Evaluation](#evaluation)\n* [Hardware Utilization](#hardware-utilization)\n* [Simulation](#simulation)\n* [Acknowledgments](#acknowledgments)\n* [References](#references)\n\n\n## Introduction\n\nThe neoTRNG aims to be a small and **platform-agnostic** TRUE random number generator (TRNG) that\ncan be synthesized for _any_ target technology (FPGAs and even ASICs). It is based on simple free-running\nring-oscillators, which are enhanced by a _special technique_ in order to allow synthesis for any platform.\nThe _phase noise_ that occurs when sampling free-running ring-oscillators is used as physical entropy source.\n\nThis project is a \"spin-off\" from the [NEORV32 RISC-V Processor](https://github.com/stnolting/neorv32) where\nthe neoTRNG is implemented as default SoC module.\n\n**Key Features**\n\n* [x] technology, vendor and platform/technology independent - can be synthesized for **any** platform\n* [x] tiny hardware footprint (less than 100 LUT4s/FFs for the standard configuration)\n* [x] high throughput (for a physical TRNG)\n* [x] fully open source with a [permissive license](https://github.com/stnolting/neoTRNG/blob/main/LICENSE)\n* [x] full-digital design; single-file VHDL module without any dependencies\n* [x] very high operating frequency to ease timing closure\n* [x] easy to use / simple integration\n* [x] full documentation down to rtl level + evaluation\n\n\u003e [!CAUTION]\n\u003e It is possible that there might be at least _some_ cross correlations between internal/external\nsignals/events and the generated random numbers. Hence, there is **no guarantee at all** the neoTRNG provides\n_perfect or even cryptographically secure_ random numbers! See the provided evaluation results or (even better)\ntest it by yourself. Furthermore, there is no tampering detection mechanism or online health monitoring available\nyet to check for integrity/quality of the generated random data.\n\n\u003e [!WARNING]\n\u003e Keeping the neoTRNG _permanently enabled_ will increase dynamic power consumption and might also cause\nlocal heating of the chip (when using very large configurations). Furthermore, additional electromagnetic\ninterference (EMI) might be emitted by the design.\n\n\n## Top Entity\n\nThe whole design is implemented as a single VHDL file\n[`rtl/neoTRNG.vhd`](https://github.com/stnolting/neoTRNG/blob/main/rtl/neoTRNG.vhd) that\nhas no dependencies at all (like special libraries, packages or submodules).\n\n```vhdl\nentity neoTRNG is\n  generic (\n    NUM_CELLS     : natural range 1 to 255;  -- number of ring-oscillator cells\n    NUM_INV_START : natural range 3 to 4095; -- number of inverters in first ring-oscillator cell, has to be odd\n    NUM_RAW_BITS  : natural range 1 to 4096; -- number of XOR-ed raw bits per random sample byte (has to be a power of 2)\n    SIM_MODE      : boolean                  -- enable simulation mode (no physical random if enabled!)\n  );\n  port (\n    clk_i    : in  std_ulogic; -- module clock\n    rstn_i   : in  std_ulogic; -- module reset, low-active, async, optional\n    enable_i : in  std_ulogic; -- module enable (high-active)\n    valid_o  : out std_ulogic; -- data_o is valid when set (high for one cycle)\n    data_o   : out std_ulogic_vector(7 downto 0) -- random data byte output\n  );\nend neoTRNG;\n```\n\n### Interface and Configuration\n\nThe neoTRNG uses a single clock domain driven by the `clk_i` signal. The module's reset signal `rstn_i`\nis _optional_ (tie to `'1'` if not used). Random data is obtained by using a simple data/valid interface:\nwhenever a new valid random byte is available the `valid_o` output will be high for exactly one cycle so\nthe `data_o` output can be sampled by the user logic.\n\nThe `enable_i` signal is used to initialize and start the TRNG. Before the TRNG can be used this signal\nshould be kept low for at least several 100 clock cycles (depending on the configuration) to ensure that\nall bits of the internal shift registers are cleared again. When `enable_i` is set and `valid_o` becomes\nset for the first time the TRNG is operational. Disabling the TRNG also requires `enable_i` being low for\nthe same amount of clock cycles. When `enable_i` gets low all ring-oscillators will be stopped reducing\ndynamic switching activity and power consumption.\n\nThree generics are provided to configure the neoTRNG. `NUM_CELLS` defines the total number of entropy\ncells. `NUM_INV_START` defines the number of inverters (= the length of the ring-oscillator) in the very\nfirst cell. These two generics are further described in the [Architecture](#architecture) section below.\n`NUM_RAW_BITS` defines the number of raw entropy bits that get XOR-ed into the final random sample byte.\nThe last generic `SIM_MODE` can be set to allow [simulating](#simulation) of the TRNG within a plain RTL\nsimulation.\n\n### Example/Default Configuration and Instantiation\n\n```vhdl\nneoTRNG_inst: neoTRNG\ngeneric map (\n  NUM_CELLS     =\u003e 3,    -- 3 entropy cells / ring-oscillators in total\n  NUM_INV_START =\u003e 5,    -- 5 inverters in first ring-oscillator\n  NUM_RAW_BITS  =\u003e 64,   -- consume 64 raw random bits per output byte\n  SIM_MODE      =\u003e false -- disable simulation-mode for physical implementation\n)\nport map (\n  clk_i    =\u003e clk,\n  rstn_i   =\u003e rstn,\n  enable_i =\u003e enable,\n  valid_o  =\u003e valid,\n  data_o   =\u003e data\n);\n```\n\n\n## Architecture\n\n![neoTRNG architecture](https://raw.githubusercontent.com/stnolting/neoTRNG/main/img/neotrng_architecture.png)\n\nThe neoTRNG is based on a configurable number (`NUM_CELLS`) of [entropy cells](#entropy-cells). Each cell\nprovides a simple a ring-oscillator (\"RO\") that is built using an odd number of inverters. The oscillation\nfrequency of the RO is defined by the propagation delay of the elements within the ring. This frequency is\nnot static as it is subject to minimal fluctuations caused by thermal noise electronic shot noise. The\nstate of the RO's last inverter is sampled into a flip flop by using a static clock (`clk_i`). As the RO's\nfrequency chaotically varies over time the inherent **phase noise** of the sampled data is used as actual\nentropy source.\n\nEach entropy cell generates a 1-bit stream of random data. The outputs of all cells are mixed using a wide\nXOR gate before the stream is [de-biased](#de-biasing) by a simple randomness extractor. Several de-biased\nbits are sampled / de-serialized by the [sampling unit](#sampling-unit) to provide byte-wide random number.\nThe sampling unit also applies a simple post-processing in order to improve the spectral distribution of\nthe random numbers.\n\n### Entropy Cells\n\nEach entropy cell consists of a ring-oscillator that is build from an odd number of **inverting latches**.\nThe length of ring in the very first entropy cell is defined by the `NUM_INV_START` generic. Every\nadditional entropy cell adds another 2 inverters to this initial chain length. Hence, each additional\nentropy cell oscillates at a lower frequency then the one before.\n\nAsynchronous elements like ring-oscillators are hard to implement in a platform-independent way as they\nusually require the use of platform-/technology-specific primitives, attributes or synthesis settings. In\norder to provide a real target-agnostic architecture, which can be synthesized for any target technology,\na special technique is applied: each inverter inside the RO is followed by a **latch** that provides a\nglobal reset and also an individual latch-enable to switch the latch to transparent mode.\n\nThe individual latch-enables are controlled by a long shift register that features a distinct FF for every\nsingle latch in the RO chain. When the TRNG is enabled, this shift register starts to fill with ones. Thus,\nthe latches are individually enabled one-by-one making it impossible for the synthesis tool to trim any\nlogic/elements from the RO chain as the start-up states of each latch can (theoretically) be monitored by\nexternal logic. The enable shift register of all entropy cells are daisy-chained to continue this start-up\nprocedure across the entire entropy array.\n\nThe following image shows the simplified schematic of the very first entropy cell consisting of 5\ninverter-latch elements for the rings oscillator, 5 flip flops for the enable shift register and another 2\nflip flops for the synchronizer.\n\n![neoTRNG entropy cell](https://raw.githubusercontent.com/stnolting/neoTRNG/main/img/neotrng_ring_oscillator.png)\n\nAn image showing the FPGA the mapping result (generated by Intel Quartus Prime) of the very first entropy\ncell can be seen below. It shows that all latch+inverter elements of the ring-oscillator chain were\nsuccessfully mapped to individual LUT4s.\n\n![neoTRNG Quartus Prime mapping](https://raw.githubusercontent.com/stnolting/neoTRNG/main/img/neotrng_cell_map.png)\n\n\n### De-Biasing\n\nAs soon as the last bit of the entropy cell's daisy-chained enable shift register is set the de-biasing\nunit gets started. This unit implements a simple \"John von Neumann Randomness Extractor\" to de-bias the\nobtained random data stream. The extractor implements a 2-bit shift register that samples the XOR-ed\nrandom bit from the entropy cell array. In every second cycle the extractor evaluates the two sampled bits\nto check a non-overlapping pair of bits for _edges_.\n\n![neoTRNG de-biasing](https://raw.githubusercontent.com/stnolting/neoTRNG/main/img/neotrng_debiasing.png)\n\nWhenever an edge has been detected a \"valid\" signal is send to the following sampling unit. A rising-edge\n(`01`) emits a `1` data bit and a falling-edge (`10`) emits a `0` data bit. Hence, the de-biasing unit\nrequires at least two clock cycles to generate a single random bit. If no edge is detected (`00` or `11`)\nthe valid signal remains low and the sampling unit halts.\n\n### Sampling Unit\n\nThe sampling unit implements a 8-bit shift register to convert the serial de-biased bitstream into byte-wide\nrandom numbers. Additionally, the sample unit provides a simple post processing to improve the spectral\ndistribution of the obtained random samples.\n\n![neoTRNG sampling unit](https://raw.githubusercontent.com/stnolting/neoTRNG/main/img/neotrng_sampling_unit.png)\n\nIn order to generate one byte of random data the sampling unit reset its internal shift register to all-zero\nand starts consuming single bits from the de-biased random stream. By default, 64 raw entropy bits are used,\nbut this number can be adjusted by the `NUM_RAW_BITS` generic (using more random bits might improve random\nquality at the extend of the final generation rate). The shift register implements a simple 8-bit\n[CRC](https://en.wikipedia.org/wiki/Cyclic_redundancy_check) for entropy compression. The following\npolynomial is used: `x^8 + x^2 + x^1 + 1`\n\n\n## Evaluation\n\nThe neoTRNG is evaluated as part of the [NEORV32](https://github.com/stnolting/neorv32) processor, where the\nneoTRNG is available as standard SoC module. The system was implemented on an AMD Artix-7 (`xc7a35ticsg324-1L`)\nFPGA running at 150MHz. For the evaluation the tiny **default configuration** has been used:\n\n```\nNUM_CELLS     = 3\nNUM_INV_START = 5\nNUM_RAW_BITS  = 64\nSIM_MODE      = false\n```\n\n\u003e [!NOTE]\n\u003e A total amount of **32MB** of random data has been obtained for the evaluations. This data set is\navailable as `data.bin` binary file in the [release](https://github.com/stnolting/neoTRNG/releases) assets.\n\n### Histogram Analysis\n\nFor the simple histogram analysis 32MB of random bytes were sampled from the neoTRNG. The obtained bytes\nwere accumulated according to their occurrence and sorted into bins where each bin represents one specific\nbyte pattern (1 byte = 8 bits = 256 different patterns). The resulting was then analyzed with regard to\nits statistical properties:\n\n* arithmetic mean of all sampled random bytes\n* average occurrence across all bit patterns\n* min and max occurrences and deviation from the average occurrence\n\n```\n[NOTE] integer numbers only\nNumber of samples: 33554432\nArithmetic mean:   127 (optimum would be 127)\n\nHistogram occurrence\nAverage:      131072 (optimum would be 33554432/256 = 131072)\nMin:          130036 = average - 1036 (deviation) at bin 210 (optimum deviation would be 0)\nMax:          132035 = average + 963 (deviation) at bin 163 (optimum deviation would be 0)\nAverage dev.: +/- 282 (optimum would be 0)\n```\n\n### Entropy per Byte\n\n```\nEntropy = 7.999995 bits per byte.\n\nOptimum compression would reduce the size\nof this 33226752 byte file by 0 percent.\n\nChi square distribution for 33226752 samples is 243.56, and randomly\nwould exceed this value 68.61 percent of the times.\n\nArithmetic mean value of data bytes is 127.4802 (127.5 = random).\nMonte Carlo value for Pi is 3.141387759 (error 0.01 percent).\nSerial correlation coefficient is 0.000155 (totally uncorrelated = 0.0).\n```\n\n### FIPS 140-2 RNG Tests\n\n```\n$ rngtest \u003c entropy.bin\nrngtest 5\nCopyright (c) 2004 by Henrique de Moraes Holschuh\nThis is free software; see the source for copying conditions.  There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\nrngtest: starting FIPS tests...\nrngtest: entropy source drained\nrngtest: bits received from input: 265814016\nrngtest: FIPS 140-2 successes: 13279\nrngtest: FIPS 140-2 failures: 11\nrngtest: FIPS 140-2(2001-10-10) Monobit: 1\nrngtest: FIPS 140-2(2001-10-10) Poker: 1\nrngtest: FIPS 140-2(2001-10-10) Runs: 4\nrngtest: FIPS 140-2(2001-10-10) Long run: 5\nrngtest: FIPS 140-2(2001-10-10) Continuous run: 0\n```\n\n### Hardware Utilization\n\nMapping results for the neoTRNG implemented within the NEORV32 RISC-V Processor using the default\nconfiguration. Results generated for an Intel Cyclone `EP4CE22F17C6N` FPGA running at 100MHz using Intel\nQuartus Prime.\n\n```\nModule Hierarchy                                      Logic Cells    Logic Registers\n------------------------------------------------------------------------------------\nneoTRNG:neoTRNG_inst                                      57 (27)            46 (19)\n  neoTRNG_cell:\\entropy_source:0:neoTRNG_cell_inst         8  (8)             7  (7)\n  neoTRNG_cell:\\entropy_source:1:neoTRNG_cell_inst        10 (10)             9  (9)\n  neoTRNG_cell:\\entropy_source:2:neoTRNG_cell_inst        15 (15)            11 (11)\n```\n\n\u003e [!NOTE]\n\u003e Synthesis tools might emit a warning that latches and combinatorial loops\nhave been detected. However, this is no design flaw as this is exactly what we want. :wink:\n\n### Throughput\n\nThe neoTRNG's maximum generation rate is defined by two factors:\n\n* A = 2: cycles required by the de-biasing logic to output one raw random bit\n* B = NUM_RAW_BITS (default = 64): number of raw random bits required by the sampling unit to generate one random byte\n\nHence, the neoTRNG requires _at least_ `A * B = 2 * 64 = 128` clock cycles to emit one random byte.\nFPGA evaluation has shown that the actual sampling time is around 300 clock cycles. Thus, an\nimplementation running at 100 MHz can generate approximately 330kB of random data per second.\nHigher generation rates can be achieved by running several neoTRNG instances in parallel.\n\n\n## Simulation\n\nSince the asynchronous ring-oscillators cannot be rtl-simulated (due to the combinatorial loops), the\nneoTRNG provides a dedicated simulation mode that is enabled by the `SIM_MODE` generic. When enabled,\na \"propagation delay\" implemented as simple flip flop is added to the ring-oscillator's inverters.\n\n\u003e [!IMPORTANT]\n\u003e The simulation mode is intended for simulation/debugging only!\n\u003e Designs with `SIM_MODE` enabled can be synthesized but will **not provide any true/physical random** numbers at all!\n\nThe [`sim`](https://github.com/stnolting/neoTRNG/sim) folder provides a simple testbench for the neoTRNG\nusing the default configuration. The testbench will output the obtained random data bytes as decimal\nvalues to the simulator console. The testbench can be simulated with GHDL by using the provided script:\n\n```\nneoTRNG/sim$ sh ghdl.sh\n../rtl/neoTRNG.vhd:120:3:@0ms:(assertion note): [neoTRNG] The neoTRNG (v3.3) - A Tiny and Platform-Independent True Random Number Generator, https://github.com/stnolting/neoTRNG\n../rtl/neoTRNG.vhd:130:3:@0ms:(assertion warning): [neoTRNG] Simulation-mode enabled (NO TRUE/PHYSICAL RANDOM)!\n89\n147\n99\n116\n11\n55\n203\n84\n97\n204\n117\n196\nghdl:info: simulation stopped by --stop-time @100u\n```\n\nThe GHDL waveform data is stored to `sim/neoTRNG_tb.ghw` and can be viewed using `gtkwave`:\n\n```\nneoTRNG/sim$ gtkwave neoTRNG_tb.ghw\n```\n\nA simple simulation run is executed by the [`neoTRNG-sim`](https://github.com/stnolting/neoTRNG/actions)\nGitHub actions workflow.\n\n\n## Acknowledgments\n\nA big thank you to Maarten Baert ([@MaartenBaert](https://github.com/MaartenBaert)) who did a great\n[evaluation of the neoTRNG (v3.2)](https://github.com/stnolting/neoTRNG/issues/6)\nand came up with excellent ideas to improve it.\n\n\n## References\n\n* Kumar, Sandeep S., et al. \"The butterfly PUF protecting IP on every FPGA.\" 2008 IEEE International Workshop\non Hardware-Oriented Security and Trust. IEEE, 2008.\n* Tuncer, Taner, et al. \"Implementation of non-periodic sampling true random number generator on FPGA.\"\nInformacije Midem 44.4 (2014): 296-302.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstnolting%2Fneotrng","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstnolting%2Fneotrng","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstnolting%2Fneotrng/lists"}