Hardware

This page summarizes the hardware architecture and gives help for HDL simulation, FPGA compilation and target programmation.

Hardware architecture

As illustrated in figure below, the top.vhd architecture contains the PTRNG, including the digital noise source (more information on its configuration).

Top architecture

A communication chain is enabled from the PC to the PTRNG with the help of an UART, and a simple interpreter for read/write commands that performs transactions on the register map.

The register map is required to:

  • send control and configurations to the PTRNG,
  • read statuses from the PTRNG,
  • read random data generated by the PTRNG in the FIFO.

Digital noise source

The digital noise source primarily consists of at least two ring-oscillators and a digitizer block, which is responsible for sampling the relative phase noise of the oscillators.

Ring-oscillators

A generic ring oscillator is defined in ring.vhd, located in hardware/target/common/generic. The loop consists of inverters and a NAND gate, which enables and disables the oscillation.

Generic ring-oscillator

In FPGA implementations, ring oscillators are composed of Lookup Tables (LUTs): one LUT2 for the NAND gate and several LUT1 units for the inverters (or buffers).

It is essential to provide the synthesis tool with specific constraints to enable combinatorial loops. Additionally, the place and route tool requires physical constraints to ensure signal integrity, particularly to minimize crosstalk from other parts of the design via cells or nets.

As shown in the following floorplan:

  • Ring oscillators are isolated within their respective bank.
  • The digitizer block, responsible for clock-domain crossing (from RO to system clock), is positioned near the ring oscillators.
  • The digital noise block is surrounded by a forbidden area to ensure isolation.

Digital noise place and route

All constraints are defined in the constraints.xdc file, located in hardware/config/digitalnoise. This file is generated by a script, as detailed in the digital noise configuration section.

Digitizer

The digitizer comes with the following sampling architectures: ERO, MURO and COSO.

ERO

The Elementary Ring-Oscillator (ERO) TRNG is the simpliest sampling architecture. It instanciates two ring-oscillators:

  • RO0 frequency is divided by factor K in order to accumulate jitter (i.e. phase noise),
  • RO1 that is sampled by the previously divided ring-oscillator.

ERO sampling architecture

This architecture benefits from a simple design, however the division factor required to accumulated enough noise makes the output bitrate very slow. As instance with a 100MHz ring-oscillator and a division factor of K=1000, the output rate is limited to 100kbit/s.

MURO

The MUlti Ring-Oscillator (MURO) TRNG is designed to improve the entropy rate by accumulating noise from several ring-oscillators that are XORed and the sampled with the same principle as for ERO.

MURO sampling architecture

With lower accumulation time, the MURO benefits from higher throughput. However, instanciating multiple ring-oscillators increase the risk of locking phenomenon that would cancel all captured noise.

COSO

The COherent Sampling Oscillator (COSO) TRNG samples directly RO1 with RO0. The sampled output is called the beat signal and is the image of the accumulated jitter between the two oscillators. The beat signal period is measured with a counter that is incremented in steps of RO0. In other words, this counter measures the accumulation of the phase noise. The less significant bit (LSB) of the counter final value is taken as output for the random bit.

COSO sampling architecture

The COSO architecture benefits from small footprint, a relevant output rate and has an intrinsic failure alarm. However, the COSO needs the frequencies ratio to be controlled.

Dependencies

OpenTRNG projects depends on the following submodules:

GitHub Descrition
vhdl-extras Provides a set of standard and common VHDL entities.
fluart The feature-less UART to provide communication between PC and target.
cmd_proc handle simple read-write adress/data packet processing on the UART.

The Corsair tool is also used to generate the register map (see the register map configuration section).

Simulate HDL sources

Testbenches for simulating HDL sources are scripted in Python using cocotb and are stored in the hardware/sim directory. Each testbench contains multiple test cases. The Python-based ring-oscillator emulator is used to generate noisy clock signals for these test cases.

For example, to run the simulation for the COSO testbench, use the following commands:

$ cd hardware/sim/test_coso
$ make

For instance, the summary of the testbench simulation is displayed in the terminal as follows:

*************************************************************
** TEST                                STATUS  SIM TIME (ns) 
*************************************************************
** test_coso.test_total_failure_alarm   PASS       10010.00  
** test_coso.test_gen_random_100        PASS       63706.73  
*************************************************************
** TESTS=2 PASS=2 FAIL=0 SKIP=0                    73716.73  
*************************************************************

Thanks to the ghdl simulator, all testbenches store their waveforms in the waves.vcd file. These waveform files can be visualized using tools such as GTKWave or Wavedrom, among others.

COSO testbench waves

Compile for FPGA

The VHDL provided in the hardware/hdl directory is target-agnostic and can be synthesized for all FPGA vendors (and even ASICs). In contrast, the ring-oscillator implementations are target-specific. For example, the target/common/xilinx directory contains a dedicated ring.vhd implementation for Xilinx FPGAs.

FPGA targets

Currently, OpenTRNG supports the Digilent Arty A7 35T board, which is based on the Xilinx Artix-7 FPGA.

image-center

