From 4b8d3a9da9a1d2639dd5d3adeaad55f338ead612 Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Mon, 7 Jun 2021 14:13:23 -0400 Subject: 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(-) (limited to 'src') 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> 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> 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 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> 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> 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> 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 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