Replace FiGaRO based TRNG with new ROSC based TRNG

This commit is contained in:
Joachim Strömbergson 2022-10-11 13:17:04 +02:00
parent af36a40f3e
commit 7e0692b150
No known key found for this signature in database
GPG Key ID: 865B8A548EA61679
8 changed files with 24 additions and 400 deletions

View File

@ -275,9 +275,8 @@ Assigned core prefixes:
| *name* | *fw* | *app | *size* | *type* | *content* | *description* |
|--------------------|------|------------|--------|---------|-----------|--------------------------------------------------------|
| `TRNG_STATUS` | r | r | | | | TBD |
| `TRNG_SAMPLE_RATE` | | r | | | | TBD |
| `TRNG_ENTROPY` | | | | | | TBD |
| `TRNG_STATUS` | r | r | | | | Non-zero when an entropy word is available. |
| `TRNG_ENTROPY` | r | r | | | | Entropy word. Reading a word will clear status. |
| `TIMER_CTRL` | | | | | | TBD |
| `TIMER_STATUS` | r | | | | | TBD |
| `TIMER_PRESCALER` | | r/w | | | | TBD |

View File

@ -63,10 +63,7 @@ VERILOG_SRCS = \
$(P)/core/uart/rtl/uart_core.v \
$(P)/core/uart/rtl/uart_fifo.v \
$(P)/core/uart/rtl/uart.v \
$(P)/core/trng/rtl/firo.v \
$(P)/core/trng/rtl/garo.v \
$(P)/core/trng/rtl/figaro_core.v \
$(P)/core/trng/rtl/figaro.v
$(P)/core/trng/rtl/rosc.v
FIRMWARE_DEPS = \
$(P)/fw/mta1_mkdf_mem.h \

View File

