diff --git a/doc/system_description/software.md b/doc/system_description/software.md index bc6c29b..f8690c2 100644 --- a/doc/system_description/software.md +++ b/doc/system_description/software.md @@ -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 | diff --git a/hw/application_fpga/Makefile b/hw/application_fpga/Makefile index e87e222..f653e1a 100644 --- a/hw/application_fpga/Makefile +++ b/hw/application_fpga/Makefile @@ -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 \ diff --git a/hw/application_fpga/core/trng/rtl/figaro_core.v b/hw/application_fpga/core/trng/rtl/figaro_core.v deleted file mode 100644 index 1698146..0000000 --- a/hw/application_fpga/core/trng/rtl/figaro_core.v +++ /dev/null @@ -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 -//====================================================================== diff --git a/hw/application_fpga/core/trng/rtl/firo.v b/hw/application_fpga/core/trng/rtl/firo.v deleted file mode 100644 index 5125c02..0000000 --- a/hw/application_fpga/core/trng/rtl/firo.v +++ /dev/null @@ -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 -//====================================================================== diff --git a/hw/application_fpga/core/trng/rtl/garo.v b/hw/application_fpga/core/trng/rtl/garo.v deleted file mode 100644 index 74808fe..0000000 --- a/hw/application_fpga/core/trng/rtl/garo.v +++ /dev/null @@ -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 -//====================================================================== diff --git a/hw/application_fpga/core/trng/rtl/figaro.v b/hw/application_fpga/core/trng/rtl/rosc.v similarity index 92% rename from hw/application_fpga/core/trng/rtl/figaro.v rename to hw/application_fpga/core/trng/rtl/rosc.v index e72caf8..ec032f2 100644 --- a/hw/application_fpga/core/trng/rtl/figaro.v +++ b/hw/application_fpga/core/trng/rtl/rosc.v @@ -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,19 +16,19 @@ `default_nettype none -module figaro( - input wire clk, - input wire reset_n, +module rosc( + input wire clk, + input wire reset_n, - input wire cs, - input wire we, - input wire [7 : 0] address, - /* verilator lint_off UNUSED */ - input wire [31 : 0] write_data, - /* verilator lint_on UNUSED */ - output wire [31 : 0] read_data, - output wire ready - ); + input wire cs, + input wire we, + input wire [7 : 0] address, + /* verilator lint_off UNUSED */ + input wire [31 : 0] write_data, + /* verilator lint_on UNUSED */ + output wire [31 : 0] read_data, + output wire ready + ); //---------------------------------------------------------------- @@ -298,8 +301,8 @@ module figaro( endcase // case (rosc_ctrl_reg) end -endmodule // figaro +endmodule // rosc //====================================================================== -// EOF figaro.v +// EOF rosc.v //====================================================================== diff --git a/hw/application_fpga/fw/mta1_mkdf_mem.h b/hw/application_fpga/fw/mta1_mkdf_mem.h index 47463ef..b66af7c 100644 --- a/hw/application_fpga/fw/mta1_mkdf_mem.h +++ b/hw/application_fpga/fw/mta1_mkdf_mem.h @@ -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, diff --git a/hw/application_fpga/rtl/application_fpga.v b/hw/application_fpga/rtl/application_fpga.v index e95c442..6049ba4 100644 --- a/hw/application_fpga/rtl/application_fpga.v +++ b/hw/application_fpga/rtl/application_fpga.v @@ -217,7 +217,7 @@ module application_fpga( ); - figaro trng_inst( + rosc trng_inst( .clk(clk), .reset_n(reset_n), .cs(trng_cs),