[Cryptech-Commits] [core/hash/sha3] 02/02: Add mode bits for the various flavors of SHA-3, so that the software driver doesn't have to know that the internal block size is actually 1600 bits. This involves having the "init" state zero-extend the block data, and having "next" only absorb the block bits for that mode.

git at cryptech.is git at cryptech.is
Mon Jun 7 19:09:30 UTC 2021


This is an automated email from the git hooks/post-receive script.

paul at psgd.org pushed a commit to branch sha3_mode
in repository core/hash/sha3.

commit 4b8d3a9da9a1d2639dd5d3adeaad55f338ead612
Author: Paul Selkirk <paul at psgd.org>
AuthorDate: Mon Jun 7 14:13:23 2021 -0400

    Add mode bits for the various flavors of SHA-3, so that the software
    driver doesn't have to know that the internal block size is actually 1600
    bits. This involves having the "init" state zero-extend the block data,
    and having "next" only absorb the block bits for that mode.
---
 src/rtl/sha3.v         |   86 +++-
 src/rtl/sha3_wrapper.v |   19 +-
 src/tb/tb_sha3.v       | 1130 ++++++++++++++++++++++++------------------------
 3 files changed, 659 insertions(+), 576 deletions(-)

diff --git a/src/rtl/sha3.v b/src/rtl/sha3.v
index a8b41bc..31b6465 100644
--- a/src/rtl/sha3.v
+++ b/src/rtl/sha3.v
@@ -44,20 +44,23 @@
 `define SHA3_NUM_ROUNDS         5'd24
 
 module sha3(    input wire          clk,
-                input wire          nreset,
-                input wire          w,
-                input wire [ 8:2]   addr,
-                input wire [32-1:0] din,
+                input wire 	     nreset,
+                input wire 	     w,
+                input wire [ 8:2]    addr,
+                input wire [32-1:0]  din,
                 output wire [32-1:0] dout,
-                input wire          init,
-                input wire          next,
-                output wire         ready);
+                input wire 	     init,
+                input wire 	     next,
+		input wire [ 1:0]    mode,
+                output wire 	     ready);
 
 
-   /* The SHA-3 algorithm really wants everything to be little-endian,
+   /*
+    * The SHA-3 algorithm really wants everything to be little-endian,
     * which is at odds with everything else in our system (including the
     * register interface to sha3_wrapper). Rather than trying to rewrite
-    * Bernd's beautiful code, we'll just byte-swap all I/O.
+    * Bernd's beautiful code, I'll isolate it in its own little-endian
+    * universe by byte-swapping all reads and writes.
     */
 
    reg [31:0]                       dout_swap;
@@ -193,10 +196,69 @@ module sha3(    input wire          clk,
 
            round <= round + 'd1;
 
-        end else if (init || next) begin
+        end else if (init) begin
+
+	   /*
+	    * I'd like to have something concise like this,
+	    * but the tools don't like it.
+
+           for (i = 0; i < blksize[mode]; i = i + 1)
+             st[i] <= st[i];
+
+           for (i < blksize[mode]; i < 25; i = i + 1)
+             st[i] <= 64'h0;
+
+	    */	   
+
+	   case (mode)
+	     0: begin
+		for (i = 0; i < 18; i = i + 1)
+		  st[i] <= blk[i];
+		for (i = 18; i < 25; i = i + 1)
+		  st[i] <= 64'h0;
+		end
+	     1: begin
+		for (i = 0; i < 17; i = i + 1)
+		  st[i] <= blk[i];
+		for (i = 17; i < 25; i = i + 1)
+		  st[i] <= 64'h0;
+		end
+	     2: begin
+		for (i = 0; i < 13; i = i + 1)
+		  st[i] <= blk[i];
+		for (i = 13; i < 25; i = i + 1)
+		  st[i] <= 64'h0;
+		end
+	     3: begin
+		for (i = 0; i < 9; i = i + 1)
+		  st[i] <= blk[i];
+		for (i = 9; i < 25; i = i + 1)
+		  st[i] <= 64'h0;
+		end
+	   endcase
 
-           for (i=0; i<25; i=i+1)
-             st[i] <= init ? blk[i] : st[i] ^ blk[i];   // init has priority over next
+           round <= 'd0;
+
+        end else if (next) begin
+
+	   case (mode)
+	     0: begin
+		for (i = 0; i < 18; i = i + 1)
+		  st[i] <= st[i] ^ blk[i];
+		end
+	     1: begin
+		for (i = 0; i < 17; i = i + 1)
+		  st[i] <= st[i] ^ blk[i];
+		end
+	     2: begin
+		for (i = 0; i < 13; i = i + 1)
+		  st[i] <= st[i] ^ blk[i];
+		end
+	     3: begin
+		for (i = 0; i < 9; i = i + 1)
+		  st[i] <= st[i] ^ blk[i];
+		end
+	   endcase
 
            round <= 'd0;
 
diff --git a/src/rtl/sha3_wrapper.v b/src/rtl/sha3_wrapper.v
index f3dc554..91223f8 100644
--- a/src/rtl/sha3_wrapper.v
+++ b/src/rtl/sha3_wrapper.v
@@ -73,6 +73,8 @@ module sha3_wrapper
 
    localparam CONTROL_INIT_BIT  = 0;
    localparam CONTROL_NEXT_BIT  = 1;
+   localparam CONTROL_MODE_LOW_BIT  = 2;
+   localparam CONTROL_MODE_HIGH_BIT = 3;
 
 // localparam STATUS_READY_BIT  = 0; -- hardcoded to always read 1
    localparam STATUS_VALID_BIT  = 1;
@@ -85,8 +87,8 @@ module sha3_wrapper
    //
    // Registers
    //
-   reg [ 1:0] reg_control;
-   reg [ 1:0] reg_control_prev;
+   reg [ 3:0] reg_control;
+   reg [ 3:0] reg_control_prev;
 
 
    //
@@ -98,6 +100,10 @@ module sha3_wrapper
    wire       reg_control_next_posedge =
               reg_control[CONTROL_NEXT_BIT] & ~reg_control_prev[CONTROL_NEXT_BIT];
 
+   wire [1:0] reg_control_mode_posedge =
+	      reg_control[CONTROL_MODE_HIGH_BIT:CONTROL_MODE_LOW_BIT] &
+	      ~reg_control_prev[CONTROL_MODE_HIGH_BIT:CONTROL_MODE_LOW_BIT];
+
 
    //
    // Wires
@@ -115,6 +121,7 @@ module sha3_wrapper
 
       .init                     (reg_control_init_posedge),
       .next                     (reg_control_next_posedge),
+      .mode                     (reg_control_mode_posedge),
 
       .ready                    (reg_status_valid),
 
@@ -136,7 +143,7 @@ module sha3_wrapper
    //
    always @(posedge clk)
      //
-     if (!rst_n)        reg_control_prev <= 2'b00;
+     if (!rst_n)        reg_control_prev <= 4'b00;
           else          reg_control_prev <= reg_control;
 
 
@@ -147,7 +154,7 @@ module sha3_wrapper
      //
      if (!rst_n) begin
         //
-        reg_control <= 2'b00;
+        reg_control <= 4'b00;
         //
      end else if (cs && we && (addr_msb == ADDR_MSB_REGS)) begin
         //
@@ -155,7 +162,7 @@ module sha3_wrapper
         //
         case (addr_lsb)
           //
-          ADDR_CONTROL: reg_control <= write_data[CONTROL_NEXT_BIT:CONTROL_INIT_BIT];
+          ADDR_CONTROL: reg_control <= write_data[CONTROL_MODE_HIGH_BIT:CONTROL_INIT_BIT];
           //
         endcase
         //
@@ -171,7 +178,7 @@ module sha3_wrapper
          ADDR_NAME0:        tmp_read_data = CORE_NAME0;
          ADDR_NAME1:        tmp_read_data = CORE_NAME1;
          ADDR_VERSION:      tmp_read_data = CORE_VERSION;
-         ADDR_CONTROL:      tmp_read_data = {{30{1'b0}}, reg_control};
+         ADDR_CONTROL:      tmp_read_data = {{28{1'b0}}, reg_control};
          ADDR_STATUS:       tmp_read_data = {{30{1'b0}}, reg_status_valid, 1'b1};
          //
          default:           tmp_read_data = 32'h00000000;
diff --git a/src/tb/tb_sha3.v b/src/tb/tb_sha3.v
index 5dd93c4..cd40ec4 100644
--- a/src/tb/tb_sha3.v
+++ b/src/tb/tb_sha3.v
@@ -37,567 +37,581 @@
 //======================================================================
 
 module tb_sha3();
-
-
-	//----------------------------------------------------------------
-	// Hashes of empty messages
-	//----------------------------------------------------------------
-	localparam	[511:0]	SHA3_224_EMPTY_MSG =
-		{	224'h6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7,
-			{512-224{1'bX}}};
-
-	localparam	[511:0]	SHA3_256_EMPTY_MSG =
-		{	256'ha7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a,
-			{512-256{1'bX}}};
-			
-	localparam	[511:0]	SHA3_384_EMPTY_MSG =
-		{	384'h0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004,
-			{512-384{1'bX}}};
-
-	localparam	[511:0]	SHA3_512_EMPTY_MSG =
-		{	512'ha69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26};
-
-		/*
-		 * The "short" message is the "abc" string (0x616263):
-		 *
-		 * https://www.di-mgt.com.au/sha_testvectors.html
-		 *
-		 */
-	localparam	[511:0]	SHA3_224_SHORT_MSG =
-		{	224'he642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf,
-			{512-224{1'bX}}};
-
-	localparam	[511:0]	SHA3_256_SHORT_MSG =
-		{	256'h3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532,
-			{512-256{1'bX}}};
-
-	localparam	[511:0]	SHA3_384_SHORT_MSG =
-		{	384'hec01498288516fc926459f58e2c6ad8df9b473cb0fc08c2596da7cf0e49be4b298d88cea927ac7f539f1edf228376d25,
-			{512-384{1'bX}}};
-
-	localparam	[511:0]	SHA3_512_SHORT_MSG =
-		{	512'hb751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0};
-
-		/*
-		 * The "long" message is the 1600-bit string 0xA3...A3 taken from:
-		 * https://csrc.nist.gov/Projects/Cryptographic-Standards-and-Guidelines/example-values
-		 *
-		 */
-
-	localparam	[511:0]	SHA3_224_LONG_MSG =
-		{	224'h9376816ABA503F72F96CE7EB65AC095DEEE3BE4BF9BBC2A1CB7E11E0,
-			{512-224{1'bX}}};
-
-	localparam	[511:0]	SHA3_256_LONG_MSG =
-		{	256'h79F38ADEC5C20307A98EF76E8324AFBFD46CFD81B22E3973C65FA1BD9DE31787,
-			{512-256{1'bX}}};
-
-	localparam	[511:0]	SHA3_384_LONG_MSG =
-		{	384'h1881DE2CA7E41EF95DC4732B8F5F002B189CC1E42B74168ED1732649CE1DBCDD76197A31FD55EE989F2D7050DD473E8F,
-			{512-384{1'bX}}};
-
-	localparam	[511:0]	SHA3_512_LONG_MSG =
-		{	512'hE76DFAD22084A8B1467FCF2FFA58361BEC7628EDF5F3FDC0E4805DC48CAEECA81B7C13C30ADF52A3659584739A2DF46BE589C51CA1A4A8416DF6545A1CE8BA00};
-
-		/*
-		 * Sponge Parameters
-		 *
-		 */
-	`define SHA3_224_BLOCK_BITS	1152
-	`define SHA3_256_BLOCK_BITS	1088
-	`define SHA3_384_BLOCK_BITS	 832
-	`define SHA3_512_BLOCK_BITS	 576
-
-	`define SHA3_224_OUTPUT_BITS	 224
-	`define SHA3_256_OUTPUT_BITS	 256
-	`define SHA3_384_OUTPUT_BITS	 384
-	`define SHA3_512_OUTPUT_BITS	 512
-			
-
-	//----------------------------------------------------------------
-	// Internal constant and parameter definitions.
-	//----------------------------------------------------------------
-	parameter CLK_HALF_PERIOD = 2;
-	parameter CLK_PERIOD = 2 * CLK_HALF_PERIOD;
-
-
-	//----------------------------------------------------------------
-	// Register and Wire declarations.
-	//----------------------------------------------------------------
-	reg				tb_clk;
-	reg				tb_rst_n;
-	reg				tb_we;
-	reg	[ 6:0]	tb_addr;
-	reg	[31:0]	tb_wr_data;
-	reg				tb_dut_init;
-	reg				tb_dut_next;
-	wire	[31:0]	tb_rd_data;
-	wire				tb_rdy;
-	
-	integer i, j;
-	integer num_err;
-	integer total_bits;
-	integer block_words, output_words;
-	
-	reg	[511:0]	hash_shreg;		// output
-	reg	[31: 0]	hash_word;		// current output word
-	
-	reg				mismatch;		// error flag
-
-
-  //----------------------------------------------------------------
-  // Device Under Test.
-  //----------------------------------------------------------------
-  sha3 dut
-  (
-		.clk		(tb_clk),
-		.nreset	(tb_rst_n),
-		.w			(tb_we),
-		.addr		(tb_addr),
-		.din		(tb_wr_data),
-		.dout		(tb_rd_data),
-		.init		(tb_dut_init),
-		.next		(tb_dut_next),
-		.ready	(tb_rdy)
-	);
-
-
-	//----------------------------------------------------------------
-	// clk_gen
-	//
-	// Clock generator process.
-	//----------------------------------------------------------------
-	always
-		begin : clk_gen
-			#CLK_HALF_PERIOD tb_clk = ~tb_clk;
-		end // clk_gen
-		
-
-	//----------------------------------------------------------------
-	// reset_dut()
-	//
-	// Toggles reset to force the DUT into a well defined state.
-	//----------------------------------------------------------------
-	task reset_dut;
-		begin
-			$display("*** Toggling reset...");
-			tb_rst_n = 0;
-			#(4 * CLK_HALF_PERIOD);
-			tb_rst_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
-			tb_clk		= 0;
-			tb_rst_n		= 0;
-			tb_we			= 0;
-			tb_addr		= 7'd0;
-			tb_wr_data	= 32'h0;
-			tb_dut_init = 0;
-			tb_dut_next = 0;
-		end
-	endtask // init_sim()
-
-
-	//----------------------------------------------------------------
-	// test_empty_message()
-	//
-	// The first pritimive test that verifies what happens with an
-	// empty input message.
-	//----------------------------------------------------------------
-	task test_empty_message;
+
+
+   //----------------------------------------------------------------
+   // Hashes of empty messages
+   //----------------------------------------------------------------
+   localparam	[511:0]	SHA3_224_EMPTY_MSG =
+	    {	224'h6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7,
+		{512-224{1'bX}}};
+
+   localparam	[511:0]	SHA3_256_EMPTY_MSG =
+	    {	256'ha7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a,
+		{512-256{1'bX}}};
+   
+   localparam	[511:0]	SHA3_384_EMPTY_MSG =
+	    {	384'h0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004,
+		{512-384{1'bX}}};
+
+   localparam	[511:0]	SHA3_512_EMPTY_MSG =
+	    {	512'ha69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26};
+
+   /*
+    * The "short" message is the "abc" string (0x616263):
+    *
+    * https://www.di-mgt.com.au/sha_testvectors.html
+    *
+    */
+   localparam	[511:0]	SHA3_224_SHORT_MSG =
+	    {	224'he642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf,
+		{512-224{1'bX}}};
+
+   localparam	[511:0]	SHA3_256_SHORT_MSG =
+	    {	256'h3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532,
+		{512-256{1'bX}}};
+
+   localparam	[511:0]	SHA3_384_SHORT_MSG =
+	    {	384'hec01498288516fc926459f58e2c6ad8df9b473cb0fc08c2596da7cf0e49be4b298d88cea927ac7f539f1edf228376d25,
+		{512-384{1'bX}}};
+
+   localparam	[511:0]	SHA3_512_SHORT_MSG =
+	    {	512'hb751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0};
+
+   /*
+    * The "long" message is the 1600-bit string 0xA3...A3 taken from:
+    * https://csrc.nist.gov/Projects/Cryptographic-Standards-and-Guidelines/example-values
+    *
+    */
+
+   localparam	[511:0]	SHA3_224_LONG_MSG =
+	   {	224'h9376816ABA503F72F96CE7EB65AC095DEEE3BE4BF9BBC2A1CB7E11E0,
+		{512-224{1'bX}}};
+
+   localparam	[511:0]	SHA3_256_LONG_MSG =
+	   {	256'h79F38ADEC5C20307A98EF76E8324AFBFD46CFD81B22E3973C65FA1BD9DE31787,
+		{512-256{1'bX}}};
+
+   localparam	[511:0]	SHA3_384_LONG_MSG =
+	   {	384'h1881DE2CA7E41EF95DC4732B8F5F002B189CC1E42B74168ED1732649CE1DBCDD76197A31FD55EE989F2D7050DD473E8F,
+		{512-384{1'bX}}};
+
+   localparam	[511:0]	SHA3_512_LONG_MSG =
+	   {	512'hE76DFAD22084A8B1467FCF2FFA58361BEC7628EDF5F3FDC0E4805DC48CAEECA81B7C13C30ADF52A3659584739A2DF46BE589C51CA1A4A8416DF6545A1CE8BA00};
+
+   /*
+    * Sponge Parameters
+    *
+    */
+`define SHA3_224_BLOCK_BITS	1152
+`define SHA3_256_BLOCK_BITS	1088
+`define SHA3_384_BLOCK_BITS	 832
+`define SHA3_512_BLOCK_BITS	 576
+
+`define SHA3_224_OUTPUT_BITS	 224
+`define SHA3_256_OUTPUT_BITS	 256
+`define SHA3_384_OUTPUT_BITS	 384
+`define SHA3_512_OUTPUT_BITS	 512
+   
+`define SHA3_224_MODE            0
+`define SHA3_256_MODE            1
+`define SHA3_384_MODE            2
+`define SHA3_512_MODE            3
+   
+
+   //----------------------------------------------------------------
+   // Internal constant and parameter definitions.
+   //----------------------------------------------------------------
+   parameter CLK_HALF_PERIOD = 2;
+   parameter CLK_PERIOD = 2 * CLK_HALF_PERIOD;
+
+
+   //----------------------------------------------------------------
+   // Register and Wire declarations.
+   //----------------------------------------------------------------
+   reg				tb_clk;
+   reg				tb_rst_n;
+   reg				tb_we;
+   reg [ 6:0] 			tb_addr;
+   reg [31:0] 			tb_wr_data;
+   reg				tb_dut_init;
+   reg				tb_dut_next;
+   reg [1:0] 			tb_dut_mode;
+   wire [31:0] 			tb_rd_data;
+   wire				tb_rdy;
+   
+   integer 			i, j;
+   integer 			num_err;
+   integer 			total_bits;
+   integer 			block_words, output_words;
+   
+   reg [511:0] 			hash_shreg;		// output
+   reg [31: 0] 			hash_word;		// current output word
+   
+   reg				mismatch;		// error flag
+
+
+   //----------------------------------------------------------------
+   // Device Under Test.
+   //----------------------------------------------------------------
+   sha3 dut
+     (
+      .clk		(tb_clk),
+      .nreset	        (tb_rst_n),
+      .w		(tb_we),
+      .addr		(tb_addr),
+      .din		(tb_wr_data),
+      .dout		(tb_rd_data),
+      .init		(tb_dut_init),
+      .next		(tb_dut_next),
+      .mode             (tb_dut_mode),
+      .ready	        (tb_rdy)
+      );
+
+
+   //----------------------------------------------------------------
+   // clk_gen
+   //
+   // Clock generator process.
+   //----------------------------------------------------------------
+   always
+     begin : clk_gen
+	#CLK_HALF_PERIOD tb_clk = ~tb_clk;
+     end // clk_gen
+   
+
+   //----------------------------------------------------------------
+   // reset_dut()
+   //
+   // Toggles reset to force the DUT into a well defined state.
+   //----------------------------------------------------------------
+   task reset_dut;
+      begin
+	 $display("*** Toggling reset...");
+	 tb_rst_n = 0;
+	 #(4 * CLK_HALF_PERIOD);
+	 tb_rst_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
+	 tb_clk		= 0;
+	 tb_rst_n	= 0;
+	 tb_we		= 0;
+	 tb_addr	= 7'd0;
+	 tb_wr_data	= 32'h0;
+	 tb_dut_init    = 0;
+	 tb_dut_next    = 0;
+	 tb_dut_mode    = 2'b0;
+      end
+   endtask // init_sim()
+
+
+   //----------------------------------------------------------------
+   // test_empty_message()
+   //
+   // The first pritimive test that verifies what happens with an
+   // empty input message.
+   //----------------------------------------------------------------
+   task test_empty_message;
+      
+      input	[511:0]	correct_hash;	// known-good hash
+      input integer	block_size;	// block length (bits)
+      input integer	output_size;	// output length (bits)
+      input integer     mode;
+      
+      begin
+
+	 $display("*** Testing %0d-bit hash (%0d-bit block)...", output_size, block_size);
+
+	 // number of words in block and output
+	 block_words = block_size >> 5;		// block_words = block_length / 32
+	 output_words = output_size >> 5;	// output_words = output_length / 32
+	 
+	 // wait for some time
+	 #(4*CLK_PERIOD);
+
+	 /*
+	  * Note, that we must wipe entire block buffer, because
+	  * it may contain leftovers from previous calculations!
+	  * We wipe the registers and apply padding at the same time.
+	  *
+	  */
+	 
+	 for (i=0; i<50; i=i+1) begin
+	    case (i)
+	      0:		tb_wr_data = 32'h06000000;		// ...0001 | 10
+	      block_words-1:	tb_wr_data = 32'h00000080;		//	1000...
+	      default:		tb_wr_data = 32'h00000000;		
+	    endcase
+	    tb_addr = {1'b0, i[5:0]};	// increment address
+	    tb_we = 1;			// enable writing
+	    tb_dut_mode = mode;
+	    #(CLK_PERIOD);
+	 end
+
+	 tb_addr = 'bX;
+	 tb_we = 0;
+
+	 /* run one absord-squeeze cycle */
+	 sha3_sponge_pump_init();
+	 
+	 // reset error counter
+	 mismatch = 0;
+	 
+	 // save the expected result
+	 hash_shreg = correct_hash;
+	 
+	 // now read and compare
+	 for (i=0; i<output_words; i=i+1) begin
+	    
+	    tb_addr = {1'b1, i[5:0]};
+	    #(CLK_PERIOD);
+	    
+	    hash_word = tb_rd_data;
+	    
+	    $display("    *** hash_word[%0d]: reference = %08x, calculated = %08x",
+		     i, hash_shreg[511-:32], hash_word);
+	    
+	    // compare
+	    if (hash_shreg[511-:32] !== hash_word) begin
+	       mismatch = 1;
+	       num_err = num_err + 1;
+	    end
+	    
+	    hash_shreg = {hash_shreg[511-32:0], {32{1'bX}}};
+	 end			
+	 
+	 if (mismatch) $display("    *** Test failed.");
+	 else          $display("    *** Test passed.");
+	 
+      end
+
+   endtask // test_empty_message
+
+
+   //----------------------------------------------------------------
+   // test_short_message()
+   //
+   // The second simple test that verifies what happens with an
+   // input message, that fits into just one block.
+   //----------------------------------------------------------------
+   task test_short_message;
+      
+      input	[511:0]	correct_hash;	// known-good hash
+      input integer	block_size;	// block length (bits)
+      input integer	output_size;	// output length (bits)
+      input integer     mode;
+      
+      begin
+
+	 $display("*** Testing %0d-bit hash (%0d-bit block)...", output_size, block_size);
+
+	 // number of words in block and output
+	 block_words = block_size >> 5;	// block_words = block_length / 32
+	 output_words = output_size >> 5;	// output_words = output_length / 32
+	 
+	 // wait for some time
+	 #(4*CLK_PERIOD);
+
+	 /*
+	  * Note, that we must wipe entire internal state, because
+	  * it may contain leftovers from previous calculations!
+	  * We wipe the internal state, fill in the message (0x616263)
+	  * and apply padding all at once.
+	  *
+	  */
+	 
+	 for (i=0; i<50; i=i+1) begin
+	    case (i)
+	      0:		tb_wr_data = 32'h61626306;		// ...0001 | 10 | 'cba'
+	      block_words-1:	tb_wr_data = 32'h00000080;		//	1000...
+	      default:		tb_wr_data = 32'h00000000;							
+	    endcase
+	    tb_addr = {1'b0, i[5:0]};	// increment address
+	    tb_we = 1;						// enable writing
+	    tb_dut_mode = mode;
+	    #(CLK_PERIOD);
+	 end
+
+	 tb_addr = 'bX;
+	 tb_we = 0;
+
+	 /* run one absord-squeeze cycle */
+	 sha3_sponge_pump_init();
+	 
+	 // reset error counter
+	 mismatch = 0;
+	 
+	 // save the expected result
+	 hash_shreg = correct_hash;
+	 
+	 // now read and compare
+	 for (i=0; i<output_words; i=i+1) begin
+	    
+	    tb_addr = {1'b1, i[5:0]};
+	    #(CLK_PERIOD);
+	    
+	    hash_word = tb_rd_data;
+	    
+	    $display("    *** hash_word[%0d]: reference = %08x, calculated = %08x",
+		     i, hash_shreg[511-:32], hash_word);
+	    
+	    // compare
+	    if (hash_shreg[511-:32] !== hash_word) begin
+	       mismatch = 1;
+	       num_err = num_err + 1;
+	    end
+	    
+	    hash_shreg = {hash_shreg[511-32:0], {32{1'bX}}};
+	 end			
+	 
+	 if (mismatch) $display("    *** Test failed.");
+	 else          $display("    *** Test passed.");
+	 
+      end
+
+   endtask // test_short_message
+
+
+   //----------------------------------------------------------------
+   // test_long_message()
+   //
+   // The second not so pritimive test, that verifies what happens
+   // when an input message spans more than one block.
+   //----------------------------------------------------------------
+   task test_long_message;
+      
+      input	[511:0]	correct_hash;
+      input integer	block_size;
+      input integer	output_size;
+      input integer     mode;
+      
+      begin
+
+	 $display("*** Testing %0d-bit hash (%0d-bit block)...", output_size, block_size);
+
+	 // number of words in block and output
+	 block_words = block_size >> 5;		// block_words = block_length / 32
+	 output_words = output_size >> 5;	// output_words = output_length / 32
+	 
+	 // wait for some time
+	 #(4*CLK_PERIOD);
+
+	 /* start filling the first block */
+	 total_bits = 1600;
+
+	 /*
+	  * note, that we must wipe entire internal state, because
+	  * it may contain leftovers from previous calculations!
+	  */
+
+	 for (i=0; i<50; i=i+1) begin
+	    tb_wr_data = (i < block_words) ? 32'hA3A3A3A3 : 32'h00000000;
+	    tb_addr = {1'b0, i[5:0]};
+	    tb_we = 1;
+	    #(CLK_PERIOD);
+	    if (i < block_words)
+	      total_bits = total_bits - 32;
+	 end
+
+	 tb_addr = 'bX;
+	 tb_we = 0;
+	 tb_dut_mode = mode;
+
+	 /* run one absord-squeeze cycle */
+	 sha3_sponge_pump_init();
+
+	 // process remaining bits
+	 while (total_bits > -64) begin
+
+	    /*
+	     * note, that there's no need to fill entire bank now,
+	     * because x ^ 0 == x
+	     */
+
+	    for (i=0; i<block_words; i=i+1) begin
+	       
+	       
+	       if (total_bits > 0) begin
+		  // message
+		  tb_wr_data = 32'hA3A3A3A3;
+		  tb_addr = {1'b0, i[5:0]};
+		  tb_we = 1;
+		  #(CLK_PERIOD);
+		  total_bits = total_bits - 32;
+	       end else if (total_bits == 0) begin
+		  // padding
+		  tb_wr_data = 32'h06000000;
+		  tb_addr = {1'b0, i[5:0]};
+		  tb_we = 1;
+		  #(CLK_PERIOD);
+		  total_bits = total_bits - 32;
+	       end else if (i == (block_words-1)) begin
+		  // more padding
+		  tb_wr_data = 32'h00000080;
+		  tb_addr = {1'b0, i[5:0]};
+		  tb_we = 1;
+		  #(CLK_PERIOD);
+		  total_bits = total_bits - 32;
+	       end else begin
+		  // intermediate bytes
+		  tb_wr_data = 32'h00000000;
+		  tb_addr = {1'b0, i[5:0]};
+		  tb_we = 1;
+		  #(CLK_PERIOD);						
+	       end
+	       
+	    end
+
+	    tb_addr = 'bX;
+	    tb_we = 0;
+
+	    /* run one absord-squeeze cycle */
+	    sha3_sponge_pump_next();
+
+	 end
+	 
+	 // reset error counter
+	 mismatch = 0;
+	 
+	 // save the expected result
+	 hash_shreg = correct_hash;
+	 
+	 // now read and compare
+	 for (i=0; i<output_words; i=i+1) begin
+	    
+	    tb_addr = {1'b1, i[5:0]};
+	    #(CLK_PERIOD);
+	    
+	    hash_word = tb_rd_data;
+	    
+	    $display("    *** hash_word[%0d]: reference = %08x, calculated = %08x",
+		     i, hash_shreg[511-:32], hash_word);
+	    
+	    // compare
+	    if (hash_shreg[511-:32] !== hash_word) begin
+	       mismatch = 1;
+	       num_err = num_err + 1;
+	    end
+	    
+	    hash_shreg = {hash_shreg[511-32:0], {32{1'bX}}};
+	 end			
+	 
+	 if (mismatch) $display("    *** Test failed.");
+	 else          $display("    *** Test passed.");
+	 
+      end
+
+   endtask // test_long_message
+
+
+   //----------------------------------------------------------------
+   // sha3_sponge_pump_init;
+   //
+   // Make the "sponge" absord input data and then wait for output
+   // data to be "squeezed out".
+   //----------------------------------------------------------------
+   task sha3_sponge_pump_init;
+      
+      begin : sha3_sponge_pump_init_task
+	 
+	 reg	poll_rdy;		// flag to keep waiting while the DUT is busy
+
+	 // start operation
+	 tb_dut_init = 1;
+	 #(CLK_PERIOD);
+	 tb_dut_init = 0;
+	 
+	 // poll ready output until the operation is finished
+	 poll_rdy = 1;
+	 while (poll_rdy) begin
+	    #(CLK_PERIOD);
+	    poll_rdy = !tb_rdy;
+	 end
+	 
+      end
+      
+   endtask // sha3_sponge_pump
+
+
+   //----------------------------------------------------------------
+   // sha3_sponge_pump_next;
+   //
+   // Make the "sponge" absord input data and then wait for output
+   // data to be "squeezed out".
+   //----------------------------------------------------------------
+   task sha3_sponge_pump_next;
+      
+      begin : sha3_sponge_pump_next_task
+	 
+	 reg	poll_rdy;		// flag to keep waiting while the DUT is busy
+
+	 // start operation
+	 tb_dut_next = 1;
+	 #(CLK_PERIOD);
+	 tb_dut_next = 0;
+	 
+	 // poll ready output until the operation is finished
+	 poll_rdy = 1;
+	 while (poll_rdy) begin
+	    #(CLK_PERIOD);
+	    poll_rdy = !tb_rdy;
+	 end
+	 
+      end
+      
+   endtask // sha3_sponge_pump
+
+
+   //----------------------------------------------------------------
+   // sha3_test
+   // The main test functionality.
+   //----------------------------------------------------------------
+   initial
+      
+     begin : sha3_test
+	$display("*** Testbench for sha3.v started.");
+
+	num_err = 0;
+
+	init_sim();
+	reset_dut();
+	
+	test_empty_message(SHA3_224_EMPTY_MSG, `SHA3_224_BLOCK_BITS, `SHA3_224_OUTPUT_BITS, `SHA3_224_MODE);
+	test_empty_message(SHA3_256_EMPTY_MSG, `SHA3_256_BLOCK_BITS, `SHA3_256_OUTPUT_BITS, `SHA3_256_MODE);
+	test_empty_message(SHA3_384_EMPTY_MSG, `SHA3_384_BLOCK_BITS, `SHA3_384_OUTPUT_BITS, `SHA3_384_MODE);
+	test_empty_message(SHA3_512_EMPTY_MSG, `SHA3_512_BLOCK_BITS, `SHA3_512_OUTPUT_BITS, `SHA3_512_MODE);
+	
+	test_short_message(SHA3_224_SHORT_MSG, `SHA3_224_BLOCK_BITS, `SHA3_224_OUTPUT_BITS, `SHA3_224_MODE);
+	test_short_message(SHA3_256_SHORT_MSG, `SHA3_256_BLOCK_BITS, `SHA3_256_OUTPUT_BITS, `SHA3_256_MODE);
+	test_short_message(SHA3_384_SHORT_MSG, `SHA3_384_BLOCK_BITS, `SHA3_384_OUTPUT_BITS, `SHA3_384_MODE);
+	test_short_message(SHA3_512_SHORT_MSG, `SHA3_512_BLOCK_BITS, `SHA3_512_OUTPUT_BITS, `SHA3_512_MODE);
+
+	test_long_message(SHA3_224_LONG_MSG, `SHA3_224_BLOCK_BITS, `SHA3_224_OUTPUT_BITS, `SHA3_224_MODE);
+	test_long_message(SHA3_256_LONG_MSG, `SHA3_256_BLOCK_BITS, `SHA3_256_OUTPUT_BITS, `SHA3_256_MODE);
+	test_long_message(SHA3_384_LONG_MSG, `SHA3_384_BLOCK_BITS, `SHA3_384_OUTPUT_BITS, `SHA3_384_MODE);
+	test_long_message(SHA3_512_LONG_MSG, `SHA3_512_BLOCK_BITS, `SHA3_512_OUTPUT_BITS, `SHA3_512_MODE);
+
+	$display("*** Testbench for sha3.v done.");
 	
-		input	[511:0]	correct_hash;	// known-good hash
-		input integer	block_size;		// block length (bits)
-		input integer	output_size;	// output length (bits)
-		
-		begin
-
-			$display("*** Testing %0d-bit hash (%0d-bit block)...", output_size, block_size);
-
-				// number of words in block and output
-			block_words = block_size >> 5;	// block_words = block_length / 32
-			output_words = output_size >> 5;	// output_words = output_length / 32
-			
-				// wait for some time
-			#(4*CLK_PERIOD);
-
-				/*
-				 * Note, that we must wipe entire block buffer, because
-				 * it may contain leftovers from previous calculations!
-				 * We wipe the registers and apply padding at the same time.
-				 *
-				 */
-				 
-			for (i=0; i<50; i=i+1) begin
-				case (i)
-					0:					tb_wr_data = 32'h06000000;		// ...0001 | 10
-					block_words-1:	tb_wr_data = 32'h00000080;		//	1000...
-					default:			tb_wr_data = 32'h00000000;		
-				endcase
-				tb_addr = {1'b0, i[5:0]};	// increment address
-				tb_we = 1;						// enable writing
-				#(CLK_PERIOD);
-			end
-
-			tb_addr = 'bX;
-			tb_we = 0;
-
-				/* run one absord-squeeze cycle */
-			sha3_sponge_pump_init();
-			
-				// reset error counter
-			mismatch = 0;
-				
-				// save the expected result
-			hash_shreg = correct_hash;
-			
-				// now read and compare
-			for (i=0; i<output_words; i=i+1) begin
-			
-				tb_addr = {1'b1, i[5:0]};
-				#(CLK_PERIOD);
-				
-				hash_word = tb_rd_data;
-				
-				$display("    *** hash_word[%0d]: reference = %08x, calculated = %08x",
-					i, hash_shreg[511-:32], hash_word);
-				
-					// compare
-				if (hash_shreg[511-:32] !== hash_word) begin
-					mismatch = 1;
-					num_err = num_err + 1;
-				end
-				
-				hash_shreg = {hash_shreg[511-32:0], {32{1'bX}}};
-			end			
-			
-			if (mismatch) $display("    *** Test failed.");
-			else          $display("    *** Test passed.");
-			
-		end
-
-	endtask // test_empty_message
-
-
-	//----------------------------------------------------------------
-	// test_short_message()
-	//
-	// The second simple test that verifies what happens with an
-	// input message, that fits into just one block.
-	//----------------------------------------------------------------
-	task test_short_message;
+	if (num_err == 0)
+	  $display("    *** All tests passed.");
+	else
+	  $display("    *** %0d tests not passed.", num_err);
 	
-		input	[511:0]	correct_hash;	// known-good hash
-		input integer	block_size;		// block length (bits)
-		input integer	output_size;	// output length (bits)
-		
-		begin
-
-			$display("*** Testing %0d-bit hash (%0d-bit block)...", output_size, block_size);
-
-				// number of words in block and output
-			block_words = block_size >> 5;	// block_words = block_length / 32
-			output_words = output_size >> 5;	// output_words = output_length / 32
-			
-				// wait for some time
-			#(4*CLK_PERIOD);
-
-				/*
-				 * Note, that we must wipe entire internal state, because
-				 * it may contain leftovers from previous calculations!
-				 * We wipe the internal state, fill in the message (0x616263)
-				 * and apply padding all at once.
-				 *
-				 */
-				 
-			for (i=0; i<50; i=i+1) begin
-				case (i)
-					0:					tb_wr_data = 32'h61626306;		// ...0001 | 10 | 'cba'
-					block_words-1:	tb_wr_data = 32'h00000080;		//	1000...
-					default:			tb_wr_data = 32'h00000000;							
-				endcase
-				tb_addr = {1'b0, i[5:0]};	// increment address
-				tb_we = 1;						// enable writing
-				#(CLK_PERIOD);
-			end
-
-			tb_addr = 'bX;
-			tb_we = 0;
-
-				/* run one absord-squeeze cycle */
-			sha3_sponge_pump_init();
-			
-				// reset error counter
-			mismatch = 0;
-				
-				// save the expected result
-			hash_shreg = correct_hash;
-			
-				// now read and compare
-			for (i=0; i<output_words; i=i+1) begin
-			
-				tb_addr = {1'b1, i[5:0]};
-				#(CLK_PERIOD);
-				
-				hash_word = tb_rd_data;
-				
-				$display("    *** hash_word[%0d]: reference = %08x, calculated = %08x",
-					i, hash_shreg[511-:32], hash_word);
-				
-					// compare
-				if (hash_shreg[511-:32] !== hash_word) begin
-					mismatch = 1;
-					num_err = num_err + 1;
-				end
-				
-				hash_shreg = {hash_shreg[511-32:0], {32{1'bX}}};
-			end			
-			
-			if (mismatch) $display("    *** Test failed.");
-			else          $display("    *** Test passed.");
-			
-		end
-
-	endtask // test_short_message
-
-
-	//----------------------------------------------------------------
-	// test_long_message()
-	//
-	// The second not so pritimive test, that verifies what happens
-	// when an input message spans more than one block.
-	//----------------------------------------------------------------
-	task test_long_message;
+	$finish;
 	
-		input	[511:0]	correct_hash;
-		input integer	block_size;
-		input integer	output_size;
-				
-		begin
-
-			$display("*** Testing %0d-bit hash (%0d-bit block)...", output_size, block_size);
-
-				// number of words in block and output
-			block_words = block_size >> 5;		// block_words = block_length / 32
-			output_words = output_size >> 5;	// output_words = output_length / 32
-		
-				// wait for some time
-			#(4*CLK_PERIOD);
-
-				/* start filling the first block */
-			total_bits = 1600;
-
-				/*
-				 * note, that we must wipe entire internal state, because
-				 * it may contain leftovers from previous calculations!
-				 */
-
-			for (i=0; i<50; i=i+1) begin
-				tb_wr_data = (i < block_words) ? 32'hA3A3A3A3 : 32'h00000000;
-				tb_addr = {1'b0, i[5:0]};
-				tb_we = 1;
-				#(CLK_PERIOD);
-				if (i < block_words)
-					total_bits = total_bits - 32;
-			end
-
-			tb_addr = 'bX;
-			tb_we = 0;
-
-				/* run one absord-squeeze cycle */
-			sha3_sponge_pump_init();
-
-				// process remaining bits
-			while (total_bits > -64) begin
-
-					/*
-					 * note, that there's no need to fill entire bank now,
-					 * because x ^ 0 == x
-					 */
-
-				for (i=0; i<block_words; i=i+1) begin
-				
-						
-					if (total_bits > 0) begin
-							// message
-						tb_wr_data = 32'hA3A3A3A3;
-						tb_addr = {1'b0, i[5:0]};
-						tb_we = 1;
-						#(CLK_PERIOD);
-						total_bits = total_bits - 32;
-					end else if (total_bits == 0) begin
-							// padding
-						tb_wr_data = 32'h06000000;
-						tb_addr = {1'b0, i[5:0]};
-						tb_we = 1;
-						#(CLK_PERIOD);
-						total_bits = total_bits - 32;
-					end else if (i == (block_words-1)) begin
-							// more padding
-						tb_wr_data = 32'h00000080;
-						tb_addr = {1'b0, i[5:0]};
-						tb_we = 1;
-						#(CLK_PERIOD);
-						total_bits = total_bits - 32;
-					end else begin
-							// intermediate bytes
-						tb_wr_data = 32'h00000000;
-						tb_addr = {1'b0, i[5:0]};
-						tb_we = 1;
-						#(CLK_PERIOD);						
-					end
-					
-				end
-
-				tb_addr = 'bX;
-				tb_we = 0;
-
-					/* run one absord-squeeze cycle */
-				sha3_sponge_pump_next();
-
-			end
-			
-				// reset error counter
-			mismatch = 0;
-				
-				// save the expected result
-			hash_shreg = correct_hash;
-			
-				// now read and compare
-			for (i=0; i<output_words; i=i+1) begin
-			
-				tb_addr = {1'b1, i[5:0]};
-				#(CLK_PERIOD);
-				
-				hash_word = tb_rd_data;
-				
-				$display("    *** hash_word[%0d]: reference = %08x, calculated = %08x",
-					i, hash_shreg[511-:32], hash_word);
-				
-					// compare
-				if (hash_shreg[511-:32] !== hash_word) begin
-					mismatch = 1;
-					num_err = num_err + 1;
-				end
-				
-				hash_shreg = {hash_shreg[511-32:0], {32{1'bX}}};
-			end			
-			
-			if (mismatch) $display("    *** Test failed.");
-			else          $display("    *** Test passed.");
-			
-		end
-
-	endtask // test_long_message
-
-
-	//----------------------------------------------------------------
-	// sha3_sponge_pump_init;
-	//
-	// Make the "sponge" absord input data and then wait for output
-	// data to be "squeezed out".
-	//----------------------------------------------------------------
-	task sha3_sponge_pump_init;
-	
-		begin : sha3_sponge_pump_init_task
-		
-			reg	poll_rdy;		// flag to keep waiting while the DUT is busy
-
-				// start operation
-			tb_dut_init = 1;
-			#(CLK_PERIOD);
-			tb_dut_init = 0;
-				
-				// poll ready output until the operation is finished
-			poll_rdy = 1;
-			while (poll_rdy) begin
-				#(CLK_PERIOD);
-				poll_rdy = !tb_rdy;
-			end
-			
-		end
-		
-	endtask // sha3_sponge_pump
-
-
-	//----------------------------------------------------------------
-	// sha3_sponge_pump_next;
-	//
-	// Make the "sponge" absord input data and then wait for output
-	// data to be "squeezed out".
-	//----------------------------------------------------------------
-	task sha3_sponge_pump_next;
-	
-		begin : sha3_sponge_pump_next_task
-		
-			reg	poll_rdy;		// flag to keep waiting while the DUT is busy
-
-				// start operation
-			tb_dut_next = 1;
-			#(CLK_PERIOD);
-			tb_dut_next = 0;
-				
-				// poll ready output until the operation is finished
-			poll_rdy = 1;
-			while (poll_rdy) begin
-				#(CLK_PERIOD);
-				poll_rdy = !tb_rdy;
-			end
-			
-		end
-		
-	endtask // sha3_sponge_pump
-
-
-  //----------------------------------------------------------------
-  // sha3_test
-  // The main test functionality.
-  //----------------------------------------------------------------
-  initial
-  
-    begin : sha3_test
-      $display("*** Testbench for sha3.v started.");
-
-		num_err = 0;
-
-      init_sim();
-      reset_dut();
-		
-      test_empty_message(SHA3_224_EMPTY_MSG, `SHA3_224_BLOCK_BITS, `SHA3_224_OUTPUT_BITS);
-      test_empty_message(SHA3_256_EMPTY_MSG, `SHA3_256_BLOCK_BITS, `SHA3_256_OUTPUT_BITS);
-      test_empty_message(SHA3_384_EMPTY_MSG, `SHA3_384_BLOCK_BITS, `SHA3_384_OUTPUT_BITS);
-      test_empty_message(SHA3_512_EMPTY_MSG, `SHA3_512_BLOCK_BITS, `SHA3_512_OUTPUT_BITS);
-		
-		test_short_message(SHA3_224_SHORT_MSG, `SHA3_224_BLOCK_BITS, `SHA3_224_OUTPUT_BITS);
-		test_short_message(SHA3_256_SHORT_MSG, `SHA3_256_BLOCK_BITS, `SHA3_256_OUTPUT_BITS);
-		test_short_message(SHA3_384_SHORT_MSG, `SHA3_384_BLOCK_BITS, `SHA3_384_OUTPUT_BITS);
-		test_short_message(SHA3_512_SHORT_MSG, `SHA3_512_BLOCK_BITS, `SHA3_512_OUTPUT_BITS);
-
-		test_long_message(SHA3_224_LONG_MSG, `SHA3_224_BLOCK_BITS, `SHA3_224_OUTPUT_BITS);
-		test_long_message(SHA3_256_LONG_MSG, `SHA3_256_BLOCK_BITS, `SHA3_256_OUTPUT_BITS);
-		test_long_message(SHA3_384_LONG_MSG, `SHA3_384_BLOCK_BITS, `SHA3_384_OUTPUT_BITS);
-		test_long_message(SHA3_512_LONG_MSG, `SHA3_512_BLOCK_BITS, `SHA3_512_OUTPUT_BITS);
-
-      $display("*** Testbench for sha3.v done.");
-		
-		if (num_err == 0)
-			$display("    *** All tests passed.");
-		else
-			$display("    *** %0d tests not passed.", num_err);
-		
-      $finish;
-		
-    end // sha3_test
-	 
+     end // sha3_test
+   
 endmodule // tb_sha3
 
 //======================================================================



More information about the Commits mailing list