aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel V. Shatov (Meister) <meisterpaul1@yandex.ru>2017-12-05 22:26:31 +0300
committerPavel V. Shatov (Meister) <meisterpaul1@yandex.ru>2017-12-05 22:29:26 +0300
commit267a42bc7463c5ff1f4115eabb083cc9cb035fbc (patch)
treed4dc0416c54bba1ebbf463efb6e11999401b0c68
parent9ba428e606573d233b193c8afe0ecd875866e839 (diff)
Added new testbench.
-rw-r--r--src/tb/tb_sha3.v761
-rw-r--r--src/tb/tb_sha3_old.v256
2 files changed, 814 insertions, 203 deletions
diff --git a/src/tb/tb_sha3.v b/src/tb/tb_sha3.v
index b7e29d6..28d06a3 100644
--- a/src/tb/tb_sha3.v
+++ b/src/tb/tb_sha3.v
@@ -1,12 +1,11 @@
//======================================================================
//
// tb_sha3.v
-// -----------
+// -----------------------------
// Testbench for the SHA-3 core.
//
-//
-// Author: Joachim Strombergson, Pernd Paysan
-// Copyright (c) 2015, NORDUnet A/S
+// Authors: Pavel Shatov, Joachim Strombergson, Pernd Paysan
+// Copyright (c) 2015, 2017 NORDUnet A/S
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -38,217 +37,573 @@
//======================================================================
module tb_sha3();
-
- //----------------------------------------------------------------
- // Internal constant and parameter definitions.
- //----------------------------------------------------------------
- parameter DEBUG = 0;
-
- parameter CLK_HALF_PERIOD = 2;
- parameter CLK_PERIOD = 2 * CLK_HALF_PERIOD;
-
-
- //----------------------------------------------------------------
- // Register and Wire declarations.
- //----------------------------------------------------------------
- reg [31 : 0] cycle_ctr;
- reg [31 : 0] error_ctr;
- reg [31 : 0] tc_ctr;
-
- reg tb_clk;
- reg tb_reset_n;
- reg tb_we;
- reg [7 : 0] tb_address;
- reg [31 : 0] tb_write_data;
- wire [31 : 0] tb_read_data;
- wire tb_ready;
-
+
+
+ //----------------------------------------------------------------
+ // 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_reset_n),
- .w(tb_we),
- .addr(tb_address[6 : 0]),
- .din(tb_write_data),
- .dout(tb_read_data),
- .ready(tb_ready)
- );
-
-
- //----------------------------------------------------------------
- // clk_gen
- //
- // Clock generator process.
- //----------------------------------------------------------------
- always
- begin : clk_gen
- #CLK_HALF_PERIOD tb_clk = !tb_clk;
- end // clk_gen
-
-
- //----------------------------------------------------------------
- // sys_monitor
- //
- // Generates a cycle counter and displays information about
- // the dut as needed.
- //----------------------------------------------------------------
- always
- begin : sys_monitor
- #(2 * CLK_HALF_PERIOD);
- cycle_ctr = cycle_ctr + 1;
- end
-
-
- //----------------------------------------------------------------
- // dump_state()
- //
- // Dump the internal state of the DUT.
- //----------------------------------------------------------------
- task dump_state;
- begin
- $display("State of the DUT");
- $display("----------------");
- $display("st[00] = 0x%016x, st[01] = 0x%016x", dut.st[00], dut.st[01]);
- $display("st[02] = 0x%016x, st[03] = 0x%016x", dut.st[02], dut.st[03]);
- $display("st[04] = 0x%016x, st[05] = 0x%016x", dut.st[04], dut.st[05]);
- $display("st[06] = 0x%016x, st[07] = 0x%016x", dut.st[06], dut.st[07]);
- $display("st[08] = 0x%016x, st[09] = 0x%016x", dut.st[08], dut.st[09]);
- $display("st[10] = 0x%016x, st[11] = 0x%016x", dut.st[10], dut.st[11]);
- $display("st[12] = 0x%016x, st[13] = 0x%016x", dut.st[12], dut.st[13]);
- $display("st[14] = 0x%016x, st[15] = 0x%016x", dut.st[14], dut.st[15]);
- $display("st[16] = 0x%016x, st[17] = 0x%016x", dut.st[16], dut.st[17]);
- $display("st[18] = 0x%016x, st[19] = 0x%016x", dut.st[18], dut.st[19]);
- $display("st[20] = 0x%016x, st[21] = 0x%016x", dut.st[20], dut.st[21]);
- $display("st[22] = 0x%016x, st[23] = 0x%016x", dut.st[22], dut.st[23]);
- $display("st[24] = 0x%016x", dut.st[24]);
- $display("");
-
- $display("stn[00] = 0x%016x, stn[01] = 0x%016x", dut.stn[00], dut.stn[01]);
- $display("stn[02] = 0x%016x, stn[03] = 0x%016x", dut.stn[02], dut.stn[03]);
- $display("stn[04] = 0x%016x, stn[05] = 0x%016x", dut.stn[04], dut.stn[05]);
- $display("stn[06] = 0x%016x, stn[07] = 0x%016x", dut.stn[06], dut.stn[07]);
- $display("stn[08] = 0x%016x, stn[09] = 0x%016x", dut.stn[08], dut.stn[09]);
- $display("stn[10] = 0x%016x, stn[11] = 0x%016x", dut.stn[10], dut.stn[11]);
- $display("stn[12] = 0x%016x, stn[13] = 0x%016x", dut.stn[12], dut.stn[13]);
- $display("stn[14] = 0x%016x, stn[15] = 0x%016x", dut.stn[14], dut.stn[15]);
- $display("stn[16] = 0x%016x, stn[17] = 0x%016x", dut.stn[16], dut.stn[17]);
- $display("stn[18] = 0x%016x, stn[19] = 0x%016x", dut.stn[18], dut.stn[19]);
- $display("stn[20] = 0x%016x, stn[21] = 0x%016x", dut.stn[20], dut.stn[21]);
- $display("stn[22] = 0x%016x, stn[23] = 0x%016x", dut.stn[22], dut.stn[23]);
- $display("stn[24] = 0x%016x", dut.stn[24]);
- $display("");
-
- $display("bc[00] = 0x%016x, bc[01] = 0x%016x", dut.bc[00], dut.bc[01]);
- $display("bc[02] = 0x%016x, bc[03] = 0x%016x", dut.bc[02], dut.bc[03]);
- $display("bc[04] = 0x%016x", dut.stn[04]);
- $display("");
-
- $display("t = 0x%016x", dut.t);
- $display("");
-
- $display("round = 0x%04x, roundlimit = 0x%04x", dut.round, dut.roundlimit);
- $display("");
- end
- endtask // dump_state
-
-
- //----------------------------------------------------------------
- // reset_dut()
- //
- // Toggles reset to force the DUT into a well defined state.
- //----------------------------------------------------------------
- task reset_dut;
- begin
- $display("*** Toggle reset.");
- tb_reset_n = 0;
- #(4 * CLK_HALF_PERIOD);
- tb_reset_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
- cycle_ctr = 32'h0;
-
- tb_clk = 0;
- tb_reset_n = 0;
- tb_we = 0;
- tb_address = 6'h0;
- tb_write_data = 32'h0;
- end
- endtask // init_dut
-
-
- //----------------------------------------------------------------
- // display_test_result()
- //
- // Display the accumulated test results.
- //----------------------------------------------------------------
- task display_test_result;
- begin
- if (error_ctr == 0)
- begin
- $display("*** All %02d test cases completed successfully.", tc_ctr);
- end
- else
- begin
- $display("*** %02d test cases completed.", tc_ctr);
- $display("*** %02d errors detected during testing.", error_ctr);
- end
- end
- endtask // display_test_result
-
-
- //----------------------------------------------------------------
- // simple_test()
- //
- // A first simple test that verifies what happens with an all
- // zero data input.
- //----------------------------------------------------------------
- task simple_test;
- reg [7 : 0] i;
- begin
- dump_state();
-
- for (i = 0 ; i < 64 ; i = i + 1)
- begin
- tb_write_data = {i, i, i, i};
- tb_address = i[6 : 0];
- tb_we = 1;
- #(CLK_PERIOD);
- tb_we = 0;
- end
-
- dump_state();
- end
- endtask // simple_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;
+
+ 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'h00000006; // ...0001 | 10
+ block_words-1: tb_wr_data = 32'h80000000; // 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);
+
+ // swap bytes in the read value
+ for (j=31; j>0; j=j-8)
+ hash_word[j-:8] = tb_rd_data[31-j+:8];
+
+ $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)
+
+ 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'h06636261; // ...0001 | 10 | 'cba'
+ block_words-1: tb_wr_data = 32'h80000000; // 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);
+
+ // swap bytes in the read value
+ for (j=31; j>0; j=j-8)
+ hash_word[j-:8] = tb_rd_data[31-j+:8];
+
+ $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;
+
+ 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'h00000006;
+ 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'h80000000;
+ 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);
+
+ // swap bytes in the read value
+ for (j=31; j>0; j=j-8)
+ hash_word[j-:8] = tb_rd_data[31-j+:8];
+
+ $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
+ initial
+
begin : sha3_test
- $display(" -- Testbench for sha3 started --");
+ $display("*** Testbench for sha3.v started.");
+
+ num_err = 0;
init_sim();
- reset_dut();
- simple_test();
-
- $display(" -- Testbench for sha3 done. --");
- $finish;
- end // sha3_test
+ 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
+
endmodule // tb_sha3
//======================================================================
diff --git a/src/tb/tb_sha3_old.v b/src/tb/tb_sha3_old.v
new file mode 100644
index 0000000..b7e29d6
--- /dev/null
+++ b/src/tb/tb_sha3_old.v
@@ -0,0 +1,256 @@
+//======================================================================
+//
+// tb_sha3.v
+// -----------
+// Testbench for the SHA-3 core.
+//
+//
+// Author: Joachim Strombergson, Pernd Paysan
+// Copyright (c) 2015, NORDUnet A/S
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// - Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// - Neither the name of the NORDUnet nor the names of its contributors may
+// be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//======================================================================
+
+module tb_sha3();
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter DEBUG = 0;
+
+ parameter CLK_HALF_PERIOD = 2;
+ parameter CLK_PERIOD = 2 * CLK_HALF_PERIOD;
+
+
+ //----------------------------------------------------------------
+ // Register and Wire declarations.
+ //----------------------------------------------------------------
+ reg [31 : 0] cycle_ctr;
+ reg [31 : 0] error_ctr;
+ reg [31 : 0] tc_ctr;
+
+ reg tb_clk;
+ reg tb_reset_n;
+ reg tb_we;
+ reg [7 : 0] tb_address;
+ reg [31 : 0] tb_write_data;
+ wire [31 : 0] tb_read_data;
+ wire tb_ready;
+
+
+ //----------------------------------------------------------------
+ // Device Under Test.
+ //----------------------------------------------------------------
+ sha3 dut(
+ .clk(tb_clk),
+ .nreset(tb_reset_n),
+ .w(tb_we),
+ .addr(tb_address[6 : 0]),
+ .din(tb_write_data),
+ .dout(tb_read_data),
+ .ready(tb_ready)
+ );
+
+
+ //----------------------------------------------------------------
+ // clk_gen
+ //
+ // Clock generator process.
+ //----------------------------------------------------------------
+ always
+ begin : clk_gen
+ #CLK_HALF_PERIOD tb_clk = !tb_clk;
+ end // clk_gen
+
+
+ //----------------------------------------------------------------
+ // sys_monitor
+ //
+ // Generates a cycle counter and displays information about
+ // the dut as needed.
+ //----------------------------------------------------------------
+ always
+ begin : sys_monitor
+ #(2 * CLK_HALF_PERIOD);
+ cycle_ctr = cycle_ctr + 1;
+ end
+
+
+ //----------------------------------------------------------------
+ // dump_state()
+ //
+ // Dump the internal state of the DUT.
+ //----------------------------------------------------------------
+ task dump_state;
+ begin
+ $display("State of the DUT");
+ $display("----------------");
+ $display("st[00] = 0x%016x, st[01] = 0x%016x", dut.st[00], dut.st[01]);
+ $display("st[02] = 0x%016x, st[03] = 0x%016x", dut.st[02], dut.st[03]);
+ $display("st[04] = 0x%016x, st[05] = 0x%016x", dut.st[04], dut.st[05]);
+ $display("st[06] = 0x%016x, st[07] = 0x%016x", dut.st[06], dut.st[07]);
+ $display("st[08] = 0x%016x, st[09] = 0x%016x", dut.st[08], dut.st[09]);
+ $display("st[10] = 0x%016x, st[11] = 0x%016x", dut.st[10], dut.st[11]);
+ $display("st[12] = 0x%016x, st[13] = 0x%016x", dut.st[12], dut.st[13]);
+ $display("st[14] = 0x%016x, st[15] = 0x%016x", dut.st[14], dut.st[15]);
+ $display("st[16] = 0x%016x, st[17] = 0x%016x", dut.st[16], dut.st[17]);
+ $display("st[18] = 0x%016x, st[19] = 0x%016x", dut.st[18], dut.st[19]);
+ $display("st[20] = 0x%016x, st[21] = 0x%016x", dut.st[20], dut.st[21]);
+ $display("st[22] = 0x%016x, st[23] = 0x%016x", dut.st[22], dut.st[23]);
+ $display("st[24] = 0x%016x", dut.st[24]);
+ $display("");
+
+ $display("stn[00] = 0x%016x, stn[01] = 0x%016x", dut.stn[00], dut.stn[01]);
+ $display("stn[02] = 0x%016x, stn[03] = 0x%016x", dut.stn[02], dut.stn[03]);
+ $display("stn[04] = 0x%016x, stn[05] = 0x%016x", dut.stn[04], dut.stn[05]);
+ $display("stn[06] = 0x%016x, stn[07] = 0x%016x", dut.stn[06], dut.stn[07]);
+ $display("stn[08] = 0x%016x, stn[09] = 0x%016x", dut.stn[08], dut.stn[09]);
+ $display("stn[10] = 0x%016x, stn[11] = 0x%016x", dut.stn[10], dut.stn[11]);
+ $display("stn[12] = 0x%016x, stn[13] = 0x%016x", dut.stn[12], dut.stn[13]);
+ $display("stn[14] = 0x%016x, stn[15] = 0x%016x", dut.stn[14], dut.stn[15]);
+ $display("stn[16] = 0x%016x, stn[17] = 0x%016x", dut.stn[16], dut.stn[17]);
+ $display("stn[18] = 0x%016x, stn[19] = 0x%016x", dut.stn[18], dut.stn[19]);
+ $display("stn[20] = 0x%016x, stn[21] = 0x%016x", dut.stn[20], dut.stn[21]);
+ $display("stn[22] = 0x%016x, stn[23] = 0x%016x", dut.stn[22], dut.stn[23]);
+ $display("stn[24] = 0x%016x", dut.stn[24]);
+ $display("");
+
+ $display("bc[00] = 0x%016x, bc[01] = 0x%016x", dut.bc[00], dut.bc[01]);
+ $display("bc[02] = 0x%016x, bc[03] = 0x%016x", dut.bc[02], dut.bc[03]);
+ $display("bc[04] = 0x%016x", dut.stn[04]);
+ $display("");
+
+ $display("t = 0x%016x", dut.t);
+ $display("");
+
+ $display("round = 0x%04x, roundlimit = 0x%04x", dut.round, dut.roundlimit);
+ $display("");
+ end
+ endtask // dump_state
+
+
+ //----------------------------------------------------------------
+ // reset_dut()
+ //
+ // Toggles reset to force the DUT into a well defined state.
+ //----------------------------------------------------------------
+ task reset_dut;
+ begin
+ $display("*** Toggle reset.");
+ tb_reset_n = 0;
+ #(4 * CLK_HALF_PERIOD);
+ tb_reset_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
+ cycle_ctr = 32'h0;
+
+ tb_clk = 0;
+ tb_reset_n = 0;
+ tb_we = 0;
+ tb_address = 6'h0;
+ tb_write_data = 32'h0;
+ end
+ endtask // init_dut
+
+
+ //----------------------------------------------------------------
+ // display_test_result()
+ //
+ // Display the accumulated test results.
+ //----------------------------------------------------------------
+ task display_test_result;
+ begin
+ if (error_ctr == 0)
+ begin
+ $display("*** All %02d test cases completed successfully.", tc_ctr);
+ end
+ else
+ begin
+ $display("*** %02d test cases completed.", tc_ctr);
+ $display("*** %02d errors detected during testing.", error_ctr);
+ end
+ end
+ endtask // display_test_result
+
+
+ //----------------------------------------------------------------
+ // simple_test()
+ //
+ // A first simple test that verifies what happens with an all
+ // zero data input.
+ //----------------------------------------------------------------
+ task simple_test;
+ reg [7 : 0] i;
+ begin
+ dump_state();
+
+ for (i = 0 ; i < 64 ; i = i + 1)
+ begin
+ tb_write_data = {i, i, i, i};
+ tb_address = i[6 : 0];
+ tb_we = 1;
+ #(CLK_PERIOD);
+ tb_we = 0;
+ end
+
+ dump_state();
+ end
+ endtask // simple_test
+
+
+ //----------------------------------------------------------------
+ // sha3_test
+ // The main test functionality.
+ //----------------------------------------------------------------
+ initial
+ begin : sha3_test
+ $display(" -- Testbench for sha3 started --");
+
+ init_sim();
+ reset_dut();
+ simple_test();
+
+ $display(" -- Testbench for sha3 done. --");
+ $finish;
+ end // sha3_test
+endmodule // tb_sha3
+
+//======================================================================
+// EOF tb_sha3.v
+//======================================================================