aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/rtl/trng.v121
-rw-r--r--src/rtl/trng_csprng.v61
-rw-r--r--src/rtl/trng_csprng_fifo.v181
-rw-r--r--src/rtl/trng_mixer.v46
-rw-r--r--src/tb/tb_csprng.v105
-rw-r--r--src/tb/tb_csprng_fifo.v199
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();