diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/rtl/bp_osc.v | 103 | ||||
-rw-r--r-- | src/rtl/fpga_entropy.v | 281 | ||||
-rw-r--r-- | src/rtl/fpga_entropy_core.v | 196 | ||||
-rw-r--r-- | src/tb/tb_fpga_entropy_core.v | 208 |
4 files changed, 788 insertions, 0 deletions
diff --git a/src/rtl/bp_osc.v b/src/rtl/bp_osc.v new file mode 100644 index 0000000..42c0255 --- /dev/null +++ b/src/rtl/bp_osc.v @@ -0,0 +1,103 @@ +//====================================================================== +// +// bp_osc.v +// -------- +// Digital ring oscillator used as entropy source. Based on the +// idea of using carry chain in adders as inverter by Bernd Paysan. +// +// +// Author: Joachim Strombergson +// Copyright (c) 2014, Secworks Sweden AB +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or +// without modification, are permitted provided that the following +// conditions are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//====================================================================== + +module bp_osc #(parameter WIDTH = 8) + ( + input wire clk, + input wire reset_n, + + input wire [(WIDTH - 1) : 0] opa, + input wire [(WIDTH - 1) : 0] opb, + + output wire dout + ); + + //---------------------------------------------------------------- + // Registers. + //---------------------------------------------------------------- + reg dout_reg; + + + //---------------------------------------------------------------- + // Wires. + //---------------------------------------------------------------- + reg [WIDTH : 0] sum; + reg cin; + + + //---------------------------------------------------------------- + // Concurrent assignment. + //---------------------------------------------------------------- + assign dout = dout_reg; + + + //---------------------------------------------------------------- + // reg_update + //---------------------------------------------------------------- + always @ (posedge clk) + begin + if (!reset_n) + begin + dout_reg <= 1'b0; + end + else + begin + dout_reg <= cin; + end + end + + + //---------------------------------------------------------------- + // adder_osc + // + // Adder logic that generates the oscillator. + // + // NOTE: This logic contains a combinational loop and does + // not play well with an event driven simulator. + //---------------------------------------------------------------- + always @* + begin: adder_osc + cin = ~sum[WIDTH]; + sum = opa + opb + cin; + end +endmodule // bp_osc + +//====================================================================== +// EOF bp_osc.v +//====================================================================== diff --git a/src/rtl/fpga_entropy.v b/src/rtl/fpga_entropy.v new file mode 100644 index 0000000..2db2f97 --- /dev/null +++ b/src/rtl/fpga_entropy.v @@ -0,0 +1,281 @@ +//====================================================================== +// +// fpga_entropy.v +// -------------- +// Top level wrapper for the fpga entropy generator core. +// +// +// Author: Joachim Strombergson +// Copyright (c) 2014, Secworks Sweden AB +// +// Redistribution and use in source and binary forms, with or +// without modification, are permitted provided that the following +// conditions are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//====================================================================== + +module fpga_entropy( + input wire clk, + input wire reset_n, + + // API interface. + input wire cs, + input wire we, + input wire [7 : 0] address, + input wire [31 : 0] write_data, + output wire [31 : 0] read_data, + output wire error, + + // Debug output. + output wire [7 : 0] debug + ); + + + //---------------------------------------------------------------- + // Internal constant and parameter definitions. + //---------------------------------------------------------------- + // API addresses. + parameter ADDR_CORE_NAME0 = 8'h00; + parameter ADDR_CORE_NAME1 = 8'h01; + parameter ADDR_CORE_VERSION = 8'h02; + + parameter ADDR_UPDATE = 8'h10; + parameter ADDR_OPA = 8'h11; + + parameter ADDR_RND_READ = 8'h20; + + // Core ID constants. + parameter CORE_NAME0 = 32'h66706761; // "fpga" + parameter CORE_NAME1 = 32'h5f656e74; // "_ent" + parameter CORE_VERSION = 32'h302e3031; // "0.01" + + // Default value assigned to operand A. + // Operand B will be the inverse value of operand A. + parameter DEFAULT_OPA = 32'haaaaaaaa; + + // Delay in cycles between updating the debug port with + // a new random value sampled from the rng core port. + // Corresponds to about 1/20s with a clock @ 50 MHz. + parameter DELAY_MAX = 32'h002625a0; + + + //---------------------------------------------------------------- + // Registers including update variables and write enable. + //---------------------------------------------------------------- + reg [31 : 0] opa_reg; + reg [31 : 0] opb_reg; + reg [31 : 0] opa_new; + reg opa_we; + + reg update_reg; + reg update_new; + reg update_we; + + reg [31 : 0] delay_ctr_reg; + reg [31 : 0] delay_ctr_new; + + reg [7 : 0] debug_reg; + reg debug_we; + + + //---------------------------------------------------------------- + // Wires. + //---------------------------------------------------------------- + reg tmp_error; + reg [31 : 0] tmp_read_data; + wire [31 : 0] core_rnd; + + + //---------------------------------------------------------------- + // Concurrent connectivity for ports etc. + //---------------------------------------------------------------- + assign read_data = tmp_read_data; + assign error = tmp_error; + assign debug = debug_reg; + + + //---------------------------------------------------------------- + // core + // + // Instantiation of the uart core. + //---------------------------------------------------------------- + fpga_entropy_core core( + .clk(clk), + .reset_n(reset_n), + .opa(opa_reg), + .opb(opb_reg), + .update(update_reg), + .rnd(core_rnd) + ); + + + //---------------------------------------------------------------- + // reg_update + // + // Update functionality for all registers in the core. + // All registers are positive edge triggered with synchronous + // active low reset. All registers have write enable. + //---------------------------------------------------------------- + always @ (posedge clk) + begin: reg_update + if (!reset_n) + begin + opa_reg <= DEFAULT_OPA; + opb_reg <= ~DEFAULT_OPA; + update_reg <= 1; + debug_reg <= 8'h00; + end + else + begin + delay_ctr_reg <= delay_ctr_new; + + if (opa_we) + begin + opa_reg <= opa_new; + opb_reg <= ~opa_new; + end + + if (update_we) + begin + update_reg <= update_new; + end + + if (debug_we) + begin + debug_reg <= core_rnd[7 : 0]; + end + end + end // reg_update + + + //---------------------------------------------------------------- + // delay_ctr + // + // Simple counter that counts to DELAY_MAC. Used to slow down + // the debug port updates to human speeds. + //---------------------------------------------------------------- + always @* + begin : delay_ctr + debug_we = 0; + + if (delay_ctr_reg == DELAY_MAX) + begin + delay_ctr_new = 32'h00000000; + debug_we = 1; + end + else + begin + delay_ctr_new = delay_ctr_reg + 1'b1; + end + end // delay_ctr + + + //---------------------------------------------------------------- + // api + // + // The core API that allows an internal host to control the + // core functionality. + //---------------------------------------------------------------- + always @* + begin: api + // Default assignments. + opa_new = 32'h00000000; + opa_we = 0; + update_new = 0; + update_we = 0; + tmp_read_data = 32'h00000000; + tmp_error = 0; + + if (cs) + begin + if (we) + begin + // Write operations. + case (address) + ADDR_UPDATE: + begin + update_new = write_data[0]; + update_we = 1; + end + + ADDR_OPA: + begin + opa_new = write_data; + opa_we = 1; + end + + default: + begin + tmp_error = 1; + end + endcase // case (address) + end + else + begin + // Read operations. + case (address) + ADDR_CORE_NAME0: + begin + tmp_read_data = CORE_NAME0; + end + + ADDR_CORE_NAME1: + begin + tmp_read_data = CORE_NAME1; + end + + ADDR_CORE_VERSION: + begin + tmp_read_data = CORE_VERSION; + end + + ADDR_UPDATE: + begin + tmp_read_data = update_reg; + end + + ADDR_OPA: + begin + tmp_read_data = opa_reg; + end + + ADDR_RND_READ: + begin + tmp_read_data = core_rnd; + end + + default: + begin + tmp_error = 1; + end + endcase // case (address) + end + end + end + +endmodule // fpga_entropy + +//====================================================================== +// EOF fpga_entropy.v +//====================================================================== diff --git a/src/rtl/fpga_entropy_core.v b/src/rtl/fpga_entropy_core.v new file mode 100644 index 0000000..6c9ba6d --- /dev/null +++ b/src/rtl/fpga_entropy_core.v @@ -0,0 +1,196 @@ +//====================================================================== +// +// fpga_entropy_core.v +// ------------------- +// fpga entropy generation core. +// +// +// Author: Joachim Strombergson +// Copyright (c) 2014, Secworks Sweden AB +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or +// without modification, are permitted provided that the following +// conditions are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//====================================================================== + +module fpga_entropy_core( + // Clock and reset. + input wire clk, + input wire reset_n, + + input wire [31 : 0] opa, + input wire [31 : 0] opb, + input wire update, + + output wire [31 : 0] rnd + ); + + + //---------------------------------------------------------------- + // Registers including update variables and write enable. + //---------------------------------------------------------------- + reg [31 : 0] shift_reg; + reg shift_we; + reg [31 : 0] rnd_reg; + reg [4 : 0] bit_ctr_reg; + reg rnd_ctr_reg; + + reg bit0_reg; + reg bit1_reg; + reg bit_new; + + + //---------------------------------------------------------------- + // Wires. + //---------------------------------------------------------------- + wire dout02; + wire dout03; + wire dout07; + wire dout13; + wire dout41; + wire dout43; + + + //---------------------------------------------------------------- + // Concurrent connectivity for ports etc. + //---------------------------------------------------------------- + assign rnd = rnd_reg; + + + //---------------------------------------------------------------- + // module instantiations. + //---------------------------------------------------------------- + bp_osc #(.WIDTH(2)) osc02(.clk(clk), + .reset_n(reset_n), + .opa(opa[1 : 0]), + .opb(opb[1 : 0]), + .dout(dout02) + ); + + bp_osc #(.WIDTH(3)) osc03(.clk(clk), + .reset_n(reset_n), + .opa(opa[2 : 0]), + .opb(opb[2 : 0]), + .dout(dout03) + ); + + bp_osc #(.WIDTH(7)) osc07(.clk(clk), + .reset_n(reset_n), + .opa(opa[6 : 0]), + .opb(opb[6 : 0]), + .dout(dout07) + ); + + bp_osc #(.WIDTH(13)) osc13(.clk(clk), + .reset_n(reset_n), + .opa(opa[12 : 0]), + .opb(opb[12 : 0]), + .dout(dout13) + ); + + bp_osc #(.WIDTH(41)) osc41(.clk(clk), + .reset_n(reset_n), + .opa({opa[8 : 0], opa[31 : 0]}), + .opb({opb[8 : 0], opb[31 : 0]}), + .dout(dout41) + ); + + bp_osc #(.WIDTH(43)) osc43(.clk(clk), + .reset_n(reset_n), + .opa({opa[10 : 0], opa[31 : 0]}), + .opb({opb[10 : 0], opb[31 : 0]}), + .dout(dout43) + ); + + + //---------------------------------------------------------------- + // reg_update + // + // Update functionality for all registers in the core. + // All registers are positive edge triggered with synchronous + // active low reset. All registers have write enable. + //---------------------------------------------------------------- + always @ (posedge clk) + begin + if (!reset_n) + begin + shift_reg <= 32'h00000000; + rnd_reg <= 32'h00000000; + bit_ctr_reg <= 5'h00; + rnd_ctr_reg <= 1'b0; + bit0_reg <= 1'b0; + bit1_reg <= 1'b0; + end + else + begin + rnd_ctr_reg <= ~rnd_ctr_reg; + + if (rnd_ctr_reg) + begin + bit0_reg <= bit_new; + end + + if (!rnd_ctr_reg) + begin + bit1_reg <= bit_new; + end + + if (shift_we) + begin + shift_reg <= {shift_reg[30 : 0], bit0_reg}; + bit_ctr_reg <= bit_ctr_reg + 1'b1; + end + + if (bit_ctr_reg == 5'h1f) + begin + rnd_reg <= shift_reg; + end + end + end // reg_update + + + //---------------------------------------------------------------- + // rnd_gen + // + // Logic that implements the actual random bit value generator + // Note: This logic also performs von Neumann decorrelation. + //---------------------------------------------------------------- + always @* + begin : rnd_gen + shift_we = 1'b0; + bit_new = dout02 ^ dout03 ^ dout07 ^ dout13 ^ dout41 ^ dout43; + + if (update && rnd_ctr_reg) + begin + shift_we = bit0_reg ^ bit1_reg; + end + end + +endmodule // fpga_entropy_core + +//====================================================================== +// EOF fpga_entropy_core.v +//====================================================================== diff --git a/src/tb/tb_fpga_entropy_core.v b/src/tb/tb_fpga_entropy_core.v new file mode 100644 index 0000000..31696b8 --- /dev/null +++ b/src/tb/tb_fpga_entropy_core.v @@ -0,0 +1,208 @@ +//====================================================================== +// +// tb_fpga_entropy.v +// ----------------- +// Testbench for the FPGA Entropy generator core. +// +// +// Author: Joachim Strombergson +// Copyright (c) 2014, Secworks Sweden AB +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or +// without modification, are permitted provided that the following +// conditions are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//====================================================================== + +//------------------------------------------------------------------ +// Simulator directives. +//------------------------------------------------------------------ +`timescale 1ns/10ps + + +module tb_fpga_entropy(); + + //---------------------------------------------------------------- + // Internal constant and parameter definitions. + //---------------------------------------------------------------- + parameter DEBUG = 1; + parameter VERBOSE = 0; + + parameter CLK_HALF_PERIOD = 1; + parameter CLK_PERIOD = CLK_HALF_PERIOD * 2; + + + //---------------------------------------------------------------- + // Register and Wire declarations. + //---------------------------------------------------------------- + reg [31 : 0] cycle_ctr; + reg [31 : 0] error_ctr; + reg [31 : 0] tc_ctr; + + reg tb_clk; + reg tb_reset_n; + reg tb_init; + reg tb_update; + reg tb_seed; + wire [31 : 0] tb_rnd; + + + //---------------------------------------------------------------- + // Device Under Test. + //---------------------------------------------------------------- + fpga_entropy_core dut( + // Clock and reset. + .clk(), + .reset_n(), + + .init(tb_init), + .update(tb_update), + .seed(tb_seed), + + .rnd(tb_rnd) + ); + + + //---------------------------------------------------------------- + // clk_gen + // + // Clock generator process. + //---------------------------------------------------------------- + always + begin : clk_gen + #CLK_HALF_PERIOD tb_clk = !tb_clk; + end // clk_gen + + + //---------------------------------------------------------------- + // sys_monitor + // + // System monitor. Can display status about the dut and TB + // every cycle. + //---------------------------------------------------------------- + always + begin : sys_monitor + #(CLK_PERIOD); + if (DEBUG) + begin + dump_dut_state(); + $display(""); + end + + if (VERBOSE) + begin + $display("cycle: 0x%016x", cycle_ctr); + end + cycle_ctr = cycle_ctr + 1; + end + + + //---------------------------------------------------------------- + // dump_dut_state() + // + // Dump the state of the dut when needed. + //---------------------------------------------------------------- + task dump_dut_state(); + begin + $display("State of DUT"); + $display("------------"); + $display("Inputs and outputs:"); + $display("init = 0x%01x, update = 0x%01x, seed = 0x%01x", + tb_init, tb_update, tb_seed); + $display("rnd= 0x%08x", tb_rnd); + $display(""); + + $display("Internal values:"); + $display("shift_reg = 0x%08x, rnd_reg = 0x%08x, bit_ctr_reg = 0x%02x", + dut.shift_reg, dut.rnd_reg, dut.bit_ctr_reg); + + $display("l5d = 0x%01x, l7d = 0x%01x, l13d = 0x%01x, l41d = 0x01x, l43d = 0x%01x", + dut.l5d, dut.l7d, dut.l13d, dut.l41d, dut.l43d); + $display(""); + end + endtask // dump_dut_state + + + //---------------------------------------------------------------- + // reset_dut() + //---------------------------------------------------------------- + task reset_dut(); + begin + $display("*** Toggle reset."); + tb_reset_n = 0; + #(2 * CLK_PERIOD); + tb_reset_n = 1; + end + endtask // reset_dut + + + //---------------------------------------------------------------- + // init_sim() + // + // Initialize all counters and testbed functionality as well + // as setting the DUT inputs to defined values. + //---------------------------------------------------------------- + task init_sim(); + begin + cycle_ctr = 0; + error_ctr = 0; + tc_ctr = 0; + + tb_clk = 0; + tb_reset_n = 1; + tb_init = 1; + tb_seed = 1; + tb_update = 0; + end + endtask // init_sim + + + //---------------------------------------------------------------- + // fpga_entropy_test + // + // The main test functionality. + //---------------------------------------------------------------- + initial + begin : fpga_entropy_test + $display(" -- Testbench for fpga entropy core started --"); + + init_sim(); + dump_dut_state(); + reset_dut(); + dump_dut_state(); + + tb_update = 1; + #(64 * CLK_PERIOD); + tb_init = 0; + #(1000 * CLK_PERIOD); + + $display("*** Simulation done. ***"); + $finish; + end // fpga_entropy_test +endmodule // tb_fpga_entropy + +//====================================================================== +// EOF tb_fpga_entropy.v +//====================================================================== |