//====================================================================== // // trng.v // -------- // Top level wrapper for the True Random Number Generator. // // // Author: Joachim Strombergson // Copyright (c) 2014, SUNET // 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 trng( // Clock and reset. input wire clk, input wire reset_n, input wire avalanche_noise, input wire cs, input wire we, input wire [11 : 0] address, input wire [31 : 0] write_data, output wire [31 : 0] read_data, output wire error, output wire [7 : 0] debug, input wire debug_update, output wire security_error ); //---------------------------------------------------------------- // Internal constant and parameter definitions. //---------------------------------------------------------------- localparam TRNG_PREFIX = 4'h0; localparam ENTROPY1_PREFIX = 4'h5; localparam ENTROPY2_PREFIX = 4'h6; localparam MIXER_PREFIX = 4'ha; localparam CSPRNG_PREFIX = 4'hb; localparam DEBUG_ENTROPY0 = 3'h0; localparam DEBUG_ENTROPY1 = 3'h1; localparam DEBUG_ENTROPY2 = 3'h2; localparam DEBUG_MIXER = 3'h3; localparam DEBUG_CSPRNG = 3'h4; localparam ADDR_NAME0 = 8'h00; localparam ADDR_NAME1 = 8'h01; localparam ADDR_VERSION = 8'h02; localparam ADDR_TRNG_CTRL = 8'h08; localparam TRNG_CTRL_DISCARD_BIT = 0; localparam TRNG_CTRL_TEST_MODE_BIT = 1; localparam ADDR_TRNG_STATUS = 8'h09; localparam ADDR_DEBUG_CTRL = 8'h12; localparam ADDR_DEBUG_DELAY = 8'h13; localparam TRNG_NAME0 = 32'h74726e67; // "trng" localparam TRNG_NAME1 = 32'h20202020; // " " localparam TRNG_VERSION = 32'h302e3531; // "0.51" // 20x/s @ 50 MHz. localparam DEFAULT_DEBUG_DELAY = 32'h002625a0; //---------------------------------------------------------------- // Registers including update variables and write enable. //---------------------------------------------------------------- reg discard_reg; reg discard_new; reg test_mode_reg; reg test_mode_new; reg test_mode_we; reg [7 : 0] debug_out_reg; reg debug_out_we; reg [2 : 0] debug_mux_reg; reg [2 : 0] debug_mux_new; reg debug_mux_we; reg [31 : 0] debug_delay_ctr_reg; reg [31 : 0] debug_delay_ctr_new; reg debug_delay_ctr_we; reg [31 : 0] debug_delay_reg; reg [31 : 0] debug_delay_new; reg debug_delay_we; //---------------------------------------------------------------- // Wires. //---------------------------------------------------------------- wire trng_api_cs = cs && (addr_core_num == TRNG_PREFIX); wire trng_api_we = we; reg [31 : 0] trng_api_read_data; reg trng_api_error; wire mixer_more_seed; wire [511 : 0] mixer_seed_data; wire mixer_seed_syn; wire mixer_seed_ack; wire mixer_api_cs = cs && (addr_core_num == MIXER_PREFIX); wire mixer_api_we = we; wire [31 : 0] mixer_api_read_data; wire mixer_api_error; wire mixer_security_error; wire [7 : 0] mixer_debug; reg mixer_debug_update; wire csprng_more_seed; wire csprng_seed_ack; wire csprng_api_cs = cs && (addr_core_num == CSPRNG_PREFIX); wire csprng_api_we = we; wire [31 : 0] csprng_api_read_data; wire csprng_api_error; wire [7 : 0] csprng_debug; reg csprng_debug_update; wire csprng_security_error; wire entropy0_entropy_enabled; wire [31 : 0] entropy0_entropy_data; wire entropy0_entropy_syn; wire entropy0_entropy_ack; wire entropy1_api_cs = cs && (addr_core_num == ENTROPY1_PREFIX); wire entropy1_api_we = we; wire [31 : 0] entropy1_api_read_data; wire entropy1_api_error; wire entropy1_entropy_enabled; wire [31 : 0] entropy1_entropy_data; wire entropy1_entropy_syn; wire entropy1_entropy_ack; //wire entropy1_test_mode; wire [7 : 0] entropy1_debug; reg entropy1_debug_update; wire entropy1_security_error; wire entropy2_api_cs = cs && (addr_core_num == ENTROPY2_PREFIX); wire entropy2_api_we = we; wire [31 : 0] entropy2_api_read_data; wire entropy2_api_error; wire entropy2_entropy_enabled; wire [31 : 0] entropy2_entropy_data; wire entropy2_entropy_syn; wire entropy2_entropy_ack; //wire entropy2_test_mode; wire [7 : 0] entropy2_debug; reg entropy2_debug_update; wire entropy2_security_error; wire [7 : 0] api_address = addr_core_reg; reg [31 : 0] tmp_read_data; reg tmp_error; reg [7 : 0] tmp_debug; //---------------------------------------------------------------- // Concurrent connectivity for ports etc. //---------------------------------------------------------------- assign read_data = tmp_read_data; assign error = tmp_error; assign security_error = entropy1_security_error | entropy2_security_error; assign debug = debug_out_reg; // Patches to get our first version to work. assign entropy0_entropy_enabled = 0; assign entropy0_entropy_syn = 0; assign entropy0_entropy_data = 32'h00000000; //---------------------------------------------------------------- // Address Decoder //---------------------------------------------------------------- // upper 4 bits specify core being addressed. wire [3 : 0] addr_core_num = address[11 : 8]; // lower 8 bits specify register offset in core. wire [7 : 0] addr_core_reg = address[7 : 0]; //---------------------------------------------------------------- // core instantiations. //---------------------------------------------------------------- trng_mixer mixer_inst( .clk(clk), .reset_n(reset_n), .cs(mixer_api_cs), .we(mixer_api_we), .address(api_address), .write_data(write_data), .read_data(mixer_api_read_data), .error(mixer_api_error), .discard(discard_reg), .test_mode(test_mode_reg), .security_error(mixer_security_error), .more_seed(csprng_more_seed), .entropy0_enabled(entropy0_entropy_enabled), .entropy0_syn(entropy0_entropy_syn), .entropy0_data(entropy0_entropy_data), .entropy0_ack(entropy0_entropy_ack), .entropy1_enabled(entropy1_entropy_enabled), .entropy1_syn(entropy1_entropy_syn), .entropy1_data(entropy1_entropy_data), .entropy1_ack(entropy1_entropy_ack), .entropy2_enabled(entropy2_entropy_enabled), .entropy2_syn(entropy2_entropy_syn), .entropy2_data(entropy2_entropy_data), .entropy2_ack(entropy2_entropy_ack), .seed_data(mixer_seed_data), .seed_syn(mixer_seed_syn), .seed_ack(csprng_seed_ack), .debug(mixer_debug), .debug_update(mixer_debug_update) ); trng_csprng csprng_inst( .clk(clk), .reset_n(reset_n), .cs(csprng_api_cs), .we(csprng_api_we), .address(api_address), .write_data(write_data), .read_data(csprng_api_read_data), .error(csprng_api_error), .discard(discard_reg), .test_mode(test_mode_reg), .security_error(csprng_security_error), .more_seed(csprng_more_seed), .seed_data(mixer_seed_data), .seed_syn(mixer_seed_syn), .seed_ack(csprng_seed_ack), .debug(csprng_debug), .debug_update(csprng_debug_update) ); avalanche_entropy entropy1( .clk(clk), .reset_n(reset_n), .noise(avalanche_noise), .cs(entropy1_api_cs), .we(entropy1_api_we), .address(api_address), .write_data(write_data), .read_data(entropy1_api_read_data), .error(entropy1_api_error), .discard(discard_reg), .test_mode(test_mode_reg), .security_error(entropy1_security_error), .entropy_enabled(entropy1_entropy_enabled), .entropy_data(entropy1_entropy_data), .entropy_valid(entropy1_entropy_syn), .entropy_ack(entropy1_entropy_ack), .debug(entropy1_debug), .debug_update(entropy1_debug_update) ); rosc_entropy entropy2( .clk(clk), .reset_n(reset_n), .cs(entropy2_api_cs), .we(entropy2_api_we), .address(api_address), .write_data(write_data), .read_data(entropy2_api_read_data), .error(entropy2_api_error), .discard(discard_reg), .test_mode(test_mode_reg), .security_error(entropy2_security_error), .entropy_enabled(entropy2_entropy_enabled), .entropy_data(entropy2_entropy_data), .entropy_valid(entropy2_entropy_syn), .entropy_ack(entropy2_entropy_ack), .debug(entropy2_debug), .debug_update(entropy2_debug_update) ); //---------------------------------------------------------------- // reg_update // // Update functionality for all registers in the core. // All registers are positive edge triggered with asynchronous // active low reset. //---------------------------------------------------------------- always @ (posedge clk or negedge reset_n) begin if (!reset_n) begin discard_reg <= 0; test_mode_reg <= 0; debug_mux_reg <= DEBUG_CSPRNG; debug_delay_reg <= DEFAULT_DEBUG_DELAY; debug_delay_ctr_reg <= 32'h00000000; debug_out_reg <= 8'h00; end else begin discard_reg <= discard_new; debug_delay_ctr_reg <= debug_delay_ctr_new; if (debug_out_we) debug_out_reg <= tmp_debug; if (test_mode_we) test_mode_reg <= test_mode_new; if (debug_mux_we) debug_mux_reg <= debug_mux_new; if (debug_delay_we) debug_delay_reg <= debug_delay_new; end end // reg_update //---------------------------------------------------------------- // core_mux // // This is a simple decoder that looks at the top 4 bits of // the given api address and selects which of the sub modules // or the top level mux that gets to handle any API // operations. //---------------------------------------------------------------- always @* begin : core_mux case (address[11 : 8]) TRNG_PREFIX: begin tmp_read_data = trng_api_read_data; tmp_error = trng_api_error; end ENTROPY1_PREFIX: begin tmp_read_data = entropy1_api_read_data; tmp_error = entropy1_api_error; end ENTROPY2_PREFIX: begin tmp_read_data = entropy2_api_read_data; tmp_error = entropy2_api_error; end MIXER_PREFIX: begin tmp_read_data = mixer_api_read_data; tmp_error = mixer_api_error; end CSPRNG_PREFIX: begin tmp_read_data = csprng_api_read_data; tmp_error = csprng_api_error; end default: begin tmp_read_data = {32{1'b0}}; tmp_error = 0; end endcase // case (address[11 : 8]) end // core_mux //---------------------------------------------------------------- // debug_update_logic // // Debug update counter and update logic. //---------------------------------------------------------------- always @* begin : debug_update_logic if (debug_delay_ctr_reg == debug_delay_reg) begin debug_out_we = 1; debug_delay_ctr_new = 32'h00000000; end else begin debug_out_we = 0; debug_delay_ctr_new = debug_delay_ctr_reg + 1'b1; end end // debug_update //---------------------------------------------------------------- // debug_mux // // Select which of the sub modules that are connected to // the debug port. //---------------------------------------------------------------- always @* begin : debug_mux entropy1_debug_update = 0; entropy2_debug_update = 0; mixer_debug_update = 0; csprng_debug_update = 0; tmp_debug = 8'h00; case(debug_mux_reg) DEBUG_ENTROPY1: begin entropy1_debug_update = debug_update; tmp_debug = entropy1_debug; end DEBUG_ENTROPY2: begin entropy2_debug_update = debug_update; tmp_debug = entropy2_debug; end DEBUG_MIXER: begin mixer_debug_update = debug_update; tmp_debug = mixer_debug; end DEBUG_CSPRNG: begin csprng_debug_update = debug_update; tmp_debug = csprng_debug; end default: begin end endcase // case (debug_mux_reg) end // debug_mux //---------------------------------------------------------------- // trng_api_logic // // Implementation of the top level api logic. //---------------------------------------------------------------- always @* begin : trng_api_logic discard_new = 0; test_mode_new = 0; test_mode_we = 0; debug_mux_new = 3'h0; debug_mux_we = 0; debug_delay_new = 32'h00000000; debug_delay_we = 0; trng_api_read_data = 32'h00000000; trng_api_error = 0; if (trng_api_cs) begin if (trng_api_we) begin case (api_address) ADDR_TRNG_CTRL: begin discard_new = write_data[TRNG_CTRL_DISCARD_BIT]; test_mode_new = write_data[TRNG_CTRL_TEST_MODE_BIT]; test_mode_we = 1; end ADDR_DEBUG_CTRL: begin debug_mux_new = write_data[2 : 0]; debug_mux_we = 1; end ADDR_DEBUG_DELAY: begin debug_delay_new = write_data; debug_delay_we = 1; end default: trng_api_error = 1; endcase // case (address) end // if (we) else begin case (api_address) ADDR_NAME0: trng_api_read_data = TRNG_NAME0; ADDR_NAME1: trng_api_read_data = TRNG_NAME1; ADDR_VERSION: trng_api_read_data = TRNG_VERSION; ADDR_TRNG_CTRL: trng_api_read_data = {30'h0000000, test_mode_reg, discard_reg}; ADDR_TRNG_STATUS: begin // No error caused by reading status. end ADDR_DEBUG_CTRL: trng_api_read_data = {29'h0000000, debug_mux_new}; ADDR_DEBUG_DELAY: trng_api_read_data = debug_delay_reg; default: trng_api_error = 1; endcase // case (address) end end end // trng_api_logic endmodule // trng //====================================================================== // EOF trng.v //======================================================================