@ -1,204 +0,0 @@
//======================================================================
//
// figaro_core.v
// -----------
// FiGaRO based FIGARO for iCE40 device.
//
//
// Author: Joachim Strombergson
// Copyright (C) 2022 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
//
//======================================================================
module figaro_core(
input wire clk,
input wire reset_n,
input wire set_sample_rate,
input wire [23 : 0] sample_rate,
input wire read_entropy,
output wire [31 : 0] entropy,
output wire ready
);
//---------------------------------------------------------------
// Local parameters.
//---------------------------------------------------------------
localparam DEFAULT_SAMPLE_RATE = 24'h010000;
//---------------------------------------------------------------
// Registers.
//---------------------------------------------------------------
reg [23 : 0] sample_rate_ctr_reg;
reg [23 : 0] sample_rate_ctr_new;
reg [23 : 0] sample_rate_reg;
reg sample_rate_we;
reg [5 : 0] bit_ctr_reg;
reg [5 : 0] bit_ctr_new;
reg bit_ctr_rst;
reg bit_ctr_inc;
reg bit_ctr_we;
reg [31 : 0] entropy_reg;
reg [31 : 0] entropy_new;
reg entropy_we;
reg ready_reg;
reg ready_new;
reg ready_we;
//---------------------------------------------------------------
// Firo oscillator instances and XOR combined result.
//---------------------------------------------------------------
wire firo_ent[3 : 0];
wire firo_entropy;
firo #(.POLY(10'b1111110111)) firo0(.clk(clk), .entropy(firo_ent[0]));
firo #(.POLY(10'b1011111001)) firo1(.clk(clk), .entropy(firo_ent[1]));
firo #(.POLY(10'b1100000001)) firo2(.clk(clk), .entropy(firo_ent[2]));
firo #(.POLY(10'b1011111111)) firo3(.clk(clk), .entropy(firo_ent[3]));
assign firo_entropy = firo_ent[0] ^ firo_ent[1] ^
firo_ent[2] ^ firo_ent[3];
//---------------------------------------------------------------
// garo oscillator instances and XOR combined result.
//---------------------------------------------------------------
wire garo_ent[3 : 0];
wire garo_entropy;
garo #(.POLY(11'b11111101111)) garo0(.clk(clk), .entropy(garo_ent[0]));
garo #(.POLY(11'b10111110011)) garo1(.clk(clk), .entropy(garo_ent[1]));
garo #(.POLY(11'b11000000011)) garo2(.clk(clk), .entropy(garo_ent[2]));
garo #(.POLY(11'b10111111111)) garo3(.clk(clk), .entropy(garo_ent[3]));
assign garo_entropy = garo_ent[0] ^ garo_ent[1] ^
garo_ent[2] ^ garo_ent[3];
//---------------------------------------------------------------
// Assignments.
//---------------------------------------------------------------
assign ready = ready_reg;
assign entropy = entropy_reg;
//---------------------------------------------------------------
// reg_update
//---------------------------------------------------------------
always @(posedge clk)
begin : reg_update
if (!reset_n) begin
sample_rate_reg <= DEFAULT_SAMPLE_RATE;
sample_rate_ctr_reg <= 24'h0;
bit_ctr_reg <= 6'h0;
entropy_reg <= 32'h0;
ready_reg <= 1'h0;
end
else begin
sample_rate_ctr_reg <= sample_rate_ctr_new;
if (sample_rate_we) begin
sample_rate_reg <= sample_rate;
end
if (bit_ctr_we) begin
bit_ctr_reg <= bit_ctr_new;
end
if (entropy_we) begin
entropy_reg <= entropy_new;
end
if (ready_we) begin
ready_reg <= ready_new;
end
end
end
//---------------------------------------------------------------
// ready_logic
//
// After an entropy word has been read we wait 32 bits before
// setting ready again, indicating that a new word is ready.
//---------------------------------------------------------------
always @*
begin : ready_logic;
bit_ctr_new = 6'h0;
bit_ctr_we = 1'h0;
ready_new = 1'h0;
ready_we = 1'h0;
if (bit_ctr_reg >= 6'h20) begin
ready_new = 1'h1;
ready_we = 1'h1;
end
if (bit_ctr_rst) begin
bit_ctr_new = 6'h0;
bit_ctr_we = 1'h1;
ready_new = 1'h0;
ready_we = 1'h1;
end
else if (bit_ctr_inc) begin
if (bit_ctr_reg < 6'h24) begin
bit_ctr_new = bit_ctr_reg + 1'h1;
bit_ctr_we = 1'h1;
end
end
end
//---------------------------------------------------------------
// figaro_sample_logic
//
// Wait sample_rate_reg number of cycles between sampling a bit
// from the entropy source.
//---------------------------------------------------------------
always @*
begin : figaro_sample_logic
sample_rate_we = 1'h0;
bit_ctr_rst = 1'h0;
bit_ctr_inc = 1'h0;
entropy_we = 1'h0;
entropy_new = {entropy_reg[30 : 0], firo_entropy ^ garo_entropy};
if (read_entropy) begin
bit_ctr_rst = 1'h1;
sample_rate_ctr_new = 24'h0;
end
else if (set_sample_rate) begin
bit_ctr_rst = 1'h1;
sample_rate_we = 1'h1;
sample_rate_ctr_new = 24'h0;
end
else if (sample_rate_ctr_reg == sample_rate_reg) begin
sample_rate_ctr_new = 24'h0;
entropy_we = 1'h1;
bit_ctr_inc = 1'h1;
end
else begin
sample_rate_ctr_new = sample_rate_ctr_reg + 1'h1;
end
end
endmodule // figaro_core
//======================================================================
// EOF figaro_core.v
//======================================================================

View File

@ -1,80 +0,0 @@
//======================================================================
//
// firo.v
// ------
// Fibonacci Ring Oscillator with state sampling.
// The Fibonacci depth is 10 bits, and the bits are always sampled.
//
//
// Author: Joachim Strombergson
// Copyright (C) 2022 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
//
//======================================================================
`default_nettype none
module firo(
input wire clk,
output wire entropy
);
parameter POLY = 10'b1111111111;
//----------------------------------------------------------------
// Registers and wires.
//----------------------------------------------------------------
reg entropy_reg;
/* verilator lint_off UNOPTFLAT */
wire [10 : 0] f;
/* verilator lint_on UNOPTFLAT */
//---------------------------------------------------------------
// Combinational loop inverters.
//---------------------------------------------------------------
/* verilator lint_off PINMISSING */
(* keep *) SB_LUT4 #(.LUT_INIT(16'h1)) osc_inv1 (.I0(f[0]), .O(f[1]));
(* keep *) SB_LUT4 #(.LUT_INIT(16'h1)) osc_inv2 (.I0(f[1]), .O(f[2]));
(* keep *) SB_LUT4 #(.LUT_INIT(16'h1)) osc_inv3 (.I0(f[2]), .O(f[3]));
(* keep *) SB_LUT4 #(.LUT_INIT(16'h1)) osc_inv4 (.I0(f[3]), .O(f[4]));
(* keep *) SB_LUT4 #(.LUT_INIT(16'h1)) osc_inv5 (.I0(f[4]), .O(f[5]));
(* keep *) SB_LUT4 #(.LUT_INIT(16'h1)) osc_inv6 (.I0(f[5]), .O(f[6]));
(* keep *) SB_LUT4 #(.LUT_INIT(16'h1)) osc_inv7 (.I0(f[6]), .O(f[7]));
(* keep *) SB_LUT4 #(.LUT_INIT(16'h1)) osc_inv8 (.I0(f[7]), .O(f[8]));
(* keep *) SB_LUT4 #(.LUT_INIT(16'h1)) osc_inv9 (.I0(f[8]), .O(f[9]));
(* keep *) SB_LUT4 #(.LUT_INIT(16'h1)) osc_inv10 (.I0(f[9]), .O(f[10]));
/* verilator lint_on PINMISSING */
//---------------------------------------------------------------
// parameterized feedback logic.
//---------------------------------------------------------------
assign f[0] = (POLY[0] & f[1]) ^ (POLY[1] & f[2]) ^
(POLY[2] & f[3]) ^ (POLY[3] & f[4]) ^
(POLY[4] & f[5]) ^ (POLY[5] & f[6]) ^
(POLY[6] & f[7]) ^ (POLY[7] & f[8]) ^
(POLY[8] & f[9]) ^ (POLY[9] & f[10]);
//----------------------------------------------------------------
// Concurrent connectivity for ports etc.
//----------------------------------------------------------------
assign entropy = entropy_reg;
//---------------------------------------------------------------
// reg_update
//---------------------------------------------------------------
always @(posedge clk)
begin : reg_update
entropy_reg <= ^f;
end
endmodule // firo
//======================================================================
// EOF firo.v
//======================================================================

View File

@ -1,90 +0,0 @@
//======================================================================
//
// garo.v
// ------
// GaloisRing Oscillator with state sampling.
// The Galois depth is 11 bits, and the bits are always sampled.
//
//
// Author: Joachim Strombergson
// Copyright (C) 2022 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
//
//======================================================================
`default_nettype none
module garo(
input wire clk,
output wire entropy
);
parameter POLY = 11'b11111111111;
//----------------------------------------------------------------
// Registers and wires.
//----------------------------------------------------------------
reg entropy_reg;
/* verilator lint_off UNOPTFLAT */
wire [11 : 0] g;
wire [11 : 0] gp;
/* verilator lint_on UNOPTFLAT */
//---------------------------------------------------------------
// Combinational loop inverters.
//---------------------------------------------------------------
/* verilator lint_off PINMISSING */
(* keep *) SB_LUT4 #(.LUT_INIT(16'h1)) osc_inv1 (.I0(g[0]), .O(gp[0]));
(* keep *) SB_LUT4 #(.LUT_INIT(16'h1)) osc_inv2 (.I0(g[1]), .O(gp[1]));
(* keep *) SB_LUT4 #(.LUT_INIT(16'h1)) osc_inv3 (.I0(g[2]), .O(gp[2]));
(* keep *) SB_LUT4 #(.LUT_INIT(16'h1)) osc_inv4 (.I0(g[3]), .O(gp[3]));
(* keep *) SB_LUT4 #(.LUT_INIT(16'h1)) osc_inv5 (.I0(g[4]), .O(gp[4]));
(* keep *) SB_LUT4 #(.LUT_INIT(16'h1)) osc_inv6 (.I0(g[5]), .O(gp[5]));
(* keep *) SB_LUT4 #(.LUT_INIT(16'h1)) osc_inv7 (.I0(g[6]), .O(gp[6]));
(* keep *) SB_LUT4 #(.LUT_INIT(16'h1)) osc_inv8 (.I0(g[7]), .O(gp[7]));
(* keep *) SB_LUT4 #(.LUT_INIT(16'h1)) osc_inv9 (.I0(g[8]), .O(gp[8]));
(* keep *) SB_LUT4 #(.LUT_INIT(16'h1)) osc_inv10 (.I0(g[9]), .O(gp[9]));
(* keep *) SB_LUT4 #(.LUT_INIT(16'h1)) osc_inv11 (.I0(g[10]), .O(gp[10]));
(* keep *) SB_LUT4 #(.LUT_INIT(16'h1)) osc_inv12 (.I0(g[11]), .O(gp[11]));
/* verilator lint_on PINMISSING */
//---------------------------------------------------------------
// parameterized feedback logic.
//---------------------------------------------------------------
assign g[11] = gp[0];
assign g[10] = gp[11] ^ (POLY[10] & gp[0]);
assign g[9] = gp[10] ^ (POLY[9] & gp[0]);
assign g[8] = gp[9] ^ (POLY[8] & gp[0]);
assign g[7] = gp[8] ^ (POLY[7] & gp[0]);
assign g[6] = gp[7] ^ (POLY[6] & gp[0]);
assign g[5] = gp[6] ^ (POLY[5] & gp[0]);
assign g[4] = gp[5] ^ (POLY[4] & gp[0]);
assign g[3] = gp[4] ^ (POLY[3] & gp[0]);
assign g[2] = gp[3] ^ (POLY[2] & gp[0]);
assign g[1] = gp[2] ^ (POLY[1] & gp[0]);
assign g[0] = gp[1] ^ (POLY[0] & gp[0]);
//----------------------------------------------------------------
// Concurrent connectivity for ports etc.
//----------------------------------------------------------------
assign entropy = entropy_reg;
//---------------------------------------------------------------
// reg_update
//---------------------------------------------------------------
always @(posedge clk)
begin : reg_update
entropy_reg <= ^g;
end
endmodule // garo
//======================================================================
// EOF garo.v
//======================================================================

View File

@ -1,8 +1,11 @@
//======================================================================
//
// figaro.v
// --------
// Top level wrapper for the figaro core.
// rosc.v
// ------
// Digital ring oscillator based entropy generator.
// Use this as a source of entropy, for example as seeds.
// Do **NOT** use directly as random number in any security
// related use cases.
//
//
// Author: Joachim Strombergson
@ -13,7 +16,7 @@
`default_nettype none
module figaro(
module rosc(
input wire clk,
input wire reset_n,
@ -298,8 +301,8 @@ module figaro(
endcase // case (rosc_ctrl_reg)
end
endmodule // figaro
endmodule // rosc
//======================================================================
// EOF figaro.v
// EOF rosc.v
//======================================================================

View File

@ -39,7 +39,6 @@ enum {
MTA1_MKDF_MMIO_TRNG_STATUS = MTA1_MKDF_MMIO_TRNG_BASE | 0x24,
MTA1_MKDF_MMIO_TRNG_STATUS_READY_BIT = 0,
MTA1_MKDF_MMIO_TRNG_SAMPLE_RATE = MTA1_MKDF_MMIO_TRNG_BASE | 0x40,
MTA1_MKDF_MMIO_TRNG_ENTROPY = MTA1_MKDF_MMIO_TRNG_BASE | 0x80,
MTA1_MKDF_MMIO_TIMER_CTRL = MTA1_MKDF_MMIO_TIMER_BASE | 0x20,

View File

@ -217,7 +217,7 @@ module application_fpga(
);
figaro trng_inst(
rosc trng_inst(
.clk(clk),
.reset_n(reset_n),
.cs(trng_cs),