aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/rtl/external_avalanche_entropy.v383
1 files changed, 320 insertions, 63 deletions
diff --git a/src/rtl/external_avalanche_entropy.v b/src/rtl/external_avalanche_entropy.v
index df72b3a..3f1c3f9 100644
--- a/src/rtl/external_avalanche_entropy.v
+++ b/src/rtl/external_avalanche_entropy.v
@@ -13,83 +13,147 @@
//
// Author: Joachim Strombergson
// Copyright (c) 2011, NORDUnet A/S All rights reserved.
-//
+//
// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions
+// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
-//
-// * 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
+//
+// * 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.
-//
-// * Neither the name of the NORDUnet nor the names of its
-// contributors may be used to endorse or promote products
-// derived from this software without specific prior written
+//
+// * Neither the name of the NORDUnet nor the names of its
+// contributors may be used to endorse or promote products
+// derived from this software without specific prior written
// permission.
-//
-// 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 HOLDER 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
+//
+// 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 HOLDER 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 external_avalanche_entropy(
- input wire clk,
- input wire reset_n,
+ input wire clk,
+ input wire reset_n,
+
+ 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,
+
+ input wire noise,
+
+ input wire entropy_read,
+ output wire entropy_ready,
+ output wire [31 : 0] entropy_data,
+ output wire [7 : 0] debug
+ );
- input wire noise,
-
- output wire [7 : 0] debug
- );
//----------------------------------------------------------------
// Internal constant and parameter definitions.
//----------------------------------------------------------------
- parameter DEBUG_RATE = 32'h00300000;
-
-
+ parameter ADDR_STATUS = 8'h00;
+ parameter ADDR_ENTROPY = 8'h10;
+ parameter ADDR_POS_FLANKS = 8'h20;
+ parameter ADDR_NEG_FLANKS = 8'h21;
+ parameter ADDR_TOT_FLANKS = 8'h22;
+
+ parameter DEBUG_RATE = 32'h00300000;
+ parameter SECONDS_RATE = 32'h02faf080;
+
+
//----------------------------------------------------------------
// Registers including update variables and write enable.
//----------------------------------------------------------------
- reg noise_sample0_reg;
- reg noise_sample_reg;
+ reg noise_sample0_reg;
+ reg noise_sample_reg;
- reg flank0_reg;
- reg flank1_reg;
+ reg flank0_reg;
+ reg flank1_reg;
reg [31 : 0] cycle_ctr_reg;
+ reg [31 : 0] seconds_ctr_reg;
+ reg [31 : 0] seconds_ctr_new;
+
+ reg [5 : 0] bit_ctr_reg;
+ reg [5 : 0] bit_ctr_new;
+ reg bit_ctr_inc;
+ reg bit_ctr_rst;
+ reg bit_ctr_we;
+
reg [31 : 0] entropy_reg;
reg [31 : 0] entropy_new;
reg entropy_we;
-
+
+ reg entropy_ready_reg;
+ reg entropy_ready_new;
+
reg [31 : 0] debug_ctr_reg;
reg [31 : 0] debug_ctr_new;
reg debug_ctr_we;
-
- reg [7 : 0] debug_reg;
- reg [7 : 0] debug_new;
- reg debug_we;
-
+ reg [7 : 0] debug_reg;
+ reg [7 : 0] debug_new;
+ reg debug_we;
+
+ reg [31 : 0] posflank_ctr_reg;
+ reg [31 : 0] posflank_ctr_new;
+ reg posflank_ctr_rst;
+ reg posflank_ctr_we;
+
+ reg [31 : 0] negflank_ctr_reg;
+ reg [31 : 0] negflank_ctr_new;
+ reg negflank_ctr_rst;
+ reg negflank_ctr_we;
+
+ reg [31 : 0] posflank_sample_reg;
+ reg [31 : 0] posflank_sample_new;
+ reg posflank_sample_we;
+
+ reg [31 : 0] negflank_sample_reg;
+ reg [31 : 0] negflank_sample_new;
+ reg negflank_sample_we;
+
+ reg [31 : 0] totflank_sample_reg;
+ reg [31 : 0] totflank_sample_new;
+ reg totflank_sample_we;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg [31 : 0] tmp_read_data;
+ reg tmp_error;
+
+
//----------------------------------------------------------------
// Concurrent connectivity for ports etc.
//----------------------------------------------------------------
- assign debug = debug_reg;
-
-
+ assign entropy_ready = entropy_ready_reg;
+ assign entropy_data = entropy_reg;
+ assign debug = debug_reg;
+
+ assign read_data = tmp_read_data;
+ assign error = tmp_error;
+
+
//----------------------------------------------------------------
// reg_update
//----------------------------------------------------------------
@@ -97,25 +161,42 @@ module external_avalanche_entropy(
begin
if (!reset_n)
begin
- noise_sample_reg <= 1'b0;
- flank0_reg <= 1'b0;
- flank1_reg <= 1'b0;
- cycle_ctr_reg <= 32'h00000000;
- debug_ctr_reg <= 32'h00000000;
- entropy_reg <= 32'h00000000;
- debug_reg <= 8'h00;
+ noise_sample0_reg <= 1'b0;
+ noise_sample_reg <= 1'b0;
+ flank0_reg <= 1'b0;
+ flank1_reg <= 1'b0;
+ debug_reg <= 8'h00;
+ entropy_ready_reg <= 1'b0;
+ entropy_reg <= 32'h00000000;
+ cycle_ctr_reg <= 32'h00000000;
+ seconds_ctr_reg <= 32'h00000000;
+ debug_ctr_reg <= 32'h00000000;
+ bit_ctr_reg <= 6'h00;
+ posflank_ctr_reg <= 32'h00000000;
+ negflank_ctr_reg <= 32'h00000000;
+ posflank_sample_reg <= 32'h00000000;
+ negflank_sample_reg <= 32'h00000000;
+ totflank_sample_reg <= 32'h00000000;
end
else
begin
noise_sample0_reg <= noise;
- noise_sample_reg <= noise_sample0_reg;
+ noise_sample_reg <= noise_sample0_reg;
+
+ flank0_reg <= noise_sample_reg;
+ flank1_reg <= flank0_reg;
+
+ entropy_ready_reg <= entropy_ready_new;
- flank0_reg <= noise_sample_reg;
- flank1_reg <= flank0_reg;
+ cycle_ctr_reg <= cycle_ctr_reg + 1'b1;
+ seconds_ctr_reg <= cycle_ctr_reg + 1'b1;
+ debug_ctr_reg <= debug_ctr_new;
+
+ if (bit_ctr_we)
+ begin
+ bit_ctr_reg <= bit_ctr_new;
+ end
- cycle_ctr_reg <= cycle_ctr_reg + 1'b1;
- debug_ctr_reg <= debug_ctr_new;
-
if (entropy_we)
begin
entropy_reg <= entropy_new;
@@ -125,6 +206,31 @@ module external_avalanche_entropy(
begin
debug_reg <= debug_new;
end
+
+ if (posflank_ctr_we)
+ begin
+ posflank_ctr_reg <= posflank_ctr_new;
+ end
+
+ if (negflank_ctr_we)
+ begin
+ posflank_ctr_reg <= posflank_ctr_new;
+ end
+
+ if (posflank_sample_we)
+ begin
+ posflank_sample_reg <= posflank_sample_new;
+ end
+
+ if (negflank_sample_we)
+ begin
+ negflank_sample_reg <= negflank_sample_new;
+ end
+
+ if (totflank_sample_we)
+ begin
+ totflank_sample_reg <= totflank_sample_new;
+ end
end
end // reg_update
@@ -132,23 +238,55 @@ module external_avalanche_entropy(
//----------------------------------------------------------------
// entropy_collect
//
- // This is where we collect entropy by adding the LSB of the
- // cycle counter to the entropy shift register every time
- // we detect a positive flank at the noise source.
+ // We collect entropy by adding the LSB of the cycle counter to
+ // the entropy shift register every time we detect a positive
+ // flank in the noise source.
//----------------------------------------------------------------
always @*
begin : entropy_collect
entropy_new = 32'h00000000;
entropy_we = 1'b0;
+ bit_ctr_inc = 1'b0;
- // Update the entropy shift register every positive flank.
if ((flank0_reg) && (!flank1_reg))
begin
entropy_new = {entropy_reg[30 : 0], cycle_ctr_reg[0]};
entropy_we = 1'b1;
+ bit_ctr_inc = 1'b1;
end
end // entropy_collect
-
+
+
+ //----------------------------------------------------------------
+ // entropy_read_logic
+ //
+ // The logic needed to handle detection that entropy has been
+ // read and ensure that we collect more than 32 entropy
+ // bits beforeproviding more entropy.
+ //----------------------------------------------------------------
+ always @*
+ begin : entropy_read_logic
+ bit_ctr_new = 6'h00;
+ bit_ctr_we = 1'b0;
+ entropy_ready_new = 1'b0;
+
+ if (bit_ctr_reg == 6'h20)
+ begin
+ entropy_ready_new = 1'b1;
+ end
+
+ if ((bit_ctr_inc) && (bit_ctr_reg < 6'h20))
+ begin
+ bit_ctr_new = bit_ctr_reg + 1'b1;
+ bit_ctr_we = 1'b1;
+ end
+ else if (entropy_read || bit_ctr_rst)
+ begin
+ bit_ctr_new = 6'h00;
+ bit_ctr_we = 1'b1;
+ end
+ end // entropy_read_logic
+
//----------------------------------------------------------------
// debug_update
@@ -168,7 +306,126 @@ module external_avalanche_entropy(
debug_we = 1'b1;
end
end // debug_update
-
+
+
+ //----------------------------------------------------------------
+ // flank_counters
+ //----------------------------------------------------------------
+ always @*
+ begin : flank_counters
+ posflank_ctr_new = 32'h00000000;
+ posflank_ctr_we = 1'b0;
+ negflank_ctr_new = 32'h00000000;
+ negflank_ctr_we = 1'b0;
+
+ if ((flank0_reg) && (!flank1_reg))
+ begin
+ posflank_ctr_new = posflank_ctr_reg + 1'b1;
+ posflank_ctr_we = 1'b0;
+ end
+
+ if ((!flank0_reg) && (flank1_reg))
+ begin
+ negflank_ctr_new = negflank_ctr_reg + 1'b1;
+ negflank_ctr_we = 1'b0;
+ end
+ end // flank_counters
+
+
+ //----------------------------------------------------------------
+ // stats_updates
+ //
+ // Update the statistics counters once every second.
+ //----------------------------------------------------------------
+ always @*
+ begin : stats_update
+ seconds_ctr_new = seconds_ctr_reg + 1'b1;
+ posflank_sample_new = 32'h00000000;
+ posflank_sample_we = 1'b0;
+ negflank_sample_new = 32'h00000000;
+ negflank_sample_we = 1'b0;
+ totflank_sample_new = 32'h00000000;
+ totflank_sample_we = 1'b0;
+ posflank_ctr_rst = 1'b0;
+ negflank_ctr_rst = 1'b0;
+
+ if (seconds_ctr_reg == SECONDS_RATE)
+ begin
+ seconds_ctr_new = 32'h00000000;
+ posflank_sample_new = posflank_ctr_reg;
+ negflank_sample_new = negflank_ctr_reg;
+ totflank_sample_new = posflank_ctr_reg + negflank_ctr_reg;
+ posflank_sample_we = 1'b1;
+ negflank_sample_we = 1'b1;
+ totflank_sample_we = 1'b1;
+ posflank_ctr_rst = 1'b1;
+ negflank_ctr_rst = 1'b1;
+ end
+ end // stats_update
+
+
+ //----------------------------------------------------------------
+ // api_logic
+ //----------------------------------------------------------------
+ always @*
+ begin : api_logic
+ tmp_read_data = 32'h00000000;
+ tmp_error = 1'b0;
+ bit_ctr_rst = 1'b1;
+
+ if (cs)
+ begin
+ if (we)
+ begin
+ case (address)
+ // Write operations.
+
+ default:
+ begin
+ tmp_error = 1;
+ end
+ endcase // case (address)
+ end // if (we)
+
+ else
+ begin
+ case (address)
+ // Read operations.
+ ADDR_STATUS:
+ begin
+ tmp_read_data = {31'h00000000, entropy_ready_reg};
+ end
+
+ ADDR_ENTROPY:
+ begin
+ tmp_read_data = entropy_reg;
+ bit_ctr_rst = 1'b1;
+ end
+
+ ADDR_POS_FLANKS:
+ begin
+ tmp_read_data = posflank_sample_reg;
+ end
+
+ ADDR_NEG_FLANKS:
+ begin
+ tmp_read_data = negflank_sample_reg;
+ end
+
+ ADDR_TOT_FLANKS:
+ begin
+ tmp_read_data = totflank_sample_reg;
+ end
+
+ default:
+ begin
+ tmp_error = 1;
+ end
+ endcase // case (address)
+ end // else: !if(we)
+ end // if (cs)
+ end // api_logic
+
endmodule // external_avalanche_entropy
//======================================================================