Please follow these instructions to add the support for a new Xilinx target:

  • create a new directory in hardware/target/fpga and jump into,
  • then create a target.vhd for the global top for the target,
  • create a target.xdc to specify the physical constraints (such as pinout, clocking, IO settings…),
  • then call the script generate_vivado_project.tcl as explained in the next section to create the Vivado project.

To add support for a new Xilinx target, please follow these steps:

  • Create a new directory under hardware/target/fpga and navigate into it.
  • Create a target.vhd file for the global top module for the target.
  • Create a target.xdc file to define the physical constraints (e.g., pinout, clocking, I/O settings, etc.).
  • Run the generate_vivado_project.tcl script, as explained in the next section, to generate the Vivado project.

Synthetize, place route and program device

Scaffold script generate_vivado_project.tcl is provided to generate Xilinx Vivado projects for any targets, the tcl script is located here hardware/target/fpga. Use the following command to generate the Vivado project opentrng_arty_a7_35t.xpr in the directory arty_a7_35t for the target xc7a35ticsg324-1L:

The boilerplate script generate_vivado_project.tcl is provided to generate Xilinx Vivado projects for any target. The tcl script is located in hardware/target/fpga. To generate the Vivado project opentrng_arty_a7_35t.xpr in the arty_a7_35t directory for the target xc7a35ticsg324-1L, use the following command:

$ cd hardware/target/fpga
$ vivado -mode tcl -source generate_vivado_project.tcl -tclargs arty_a7_35t xc7a35ticsg324-1L

Then start Vivado with the command:

$ vivado -mode gui arty_a7_35t/opentrng_arty_a7_35t.xpr

After runing Vivado’s Synthesis, Implementation and Bitstream generation, the target can be programmed using the Hardware Manager.

Design configurations

Some part of the design are generated using scripts (eg. register map) or configured via scripts (such as for digital noise).

Register map configuration

The PTRNG block exposes several configuration, status, and data registers as ports of the entity. These registers are organized into a register map, enabling simple read and write operations to access them from the PC. All the code, both target-side and PC-side, is generated using Corsair, with the registers.yml configuration file located in hardware/config/registers as input.

The register map specification can be found here in the PTRNG repository.

Digital noise configuration

The digitalnoise entity, described in the file digitalnoise.vhd, requires configuration. On the supported targets, this entity comes with a default configuration.

The configuration process generates:

  • The settings.vhd VHDL package, which defines the size and number of ring oscillators, as well as the type of sampling architecture.
  • The constraints.xdc file (for Xilinx), which specifies the physical constraints for the place and route of the ring oscillators.

The generate.py script, located in hardware/config/digitalnoise, can be used with the following parameters:

$ python generate.py -h
usage: generate.py [-h] [-args ARGS] [-verbose] [-vendor {xilinx}] [-luts LUTS] [-fixedlutpin FIXEDLUTPIN] [-x X]
                   [-y Y] [-maxwidth MAXWIDTH] [-maxheight MAXHEIGHT] [-border BORDER] [-ringwidth RINGWIDTH]
                   [-digitheight DIGITHEIGHT] [-digittype {TEST,ERO,MURO,COSO}] [-hpad HPAD] [-vpad VPAD] [-fmax FMAX]
                   [-len LEN [LEN ...]]

Generate configuration files for the digitalnoise entity. More specifically it generates: 'settings.vhd' that contains
HDL constants and 'placeroute.*' that contains all timing/place/route constraints for digitalnoise (extension
depending on vendor).

options:
  -h, --help            show this help message and exit
  -args ARGS            load all arguments from file
  -verbose              add verbosity to the output
  -vendor {xilinx}      target vendor (for selecting the templates)
  -luts LUTS            number of LUT per item (per slice for Xilinx, per LE for Intel Altera)
  -fixedlutpin FIXEDLUTPIN
                        optional parameter to fix the input pin for all LUTs (the value is the name of the pin)
  -x X                  origin abscissa for the reserved area
  -y Y                  origin ordinate for the reserved area
  -maxwidth MAXWIDTH    maximum width for the reserved area
  -maxheight MAXHEIGHT  maximum height for the reserved area
  -border BORDER        forbidden border all around inside the reserved area
  -ringwidth RINGWIDTH  column width for a ring-oscillator
  -digitheight DIGITHEIGHT
                        height for the digitizer block
  -digittype {TEST,ERO,MURO,COSO}
                        choice of the sampling architecture for the digitizer
  -hpad HPAD            horizontal padding between ROs
  -vpad VPAD            vertical padding between ROs
  -fmax FMAX            maximum estimated frequency for all ring-oscillators (Hz)
  -len LEN [LEN ...]    number of elements in each ring-oscillator

The default configurations for the Digilent Arty7 board can be loaded with the following commands:

$ python generate.py -args ../../target/fpga/xilinx/arty_a7_35t/generate_ero.args
$ python generate.py -args ../../target/fpga/xilinx/arty_a7_35t/generate_muro.args
$ python generate.py -args ../../target/fpga/xilinx/arty_a7_35t/generate_coso.args