diff options
-rw-r--r-- | src/rtl/trng.v | 121 | ||||
-rw-r--r-- | src/rtl/trng_csprng.v | 61 | ||||
-rw-r--r-- | src/rtl/trng_csprng_fifo.v | 181 | ||||
-rw-r--r-- | src/rtl/trng_mixer.v | 46 | ||||
-rw-r--r-- | src/tb/tb_csprng.v | 105 | ||||
-rw-r--r-- | src/tb/tb_csprng_fifo.v | 199 |
6 files changed, 495 insertions, 218 deletions
diff --git a/src/rtl/trng.v b/src/rtl/trng.v index 9e8bf69..7a15e7e 100644 --- a/src/rtl/trng.v +++ b/src/rtl/trng.v @@ -76,17 +76,18 @@ module trng( localparam ADDR_NAME1 = 8'h01; localparam ADDR_VERSION = 8'h02; - localparam ADDR_TRNG_CTRL = 8'h10; + localparam ADDR_TRNG_CTRL = 8'h08; localparam TRNG_CTRL_DISCARD_BIT = 0; localparam TRNG_CTRL_TEST_MODE_BIT = 1; - localparam ADDR_TRNG_STATUS = 8'h11; + 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'h302e3530; // "0.50" + localparam TRNG_VERSION = 32'h302e3531; // "0.51" // 20x/s @ 50 MHz. localparam DEFAULT_DEBUG_DELAY = 32'h002625a0; @@ -329,6 +330,44 @@ module trng( //---------------------------------------------------------------- + // 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 @@ -379,44 +418,6 @@ module trng( //---------------------------------------------------------------- - // 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 - - - //---------------------------------------------------------------- // debug_update_logic // // Debug update counter and update logic. @@ -505,9 +506,7 @@ module trng( begin if (trng_api_we) begin - // Write operations. case (api_address) - // Write operations. ADDR_TRNG_CTRL: begin discard_new = write_data[TRNG_CTRL_DISCARD_BIT]; @@ -528,60 +527,42 @@ module trng( end default: - begin - trng_api_error = 1; - end + trng_api_error = 1; endcase // case (address) end // if (we) else begin - // Read operations. case (api_address) - // Read operations. ADDR_NAME0: - begin - trng_api_read_data = TRNG_NAME0; - end + trng_api_read_data = TRNG_NAME0; ADDR_NAME1: - begin - trng_api_read_data = TRNG_NAME1; - end + trng_api_read_data = TRNG_NAME1; ADDR_VERSION: - begin - trng_api_read_data = TRNG_VERSION; - end + trng_api_read_data = TRNG_VERSION; ADDR_TRNG_CTRL: - begin - end + 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: - begin - trng_api_read_data = {29'h0000000, debug_mux_new}; - end + trng_api_read_data = {29'h0000000, debug_mux_new}; ADDR_DEBUG_DELAY: - begin - trng_api_read_data = debug_delay_reg; - end + trng_api_read_data = debug_delay_reg; default: - begin - trng_api_error = 1; - end + trng_api_error = 1; endcase // case (address) end end end // trng_api_logic - endmodule // trng //====================================================================== diff --git a/src/rtl/trng_csprng.v b/src/rtl/trng_csprng.v index ce5c89c..d33e72a 100644 --- a/src/rtl/trng_csprng.v +++ b/src/rtl/trng_csprng.v @@ -49,7 +49,7 @@ module trng_csprng( output wire error, input wire discard, - input test_mode, + input wire test_mode, output wire more_seed, output wire security_error, @@ -78,6 +78,7 @@ module trng_csprng( localparam ADDR_STAT_BLOCKS_LOW = 8'h14; localparam ADDR_STAT_BLOCKS_HIGH = 8'h15; + localparam ADDR_STAT_RESEEDS = 8'h16; localparam ADDR_RND_DATA = 8'h20; @@ -103,7 +104,7 @@ module trng_csprng( localparam ADDR_TEST_SEED_W15 = 8'h8f; localparam CIPHER_KEYLEN256 = 1'b1; // 256 bit key. - localparam CIPHER_MAX_BLOCKS = 64'h1000000000000000; + localparam CIPHER_MAX_BLOCKS = 64'h0000000100000000; localparam CTRL_IDLE = 4'h0; localparam CTRL_SEED0 = 4'h1; @@ -117,7 +118,7 @@ module trng_csprng( localparam CTRL_CANCEL = 4'hf; localparam DEFAULT_NUM_ROUNDS = 5'h18; - localparam DEFAULT_NUM_BLOCKS = 64'h1000000000000000; + localparam DEFAULT_NUM_BLOCKS = 64'h0000000001000000; parameter CORE_NAME0 = 32'h63737072; // "cspr" parameter CORE_NAME1 = 32'h6e672020; // "ng " @@ -152,6 +153,12 @@ module trng_csprng( reg [63 : 0] block_stat_ctr_reg; reg [63 : 0] block_stat_ctr_new; + reg block_stat_ctr_we; + + reg [31 : 0] reseed_stat_ctr_reg; + reg [31 : 0] reseed_stat_ctr_new; + reg reseed_stat_ctr_inc; + reg reseed_stat_ctr_we; reg ready_reg; reg ready_new; @@ -279,6 +286,7 @@ module trng_csprng( cipher_block_reg <= {16{32'h00000000}}; block_ctr_reg <= {2{32'h00000000}}; block_stat_ctr_reg <= {2{32'h00000000}}; + reseed_stat_ctr_reg <= 32'h00000000; more_seed_reg <= 0; seed_ack_reg <= 0; ready_reg <= 0; @@ -313,9 +321,16 @@ module trng_csprng( if (block_ctr_we) begin block_ctr_reg <= block_ctr_new; + end + + if (block_stat_ctr_we) + begin block_stat_ctr_reg <= block_stat_ctr_new; end + if (reseed_stat_ctr_we) + reseed_stat_ctr_reg <= reseed_stat_ctr_new; + if (ready_we) ready_reg <= ready_new; @@ -421,6 +436,9 @@ module trng_csprng( ADDR_STAT_BLOCKS_HIGH: tmp_read_data = block_stat_ctr_reg[63 : 32]; + ADDR_STAT_RESEEDS: + tmp_read_data = reseed_stat_ctr_reg; + ADDR_RND_DATA: begin tmp_read_data = rnd_data; @@ -453,7 +471,7 @@ module trng_csprng( // ability to detect that maximum allowed number of blocks // has been reached. Either as defined by the application // or the hard coded CIPHER_MAX_BLOCKS value. - + // // The stat counter is a sepatate block counter updated in // sync with the block counter. It is only used to track the // number of blocks generated from the cipher as a metric @@ -465,6 +483,7 @@ module trng_csprng( block_ctr_we = 1'b0; block_ctr_max = 1'b0; block_stat_ctr_new = {2{32'h00000000}}; + block_stat_ctr_we = 1'b0; if (block_ctr_rst) begin @@ -475,8 +494,9 @@ module trng_csprng( if (block_ctr_inc) begin block_ctr_new = block_ctr_reg + 1'b1; - block_stat_ctr_new = block_stat_ctr_reg + 1'b1; block_ctr_we = 1; + block_stat_ctr_new = block_stat_ctr_reg + 1'b1; + block_stat_ctr_we = 1; end if ((block_ctr_reg == {num_blocks_high_reg, num_blocks_low_reg}) || @@ -488,6 +508,27 @@ module trng_csprng( //---------------------------------------------------------------- + // reseed_ctr + // + // A simple monotonically increasing counter that counts the + // number of times the CSPRNG has been reseeded. is reseeded. + // Note that the counter is 32-bit and it is up to SW to handle + // wrap around issues. + //---------------------------------------------------------------- + always @* + begin : reseed_ctr + reseed_stat_ctr_new = 32'h00000000; + reseed_stat_ctr_we = 0; + + if (reseed_stat_ctr_inc) + begin + reseed_stat_ctr_new = reseed_stat_ctr_reg + 1'b1; + reseed_stat_ctr_we = 1; + end + end // reseed_ctr + + + //---------------------------------------------------------------- // csprng_ctrl_fsm // // Control FSM for the CSPRNG. @@ -512,6 +553,7 @@ module trng_csprng( more_seed_new = 0; fifo_discard = 0; fifo_cipher_data_valid = 0; + reseed_stat_ctr_inc = 0; csprng_ctrl_new = CTRL_IDLE; csprng_ctrl_we = 0; @@ -597,10 +639,11 @@ module trng_csprng( end else begin - cipher_init = 1; - block_ctr_rst = 1; - csprng_ctrl_new = CTRL_INIT1; - csprng_ctrl_we = 1; + reseed_stat_ctr_inc = 1; + cipher_init = 1; + block_ctr_rst = 1; + csprng_ctrl_new = CTRL_INIT1; + csprng_ctrl_we = 1; end end diff --git a/src/rtl/trng_csprng_fifo.v b/src/rtl/trng_csprng_fifo.v index 1f91802..e3fe4fb 100644 --- a/src/rtl/trng_csprng_fifo.v +++ b/src/rtl/trng_csprng_fifo.v @@ -56,11 +56,12 @@ module trng_csprng_fifo( // Internal constant and parameter definitions. //---------------------------------------------------------------- localparam FIFO_ADDR_BITS = 2; - localparam FIFO_ADDR_MAX = FIFO_ADDR_BITS - 1; - localparam FIFO_MAX = (2 ** FIFO_ADDR_BITS) - 1; + localparam FIFO_ADDR_MAX = (2**FIFO_ADDR_BITS) - 1; + localparam FIFO_MAX = (2 ** FIFO_ADDR_BITS); localparam WR_IDLE = 0; - localparam WR_STORE = 1; + localparam WR_WAIT = 1; + localparam WR_NEXT = 2; localparam WR_DISCARD = 7; localparam RD_IDLE = 0; @@ -71,7 +72,7 @@ module trng_csprng_fifo( //---------------------------------------------------------------- // Registers including update variables and write enable. //---------------------------------------------------------------- - reg [511 : 0] fifo_mem [0 : FIFO_MAX]; + reg [511 : 0] fifo_mem [0 : FIFO_ADDR_MAX]; reg fifo_mem_we; reg [3 : 0] mux_data_ptr_reg; @@ -80,26 +81,26 @@ module trng_csprng_fifo( reg mux_data_ptr_rst; reg mux_data_ptr_we; - reg [FIFO_ADDR_MAX : 0] rd_ptr_reg; - reg [FIFO_ADDR_MAX : 0] rd_ptr_new; - reg rd_ptr_inc; - reg rd_ptr_rst; - reg rd_ptr_we; - - reg [FIFO_ADDR_MAX : 0] wr_ptr_reg; - reg [FIFO_ADDR_MAX : 0] wr_ptr_new; - reg wr_ptr_inc; - reg wr_ptr_rst; - reg wr_ptr_we; - - reg [FIFO_ADDR_MAX : 0] fifo_ctr_reg; - reg [FIFO_ADDR_MAX : 0] fifo_ctr_new; - reg fifo_ctr_inc; - reg fifo_ctr_dec; - reg fifo_ctr_rst; - reg fifo_ctr_we; - reg fifo_empty; - reg fifo_full; + reg [(FIFO_ADDR_BITS - 1) : 0] rd_ptr_reg; + reg [(FIFO_ADDR_BITS - 1) : 0] rd_ptr_new; + reg rd_ptr_inc; + reg rd_ptr_rst; + reg rd_ptr_we; + + reg [(FIFO_ADDR_BITS - 1) : 0] wr_ptr_reg; + reg [(FIFO_ADDR_BITS - 1) : 0] wr_ptr_new; + reg wr_ptr_inc; + reg wr_ptr_rst; + reg wr_ptr_we; + + reg [FIFO_ADDR_BITS : 0] fifo_ctr_reg; + reg [FIFO_ADDR_BITS : 0] fifo_ctr_new; + reg fifo_ctr_inc; + reg fifo_ctr_dec; + reg fifo_ctr_rst; + reg fifo_ctr_we; + reg fifo_empty; + reg fifo_full; reg [31 : 0] rnd_data_reg; @@ -117,6 +118,7 @@ module trng_csprng_fifo( reg more_data_reg; reg more_data_new; + reg more_data_we; //---------------------------------------------------------------- @@ -147,8 +149,8 @@ module trng_csprng_fifo( fifo_mem[02] <= {16{32'h00000000}}; fifo_mem[03] <= {16{32'h00000000}}; mux_data_ptr_reg <= 4'h0; - rd_ptr_reg <= {FIFO_ADDR_BITS{1'b0}}; - wr_ptr_reg <= {FIFO_ADDR_BITS{1'b0}}; + rd_ptr_reg <= {(FIFO_ADDR_BITS){1'b0}}; + wr_ptr_reg <= {(FIFO_ADDR_BITS){1'b0}}; fifo_ctr_reg <= {FIFO_ADDR_BITS{1'b0}}; rnd_data_reg <= 32'h00000000; rnd_syn_reg <= 0; @@ -158,48 +160,34 @@ module trng_csprng_fifo( end else begin - rnd_data_reg <= muxed_data; - more_data_reg <= more_data_new; + rnd_data_reg <= muxed_data; + + if (more_data_we) + more_data_reg <= more_data_new; if (rnd_syn_we) - begin - rnd_syn_reg <= rnd_syn_new; - end + rnd_syn_reg <= rnd_syn_new; if (fifo_mem_we) - begin - fifo_mem[wr_ptr_reg] <= csprng_data; - end + fifo_mem[wr_ptr_reg] <= csprng_data; if (mux_data_ptr_we) - begin - mux_data_ptr_reg <= mux_data_ptr_new; - end + mux_data_ptr_reg <= mux_data_ptr_new; if (rd_ptr_we) - begin - rd_ptr_reg <= rd_ptr_new; - end + rd_ptr_reg <= rd_ptr_new; if (wr_ptr_we) - begin - wr_ptr_reg <= wr_ptr_new; - end + wr_ptr_reg <= wr_ptr_new; if (fifo_ctr_we) - begin - fifo_ctr_reg <= fifo_ctr_new; - end + fifo_ctr_reg <= fifo_ctr_new; if (rd_ctrl_we) - begin - rd_ctrl_reg <= rd_ctrl_new; - end + rd_ctrl_reg <= rd_ctrl_new; if (wr_ctrl_we) - begin - wr_ctrl_reg <= wr_ctrl_new; - end + wr_ctrl_reg <= wr_ctrl_new; end end // reg_update @@ -257,18 +245,16 @@ module trng_csprng_fifo( fifo_ctr_dec = 0; if (rd_ptr_rst) - rd_ptr_we = 1; + begin + rd_ptr_new = {FIFO_ADDR_BITS{1'b0}}; + rd_ptr_we = 1; + end if (rd_ptr_inc) begin - fifo_ctr_dec = 1; - if (rd_ptr_reg == FIFO_MAX) - rd_ptr_we = 1; - else - begin - rd_ptr_new = rd_ptr_reg + 1'b1; - rd_ptr_we = 1; - end + fifo_ctr_dec = 1; + rd_ptr_new = rd_ptr_reg + 1'b1; + rd_ptr_we = 1; end end // fifo_rd_ptr @@ -280,21 +266,21 @@ module trng_csprng_fifo( //---------------------------------------------------------------- always @* begin : fifo_wr_ptr - wr_ptr_new = {FIFO_ADDR_BITS{1'b0}}; - wr_ptr_we = 0; + wr_ptr_new = {FIFO_ADDR_BITS{1'b0}}; + wr_ptr_we = 0; + fifo_ctr_inc = 0; if (wr_ptr_rst) - wr_ptr_we = 1; + begin + wr_ptr_new = {FIFO_ADDR_BITS{1'b0}}; + wr_ptr_we = 1; + end if (wr_ptr_inc) begin - if (wr_ptr_reg == FIFO_MAX) - wr_ptr_we = 1; - else - begin - wr_ptr_new = wr_ptr_reg + 1'b1; - wr_ptr_we = 1; - end + fifo_ctr_inc = 1; + wr_ptr_new = wr_ptr_reg + 1'b1; + wr_ptr_we = 1; end end // fifo_wr_ptr @@ -310,7 +296,7 @@ module trng_csprng_fifo( //---------------------------------------------------------------- always @* begin : fifo_ctr - fifo_ctr_new = {FIFO_ADDR_BITS{1'b0}}; + fifo_ctr_new = {(FIFO_ADDR_BITS + 1){1'b0}}; fifo_ctr_we = 0; fifo_empty = 0; fifo_full = 0; @@ -326,15 +312,18 @@ module trng_csprng_fifo( end if (fifo_ctr_rst) - fifo_ctr_we = 1; + begin + fifo_ctr_new = {(FIFO_ADDR_BITS + 1){1'b0}}; + fifo_ctr_we = 1; + end - if ((fifo_ctr_inc) && (fifo_ctr_reg < FIFO_MAX)) + if (fifo_ctr_inc) begin fifo_ctr_new = fifo_ctr_reg + 1'b1; fifo_ctr_we = 1; end - if ((fifo_ctr_dec) && (fifo_ctr_reg > 0)) + if (fifo_ctr_dec) begin fifo_ctr_new = fifo_ctr_reg - 1'b1; fifo_ctr_we = 1; @@ -429,9 +418,9 @@ module trng_csprng_fifo( wr_ptr_inc = 0; wr_ptr_rst = 0; fifo_mem_we = 0; - fifo_ctr_inc = 0; fifo_ctr_rst = 0; more_data_new = 0; + more_data_we = 0; wr_ctrl_new = WR_IDLE; wr_ctrl_we = 0; @@ -448,31 +437,43 @@ module trng_csprng_fifo( if (!fifo_full) begin more_data_new = 1'b1; + more_data_we = 1'b1; + wr_ctrl_new = WR_WAIT; + wr_ctrl_we = 1; end - - if (csprng_data_valid) + else begin - wr_ctrl_new = WR_STORE; - wr_ctrl_we = 1; + more_data_new = 1'b0; + more_data_we = 1'b1; end end end - WR_STORE: + WR_WAIT: begin - fifo_mem_we = 1; - wr_ptr_inc = 1; - fifo_ctr_inc = 1; - wr_ctrl_new = WR_IDLE; - wr_ctrl_we = 1; + if (csprng_data_valid) + begin + fifo_mem_we = 1; + wr_ptr_inc = 1; + wr_ctrl_new = WR_NEXT; + wr_ctrl_we = 1; + end + end + + WR_NEXT: + begin + more_data_new = 1'b0; + more_data_we = 1'b1; + wr_ctrl_new = WR_IDLE; + wr_ctrl_we = 1; end WR_DISCARD: begin - fifo_ctr_rst = 1; - wr_ptr_rst = 1; - wr_ctrl_new = WR_IDLE; - wr_ctrl_we = 1; + fifo_ctr_rst = 1; + wr_ptr_rst = 1; + wr_ctrl_new = WR_IDLE; + wr_ctrl_we = 1; end endcase // case (wr_ctrl_reg) end // wr_ctrl diff --git a/src/rtl/trng_mixer.v b/src/rtl/trng_mixer.v index 97777ac..d192090 100644 --- a/src/rtl/trng_mixer.v +++ b/src/rtl/trng_mixer.v @@ -80,34 +80,36 @@ module trng_mixer( //---------------------------------------------------------------- // Internal constant and parameter definitions. //---------------------------------------------------------------- - parameter MODE_SHA_512 = 2'h3; - - parameter ENTROPY_IDLE = 4'h0; - parameter ENTROPY_SRC0 = 4'h1; - parameter ENTROPY_SRC0_ACK = 4'h2; - parameter ENTROPY_SRC1 = 4'h3; - parameter ENTROPY_SRC1_ACK = 4'h4; - parameter ENTROPY_SRC2 = 4'h5; - parameter ENTROPY_SRC2_ACK = 4'h6; - - parameter CTRL_IDLE = 4'h0; - parameter CTRL_COLLECT = 4'h1; - parameter CTRL_MIX = 4'h2; - parameter CTRL_SYN = 4'h3; - parameter CTRL_ACK = 4'h4; - parameter CTRL_NEXT = 4'h5; + localparam MODE_SHA_512 = 2'h3; + + localparam ENTROPY_IDLE = 4'h0; + localparam ENTROPY_SRC0 = 4'h1; + localparam ENTROPY_SRC0_ACK = 4'h2; + localparam ENTROPY_SRC1 = 4'h3; + localparam ENTROPY_SRC1_ACK = 4'h4; + localparam ENTROPY_SRC2 = 4'h5; + localparam ENTROPY_SRC2_ACK = 4'h6; + localparam TEST_ENTROPY = 4'he; + localparam TEST_ENTROPY_ACK = 4'hf; + + localparam CTRL_IDLE = 4'h0; + localparam CTRL_COLLECT = 4'h1; + localparam CTRL_MIX = 4'h2; + localparam CTRL_SYN = 4'h3; + localparam CTRL_ACK = 4'h4; + localparam CTRL_NEXT = 4'h5; localparam ADDR_NAME0 = 8'h00; localparam ADDR_NAME1 = 8'h01; localparam ADDR_VERSION = 8'h02; - parameter ADDR_MIXER_CTRL = 8'h10; - parameter MIXER_CTRL_ENABLE_BIT = 0; - parameter MIXER_CTRL_RESTART_BIT = 1; - parameter ADDR_MIXER_STATUS = 8'h11; - parameter ADDR_MIXER_TIMEOUT = 8'h20; + localparam ADDR_MIXER_CTRL = 8'h10; + localparam MIXER_CTRL_ENABLE_BIT = 0; + localparam MIXER_CTRL_RESTART_BIT = 1; + localparam ADDR_MIXER_STATUS = 8'h11; + localparam ADDR_MIXER_TIMEOUT = 8'h20; - parameter DEFAULT_ENTROPY_TIMEOUT = 24'h100000; + localparam DEFAULT_ENTROPY_TIMEOUT = 24'h100000; parameter CORE_NAME0 = 32'h726e676d; // "rngm" parameter CORE_NAME1 = 32'h69786572; // "ixer" diff --git a/src/tb/tb_csprng.v b/src/tb/tb_csprng.v index 0404b56..bd84489 100644 --- a/src/tb/tb_csprng.v +++ b/src/tb/tb_csprng.v @@ -50,7 +50,7 @@ module tb_csprng(); //---------------------------------------------------------------- // Internal constant and parameter definitions. //---------------------------------------------------------------- - parameter DEBUG = 1; + parameter DEBUG = 0; parameter CLK_HALF_PERIOD = 1; parameter CLK_PERIOD = 2 * CLK_HALF_PERIOD; @@ -68,6 +68,7 @@ module tb_csprng(); localparam ADDR_STAT_BLOCKS_LOW = 8'h14; localparam ADDR_STAT_BLOCKS_HIGH = 8'h15; + localparam ADDR_STAT_RESEEDS = 8'h16; localparam ADDR_RND_DATA = 8'h20; @@ -109,6 +110,7 @@ module tb_csprng(); reg tb_debug_update; reg [31 : 0] read_data; + reg [7 : 0] pbyte; //---------------------------------------------------------------- @@ -127,10 +129,9 @@ module tb_csprng(); .discard(tb_discard), .test_mode(tb_test_mode), - - .more_seed(tb_more_seed), .security_error(tb_security_error), + .more_seed(tb_more_seed), .seed_data(tb_seed_data), .seed_syn(tb_seed_syn), .seed_ack(tb_seed_ack), @@ -210,11 +211,6 @@ module tb_csprng(); dut.cipher_inst.ready, dut.cipher_inst.data_out_valid); $display("cipher data out: 0x%064x", dut.cipher_inst.data_out); $display(""); - - $display("Outputs:"); - $display("rnd_syn = 0x%01x, rnd_ack = 0x%01x, rnd_data = 0x%08x", - dut.rnd_syn, dut.rnd_ack, tb_read_data); - $display(""); end endtask // dump_dut_state @@ -237,6 +233,7 @@ module tb_csprng(); tb_write_data = word; tb_cs = 1; tb_we = 1; + #(2 * CLK_PERIOD); tb_cs = 0; tb_we = 0; @@ -330,14 +327,68 @@ module tb_csprng(); tb_test_mode = 0; tb_seed_syn = 0; - tb_seed_data = {16{32'h00000000}}; + tb_seed_data = {8{64'h0000000000000000}}; tb_rnd_ack = 0; tb_debug_update = 0; + + pbyte = 8'h00; end endtask // init_sim //---------------------------------------------------------------- + // seed_generator + // + // When a seed_syn is observed this process will provide a new + // seed to the DUT, assert SYN, wait for ACK and then update + // the seed pattern state. + //---------------------------------------------------------------- + always @ (posedge tb_more_seed) + begin : seed_generator + #(CLK_PERIOD); + tb_seed_data = {64{pbyte}}; + tb_seed_syn = 1'b1; + + while (!tb_seed_ack) + #(CLK_PERIOD); + + tb_seed_syn = 1'b0; + pbyte = pbyte + 8'h01; + end + + + //---------------------------------------------------------------- + // read_rng_data() + // + // Support task that reads a given number of data words + // from the DUT via the API. + //---------------------------------------------------------------- + task read_rng_data(input [31 : 0] num_words); + reg [31 : 0] i; + begin + i = 32'h00000000; + + $display("*** Trying to read 0x%08x RNG data words", num_words); + while (i < num_words) + begin + tb_cs = 1'b1; + tb_we = 1'b0; + tb_address = ADDR_RND_DATA; + i = i + 1; + + #CLK_PERIOD; + + if (DEBUG) + $display("*** RNG data word 0x%08x: 0x%08x", i, tb_read_data); + end + + tb_cs = 1'b0; + $display("*** Reading of RNG data words completed."); + end + endtask // read_rng_data + + + //---------------------------------------------------------------- // tc1_init_csprng() // // TC1: Test that the DUT automatically starts initialize when @@ -353,11 +404,8 @@ module tb_csprng(); tb_seed_data = {8{64'haaaaaaaa55555555}}; tb_seed_syn = 1'b1; - tb_cs = 1'b1; - tb_we = 1'b0; - tb_address = ADDR_RND_DATA; - - #(200 * CLK_PERIOD); + // Start pulling data. + read_rng_data(32'h100); $display("*** TC1: Test automatic init of csprng done."); end @@ -365,6 +413,32 @@ module tb_csprng(); //---------------------------------------------------------------- + // tc2_reseed_csprng() + // + // TC2: Test that the CSPRNG is reseeded as expected. + // We set the max block size to a small value and pull data. + //---------------------------------------------------------------- + task tc2_reseed_csprng(); + begin + tc_ctr = tc_ctr + 1; + + $display("*** TC2: Test reseed of CSPRNG started."); + + tb_seed_data = {8{64'h0102030405060708}}; + tb_seed_syn = 1'b1; + + // Set the max number of blocks to a low value + write_word(ADDR_NUM_BLOCKS_HIGH, 32'h00000000); + write_word(ADDR_NUM_BLOCKS_LOW, 32'h00000007); + + read_rng_data(32'h10000); + + $display("*** TC2 done.."); + end + endtask // tc2_reseed_csprng + + + //---------------------------------------------------------------- // csprng_test // // The main test functionality. @@ -381,7 +455,8 @@ module tb_csprng(); reset_dut(); dump_dut_state(); - tc1_init_csprng(); +// tc1_init_csprng(); + tc2_reseed_csprng(); display_test_results(); diff --git a/src/tb/tb_csprng_fifo.v b/src/tb/tb_csprng_fifo.v index 91044a5..a2db466 100644 --- a/src/tb/tb_csprng_fifo.v +++ b/src/tb/tb_csprng_fifo.v @@ -50,7 +50,7 @@ module tb_csprng_fifo(); //---------------------------------------------------------------- // Internal constant and parameter definitions. //---------------------------------------------------------------- - parameter DEBUG = 1; + parameter DEBUG = 0; parameter CLK_HALF_PERIOD = 1; parameter CLK_PERIOD = 2 * CLK_HALF_PERIOD; @@ -143,9 +143,39 @@ module tb_csprng_fifo(); $display("cycle: 0x%016x", cycle_ctr); $display("State of DUT"); $display("------------"); + $display("inputs:"); + $display("more_data = 0x%01x, data_valid = 0x%01x", + tb_more_data, tb_csprng_data_valid); + $display("input_data = 0x%0128x", tb_csprng_data); + $display(""); + $display("outputs:"); $display("rnd_syn = 0x%01x, rnd_ack = 0x%01x, rnd_data = 0x%08x", tb_rnd_syn, tb_rnd_ack, tb_rnd_data); $display(""); + $display("internals:"); + $display("rd_ptr = 0x%02x, wr_ptr = 0x%02x, fifo_ctr = 0x%02x, mux_ptr = 0x%02x", + dut.rd_ptr_reg, dut.wr_ptr_reg, dut.fifo_ctr_reg, dut.mux_data_ptr_reg); + $display("fifo_empty = 0x%01x, fifo_full = 0x%01x", dut.fifo_empty, dut.fifo_full); + $display(""); + end + endtask // dump_dut_state + + + //---------------------------------------------------------------- + // dump_fifo() + // + // Dump the state of the fifo when needed. + //---------------------------------------------------------------- + task dump_fifo(); + begin + $display("contents of the fifo"); + $display("--------------------"); + $display("fifo_mem[0] = 0x%0128x", dut.fifo_mem[0]); + $display("fifo_mem[1] = 0x%0128x", dut.fifo_mem[1]); + $display("fifo_mem[2] = 0x%0128x", dut.fifo_mem[2]); + $display("fifo_mem[3] = 0x%0128x", dut.fifo_mem[3]); + $display(""); + $display(""); end endtask // dump_dut_state @@ -156,15 +186,15 @@ module tb_csprng_fifo(); // Generate test data with distinct patterns as requested // by the dut. //---------------------------------------------------------------- - always @ (posedge tb_more_data) - begin - for (i = 0 ; i < 16 ; i = i + 1) - tb_csprng_data[i * 32 +: 32] = tb_csprng_data[i * 32 +: 32] + 32'h10101010; - - tb_csprng_data_valid = 1'b1; - #(2 * CLK_PERIOD); - tb_csprng_data_valid = 1'b0; - end +// always @ (posedge tb_more_data) +// begin +// for (i = 0 ; i < 16 ; i = i + 1) +// tb_csprng_data[i * 32 +: 32] = tb_csprng_data[i * 32 +: 32] + 32'h10101010; +// +// tb_csprng_data_valid = 1'b1; +// #(2 * CLK_PERIOD); +// tb_csprng_data_valid = 1'b0; +// end //---------------------------------------------------------------- @@ -225,15 +255,156 @@ module tb_csprng_fifo(); tb_write_data = 32'h00000000; tb_discard = 0; - tb_rnd_ack = 1; + tb_rnd_ack = 0; for (i = 0 ; i < 16 ; i = i + 1) - tb_csprng_data[i * 32 +: 32] = {i, i, i, i}; + tb_csprng_data[i * 32 +: 32] = 32'h0; + tb_csprng_data_valid = 0; end endtask // init_sim //---------------------------------------------------------------- + // wait_more_data() + // + // Wait for the DUT to signal that it wants more data. + //---------------------------------------------------------------- + task wait_more_data(); + begin + while (!tb_more_data) + #(CLK_PERIOD); + end + endtask // wait_more_data + + + //---------------------------------------------------------------- + // write_w512() + // + // Writes a 512 bit data word into the fifo. + //---------------------------------------------------------------- + task write_w512(input [7 : 0] b); + reg [511 : 0] w512; + reg [31 : 0] w00; + reg [31 : 0] w01; + reg [31 : 0] w02; + reg [31 : 0] w03; + reg [31 : 0] w04; + reg [31 : 0] w05; + reg [31 : 0] w06; + reg [31 : 0] w07; + reg [31 : 0] w08; + reg [31 : 0] w09; + reg [31 : 0] w10; + reg [31 : 0] w11; + reg [31 : 0] w12; + reg [31 : 0] w13; + reg [31 : 0] w14; + reg [31 : 0] w15; + begin + w00 = {(b + 8'd15), (b + 8'd15), (b + 8'd15), (b + 8'd15)}; + w01 = {(b + 8'd14), (b + 8'd14), (b + 8'd14), (b + 8'd14)}; + w02 = {(b + 8'd13), (b + 8'd13), (b + 8'd13), (b + 8'd13)}; + w03 = {(b + 8'd12), (b + 8'd12), (b + 8'd12), (b + 8'd12)}; + w04 = {(b + 8'd11), (b + 8'd11), (b + 8'd11), (b + 8'd11)}; + w05 = {(b + 8'd10), (b + 8'd10), (b + 8'd10), (b + 8'd10)}; + w06 = {(b + 8'd09), (b + 8'd09), (b + 8'd09), (b + 8'd09)}; + w07 = {(b + 8'd08), (b + 8'd08), (b + 8'd08), (b + 8'd08)}; + + w08 = {(b + 8'd07), (b + 8'd07), (b + 8'd07), (b + 8'd07)}; + w09 = {(b + 8'd06), (b + 8'd06), (b + 8'd06), (b + 8'd06)}; + w10 = {(b + 8'd05), (b + 8'd05), (b + 8'd05), (b + 8'd05)}; + w11 = {(b + 8'd04), (b + 8'd04), (b + 8'd04), (b + 8'd04)}; + w12 = {(b + 8'd03), (b + 8'd03), (b + 8'd03), (b + 8'd03)}; + w13 = {(b + 8'd02), (b + 8'd02), (b + 8'd02), (b + 8'd02)}; + w14 = {(b + 8'd01), (b + 8'd01), (b + 8'd01), (b + 8'd01)}; + w15 = {(b + 8'd00), (b + 8'd00), (b + 8'd00), (b + 8'd00)}; + + w512 = {w00, w01, w02, w03, w04, w05, w06, w07, + w08, w09, w10, w11, w12, w13, w14, w15}; + + wait_more_data(); + + dump_dut_state(); + dump_fifo(); + + $display("writing to fifo: 0x%0128x", w512); + tb_csprng_data = w512; + tb_csprng_data_valid = 1; + #(CLK_PERIOD); + tb_csprng_data_valid = 0; + end + endtask // write_w512 + + + //---------------------------------------------------------------- + // read_w32() + // + // read a 32 bit data word from the fifo. + //---------------------------------------------------------------- + task read_w32(); + begin + $display("*** Reading from the fifo: 0x%08x", tb_rnd_data); + tb_rnd_ack = 1; + #(2 * CLK_PERIOD); + tb_rnd_ack = 0; + dump_dut_state(); + end + endtask // read_w32 + + + //---------------------------------------------------------------- + // fifo_test() + // + // Writes a number of 512-bit words to the FIFO and then + // extracts 32-bit words and checks that we get the correct + // words all the time. + //---------------------------------------------------------------- + task fifo_test(); + reg [7 : 0] i; + reg [7 : 0] j; + + begin + $display("*** Test of FIFO by loading known data and then reading out."); + + dump_dut_state(); + dump_fifo(); + + i = 8'd0; + + // Filling up the memory with data. + for (j = 0 ; j < 4 ; j = j + 1) + begin + write_w512(i); + #(2 * CLK_PERIOD); + i = i + 16; + end + + dump_dut_state(); + dump_fifo(); + + // Read out a number of words from the fifo. + for (j = 0 ; j < 17 ; j = j + 1) + begin + read_w32(); + end + + dump_dut_state(); + dump_fifo(); + + // Write another 512-bit word into the fifo. + write_w512(8'h40); + + + // Read out all of the rest of the data. + while (tb_rnd_syn) + read_w32(); + + dump_fifo(); + end + endtask // fifo_test + + + //---------------------------------------------------------------- // csprng_test // // The main test functionality. @@ -250,6 +421,10 @@ module tb_csprng_fifo(); reset_dut(); dump_dut_state(); + #(10 * CLK_PERIOD) + + fifo_test(); + #(100 * CLK_PERIOD) display_test_results(); |