Add files via upload
diff --git a/Verilog_Code/clock_mux.v b/Verilog_Code/clock_mux.v
new file mode 100644
index 0000000..20ca430
--- /dev/null
+++ b/Verilog_Code/clock_mux.v
@@ -0,0 +1,83 @@
+//
+// Switch between two clock sources.
+// In this design the output clock stays LOW between switching clocks.
+// After a reset clk1 is selected.
+// sel_clk2 is assumed to have a high/low duration of at least 2 clock
+// periods of the slowest of clk1 or clk2.
+// (If the above rule is not followed, certain pathological patterns of
+// sel_clk2 against the input clocks will produce low period violations)
+//
+
+//
+// Design by G.J. van Loo, FenLogic Ltd, 3-January-2017.
+//
+// This program is free software. It comes without any guarantees or
+// warranty to the extent permitted by applicable law. Although the
+// author has attempted to find and correct any bugs in this free software
+// program, the author is not responsible for any damage or losses of any
+// kind caused by the use or misuse of the program. You can redistribute
+// the program and or modify it in any form without obligations, but the
+// author would appreciated if the credits stays in.
+//
+
+
+module clock_mux
+ (
+ input clk1, // Clock 1 supposed to be faster
+ input clk2, // Clock 2 supposed to be slower
+ input reset_n, // System reset
+ input sel_clk2, // Select clock2 when high
+ output clk1or2 // Selected clock
+ );
+
+reg [1:0] meta1_off,sync1_off;
+reg [1:0] meta1_on, sync1_on;
+reg [1:0] meta2_off,sync2_off;
+reg [1:0] meta2_on, sync2_on;
+
+
+ always @(posedge clk1 or negedge reset_n)
+ begin
+ if (!reset_n)
+ begin
+ meta1_off <= 1'b0;
+ sync1_off <= 1'b0;
+ meta1_on <= 1'b1;
+ sync1_on <= 1'b1;
+ end
+ else
+ begin
+ // Switch off when not selected
+ meta1_off <= sel_clk2;
+ sync1_off <= meta1_off;
+ // Switch on when other clock (clk2) is off
+ meta1_on <= sync2_off;
+ sync1_on <= meta1_on;
+ end
+ end
+
+ always @(posedge clk2 or negedge reset_n)
+ begin
+ if (!reset_n)
+ begin
+ meta2_off <= 1'b1;
+ sync2_off <= 1'b1;
+ meta2_on <= 1'b0;
+ sync2_on <= 1'b0;
+ end
+ else
+ begin
+ // Switch off when not selected
+ meta2_off <= ~sel_clk2;
+ sync2_off <= meta2_off;
+ // Switch on when other clock (clk1) is off
+ meta2_on <= sync1_off;
+ sync2_on <= meta2_on;
+ end
+ end
+
+ assign clk1or2 = (clk1 & ~sync1_off & sync1_on ) |
+ (clk2 & ~sync2_off & sync2_on );
+
+endmodule // clock_rnux
+
diff --git a/Verilog_Code/sha256.v b/Verilog_Code/sha256.v
new file mode 100644
index 0000000..c47500c
--- /dev/null
+++ b/Verilog_Code/sha256.v
@@ -0,0 +1,265 @@
+//======================================================================
+//
+// sha256.v
+// --------
+// Top level wrapper for the SHA-256 hash function providing
+// a simple memory like interface with 32 bit data access.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2013, 201, Secworks Sweden AB
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. 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.
+//
+// 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 OWNER 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.
+//
+//======================================================================
+
+`default_nettype none
+
+module sha256(
+ // Clock and reset.
+ input wire clk,
+ input wire reset_n,
+
+ // Control.
+ input wire cs,
+ input wire we,
+
+ // Data ports.
+ input wire [7 : 0] address,
+ input wire [31 : 0] write_data,
+ output wire [31 : 0] read_data,
+ output wire error
+ );
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ localparam ADDR_NAME0 = 8'h00;
+ localparam ADDR_NAME1 = 8'h01;
+ localparam ADDR_VERSION = 8'h02;
+
+ localparam ADDR_CTRL = 8'h08;
+ localparam CTRL_INIT_BIT = 0;
+ localparam CTRL_NEXT_BIT = 1;
+ localparam CTRL_MODE_BIT = 2;
+
+ localparam ADDR_STATUS = 8'h09;
+ localparam STATUS_READY_BIT = 0;
+ localparam STATUS_VALID_BIT = 1;
+
+ localparam ADDR_BLOCK0 = 8'h10;
+ localparam ADDR_BLOCK15 = 8'h1f;
+
+ localparam ADDR_DIGEST0 = 8'h20;
+ localparam ADDR_DIGEST7 = 8'h27;
+
+ localparam CORE_NAME0 = 32'h73686132; // "sha2"
+ localparam CORE_NAME1 = 32'h2d323536; // "-256"
+ localparam CORE_VERSION = 32'h312e3830; // "1.80"
+
+ localparam MODE_SHA_224 = 1'h0;
+ localparam MODE_SHA_256 = 1'h1;
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+ reg init_reg;
+ reg init_new;
+
+ reg next_reg;
+ reg next_new;
+
+ reg mode_reg;
+ reg mode_new;
+ reg mode_we;
+
+ reg ready_reg;
+
+ reg [31 : 0] block_reg [0 : 15];
+ reg block_we;
+
+ reg [255 : 0] digest_reg;
+
+ reg digest_valid_reg;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ wire core_ready;
+ wire [511 : 0] core_block;
+ wire [255 : 0] core_digest;
+ wire core_digest_valid;
+
+ reg [31 : 0] tmp_read_data;
+ reg tmp_error;
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign core_block = {block_reg[00], block_reg[01], block_reg[02], block_reg[03],
+ block_reg[04], block_reg[05], block_reg[06], block_reg[07],
+ block_reg[08], block_reg[09], block_reg[10], block_reg[11],
+ block_reg[12], block_reg[13], block_reg[14], block_reg[15]};
+
+ assign read_data = tmp_read_data;
+ assign error = tmp_error;
+
+
+ //----------------------------------------------------------------
+ // core instantiation.
+ //----------------------------------------------------------------
+ sha256_core core(
+ .clk(clk),
+ .reset_n(reset_n),
+
+ .init(init_reg),
+ .next(next_reg),
+ .mode(mode_reg),
+
+ .block(core_block),
+
+ .ready(core_ready),
+
+ .digest(core_digest),
+ .digest_valid(core_digest_valid)
+ );
+
+
+ //----------------------------------------------------------------
+ // reg_update
+ //
+ // Update functionality for all registers in the core.
+ // All registers are positive edge triggered with asynchronous
+ // active low reset. All registers have write enable.
+ //----------------------------------------------------------------
+ always @ (posedge clk or negedge reset_n)
+ begin : reg_update
+ integer i;
+
+ if (!reset_n)
+ begin
+ for (i = 0 ; i < 16 ; i = i + 1)
+ block_reg[i] <= 32'h0;
+
+ init_reg <= 0;
+ next_reg <= 0;
+ ready_reg <= 0;
+ mode_reg <= MODE_SHA_256;
+ digest_reg <= 256'h0;
+ digest_valid_reg <= 0;
+ end
+ else
+ begin
+ ready_reg <= core_ready;
+ digest_valid_reg <= core_digest_valid;
+ init_reg <= init_new;
+ next_reg <= next_new;
+
+ if (mode_we)
+ mode_reg <= mode_new;
+
+ if (core_digest_valid)
+ digest_reg <= core_digest;
+
+ if (block_we)
+ block_reg[address[3 : 0]] <= write_data;
+ end
+ end // reg_update
+
+
+ //----------------------------------------------------------------
+ // api_logic
+ //
+ // Implementation of the api logic. If cs is enabled will either
+ // try to write to or read from the internal registers.
+ //----------------------------------------------------------------
+ always @*
+ begin : api_logic
+ init_new = 0;
+ next_new = 0;
+ mode_new = 0;
+ mode_we = 0;
+ block_we = 0;
+ tmp_read_data = 32'h0;
+ tmp_error = 0;
+
+ if (cs)
+ begin
+ if (we)
+ begin
+ if (address == ADDR_CTRL)
+ begin
+ init_new = write_data[CTRL_INIT_BIT];
+ next_new = write_data[CTRL_NEXT_BIT];
+ mode_new = write_data[CTRL_MODE_BIT];
+ mode_we = 1;
+ end
+
+ if ((address >= ADDR_BLOCK0) && (address <= ADDR_BLOCK15))
+ block_we = 1;
+ end // if (we)
+
+ else
+ begin
+ if ((address >= ADDR_BLOCK0) && (address <= ADDR_BLOCK15))
+ tmp_read_data = block_reg[address[3 : 0]];
+
+ if ((address >= ADDR_DIGEST0) && (address <= ADDR_DIGEST7))
+ tmp_read_data = digest_reg[(7 - (address - ADDR_DIGEST0)) * 32 +: 32];
+
+ case (address)
+ // Read operations.
+ ADDR_NAME0:
+ tmp_read_data = CORE_NAME0;
+
+ ADDR_NAME1:
+ tmp_read_data = CORE_NAME1;
+
+ ADDR_VERSION:
+ tmp_read_data = CORE_VERSION;
+
+ ADDR_CTRL:
+ tmp_read_data = {29'h0, mode_reg, next_reg, init_reg};
+
+ ADDR_STATUS:
+ tmp_read_data = {30'h0, digest_valid_reg, ready_reg};
+
+ default:
+ begin
+ end
+ endcase // case (address)
+ end
+ end
+ end // addr_decoder
+endmodule // sha256
+
+//======================================================================
+// EOF sha256.v
+//======================================================================
diff --git a/Verilog_Code/sha256_core.v b/Verilog_Code/sha256_core.v
new file mode 100644
index 0000000..b2c880e
--- /dev/null
+++ b/Verilog_Code/sha256_core.v
@@ -0,0 +1,552 @@
+//======================================================================
+//
+// sha256_core.v
+// -------------
+// Verilog 2001 implementation of the SHA-256 hash function.
+// This is the internal core with wide interfaces.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2013, Secworks Sweden AB
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. 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.
+//
+// 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 OWNER 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.
+//
+//======================================================================
+
+`default_nettype none
+
+module sha256_core(
+ input wire clk,
+ input wire reset_n,
+
+ input wire init,
+ input wire next,
+ input wire mode,
+
+ input wire [511 : 0] block,
+
+ output wire ready,
+ output wire [255 : 0] digest,
+ output wire digest_valid
+ );
+
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ localparam SHA224_H0_0 = 32'hc1059ed8;
+ localparam SHA224_H0_1 = 32'h367cd507;
+ localparam SHA224_H0_2 = 32'h3070dd17;
+ localparam SHA224_H0_3 = 32'hf70e5939;
+ localparam SHA224_H0_4 = 32'hffc00b31;
+ localparam SHA224_H0_5 = 32'h68581511;
+ localparam SHA224_H0_6 = 32'h64f98fa7;
+ localparam SHA224_H0_7 = 32'hbefa4fa4;
+
+ localparam SHA256_H0_0 = 32'h6a09e667;
+ localparam SHA256_H0_1 = 32'hbb67ae85;
+ localparam SHA256_H0_2 = 32'h3c6ef372;
+ localparam SHA256_H0_3 = 32'ha54ff53a;
+ localparam SHA256_H0_4 = 32'h510e527f;
+ localparam SHA256_H0_5 = 32'h9b05688c;
+ localparam SHA256_H0_6 = 32'h1f83d9ab;
+ localparam SHA256_H0_7 = 32'h5be0cd19;
+
+ localparam SHA256_ROUNDS = 63;
+
+ localparam CTRL_IDLE = 0;
+ localparam CTRL_ROUNDS = 1;
+ localparam CTRL_DONE = 2;
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+ reg [31 : 0] a_reg;
+ reg [31 : 0] a_new;
+ reg [31 : 0] b_reg;
+ reg [31 : 0] b_new;
+ reg [31 : 0] c_reg;
+ reg [31 : 0] c_new;
+ reg [31 : 0] d_reg;
+ reg [31 : 0] d_new;
+ reg [31 : 0] e_reg;
+ reg [31 : 0] e_new;
+ reg [31 : 0] f_reg;
+ reg [31 : 0] f_new;
+ reg [31 : 0] g_reg;
+ reg [31 : 0] g_new;
+ reg [31 : 0] h_reg;
+ reg [31 : 0] h_new;
+ reg a_h_we;
+
+ reg [31 : 0] H0_reg;
+ reg [31 : 0] H0_new;
+ reg [31 : 0] H1_reg;
+ reg [31 : 0] H1_new;
+ reg [31 : 0] H2_reg;
+ reg [31 : 0] H2_new;
+ reg [31 : 0] H3_reg;
+ reg [31 : 0] H3_new;
+ reg [31 : 0] H4_reg;
+ reg [31 : 0] H4_new;
+ reg [31 : 0] H5_reg;
+ reg [31 : 0] H5_new;
+ reg [31 : 0] H6_reg;
+ reg [31 : 0] H6_new;
+ reg [31 : 0] H7_reg;
+ reg [31 : 0] H7_new;
+ reg H_we;
+
+ reg [5 : 0] t_ctr_reg;
+ reg [5 : 0] t_ctr_new;
+ reg t_ctr_we;
+ reg t_ctr_inc;
+ reg t_ctr_rst;
+
+ reg digest_valid_reg;
+ reg digest_valid_new;
+ reg digest_valid_we;
+
+ reg [1 : 0] sha256_ctrl_reg;
+ reg [1 : 0] sha256_ctrl_new;
+ reg sha256_ctrl_we;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg digest_init;
+ reg digest_update;
+
+ reg state_init;
+ reg state_update;
+
+ reg first_block;
+
+ reg ready_flag;
+
+ reg [31 : 0] t1;
+ reg [31 : 0] t2;
+
+ wire [31 : 0] k_data;
+
+ reg w_init;
+ reg w_next;
+ wire [31 : 0] w_data;
+
+
+ //----------------------------------------------------------------
+ // Module instantiantions.
+ //----------------------------------------------------------------
+ sha256_k_constants k_constants_inst(
+ .round(t_ctr_reg),
+ .K(k_data)
+ );
+
+
+ sha256_w_mem w_mem_inst(
+ .clk(clk),
+ .reset_n(reset_n),
+
+ .block(block),
+
+ .init(w_init),
+ .next(w_next),
+ .w(w_data)
+ );
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign ready = ready_flag;
+
+ assign digest = {H0_reg, H1_reg, H2_reg, H3_reg,
+ H4_reg, H5_reg, H6_reg, H7_reg};
+
+ assign digest_valid = digest_valid_reg;
+
+
+ //----------------------------------------------------------------
+ // reg_update
+ // Update functionality for all registers in the core.
+ // All registers are positive edge triggered with asynchronous
+ // active low reset. All registers have write enable.
+ //----------------------------------------------------------------
+ always @ (posedge clk or negedge reset_n)
+ begin : reg_update
+ if (!reset_n)
+ begin
+ a_reg <= 32'h0;
+ b_reg <= 32'h0;
+ c_reg <= 32'h0;
+ d_reg <= 32'h0;
+ e_reg <= 32'h0;
+ f_reg <= 32'h0;
+ g_reg <= 32'h0;
+ h_reg <= 32'h0;
+ H0_reg <= 32'h0;
+ H1_reg <= 32'h0;
+ H2_reg <= 32'h0;
+ H3_reg <= 32'h0;
+ H4_reg <= 32'h0;
+ H5_reg <= 32'h0;
+ H6_reg <= 32'h0;
+ H7_reg <= 32'h0;
+ digest_valid_reg <= 0;
+ t_ctr_reg <= 6'h0;
+ sha256_ctrl_reg <= CTRL_IDLE;
+ end
+ else
+ begin
+
+ if (a_h_we)
+ begin
+ a_reg <= a_new;
+ b_reg <= b_new;
+ c_reg <= c_new;
+ d_reg <= d_new;
+ e_reg <= e_new;
+ f_reg <= f_new;
+ g_reg <= g_new;
+ h_reg <= h_new;
+ end
+
+ if (H_we)
+ begin
+ H0_reg <= H0_new;
+ H1_reg <= H1_new;
+ H2_reg <= H2_new;
+ H3_reg <= H3_new;
+ H4_reg <= H4_new;
+ H5_reg <= H5_new;
+ H6_reg <= H6_new;
+ H7_reg <= H7_new;
+ end
+
+ if (t_ctr_we)
+ t_ctr_reg <= t_ctr_new;
+
+ if (digest_valid_we)
+ digest_valid_reg <= digest_valid_new;
+
+ if (sha256_ctrl_we)
+ sha256_ctrl_reg <= sha256_ctrl_new;
+ end
+ end // reg_update
+
+
+ //----------------------------------------------------------------
+ // digest_logic
+ //
+ // The logic needed to init as well as update the digest.
+ //----------------------------------------------------------------
+ always @*
+ begin : digest_logic
+ H0_new = 32'h0;
+ H1_new = 32'h0;
+ H2_new = 32'h0;
+ H3_new = 32'h0;
+ H4_new = 32'h0;
+ H5_new = 32'h0;
+ H6_new = 32'h0;
+ H7_new = 32'h0;
+ H_we = 0;
+
+ if (digest_init)
+ begin
+ H_we = 1;
+ if (mode)
+ begin
+ H0_new = SHA256_H0_0;
+ H1_new = SHA256_H0_1;
+ H2_new = SHA256_H0_2;
+ H3_new = SHA256_H0_3;
+ H4_new = SHA256_H0_4;
+ H5_new = SHA256_H0_5;
+ H6_new = SHA256_H0_6;
+ H7_new = SHA256_H0_7;
+ end
+ else
+ begin
+ H0_new = SHA224_H0_0;
+ H1_new = SHA224_H0_1;
+ H2_new = SHA224_H0_2;
+ H3_new = SHA224_H0_3;
+ H4_new = SHA224_H0_4;
+ H5_new = SHA224_H0_5;
+ H6_new = SHA224_H0_6;
+ H7_new = SHA224_H0_7;
+ end
+ end
+
+ if (digest_update)
+ begin
+ H0_new = H0_reg + a_reg;
+ H1_new = H1_reg + b_reg;
+ H2_new = H2_reg + c_reg;
+ H3_new = H3_reg + d_reg;
+ H4_new = H4_reg + e_reg;
+ H5_new = H5_reg + f_reg;
+ H6_new = H6_reg + g_reg;
+ H7_new = H7_reg + h_reg;
+ H_we = 1;
+ end
+ end // digest_logic
+
+
+ //----------------------------------------------------------------
+ // t1_logic
+ //
+ // The logic for the T1 function.
+ //----------------------------------------------------------------
+ always @*
+ begin : t1_logic
+ reg [31 : 0] sum1;
+ reg [31 : 0] ch;
+
+ sum1 = {e_reg[5 : 0], e_reg[31 : 6]} ^
+ {e_reg[10 : 0], e_reg[31 : 11]} ^
+ {e_reg[24 : 0], e_reg[31 : 25]};
+
+ ch = (e_reg & f_reg) ^ ((~e_reg) & g_reg);
+
+ t1 = h_reg + sum1 + ch + w_data + k_data;
+ end // t1_logic
+
+
+ //----------------------------------------------------------------
+ // t2_logic
+ //
+ // The logic for the T2 function
+ //----------------------------------------------------------------
+ always @*
+ begin : t2_logic
+ reg [31 : 0] sum0;
+ reg [31 : 0] maj;
+
+ sum0 = {a_reg[1 : 0], a_reg[31 : 2]} ^
+ {a_reg[12 : 0], a_reg[31 : 13]} ^
+ {a_reg[21 : 0], a_reg[31 : 22]};
+
+ maj = (a_reg & b_reg) ^ (a_reg & c_reg) ^ (b_reg & c_reg);
+
+ t2 = sum0 + maj;
+ end // t2_logic
+
+
+ //----------------------------------------------------------------
+ // state_logic
+ //
+ // The logic needed to init as well as update the state during
+ // round processing.
+ //----------------------------------------------------------------
+ always @*
+ begin : state_logic
+ a_new = 32'h0;
+ b_new = 32'h0;
+ c_new = 32'h0;
+ d_new = 32'h0;
+ e_new = 32'h0;
+ f_new = 32'h0;
+ g_new = 32'h0;
+ h_new = 32'h0;
+ a_h_we = 0;
+
+ if (state_init)
+ begin
+ a_h_we = 1;
+ if (first_block)
+ begin
+ if (mode)
+ begin
+ a_new = SHA256_H0_0;
+ b_new = SHA256_H0_1;
+ c_new = SHA256_H0_2;
+ d_new = SHA256_H0_3;
+ e_new = SHA256_H0_4;
+ f_new = SHA256_H0_5;
+ g_new = SHA256_H0_6;
+ h_new = SHA256_H0_7;
+ end
+ else
+ begin
+ a_new = SHA224_H0_0;
+ b_new = SHA224_H0_1;
+ c_new = SHA224_H0_2;
+ d_new = SHA224_H0_3;
+ e_new = SHA224_H0_4;
+ f_new = SHA224_H0_5;
+ g_new = SHA224_H0_6;
+ h_new = SHA224_H0_7;
+ end
+ end
+ else
+ begin
+ a_new = H0_reg;
+ b_new = H1_reg;
+ c_new = H2_reg;
+ d_new = H3_reg;
+ e_new = H4_reg;
+ f_new = H5_reg;
+ g_new = H6_reg;
+ h_new = H7_reg;
+ end
+ end
+
+ if (state_update)
+ begin
+ a_new = t1 + t2;
+ b_new = a_reg;
+ c_new = b_reg;
+ d_new = c_reg;
+ e_new = d_reg + t1;
+ f_new = e_reg;
+ g_new = f_reg;
+ h_new = g_reg;
+ a_h_we = 1;
+ end
+ end // state_logic
+
+
+ //----------------------------------------------------------------
+ // t_ctr
+ //
+ // Update logic for the round counter, a monotonically
+ // increasing counter with reset.
+ //----------------------------------------------------------------
+ always @*
+ begin : t_ctr
+ t_ctr_new = 0;
+ t_ctr_we = 0;
+
+ if (t_ctr_rst)
+ begin
+ t_ctr_new = 0;
+ t_ctr_we = 1;
+ end
+
+ if (t_ctr_inc)
+ begin
+ t_ctr_new = t_ctr_reg + 1'b1;
+ t_ctr_we = 1;
+ end
+ end // t_ctr
+
+
+ //----------------------------------------------------------------
+ // sha256_ctrl_fsm
+ //
+ // Logic for the state machine controlling the core behaviour.
+ //----------------------------------------------------------------
+ always @*
+ begin : sha256_ctrl_fsm
+ digest_init = 0;
+ digest_update = 0;
+
+ state_init = 0;
+ state_update = 0;
+
+ first_block = 0;
+ ready_flag = 0;
+
+ w_init = 0;
+ w_next = 0;
+
+ t_ctr_inc = 0;
+ t_ctr_rst = 0;
+
+ digest_valid_new = 0;
+ digest_valid_we = 0;
+
+ sha256_ctrl_new = CTRL_IDLE;
+ sha256_ctrl_we = 0;
+
+
+ case (sha256_ctrl_reg)
+ CTRL_IDLE:
+ begin
+ ready_flag = 1;
+
+ if (init)
+ begin
+ digest_init = 1;
+ w_init = 1;
+ state_init = 1;
+ first_block = 1;
+ t_ctr_rst = 1;
+ digest_valid_new = 0;
+ digest_valid_we = 1;
+ sha256_ctrl_new = CTRL_ROUNDS;
+ sha256_ctrl_we = 1;
+ end
+
+ if (next)
+ begin
+ t_ctr_rst = 1;
+ w_init = 1;
+ state_init = 1;
+ digest_valid_new = 0;
+ digest_valid_we = 1;
+ sha256_ctrl_new = CTRL_ROUNDS;
+ sha256_ctrl_we = 1;
+ end
+ end
+
+
+ CTRL_ROUNDS:
+ begin
+ w_next = 1;
+ state_update = 1;
+ t_ctr_inc = 1;
+
+ if (t_ctr_reg == SHA256_ROUNDS)
+ begin
+ sha256_ctrl_new = CTRL_DONE;
+ sha256_ctrl_we = 1;
+ end
+ end
+
+
+ CTRL_DONE:
+ begin
+ digest_update = 1;
+ digest_valid_new = 1;
+ digest_valid_we = 1;
+
+ sha256_ctrl_new = CTRL_IDLE;
+ sha256_ctrl_we = 1;
+ end
+ endcase // case (sha256_ctrl_reg)
+ end // sha256_ctrl_fsm
+
+endmodule // sha256_core
+
+//======================================================================
+// EOF sha256_core.v
+//======================================================================
diff --git a/Verilog_Code/sha256_k_constants.v b/Verilog_Code/sha256_k_constants.v
new file mode 100644
index 0000000..bae748e
--- /dev/null
+++ b/Verilog_Code/sha256_k_constants.v
@@ -0,0 +1,134 @@
+//======================================================================
+//
+// sha256_k_constants.v
+// --------------------
+// The table K with constants in the SHA-256 hash function.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2013, Secworks Sweden AB
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. 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.
+//
+// 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 OWNER 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.
+//
+//======================================================================
+
+`default_nettype none
+
+module sha256_k_constants(
+ input wire [5 : 0] round,
+ output wire [31 : 0] K
+ );
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg [31 : 0] tmp_K;
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign K = tmp_K;
+
+
+ //----------------------------------------------------------------
+ // round_mux
+ //----------------------------------------------------------------
+ always @*
+ begin : round_mux
+ case(round)
+ 00: tmp_K = 32'h428a2f98;
+ 01: tmp_K = 32'h71374491;
+ 02: tmp_K = 32'hb5c0fbcf;
+ 03: tmp_K = 32'he9b5dba5;
+ 04: tmp_K = 32'h3956c25b;
+ 05: tmp_K = 32'h59f111f1;
+ 06: tmp_K = 32'h923f82a4;
+ 07: tmp_K = 32'hab1c5ed5;
+ 08: tmp_K = 32'hd807aa98;
+ 09: tmp_K = 32'h12835b01;
+ 10: tmp_K = 32'h243185be;
+ 11: tmp_K = 32'h550c7dc3;
+ 12: tmp_K = 32'h72be5d74;
+ 13: tmp_K = 32'h80deb1fe;
+ 14: tmp_K = 32'h9bdc06a7;
+ 15: tmp_K = 32'hc19bf174;
+ 16: tmp_K = 32'he49b69c1;
+ 17: tmp_K = 32'hefbe4786;
+ 18: tmp_K = 32'h0fc19dc6;
+ 19: tmp_K = 32'h240ca1cc;
+ 20: tmp_K = 32'h2de92c6f;
+ 21: tmp_K = 32'h4a7484aa;
+ 22: tmp_K = 32'h5cb0a9dc;
+ 23: tmp_K = 32'h76f988da;
+ 24: tmp_K = 32'h983e5152;
+ 25: tmp_K = 32'ha831c66d;
+ 26: tmp_K = 32'hb00327c8;
+ 27: tmp_K = 32'hbf597fc7;
+ 28: tmp_K = 32'hc6e00bf3;
+ 29: tmp_K = 32'hd5a79147;
+ 30: tmp_K = 32'h06ca6351;
+ 31: tmp_K = 32'h14292967;
+ 32: tmp_K = 32'h27b70a85;
+ 33: tmp_K = 32'h2e1b2138;
+ 34: tmp_K = 32'h4d2c6dfc;
+ 35: tmp_K = 32'h53380d13;
+ 36: tmp_K = 32'h650a7354;
+ 37: tmp_K = 32'h766a0abb;
+ 38: tmp_K = 32'h81c2c92e;
+ 39: tmp_K = 32'h92722c85;
+ 40: tmp_K = 32'ha2bfe8a1;
+ 41: tmp_K = 32'ha81a664b;
+ 42: tmp_K = 32'hc24b8b70;
+ 43: tmp_K = 32'hc76c51a3;
+ 44: tmp_K = 32'hd192e819;
+ 45: tmp_K = 32'hd6990624;
+ 46: tmp_K = 32'hf40e3585;
+ 47: tmp_K = 32'h106aa070;
+ 48: tmp_K = 32'h19a4c116;
+ 49: tmp_K = 32'h1e376c08;
+ 50: tmp_K = 32'h2748774c;
+ 51: tmp_K = 32'h34b0bcb5;
+ 52: tmp_K = 32'h391c0cb3;
+ 53: tmp_K = 32'h4ed8aa4a;
+ 54: tmp_K = 32'h5b9cca4f;
+ 55: tmp_K = 32'h682e6ff3;
+ 56: tmp_K = 32'h748f82ee;
+ 57: tmp_K = 32'h78a5636f;
+ 58: tmp_K = 32'h84c87814;
+ 59: tmp_K = 32'h8cc70208;
+ 60: tmp_K = 32'h90befffa;
+ 61: tmp_K = 32'ha4506ceb;
+ 62: tmp_K = 32'hbef9a3f7;
+ 63: tmp_K = 32'hc67178f2;
+ endcase // case (round)
+ end // block: round_mux
+endmodule // sha256_k_constants
+
+//======================================================================
+// sha256_k_constants.v
+//======================================================================
diff --git a/Verilog_Code/sha256_w_mem.v b/Verilog_Code/sha256_w_mem.v
new file mode 100644
index 0000000..06f4d46
--- /dev/null
+++ b/Verilog_Code/sha256_w_mem.v
@@ -0,0 +1,272 @@
+//======================================================================
+//
+// sha256_w_mem_regs.v
+// -------------------
+// The W memory. This version uses 16 32-bit registers as a sliding
+// window to generate the 64 words.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2013, Secworks Sweden AB
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. 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.
+//
+// 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 OWNER 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.
+//
+//======================================================================
+
+`default_nettype none
+
+module sha256_w_mem(
+ input wire clk,
+ input wire reset_n,
+
+ input wire [511 : 0] block,
+
+ input wire init,
+ input wire next,
+ output wire [31 : 0] w
+ );
+
+
+ //----------------------------------------------------------------
+ // Registers including update variables and write enable.
+ //----------------------------------------------------------------
+ reg [31 : 0] w_mem [0 : 15];
+ reg [31 : 0] w_mem00_new;
+ reg [31 : 0] w_mem01_new;
+ reg [31 : 0] w_mem02_new;
+ reg [31 : 0] w_mem03_new;
+ reg [31 : 0] w_mem04_new;
+ reg [31 : 0] w_mem05_new;
+ reg [31 : 0] w_mem06_new;
+ reg [31 : 0] w_mem07_new;
+ reg [31 : 0] w_mem08_new;
+ reg [31 : 0] w_mem09_new;
+ reg [31 : 0] w_mem10_new;
+ reg [31 : 0] w_mem11_new;
+ reg [31 : 0] w_mem12_new;
+ reg [31 : 0] w_mem13_new;
+ reg [31 : 0] w_mem14_new;
+ reg [31 : 0] w_mem15_new;
+ reg w_mem_we;
+
+ reg [5 : 0] w_ctr_reg;
+ reg [5 : 0] w_ctr_new;
+ reg w_ctr_we;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg [31 : 0] w_tmp;
+ reg [31 : 0] w_new;
+
+
+ //----------------------------------------------------------------
+ // Concurrent connectivity for ports etc.
+ //----------------------------------------------------------------
+ assign w = w_tmp;
+
+
+ //----------------------------------------------------------------
+ // reg_update
+ // Update functionality for all registers in the core.
+ // All registers are positive edge triggered with synchronous
+ // active low reset. All registers have write enable.
+ //----------------------------------------------------------------
+ always @ (posedge clk or negedge reset_n)
+ begin : reg_update
+ integer i;
+
+ if (!reset_n)
+ begin
+ for (i = 0 ; i < 16 ; i = i + 1)
+ w_mem[i] <= 32'h0;
+
+ w_ctr_reg <= 6'h0;
+ end
+ else
+ begin
+ if (w_mem_we)
+ begin
+ w_mem[00] <= w_mem00_new;
+ w_mem[01] <= w_mem01_new;
+ w_mem[02] <= w_mem02_new;
+ w_mem[03] <= w_mem03_new;
+ w_mem[04] <= w_mem04_new;
+ w_mem[05] <= w_mem05_new;
+ w_mem[06] <= w_mem06_new;
+ w_mem[07] <= w_mem07_new;
+ w_mem[08] <= w_mem08_new;
+ w_mem[09] <= w_mem09_new;
+ w_mem[10] <= w_mem10_new;
+ w_mem[11] <= w_mem11_new;
+ w_mem[12] <= w_mem12_new;
+ w_mem[13] <= w_mem13_new;
+ w_mem[14] <= w_mem14_new;
+ w_mem[15] <= w_mem15_new;
+ end
+
+ if (w_ctr_we)
+ w_ctr_reg <= w_ctr_new;
+ end
+ end // reg_update
+
+
+ //----------------------------------------------------------------
+ // select_w
+ //
+ // Mux for the external read operation. This is where we exract
+ // the W variable.
+ //----------------------------------------------------------------
+ always @*
+ begin : select_w
+ if (w_ctr_reg < 16)
+ w_tmp = w_mem[w_ctr_reg[3 : 0]];
+ else
+ w_tmp = w_new;
+ end // select_w
+
+
+ //----------------------------------------------------------------
+ // w_new_logic
+ //
+ // Logic that calculates the next value to be inserted into
+ // the sliding window of the memory.
+ //----------------------------------------------------------------
+ always @*
+ begin : w_mem_update_logic
+ reg [31 : 0] w_0;
+ reg [31 : 0] w_1;
+ reg [31 : 0] w_9;
+ reg [31 : 0] w_14;
+ reg [31 : 0] d0;
+ reg [31 : 0] d1;
+
+ w_mem00_new = 32'h0;
+ w_mem01_new = 32'h0;
+ w_mem02_new = 32'h0;
+ w_mem03_new = 32'h0;
+ w_mem04_new = 32'h0;
+ w_mem05_new = 32'h0;
+ w_mem06_new = 32'h0;
+ w_mem07_new = 32'h0;
+ w_mem08_new = 32'h0;
+ w_mem09_new = 32'h0;
+ w_mem10_new = 32'h0;
+ w_mem11_new = 32'h0;
+ w_mem12_new = 32'h0;
+ w_mem13_new = 32'h0;
+ w_mem14_new = 32'h0;
+ w_mem15_new = 32'h0;
+ w_mem_we = 0;
+
+ w_0 = w_mem[0];
+ w_1 = w_mem[1];
+ w_9 = w_mem[9];
+ w_14 = w_mem[14];
+
+ d0 = {w_1[6 : 0], w_1[31 : 7]} ^
+ {w_1[17 : 0], w_1[31 : 18]} ^
+ {3'b000, w_1[31 : 3]};
+
+ d1 = {w_14[16 : 0], w_14[31 : 17]} ^
+ {w_14[18 : 0], w_14[31 : 19]} ^
+ {10'b0000000000, w_14[31 : 10]};
+
+ w_new = d1 + w_9 + d0 + w_0;
+
+ if (init)
+ begin
+ w_mem00_new = block[511 : 480];
+ w_mem01_new = block[479 : 448];
+ w_mem02_new = block[447 : 416];
+ w_mem03_new = block[415 : 384];
+ w_mem04_new = block[383 : 352];
+ w_mem05_new = block[351 : 320];
+ w_mem06_new = block[319 : 288];
+ w_mem07_new = block[287 : 256];
+ w_mem08_new = block[255 : 224];
+ w_mem09_new = block[223 : 192];
+ w_mem10_new = block[191 : 160];
+ w_mem11_new = block[159 : 128];
+ w_mem12_new = block[127 : 96];
+ w_mem13_new = block[95 : 64];
+ w_mem14_new = block[63 : 32];
+ w_mem15_new = block[31 : 0];
+ w_mem_we = 1;
+ end
+
+ if (next && (w_ctr_reg > 15))
+ begin
+ w_mem00_new = w_mem[01];
+ w_mem01_new = w_mem[02];
+ w_mem02_new = w_mem[03];
+ w_mem03_new = w_mem[04];
+ w_mem04_new = w_mem[05];
+ w_mem05_new = w_mem[06];
+ w_mem06_new = w_mem[07];
+ w_mem07_new = w_mem[08];
+ w_mem08_new = w_mem[09];
+ w_mem09_new = w_mem[10];
+ w_mem10_new = w_mem[11];
+ w_mem11_new = w_mem[12];
+ w_mem12_new = w_mem[13];
+ w_mem13_new = w_mem[14];
+ w_mem14_new = w_mem[15];
+ w_mem15_new = w_new;
+ w_mem_we = 1;
+ end
+ end // w_mem_update_logic
+
+
+ //----------------------------------------------------------------
+ // w_ctr
+ // W schedule adress counter. Counts from 0x10 to 0x3f and
+ // is used to expand the block into words.
+ //----------------------------------------------------------------
+ always @*
+ begin : w_ctr
+ w_ctr_new = 6'h0;
+ w_ctr_we = 1'h0;
+
+ if (init)
+ begin
+ w_ctr_new = 6'h0;
+ w_ctr_we = 1'h1;
+ end
+
+ if (next)
+ begin
+ w_ctr_new = w_ctr_reg + 6'h01;
+ w_ctr_we = 1'h1;
+ end
+ end // w_ctr
+endmodule // sha256_w_mem
+
+//======================================================================
+// sha256_w_mem.v
+//======================================================================
diff --git a/Verilog_Code/tb_clock_mux.v b/Verilog_Code/tb_clock_mux.v
new file mode 100644
index 0000000..cf112a8
--- /dev/null
+++ b/Verilog_Code/tb_clock_mux.v
@@ -0,0 +1,142 @@
+//
+// Switch between two clock sources testbench.
+//
+
+//
+// Design by G.J. van Loo, FenLogic Ltd, 15-January-2017.
+//
+// This program is free software. It comes without any guarantees or
+// warranty to the extent permitted by applicable law. Although the
+// author has attempted to find and correct any bugs in this free software
+// program, the author is not responsible for any damage or losses of any
+// kind caused by the use or misuse of the program. You can redistribute
+// the program and or modify it in any form without obligations, but the
+// author would appreciated if the credits stays in.
+//
+module clock_mux_test;
+
+// For specify to work CLK1PERIOD must be <= CLK2PERIOD !!
+localparam CLK1PERIOD = 8,
+ CLK2PERIOD = 10;
+
+reg clk1; // Clock 1
+reg clk2; // Clock 2
+reg reset_n; // System reset
+reg sel_clk2; // Select clock2 when high
+wire clk1or2; // Selected clock
+
+integer l,r1,r2;
+
+initial
+begin
+ sel_clk2 = 1'b0;
+ reset_n = 1'b0;
+ #50;
+ reset_n = 1'b1;
+ #250;
+ sel_clk2 = 1'b1;
+ #250;
+ sel_clk2 = 1'b0;
+ #1000;
+
+ // Test reset release with sel2 high
+ reset_n = 1'b0;
+ #50;
+ sel_clk2 = 1'b1;
+ #50;
+ reset_n = 1'b1;
+ #250;
+ // Test reset release and sel2 high at the same time
+ reset_n = 1'b0;
+ #50;
+ sel_clk2 = 1'b1;
+ reset_n = 1'b1;
+ #250;
+
+ #1000;
+
+
+ //
+ // Test clock not present
+ //
+ force clk2 = 1'b0;
+ #250;
+ // switch to not running clk2
+ sel_clk2 = 1'b1;
+ #250;
+ // switch back to clk1
+ sel_clk2 = 1'b0;
+ #250;
+ // switch to not running clk2
+ sel_clk2 = 1'b1;
+ #250;
+ // now clock2 comes on again
+ // whilst it is selected
+ release clk2;
+ #250;
+ // switch back to clk1
+ sel_clk2 = 1'b0;
+ #250;
+
+ // Switch often but never faster then 2xslowest input clock period
+ for (l=0; l<10000; l=l+1)
+ begin
+ r1 = (($random>>3)&32'h1F)+2*CLK2PERIOD;
+ r2 = (($random>>4)&32'h1F)+2*CLK2PERIOD;
+ sel_clk2 = 1'b1;
+ #r1;
+ sel_clk2 = 1'b0;
+ #r2;
+ end
+ #1000;
+
+ // Really nasty and illegal clock switching.
+ // Causes low period violations.
+ // This gives more confidence that the testbench seems to work.
+ $display("@%0t Illegal 'sel_clk2' pattern hereafter",$time);
+ $display(" gives rise to low period violations.");
+ $display(" Ignore all warnings from here.");
+ for (l=0; l<500; l=l+1)
+ begin
+ r1 = ($random>>3)&32'h1F+CLK2PERIOD;
+ r2 = ($random>>4)&32'h1F+CLK2PERIOD;
+ sel_clk2 = 1'b1;
+ #r1;
+ sel_clk2 = 1'b0;
+ #r2;
+ end
+ $stop;
+end
+
+initial
+begin
+ clk1 = 1'b0;
+ forever
+ #(CLK1PERIOD/2) clk1 <= ~clk1;
+end
+
+initial
+begin
+ clk2 = 1'b0;
+ forever
+ #(CLK2PERIOD/2) clk2 <= ~clk2;
+end
+
+clock_mux clock_mux0
+ (
+ .clk1 (clk1), // Clock 1
+ .clk2 (clk2), // Clock 2
+ .reset_n (reset_n), // System reset
+ .sel_clk2(sel_clk2), // Select clock2 when high
+ .clk1or2 (clk1or2) // Selected clock
+ );
+
+// Now check if time high or low is ever smaller than CLK1PERIOD/2
+// (This is why CLK1PERIOD <= CLK2PERIOD)
+specify
+$width(posedge clk1or2, CLK1PERIOD/2);
+$width(negedge clk1or2, CLK1PERIOD/2);
+endspecify
+
+endmodule // clock_mux_test
+
diff --git a/Verilog_Code/tb_sha256.v b/Verilog_Code/tb_sha256.v
new file mode 100644
index 0000000..3796e73
--- /dev/null
+++ b/Verilog_Code/tb_sha256.v
@@ -0,0 +1,718 @@
+//======================================================================
+//
+// tb_sha256.v
+// -----------
+// Testbench for the SHA-256 top level wrapper.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2013, Secworks Sweden AB
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. 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.
+//
+// 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 OWNER 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.
+//
+//======================================================================
+
+`default_nettype none
+
+module tb_sha256();
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter DEBUG = 0;
+
+ parameter CLK_HALF_PERIOD = 2;
+ parameter CLK_PERIOD = 2 * CLK_HALF_PERIOD;
+
+ // The address map.
+ parameter ADDR_NAME0 = 8'h00;
+ parameter ADDR_NAME1 = 8'h01;
+ parameter ADDR_VERSION = 8'h02;
+
+ parameter ADDR_CTRL = 8'h08;
+ parameter CTRL_INIT_VALUE = 8'h01;
+ parameter CTRL_NEXT_VALUE = 8'h02;
+ parameter CTRL_MODE_VALUE = 8'h04;
+
+ parameter ADDR_STATUS = 8'h09;
+ parameter STATUS_READY_BIT = 0;
+ parameter STATUS_VALID_BIT = 1;
+
+ parameter ADDR_BLOCK0 = 8'h10;
+ parameter ADDR_BLOCK1 = 8'h11;
+ parameter ADDR_BLOCK2 = 8'h12;
+ parameter ADDR_BLOCK3 = 8'h13;
+ parameter ADDR_BLOCK4 = 8'h14;
+ parameter ADDR_BLOCK5 = 8'h15;
+ parameter ADDR_BLOCK6 = 8'h16;
+ parameter ADDR_BLOCK7 = 8'h17;
+ parameter ADDR_BLOCK8 = 8'h18;
+ parameter ADDR_BLOCK9 = 8'h19;
+ parameter ADDR_BLOCK10 = 8'h1a;
+ parameter ADDR_BLOCK11 = 8'h1b;
+ parameter ADDR_BLOCK12 = 8'h1c;
+ parameter ADDR_BLOCK13 = 8'h1d;
+ parameter ADDR_BLOCK14 = 8'h1e;
+ parameter ADDR_BLOCK15 = 8'h1f;
+
+ parameter ADDR_DIGEST0 = 8'h20;
+ parameter ADDR_DIGEST1 = 8'h21;
+ parameter ADDR_DIGEST2 = 8'h22;
+ parameter ADDR_DIGEST3 = 8'h23;
+ parameter ADDR_DIGEST4 = 8'h24;
+ parameter ADDR_DIGEST5 = 8'h25;
+ parameter ADDR_DIGEST6 = 8'h26;
+ parameter ADDR_DIGEST7 = 8'h27;
+
+ parameter SHA224_MODE = 0;
+ parameter SHA256_MODE = 1;
+
+
+ //----------------------------------------------------------------
+ // 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_cs;
+ reg tb_we;
+ reg [7 : 0] tb_address;
+ reg [31 : 0] tb_write_data;
+ wire [31 : 0] tb_read_data;
+ wire tb_error;
+
+ reg [31 : 0] read_data;
+ reg [255 : 0] digest_data;
+
+
+ //----------------------------------------------------------------
+ // Device Under Test.
+ //----------------------------------------------------------------
+ sha256 dut(
+ .clk(tb_clk),
+ .reset_n(tb_reset_n),
+
+ .cs(tb_cs),
+ .we(tb_we),
+
+
+ .address(tb_address),
+ .write_data(tb_write_data),
+ .read_data(tb_read_data),
+ .error(tb_error)
+ );
+
+
+ //----------------------------------------------------------------
+ // 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_dut_state()
+ //
+ // Dump the state of the dump when needed.
+ //----------------------------------------------------------------
+ task dump_dut_state;
+ begin
+ $display("State of DUT");
+ $display("------------");
+ $display("Inputs and outputs:");
+ $display("cs = 0x%01x, we = 0x%01x",
+ dut.cs, dut.we);
+ $display("address = 0x%02x", dut.address);
+ $display("write_data = 0x%08x, read_data = 0x%08x",
+ dut.write_data, dut.read_data);
+ $display("tmp_read_data = 0x%08x", dut.tmp_read_data);
+ $display("");
+
+ $display("Control and status:");
+ $display("ctrl = 0x%02x, status = 0x%02x",
+ {dut.next_reg, dut.init_reg},
+ {dut.digest_valid_reg, dut.ready_reg});
+ $display("");
+
+ $display("Message block:");
+ $display("block0 = 0x%08x, block1 = 0x%08x, block2 = 0x%08x, block3 = 0x%08x",
+ dut.block_reg[00], dut.block_reg[01], dut.block_reg[02], dut.block_reg[03]);
+// $display("block4 = 0x%08x, block5 = 0x%08x, block6 = 0x%08x, block7 = 0x%08x",
+// dut.block_reg[04], dut.block_reg[05], dut.block_reg[06], dut.block_reg[07]);
+
+ $display("block8 = 0x%08x, block9 = 0x%08x, block10 = 0x%08x, block11 = 0x%08x",
+ dut.block_reg[08], dut.block_reg[09], dut.block_reg[10], dut.block_reg[11]);
+ $display("block12 = 0x%08x, block13 = 0x%08x, block14 = 0x%08x, block15 = 0x%08x",
+ dut.block_reg[12], dut.block_reg[13], dut.block_reg[14], dut.block_reg[15]);
+ $display("");
+
+ $display("Digest:");
+ $display("digest = 0x%064x", dut.digest_reg);
+ $display("");
+
+ end
+ endtask // dump_dut_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;
+ error_ctr = 32'h0;
+ tc_ctr = 32'h0;
+
+ tb_clk = 0;
+ tb_reset_n = 0;
+ tb_cs = 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
+
+
+ //----------------------------------------------------------------
+ // wait_ready()
+ //
+ // Wait for the ready flag in the dut to be set.
+ // (Actually we wait for either ready or valid to be set.)
+ //
+ // Note: It is the callers responsibility to call the function
+ // when the dut is actively processing and will in fact at some
+ // point set the flag.
+ //----------------------------------------------------------------
+ task wait_ready;
+ begin
+ read_data = 0;
+
+ while (read_data == 0)
+ begin
+ read_word(ADDR_STATUS);
+ end
+ end
+ endtask // wait_ready
+
+
+ //----------------------------------------------------------------
+ // write_word()
+ //
+ // Write the given word to the DUT using the DUT interface.
+ //----------------------------------------------------------------
+ task write_word(input [7 : 0] address,
+ input [31 : 0] word);
+ begin
+ if (DEBUG)
+ begin
+ $display("*** Writing 0x%08x to 0x%02x.", word, address);
+ $display("");
+ end
+
+ tb_address = address;
+ tb_write_data = word;
+ tb_cs = 1;
+ tb_we = 1;
+ #(CLK_PERIOD);
+ tb_cs = 0;
+ tb_we = 0;
+ end
+ endtask // write_word
+
+
+ //----------------------------------------------------------------
+ // write_block()
+ //
+ // Write the given block to the dut.
+ //----------------------------------------------------------------
+ task write_block(input [511 : 0] block);
+ begin
+ write_word(ADDR_BLOCK0, block[511 : 480]);
+ write_word(ADDR_BLOCK1, block[479 : 448]);
+ write_word(ADDR_BLOCK2, block[447 : 416]);
+ write_word(ADDR_BLOCK3, block[415 : 384]);
+ write_word(ADDR_BLOCK4, block[383 : 352]);
+ write_word(ADDR_BLOCK5, block[351 : 320]);
+ write_word(ADDR_BLOCK6, block[319 : 288]);
+ write_word(ADDR_BLOCK7, block[287 : 256]);
+ write_word(ADDR_BLOCK8, block[255 : 224]);
+ write_word(ADDR_BLOCK9, block[223 : 192]);
+ write_word(ADDR_BLOCK10, block[191 : 160]);
+ write_word(ADDR_BLOCK11, block[159 : 128]);
+ write_word(ADDR_BLOCK12, block[127 : 96]);
+ write_word(ADDR_BLOCK13, block[95 : 64]);
+ write_word(ADDR_BLOCK14, block[63 : 32]);
+ write_word(ADDR_BLOCK15, block[31 : 0]);
+ end
+ endtask // write_block
+
+
+ //----------------------------------------------------------------
+ // read_word()
+ //
+ // Read a data word from the given address in the DUT.
+ // the word read will be available in the global variable
+ // read_data.
+ //----------------------------------------------------------------
+ task read_word(input [7 : 0] address);
+ begin
+ tb_address = address;
+ tb_cs = 1;
+ tb_we = 0;
+ #(CLK_PERIOD);
+ read_data = tb_read_data;
+ tb_cs = 0;
+
+ if (DEBUG)
+ begin
+ $display("*** Reading 0x%08x from 0x%02x.", read_data, address);
+ $display("");
+ end
+ end
+ endtask // read_word
+
+
+ //----------------------------------------------------------------
+ // check_name_version()
+ //
+ // Read the name and version from the DUT.
+ //----------------------------------------------------------------
+ task check_name_version;
+ reg [31 : 0] name0;
+ reg [31 : 0] name1;
+ reg [31 : 0] version;
+ begin
+
+ read_word(ADDR_NAME0);
+ name0 = read_data;
+ read_word(ADDR_NAME1);
+ name1 = read_data;
+ read_word(ADDR_VERSION);
+ version = read_data;
+
+ $display("DUT name: %c%c%c%c%c%c%c%c",
+ name0[31 : 24], name0[23 : 16], name0[15 : 8], name0[7 : 0],
+ name1[31 : 24], name1[23 : 16], name1[15 : 8], name1[7 : 0]);
+ $display("DUT version: %c%c%c%c",
+ version[31 : 24], version[23 : 16], version[15 : 8], version[7 : 0]);
+ end
+ endtask // check_name_version
+
+
+ //----------------------------------------------------------------
+ // read_digest()
+ //
+ // Read the digest in the dut. The resulting digest will be
+ // available in the global variable digest_data.
+ //----------------------------------------------------------------
+ task read_digest;
+ begin
+ read_word(ADDR_DIGEST0);
+ digest_data[255 : 224] = read_data;
+ read_word(ADDR_DIGEST1);
+ digest_data[223 : 192] = read_data;
+ read_word(ADDR_DIGEST2);
+ digest_data[191 : 160] = read_data;
+ read_word(ADDR_DIGEST3);
+ digest_data[159 : 128] = read_data;
+ read_word(ADDR_DIGEST4);
+ digest_data[127 : 96] = read_data;
+ read_word(ADDR_DIGEST5);
+ digest_data[95 : 64] = read_data;
+ read_word(ADDR_DIGEST6);
+ digest_data[63 : 32] = read_data;
+ read_word(ADDR_DIGEST7);
+ digest_data[31 : 0] = read_data;
+ end
+ endtask // read_digest
+
+
+ //----------------------------------------------------------------
+ // single_block_test()
+ //
+ //
+ // Perform test of a single block digest.
+ //----------------------------------------------------------------
+ task single_block_test(input mode,
+ input [511 : 0] block,
+ input [255 : 0] expected);
+ begin
+ $display("*** TC%01d - Single block test started.", tc_ctr);
+
+ write_block(block);
+
+ if (mode)
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_INIT_VALUE));
+ else
+ write_word(ADDR_CTRL, CTRL_INIT_VALUE);
+
+ #(CLK_PERIOD);
+ wait_ready();
+ read_digest();
+
+ // We need to ignore the LSW in SHA224 mode.
+ if (mode == SHA224_MODE)
+ digest_data[31 : 0] = 32'h0;
+
+ if (digest_data == expected)
+ begin
+ $display("TC%01d: OK.", tc_ctr);
+ end
+ else
+ begin
+ $display("TC%01d: ERROR.", tc_ctr);
+ $display("TC%01d: Expected: 0x%064x", tc_ctr, expected);
+ $display("TC%01d: Got: 0x%064x", tc_ctr, digest_data);
+ error_ctr = error_ctr + 1;
+ end
+ $display("*** TC%01d - Single block test done.", tc_ctr);
+ tc_ctr = tc_ctr + 1;
+ end
+ endtask // single_block_test
+
+
+ //----------------------------------------------------------------
+ // double_block_test()
+ //
+ //
+ // Perform test of a double block digest. Note that we check
+ // the digests for both the first and final block.
+ //----------------------------------------------------------------
+ task double_block_test(input mode,
+ input [511 : 0] block0,
+ input [255 : 0] expected0,
+ input [511 : 0] block1,
+ input [255 : 0] expected1
+ );
+ begin
+ $display("*** TC%01d - Double block test started.", tc_ctr);
+
+ // First block
+ write_block(block0);
+
+ if (mode)
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_INIT_VALUE));
+ else
+ write_word(ADDR_CTRL, CTRL_INIT_VALUE);
+
+ #(CLK_PERIOD);
+ wait_ready();
+ read_digest();
+
+ // We need to ignore the LSW in SHA224 mode.
+ if (mode == SHA224_MODE)
+ digest_data[31 : 0] = 32'h0;
+
+ if (digest_data == expected0)
+ begin
+ $display("TC%01d first block: OK.", tc_ctr);
+ end
+ else
+ begin
+ $display("TC%01d: ERROR in first digest", tc_ctr);
+ $display("TC%01d: Expected: 0x%064x", tc_ctr, expected0);
+ $display("TC%01d: Got: 0x%064x", tc_ctr, digest_data);
+ error_ctr = error_ctr + 1;
+ end
+
+ // Final block
+ write_block(block1);
+
+ if (mode)
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_NEXT_VALUE));
+ else
+ write_word(ADDR_CTRL, CTRL_NEXT_VALUE);
+
+ #(CLK_PERIOD);
+ wait_ready();
+ read_digest();
+
+ // We need to ignore the LSW in SHA224 mode.
+ if (mode == SHA224_MODE)
+ digest_data[31 : 0] = 32'h0;
+
+ if (digest_data == expected1)
+ begin
+ $display("TC%01d final block: OK.", tc_ctr);
+ end
+ else
+ begin
+ $display("TC%01d: ERROR in final digest", tc_ctr);
+ $display("TC%01d: Expected: 0x%064x", tc_ctr, expected1);
+ $display("TC%01d: Got: 0x%064x", tc_ctr, digest_data);
+ error_ctr = error_ctr + 1;
+ end
+
+ $display("*** TC%01d - Double block test done.", tc_ctr);
+ tc_ctr = tc_ctr + 1;
+ end
+ endtask // double_block_test
+
+
+ //----------------------------------------------------------------
+ // sha224_tests()
+ //
+ // Run test cases for sha224.
+ // Test cases taken from:
+ // http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA224.pdf
+ //----------------------------------------------------------------
+ task sha224_tests;
+ begin : sha224_tests_block
+ reg [511 : 0] tc0;
+ reg [255 : 0] res0;
+
+ reg [511 : 0] tc1_0;
+ reg [255 : 0] res1_0;
+ reg [511 : 0] tc1_1;
+ reg [255 : 0] res1_1;
+
+ $display("*** Testcases for sha224 functionality started.");
+
+ tc0 = 512'h61626380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018;
+
+ res0 = 256'h23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA700000000;
+ single_block_test(SHA224_MODE, tc0, res0);
+
+ tc1_0 = 512'h6162636462636465636465666465666765666768666768696768696A68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F70718000000000000000;
+ res1_0 = 256'h8250e65dbcf62f8466659c3333e5e91a10c8b7b0953927691f1419c200000000;
+ tc1_1 = 512'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C0;
+ res1_1 = 256'h75388b16512776cc5dba5da1fd890150b0c6455cb4f58b195252252500000000;
+ double_block_test(SHA224_MODE, tc1_0, res1_0, tc1_1, res1_1);
+
+ $display("*** Testcases for sha224 functionality completed.");
+ end
+ endtask // sha224_tests
+
+
+ //----------------------------------------------------------------
+ // sha256_tests()
+ //
+ // Run test cases for sha256.
+ // Test cases taken from:
+ // http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA256.pdf
+ //----------------------------------------------------------------
+ task sha256_tests;
+ begin : sha256_tests_block
+ reg [511 : 0] tc0;
+ reg [255 : 0] res0;
+
+ reg [511 : 0] tc1_0;
+ reg [255 : 0] res1_0;
+ reg [511 : 0] tc1_1;
+ reg [255 : 0] res1_1;
+
+ $display("*** Testcases for sha256 functionality started.");
+
+ tc0 = 512'h61626380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018;
+ res0 = 256'hBA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD;
+ single_block_test(SHA256_MODE, tc0, res0);
+
+ tc1_0 = 512'h6162636462636465636465666465666765666768666768696768696A68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F70718000000000000000;
+ res1_0 = 256'h85E655D6417A17953363376A624CDE5C76E09589CAC5F811CC4B32C1F20E533A;
+ tc1_1 = 512'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C0;
+ res1_1 = 256'h248D6A61D20638B8E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1;
+ double_block_test(SHA256_MODE, tc1_0, res1_0, tc1_1, res1_1);
+
+ $display("*** Testcases for sha256 functionality completed.");
+ end
+ endtask // sha256_tests
+
+
+
+ //----------------------------------------------------------------
+ // issue_test()
+ //----------------------------------------------------------------
+ task issue_test;
+ reg [511 : 0] block0;
+ reg [511 : 0] block1;
+ reg [511 : 0] block2;
+ reg [511 : 0] block3;
+ reg [511 : 0] block4;
+ reg [511 : 0] block5;
+ reg [511 : 0] block6;
+ reg [511 : 0] block7;
+ reg [511 : 0] block8;
+ reg [255 : 0] expected;
+ begin : issue_test
+ block0 = 512'h6b900001_496e2074_68652061_72656120_6f662049_6f542028_496e7465_726e6574_206f6620_5468696e_6773292c_206d6f72_6520616e_64206d6f_7265626f_6f6d2c20;
+ block1 = 512'h69742068_61732062_65656e20_6120756e_69766572_73616c20_636f6e73_656e7375_73207468_61742064_61746120_69732074_69732061_206e6577_20746563_686e6f6c;
+ block2 = 512'h6f677920_74686174_20696e74_65677261_74657320_64656365_6e747261_6c697a61_74696f6e_2c496e20_74686520_61726561_206f6620_496f5420_28496e74_65726e65;
+ block3 = 512'h74206f66_20546869_6e677329_2c206d6f_72652061_6e64206d_6f726562_6f6f6d2c_20697420_68617320_6265656e_20612075_6e697665_7273616c_20636f6e_73656e73;
+ block4 = 512'h75732074_68617420_64617461_20697320_74697320_61206e65_77207465_63686e6f_6c6f6779_20746861_7420696e_74656772_61746573_20646563_656e7472_616c697a;
+ block5 = 512'h6174696f_6e2c496e_20746865_20617265_61206f66_20496f54_2028496e_7465726e_6574206f_66205468_696e6773_292c206d_6f726520_616e6420_6d6f7265_626f6f6d;
+ block6 = 512'h2c206974_20686173_20626565_6e206120_756e6976_65727361_6c20636f_6e73656e_73757320_74686174_20646174_61206973_20746973_2061206e_65772074_6563686e;
+ block7 = 512'h6f6c6f67_79207468_61742069_6e746567_72617465_73206465_63656e74_72616c69_7a617469_6f6e2c49_6e207468_65206172_6561206f_6620496f_54202849_6e746572;
+ block8 = 512'h6e657420_6f662054_68696e67_73292c20_6d6f7265_20616e64_206d6f72_65800000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_000010e8;
+
+ expected = 256'h7758a30bbdfc9cd92b284b05e9be9ca3d269d3d149e7e82ab4a9ed5e81fbcf9d;
+
+ $display("Running test for 9 block issue.");
+ tc_ctr = tc_ctr + 1;
+ write_block(block0);
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_INIT_VALUE));
+ #(CLK_PERIOD);
+ wait_ready();
+
+ write_block(block1);
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_NEXT_VALUE));
+ #(CLK_PERIOD);
+ wait_ready();
+
+ write_block(block2);
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_NEXT_VALUE));
+ #(CLK_PERIOD);
+ wait_ready();
+
+ write_block(block3);
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_NEXT_VALUE));
+ #(CLK_PERIOD);
+ wait_ready();
+
+ write_block(block4);
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_NEXT_VALUE));
+ #(CLK_PERIOD);
+ wait_ready();
+
+ write_block(block5);
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_NEXT_VALUE));
+ #(CLK_PERIOD);
+ wait_ready();
+
+ write_block(block6);
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_NEXT_VALUE));
+ #(CLK_PERIOD);
+ wait_ready();
+
+ write_block(block7);
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_NEXT_VALUE));
+ #(CLK_PERIOD);
+ wait_ready();
+
+ write_block(block8);
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_NEXT_VALUE));
+ #(CLK_PERIOD);
+ wait_ready();
+
+ read_digest();
+ if (digest_data == expected)
+ begin
+ $display("Digest ok.");
+ end
+ else
+ begin
+ $display("ERROR in digest");
+ $display("Expected: 0x%064x", expected);
+ $display("Got: 0x%064x", digest_data);
+ error_ctr = error_ctr + 1;
+ end
+ end
+ endtask // issue_test
+
+
+ //----------------------------------------------------------------
+ // The main test functionality.
+ //----------------------------------------------------------------
+ initial
+ begin : main
+ $display(" -- Testbench for sha256 started --");
+
+ init_sim();
+ reset_dut();
+
+ check_name_version();
+ sha224_tests();
+ sha256_tests();
+ issue_test();
+
+ display_test_result();
+
+ $display(" -- Testbench for sha256 done. --");
+ $finish;
+ end // main
+endmodule // tb_sha256
+
+//======================================================================
+// EOF tb_sha256.v
+//======================================================================
diff --git a/Verilog_Code/tb_sha256.v.bak b/Verilog_Code/tb_sha256.v.bak
new file mode 100644
index 0000000..79765b3
--- /dev/null
+++ b/Verilog_Code/tb_sha256.v.bak
@@ -0,0 +1,718 @@
+//======================================================================
+//
+// tb_sha256.v
+// -----------
+// Testbench for the SHA-256 top level wrapper.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2013, Secworks Sweden AB
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. 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.
+//
+// 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 OWNER 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.
+//
+//======================================================================
+
+`default_nettype none
+
+module tb_sha256();
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter DEBUG = 0;
+
+ parameter CLK_HALF_PERIOD = 2;
+ parameter CLK_PERIOD = 2 * CLK_HALF_PERIOD;
+
+ // The address map.
+ parameter ADDR_NAME0 = 8'h00;
+ parameter ADDR_NAME1 = 8'h01;
+ parameter ADDR_VERSION = 8'h02;
+
+ parameter ADDR_CTRL = 8'h08;
+ parameter CTRL_INIT_VALUE = 8'h01;
+ parameter CTRL_NEXT_VALUE = 8'h02;
+ parameter CTRL_MODE_VALUE = 8'h04;
+
+ parameter ADDR_STATUS = 8'h09;
+ parameter STATUS_READY_BIT = 0;
+ parameter STATUS_VALID_BIT = 1;
+
+ parameter ADDR_BLOCK0 = 8'h10;
+ parameter ADDR_BLOCK1 = 8'h11;
+ parameter ADDR_BLOCK2 = 8'h12;
+ parameter ADDR_BLOCK3 = 8'h13;
+ parameter ADDR_BLOCK4 = 8'h14;
+ parameter ADDR_BLOCK5 = 8'h15;
+ parameter ADDR_BLOCK6 = 8'h16;
+ parameter ADDR_BLOCK7 = 8'h17;
+ parameter ADDR_BLOCK8 = 8'h18;
+ parameter ADDR_BLOCK9 = 8'h19;
+ parameter ADDR_BLOCK10 = 8'h1a;
+ parameter ADDR_BLOCK11 = 8'h1b;
+ parameter ADDR_BLOCK12 = 8'h1c;
+ parameter ADDR_BLOCK13 = 8'h1d;
+ parameter ADDR_BLOCK14 = 8'h1e;
+ parameter ADDR_BLOCK15 = 8'h1f;
+
+ parameter ADDR_DIGEST0 = 8'h20;
+ parameter ADDR_DIGEST1 = 8'h21;
+ parameter ADDR_DIGEST2 = 8'h22;
+ parameter ADDR_DIGEST3 = 8'h23;
+ parameter ADDR_DIGEST4 = 8'h24;
+ parameter ADDR_DIGEST5 = 8'h25;
+ parameter ADDR_DIGEST6 = 8'h26;
+ parameter ADDR_DIGEST7 = 8'h27;
+
+ parameter SHA224_MODE = 0;
+ parameter SHA256_MODE = 1;
+
+
+ //----------------------------------------------------------------
+ // 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_cs;
+ reg tb_we;
+ reg [7 : 0] tb_address;
+ reg [31 : 0] tb_write_data;
+ wire [31 : 0] tb_read_data;
+ wire tb_error;
+
+ reg [31 : 0] read_data;
+ reg [255 : 0] digest_data;
+
+
+ //----------------------------------------------------------------
+ // Device Under Test.
+ //----------------------------------------------------------------
+ sha256 dut(
+ .clk(tb_clk),
+ .reset_n(tb_reset_n),
+
+ .cs(tb_cs),
+ .we(tb_we),
+
+
+ .address(tb_address),
+ .write_data(tb_write_data),
+ .read_data(tb_read_data),
+ .error(tb_error)
+ );
+
+
+ //----------------------------------------------------------------
+ // 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_dut_state()
+ //
+ // Dump the state of the dump when needed.
+ //----------------------------------------------------------------
+ task dump_dut_state;
+ begin
+ $display("State of DUT");
+ $display("------------");
+ $display("Inputs and outputs:");
+ $display("cs = 0x%01x, we = 0x%01x",
+ dut.cs, dut.we);
+ $display("address = 0x%02x", dut.address);
+ $display("write_data = 0x%08x, read_data = 0x%08x",
+ dut.write_data, dut.read_data);
+ $display("tmp_read_data = 0x%08x", dut.tmp_read_data);
+ $display("");
+
+ $display("Control and status:");
+ $display("ctrl = 0x%02x, status = 0x%02x",
+ {dut.next_reg, dut.init_reg},
+ {dut.digest_valid_reg, dut.ready_reg});
+ $display("");
+
+ $display("Message block:");
+ $display("block0 = 0x%08x, block1 = 0x%08x, block2 = 0x%08x, block3 = 0x%08x",
+ dut.block_reg[00], dut.block_reg[01], dut.block_reg[02], dut.block_reg[03]);
+// $display("block4 = 0x%08x, block5 = 0x%08x, block6 = 0x%08x, block7 = 0x%08x",
+// dut.block_reg[04], dut.block_reg[05], dut.block_reg[06], dut.block_reg[07]);
+
+ $display("block8 = 0x%08x, block9 = 0x%08x, block10 = 0x%08x, block11 = 0x%08x",
+ dut.block_reg[08], dut.block_reg[09], dut.block_reg[10], dut.block_reg[11]);
+ $display("block12 = 0x%08x, block13 = 0x%08x, block14 = 0x%08x, block15 = 0x%08x",
+ dut.block_reg[12], dut.block_reg[13], dut.block_reg[14], dut.block_reg[15]);
+ $display("");
+
+ $display("Digest:");
+ $display("digest = 0x%064x", dut.digest_reg);
+ $display("");
+
+ end
+ endtask // dump_dut_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;
+ error_ctr = 32'h0;
+ tc_ctr = 32'h0;
+
+ tb_clk = 0;
+ tb_reset_n = 0;
+ tb_cs = 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
+
+
+ //----------------------------------------------------------------
+ // wait_ready()
+ //
+ // Wait for the ready flag in the dut to be set.
+ // (Actually we wait for either ready or valid to be set.)
+ //
+ // Note: It is the callers responsibility to call the function
+ // when the dut is actively processing and will in fact at some
+ // point set the flag.
+ //----------------------------------------------------------------
+ task wait_ready;
+ begin
+ read_data = 0;
+
+ while (read_data == 0)
+ begin
+ read_word(ADDR_STATUS);
+ end
+ end
+ endtask // wait_ready
+
+
+ //----------------------------------------------------------------
+ // write_word()
+ //
+ // Write the given word to the DUT using the DUT interface.
+ //----------------------------------------------------------------
+ task write_word(input [7 : 0] address,
+ input [31 : 0] word);
+ begin
+ if (DEBUG)
+ begin
+ $display("*** Writing 0x%08x to 0x%02x.", word, address);
+ $display("");
+ end
+
+ tb_address = address;
+ tb_write_data = word;
+ tb_cs = 1;
+ tb_we = 1;
+ #(CLK_PERIOD);
+ tb_cs = 0;
+ tb_we = 0;
+ end
+ endtask // write_word
+
+
+ //----------------------------------------------------------------
+ // write_block()
+ //
+ // Write the given block to the dut.
+ //----------------------------------------------------------------
+ task write_block(input [511 : 0] block);
+ begin
+ write_word(ADDR_BLOCK0, block[511 : 480]);
+ write_word(ADDR_BLOCK1, block[479 : 448]);
+ write_word(ADDR_BLOCK2, block[447 : 416]);
+ write_word(ADDR_BLOCK3, block[415 : 384]);
+ write_word(ADDR_BLOCK4, block[383 : 352]);
+ write_word(ADDR_BLOCK5, block[351 : 320]);
+ write_word(ADDR_BLOCK6, block[319 : 288]);
+ write_word(ADDR_BLOCK7, block[287 : 256]);
+ write_word(ADDR_BLOCK8, block[255 : 224]);
+ write_word(ADDR_BLOCK9, block[223 : 192]);
+ write_word(ADDR_BLOCK10, block[191 : 160]);
+ write_word(ADDR_BLOCK11, block[159 : 128]);
+ write_word(ADDR_BLOCK12, block[127 : 96]);
+ write_word(ADDR_BLOCK13, block[95 : 64]);
+ write_word(ADDR_BLOCK14, block[63 : 32]);
+ write_word(ADDR_BLOCK15, block[31 : 0]);
+ end
+ endtask // write_block
+
+
+ //----------------------------------------------------------------
+ // read_word()
+ //
+ // Read a data word from the given address in the DUT.
+ // the word read will be available in the global variable
+ // read_data.
+ //----------------------------------------------------------------
+ task read_word(input [7 : 0] address);
+ begin
+ tb_address = address;
+ tb_cs = 1;
+ tb_we = 0;
+ #(CLK_PERIOD);
+ read_data = tb_read_data;
+ tb_cs = 0;
+
+ if (DEBUG)
+ begin
+ $display("*** Reading 0x%08x from 0x%02x.", read_data, address);
+ $display("");
+ end
+ end
+ endtask // read_word
+
+
+ //----------------------------------------------------------------
+ // check_name_version()
+ //
+ // Read the name and version from the DUT.
+ //----------------------------------------------------------------
+ task check_name_version;
+ reg [31 : 0] name0;
+ reg [31 : 0] name1;
+ reg [31 : 0] version;
+ begin
+
+ read_word(ADDR_NAME0);
+ name0 = read_data;
+ read_word(ADDR_NAME1);
+ name1 = read_data;
+ read_word(ADDR_VERSION);
+ version = read_data;
+
+ $display("DUT name: %c%c%c%c%c%c%c%c",
+ name0[31 : 24], name0[23 : 16], name0[15 : 8], name0[7 : 0],
+ name1[31 : 24], name1[23 : 16], name1[15 : 8], name1[7 : 0]);
+ $display("DUT version: %c%c%c%c",
+ version[31 : 24], version[23 : 16], version[15 : 8], version[7 : 0]);
+ end
+ endtask // check_name_version
+
+
+ //----------------------------------------------------------------
+ // read_digest()
+ //
+ // Read the digest in the dut. The resulting digest will be
+ // available in the global variable digest_data.
+ //----------------------------------------------------------------
+ task read_digest;
+ begin
+ read_word(ADDR_DIGEST0);
+ digest_data[255 : 224] = read_data;
+ read_word(ADDR_DIGEST1);
+ digest_data[223 : 192] = read_data;
+ read_word(ADDR_DIGEST2);
+ digest_data[191 : 160] = read_data;
+ read_word(ADDR_DIGEST3);
+ digest_data[159 : 128] = read_data;
+ read_word(ADDR_DIGEST4);
+ digest_data[127 : 96] = read_data;
+ read_word(ADDR_DIGEST5);
+ digest_data[95 : 64] = read_data;
+ read_word(ADDR_DIGEST6);
+ digest_data[63 : 32] = read_data;
+ read_word(ADDR_DIGEST7);
+ digest_data[31 : 0] = read_data;
+ end
+ endtask // read_digest
+
+
+ //----------------------------------------------------------------
+ // single_block_test()
+ //
+ //
+ // Perform test of a single block digest.
+ //----------------------------------------------------------------
+ task single_block_test(input mode,
+ input [511 : 0] block,
+ input [255 : 0] expected);
+ begin
+ $display("*** TC%01d - Single block test started.", tc_ctr);
+
+ write_block(block);
+
+ if (mode)
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_INIT_VALUE));
+ else
+ write_word(ADDR_CTRL, CTRL_INIT_VALUE);
+
+ #(CLK_PERIOD);
+ wait_ready();
+ read_digest();
+
+ // We need to ignore the LSW in SHA224 mode.
+ if (mode == SHA224_MODE)
+ digest_data[31 : 0] = 32'h0;
+
+ if (digest_data == expected)
+ begin
+ $display("TC%01d: OK.", tc_ctr);
+ end
+ else
+ begin
+ $display("TC%01d: ERROR.", tc_ctr);
+ $display("TC%01d: Expected: 0x%064x", tc_ctr, expected);
+ $display("TC%01d: Got: 0x%064x", tc_ctr, digest_data);
+ error_ctr = error_ctr + 1;
+ end
+ $display("*** TC%01d - Single block test done.", tc_ctr);
+ tc_ctr = tc_ctr + 1;
+ end
+ endtask // single_block_test
+
+
+ //----------------------------------------------------------------
+ // double_block_test()
+ //
+ //
+ // Perform test of a double block digest. Note that we check
+ // the digests for both the first and final block.
+ //----------------------------------------------------------------
+ task double_block_test(input mode,
+ input [511 : 0] block0,
+ input [255 : 0] expected0,
+ input [511 : 0] block1,
+ input [255 : 0] expected1
+ );
+ begin
+ $display("*** TC%01d - Double block test started.", tc_ctr);
+
+ // First block
+ write_block(block0);
+
+ if (mode)
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_INIT_VALUE));
+ else
+ write_word(ADDR_CTRL, CTRL_INIT_VALUE);
+
+ #(CLK_PERIOD);
+ wait_ready();
+ read_digest();
+
+ // We need to ignore the LSW in SHA224 mode.
+ if (mode == SHA224_MODE)
+ digest_data[31 : 0] = 32'h0;
+
+ if (digest_data == expected0)
+ begin
+ $display("TC%01d first block: OK.", tc_ctr);
+ end
+ else
+ begin
+ $display("TC%01d: ERROR in first digest", tc_ctr);
+ $display("TC%01d: Expected: 0x%064x", tc_ctr, expected0);
+ $display("TC%01d: Got: 0x%064x", tc_ctr, digest_data);
+ error_ctr = error_ctr + 1;
+ end
+
+ // Final block
+ write_block(block1);
+
+ if (mode)
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_NEXT_VALUE));
+ else
+ write_word(ADDR_CTRL, CTRL_NEXT_VALUE);
+
+ #(CLK_PERIOD);
+ wait_ready();
+ read_digest();
+
+ // We need to ignore the LSW in SHA224 mode.
+ if (mode == SHA224_MODE)
+ digest_data[31 : 0] = 32'h0;
+
+ if (digest_data == expected1)
+ begin
+ $display("TC%01d final block: OK.", tc_ctr);
+ end
+ else
+ begin
+ $display("TC%01d: ERROR in final digest", tc_ctr);
+ $display("TC%01d: Expected: 0x%064x", tc_ctr, expected1);
+ $display("TC%01d: Got: 0x%064x", tc_ctr, digest_data);
+ error_ctr = error_ctr + 1;
+ end
+
+ $display("*** TC%01d - Double block test done.", tc_ctr);
+ tc_ctr = tc_ctr + 1;
+ end
+ endtask // double_block_test
+
+
+ //----------------------------------------------------------------
+ // sha224_tests()
+ //
+ // Run test cases for sha224.
+ // Test cases taken from:
+ // http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA224.pdf
+ //----------------------------------------------------------------
+ task sha224_tests;
+ begin : sha224_tests_block
+ reg [511 : 0] tc0;
+ reg [255 : 0] res0;
+
+ reg [511 : 0] tc1_0;
+ reg [255 : 0] res1_0;
+ reg [511 : 0] tc1_1;
+ reg [255 : 0] res1_1;
+
+ $display("*** Testcases for sha224 functionality started.");
+
+ tc0 = 512'h61626380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018;
+
+ res0 = 256'h23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA700000000;
+ single_block_test(SHA224_MODE, tc0, res0);
+
+ tc1_0 = 512'h6162636462636465636465666465666765666768666768696768696A68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F70718000000000000000;
+ res1_0 = 256'h8250e65dbcf62f8466659c3333e5e91a10c8b7b0953927691f1419c200000000;
+ tc1_1 = 512'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C0;
+ res1_1 = 256'h75388b16512776cc5dba5da1fd890150b0c6455cb4f58b195252252500000000;
+ double_block_test(SHA224_MODE, tc1_0, res1_0, tc1_1, res1_1);
+
+ $display("*** Testcases for sha224 functionality completed.");
+ end
+ endtask // sha224_tests
+
+
+ //----------------------------------------------------------------
+ // sha256_tests()
+ //
+ // Run test cases for sha256.
+ // Test cases taken from:
+ // http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA256.pdf
+ //----------------------------------------------------------------
+ task sha256_tests;
+ begin : sha256_tests_block
+ reg [511 : 0] tc0;
+ reg [255 : 0] res0;
+
+ reg [511 : 0] tc1_0;
+ reg [255 : 0] res1_0;
+ reg [511 : 0] tc1_1;
+ reg [255 : 0] res1_1;
+
+ $display("*** Testcases for sha256 functionality started.");
+
+ tc0 = 512'h61626380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018;
+ res0 = 256'hBA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD;
+ single_block_test(SHA256_MODE, tc0, res0);
+
+ tc1_0 = 512'h6162636462636465636465666465666765666768666768696768696A68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F70718000000000000000;
+ res1_0 = 256'h85E655D6417A17953363376A624CDE5C76E09589CAC5F811CC4B32C1F20E533A;
+ tc1_1 = 512'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C0;
+ res1_1 = 256'h248D6A61D20638B8E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1;
+ double_block_test(SHA256_MODE, tc1_0, res1_0, tc1_1, res1_1);
+
+ $display("*** Testcases for sha256 functionality completed.");
+ end
+ endtask // sha256_tests
+
+
+
+ //----------------------------------------------------------------
+ // issue_test()
+ //----------------------------------------------------------------
+ task issue_test
+ reg [511 : 0] block0;
+ reg [511 : 0] block1;
+ reg [511 : 0] block2;
+ reg [511 : 0] block3;
+ reg [511 : 0] block4;
+ reg [511 : 0] block5;
+ reg [511 : 0] block6;
+ reg [511 : 0] block7;
+ reg [511 : 0] block8;
+ reg [255 : 0] expected;
+ begin : issue_test;
+ block0 = 512'h6b900001_496e2074_68652061_72656120_6f662049_6f542028_496e7465_726e6574_206f6620_5468696e_6773292c_206d6f72_6520616e_64206d6f_7265626f_6f6d2c20;
+ block1 = 512'h69742068_61732062_65656e20_6120756e_69766572_73616c20_636f6e73_656e7375_73207468_61742064_61746120_69732074_69732061_206e6577_20746563_686e6f6c;
+ block2 = 512'h6f677920_74686174_20696e74_65677261_74657320_64656365_6e747261_6c697a61_74696f6e_2c496e20_74686520_61726561_206f6620_496f5420_28496e74_65726e65;
+ block3 = 512'h74206f66_20546869_6e677329_2c206d6f_72652061_6e64206d_6f726562_6f6f6d2c_20697420_68617320_6265656e_20612075_6e697665_7273616c_20636f6e_73656e73;
+ block4 = 512'h75732074_68617420_64617461_20697320_74697320_61206e65_77207465_63686e6f_6c6f6779_20746861_7420696e_74656772_61746573_20646563_656e7472_616c697a;
+ block5 = 512'h6174696f_6e2c496e_20746865_20617265_61206f66_20496f54_2028496e_7465726e_6574206f_66205468_696e6773_292c206d_6f726520_616e6420_6d6f7265_626f6f6d;
+ block6 = 512'h2c206974_20686173_20626565_6e206120_756e6976_65727361_6c20636f_6e73656e_73757320_74686174_20646174_61206973_20746973_2061206e_65772074_6563686e;
+ block7 = 512'h6f6c6f67_79207468_61742069_6e746567_72617465_73206465_63656e74_72616c69_7a617469_6f6e2c49_6e207468_65206172_6561206f_6620496f_54202849_6e746572;
+ block8 = 512'h6e657420_6f662054_68696e67_73292c20_6d6f7265_20616e64_206d6f72_65800000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_000010e8;
+
+ expected = 256'h7758a30bbdfc9cd92b284b05e9be9ca3d269d3d149e7e82ab4a9ed5e81fbcf9d;
+
+ $display("Running test for 9 block issue.");
+ tc_ctr = tc_ctr + 1;
+ write_block(block0);
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_INIT_VALUE));
+ #(CLK_PERIOD);
+ wait_ready();
+
+ write_block(block1);
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_NEXT_VALUE));
+ #(CLK_PERIOD);
+ wait_ready();
+
+ write_block(block2);
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_NEXT_VALUE));
+ #(CLK_PERIOD);
+ wait_ready();
+
+ write_block(block3);
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_NEXT_VALUE));
+ #(CLK_PERIOD);
+ wait_ready();
+
+ write_block(block4);
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_NEXT_VALUE));
+ #(CLK_PERIOD);
+ wait_ready();
+
+ write_block(block5);
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_NEXT_VALUE));
+ #(CLK_PERIOD);
+ wait_ready();
+
+ write_block(block6);
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_NEXT_VALUE));
+ #(CLK_PERIOD);
+ wait_ready();
+
+ write_block(block7);
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_NEXT_VALUE));
+ #(CLK_PERIOD);
+ wait_ready();
+
+ write_block(block8);
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_NEXT_VALUE));
+ #(CLK_PERIOD);
+ wait_ready();
+
+ read_digest();
+ if (digest_data == expected)
+ begin
+ $display("Digest ok.");
+ end
+ else
+ begin
+ $display("ERROR in digest");
+ $display("Expected: 0x%064x", expected);
+ $display("Got: 0x%064x", digest_data);
+ error_ctr = error_ctr + 1;
+ end
+ end
+ endtask // issue_test
+
+
+ //----------------------------------------------------------------
+ // The main test functionality.
+ //----------------------------------------------------------------
+ initial
+ begin : main
+ $display(" -- Testbench for sha256 started --");
+
+ init_sim();
+ reset_dut();
+
+ check_name_version();
+ sha224_tests();
+ sha256_tests();
+ issue_test();
+
+ display_test_result();
+
+ $display(" -- Testbench for sha256 done. --");
+ $finish;
+ end // main
+endmodule // tb_sha256
+
+//======================================================================
+// EOF tb_sha256.v
+//======================================================================
diff --git a/Verilog_Code/tb_sha256_core.v b/Verilog_Code/tb_sha256_core.v
new file mode 100644
index 0000000..acf3867
--- /dev/null
+++ b/Verilog_Code/tb_sha256_core.v
@@ -0,0 +1,521 @@
+//======================================================================
+//
+// tb_sha256_core.v
+// ----------------
+// Testbench for the SHA-256 core.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2013, Secworks Sweden AB
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. 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.
+//
+// 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 OWNER 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.
+//
+//======================================================================
+
+`default_nettype none
+
+module tb_sha256_core();
+
+ //----------------------------------------------------------------
+ // 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_init;
+ reg tb_next;
+ reg tb_mode;
+ reg [511 : 0] tb_block;
+ wire tb_ready;
+ wire [255 : 0] tb_digest;
+ wire tb_digest_valid;
+
+
+ //----------------------------------------------------------------
+ // Device Under Test.
+ //----------------------------------------------------------------
+ sha256_core dut(
+ .clk(tb_clk),
+ .reset_n(tb_reset_n),
+
+ .init(tb_init),
+ .next(tb_next),
+ .mode(tb_mode),
+
+ .block(tb_block),
+
+ .ready(tb_ready),
+
+ .digest(tb_digest),
+ .digest_valid(tb_digest_valid)
+ );
+
+
+ //----------------------------------------------------------------
+ // clk_gen
+ //
+ // Always running clock generator process.
+ //----------------------------------------------------------------
+ always
+ begin : clk_gen
+ #CLK_HALF_PERIOD;
+ tb_clk = !tb_clk;
+ end // clk_gen
+
+
+ //----------------------------------------------------------------
+ // sys_monitor()
+ //
+ // An always running process that creates a cycle counter and
+ // conditionally displays information about the DUT.
+ //----------------------------------------------------------------
+ always
+ begin : sys_monitor
+ cycle_ctr = cycle_ctr + 1;
+ #(2 * CLK_HALF_PERIOD);
+ if (DEBUG)
+ begin
+ dump_dut_state();
+ end
+ end
+
+
+ //----------------------------------------------------------------
+ // dump_dut_state()
+ //
+ // Dump the state of the dump when needed.
+ //----------------------------------------------------------------
+ task dump_dut_state;
+ begin
+ $display("State of DUT");
+ $display("------------");
+ $display("Inputs and outputs:");
+ $display("init = 0x%01x, next = 0x%01x",
+ dut.init, dut.next);
+ $display("block = 0x%0128x", dut.block);
+
+ $display("ready = 0x%01x, valid = 0x%01x",
+ dut.ready, dut.digest_valid);
+ $display("digest = 0x%064x", dut.digest);
+ $display("H0_reg = 0x%08x, H1_reg = 0x%08x, H2_reg = 0x%08x, H3_reg = 0x%08x",
+ dut.H0_reg, dut.H1_reg, dut.H2_reg, dut.H3_reg);
+ $display("H4_reg = 0x%08x, H5_reg = 0x%08x, H6_reg = 0x%08x, H7_reg = 0x%08x",
+ dut.H4_reg, dut.H5_reg, dut.H6_reg, dut.H7_reg);
+ $display("");
+
+ $display("Control signals and counter:");
+ $display("sha256_ctrl_reg = 0x%02x", dut.sha256_ctrl_reg);
+ $display("digest_init = 0x%01x, digest_update = 0x%01x",
+ dut.digest_init, dut.digest_update);
+ $display("state_init = 0x%01x, state_update = 0x%01x",
+ dut.state_init, dut.state_update);
+ $display("first_block = 0x%01x, ready_flag = 0x%01x, w_init = 0x%01x",
+ dut.first_block, dut.ready_flag, dut.w_init);
+ $display("t_ctr_inc = 0x%01x, t_ctr_rst = 0x%01x, t_ctr_reg = 0x%02x",
+ dut.t_ctr_inc, dut.t_ctr_rst, dut.t_ctr_reg);
+ $display("");
+
+ $display("State registers:");
+ $display("a_reg = 0x%08x, b_reg = 0x%08x, c_reg = 0x%08x, d_reg = 0x%08x",
+ dut.a_reg, dut.b_reg, dut.c_reg, dut.d_reg);
+ $display("e_reg = 0x%08x, f_reg = 0x%08x, g_reg = 0x%08x, h_reg = 0x%08x",
+ dut.e_reg, dut.f_reg, dut.g_reg, dut.h_reg);
+ $display("");
+ $display("a_new = 0x%08x, b_new = 0x%08x, c_new = 0x%08x, d_new = 0x%08x",
+ dut.a_new, dut.b_new, dut.c_new, dut.d_new);
+ $display("e_new = 0x%08x, f_new = 0x%08x, g_new = 0x%08x, h_new = 0x%08x",
+ dut.e_new, dut.f_new, dut.g_new, dut.h_new);
+ $display("");
+
+ $display("State update values:");
+ $display("w = 0x%08x, k = 0x%08x", dut.w_data, dut.k_data);
+ $display("t1 = 0x%08x, t2 = 0x%08x", dut.t1, dut.t2);
+ $display("");
+ end
+ endtask // dump_dut_state
+
+
+ //----------------------------------------------------------------
+ // reset_dut()
+ //
+ // Toggle reset to put the DUT into a well known 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 = 0;
+ error_ctr = 0;
+ tc_ctr = 0;
+
+ tb_clk = 0;
+ tb_reset_n = 1;
+
+ tb_init = 0;
+ tb_next = 0;
+ tb_mode = 1;
+ tb_block = 512'h00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ 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 did not complete successfully.", error_ctr);
+ end
+ end
+ endtask // display_test_result
+
+
+ //----------------------------------------------------------------
+ // wait_ready()
+ //
+ // Wait for the ready flag in the dut to be set.
+ //
+ // Note: It is the callers responsibility to call the function
+ // when the dut is actively processing and will in fact at some
+ // point set the flag.
+ //----------------------------------------------------------------
+ task wait_ready;
+ begin
+ while (!tb_ready)
+ begin
+ #(CLK_PERIOD);
+ end
+ end
+ endtask // wait_ready
+
+
+ //----------------------------------------------------------------
+ // single_block_test()
+ //
+ // Run a test case spanning a single data block.
+ //----------------------------------------------------------------
+ task single_block_test(input [7 : 0] tc_number,
+ input [511 : 0] block,
+ input [255 : 0] expected);
+ begin
+ $display("*** TC %0d single block test case started.", tc_number);
+ tc_ctr = tc_ctr + 1;
+
+ tb_block = block;
+ tb_init = 1;
+ #(CLK_PERIOD);
+ wait_ready();
+
+
+ if (tb_digest == expected)
+ begin
+ $display("*** TC %0d successful.", tc_number);
+ $display("");
+ end
+ else
+ begin
+ $display("*** ERROR: TC %0d NOT successful.", tc_number);
+ $display("Expected: 0x%064x", expected);
+ $display("Got: 0x%064x", tb_digest);
+ $display("");
+
+ error_ctr = error_ctr + 1;
+ end
+ end
+ endtask // single_block_test
+
+
+ //----------------------------------------------------------------
+ // double_block_test()
+ //
+ // Run a test case spanning two data blocks. We check both
+ // intermediate and final digest.
+ //----------------------------------------------------------------
+ task double_block_test(input [7 : 0] tc_number,
+ input [511 : 0] block1,
+ input [255 : 0] expected1,
+ input [511 : 0] block2,
+ input [255 : 0] expected2);
+
+ reg [255 : 0] db_digest1;
+ reg [255 : 0] db_digest2;
+ reg db_error;
+ begin
+ $display("*** TC %0d double block test case started.", tc_number);
+ db_error = 0;
+ tc_ctr = tc_ctr + 1;
+
+ $display("*** TC %0d first block started.", tc_number);
+ tb_block = block1;
+ tb_init = 1;
+ #(CLK_PERIOD);
+ tb_init = 0;
+ wait_ready();
+ db_digest1 = tb_digest;
+ $display("*** TC %0d first block done.", tc_number);
+
+ $display("*** TC %0d second block started.", tc_number);
+ tb_block = block2;
+ tb_next = 1;
+ #(CLK_PERIOD);
+ tb_next = 0;
+ wait_ready();
+ db_digest2 = tb_digest;
+ $display("*** TC %0d second block done.", tc_number);
+
+ if (DEBUG)
+ begin
+ $display("Generated digests:");
+ $display("Expected 1: 0x%064x", expected1);
+ $display("Got 1: 0x%064x", db_digest1);
+ $display("Expected 2: 0x%064x", expected2);
+ $display("Got 2: 0x%064x", db_digest2);
+ $display("");
+ end
+
+ if (db_digest1 == expected1)
+ begin
+ $display("*** TC %0d first block successful", tc_number);
+ $display("");
+ end
+ else
+ begin
+ $display("*** ERROR: TC %0d first block NOT successful", tc_number);
+ $display("Expected: 0x%064x", expected1);
+ $display("Got: 0x%064x", db_digest1);
+ $display("");
+ db_error = 1;
+ end
+
+ if (db_digest2 == expected2)
+ begin
+ $display("*** TC %0d second block successful", tc_number);
+ $display("");
+ end
+ else
+ begin
+ $display("*** ERROR: TC %0d second block NOT successful", tc_number);
+ $display("Expected: 0x%064x", expected2);
+ $display("Got: 0x%064x", db_digest2);
+ $display("");
+ db_error = 1;
+ end
+
+ if (db_error)
+ begin
+ error_ctr = error_ctr + 1;
+ end
+ end
+ endtask // double_block_test
+
+
+ //----------------------------------------------------------------
+ // issue_test()
+ //----------------------------------------------------------------
+ task issue_test;
+
+ reg [511 : 0] block0;
+ reg [511 : 0] block1;
+ reg [511 : 0] block2;
+ reg [511 : 0] block3;
+ reg [511 : 0] block4;
+ reg [511 : 0] block5;
+ reg [511 : 0] block6;
+ reg [511 : 0] block7;
+ reg [511 : 0] block8;
+ reg [255 : 0] expected;
+ begin :issue_test
+ block0 = 512'h6b900001_496e2074_68652061_72656120_6f662049_6f542028_496e7465_726e6574_206f6620_5468696e_6773292c_206d6f72_6520616e_64206d6f_7265626f_6f6d2c20;
+ block1 = 512'h69742068_61732062_65656e20_6120756e_69766572_73616c20_636f6e73_656e7375_73207468_61742064_61746120_69732074_69732061_206e6577_20746563_686e6f6c;
+ block2 = 512'h6f677920_74686174_20696e74_65677261_74657320_64656365_6e747261_6c697a61_74696f6e_2c496e20_74686520_61726561_206f6620_496f5420_28496e74_65726e65;
+ block3 = 512'h74206f66_20546869_6e677329_2c206d6f_72652061_6e64206d_6f726562_6f6f6d2c_20697420_68617320_6265656e_20612075_6e697665_7273616c_20636f6e_73656e73;
+ block4 = 512'h75732074_68617420_64617461_20697320_74697320_61206e65_77207465_63686e6f_6c6f6779_20746861_7420696e_74656772_61746573_20646563_656e7472_616c697a;
+ block5 = 512'h6174696f_6e2c496e_20746865_20617265_61206f66_20496f54_2028496e_7465726e_6574206f_66205468_696e6773_292c206d_6f726520_616e6420_6d6f7265_626f6f6d;
+ block6 = 512'h2c206974_20686173_20626565_6e206120_756e6976_65727361_6c20636f_6e73656e_73757320_74686174_20646174_61206973_20746973_2061206e_65772074_6563686e;
+ block7 = 512'h6f6c6f67_79207468_61742069_6e746567_72617465_73206465_63656e74_72616c69_7a617469_6f6e2c49_6e207468_65206172_6561206f_6620496f_54202849_6e746572;
+ block8 = 512'h6e657420_6f662054_68696e67_73292c20_6d6f7265_20616e64_206d6f72_65800000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_000010e8;
+
+ expected = 256'h7758a30bbdfc9cd92b284b05e9be9ca3d269d3d149e7e82ab4a9ed5e81fbcf9d;
+
+ $display("Running test for 9 block issue.");
+ tc_ctr = tc_ctr + 1;
+ tb_block = block0;
+ tb_init = 1;
+ #(CLK_PERIOD);
+ tb_init = 0;
+ wait_ready();
+
+ tb_block = block1;
+ tb_next = 1;
+ #(CLK_PERIOD);
+ tb_next = 0;
+ wait_ready();
+
+ tb_block = block2;
+ tb_next = 1;
+ #(CLK_PERIOD);
+ tb_next = 0;
+ wait_ready();
+
+ tb_block = block3;
+ tb_next = 1;
+ #(CLK_PERIOD);
+ tb_next = 0;
+ wait_ready();
+
+ tb_block = block4;
+ tb_next = 1;
+ #(CLK_PERIOD);
+ tb_next = 0;
+ wait_ready();
+
+ tb_block = block5;
+ tb_next = 1;
+ #(CLK_PERIOD);
+ tb_next = 0;
+ wait_ready();
+
+ tb_block = block6;
+ tb_next = 1;
+ #(CLK_PERIOD);
+ tb_next = 0;
+ wait_ready();
+
+ tb_block = block7;
+ tb_next = 1;
+ #(CLK_PERIOD);
+ tb_next = 0;
+ wait_ready();
+
+ tb_block = block8;
+ tb_next = 1;
+ #(CLK_PERIOD);
+ tb_next = 0;
+ wait_ready();
+
+ if (tb_digest == expected)
+ begin
+ $display("Digest ok.");
+ end
+ else
+ begin
+ error_ctr = error_ctr + 1;
+ $display("Error! Got: 0x%064x", tb_digest);
+ $display("Error! Expected: 0x%064x", expected);
+ end
+ end
+ endtask // issue_test
+
+
+ //----------------------------------------------------------------
+ // sha256_core_test
+ // Test cases taken from:
+ // http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA256.pdf
+ //----------------------------------------------------------------
+ task sha256_core_test;
+ reg [511 : 0] tc1;
+ reg [255 : 0] res1;
+ reg [511 : 0] tc2_1;
+ reg [255 : 0] res2_1;
+ reg [511 : 0] tc2_2;
+ reg [255 : 0] res2_2;
+ begin : sha256_core_test
+ // TC1: Single block message: "abc".
+ tc1 = 512'h61626380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018;
+ res1 = 256'hBA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD;
+ single_block_test(1, tc1, res1);
+
+ // TC2: Double block message.
+ // "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ tc2_1 = 512'h6162636462636465636465666465666765666768666768696768696A68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F70718000000000000000;
+ res2_1 = 256'h85E655D6417A17953363376A624CDE5C76E09589CAC5F811CC4B32C1F20E533A;
+
+ tc2_2 = 512'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C0;
+ res2_2 = 256'h248D6A61D20638B8E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1;
+ double_block_test(2, tc2_1, res2_1, tc2_2, res2_2);
+ end
+ endtask // sha256_core_test
+
+
+ //----------------------------------------------------------------
+ // main()
+ //----------------------------------------------------------------
+ initial
+ begin : main
+ $display(" -- Testbench for sha256 core started --");
+
+ init_sim();
+ dump_dut_state();
+ reset_dut();
+ dump_dut_state();
+
+ sha256_core_test();
+ issue_test();
+
+ display_test_result();
+ $display("*** Simulation done.");
+ $finish;
+ end // main
+endmodule // tb_sha256_core
+
+//======================================================================
+// EOF tb_sha256_core.v
+//======================================================================
diff --git a/Verilog_Code/tb_sha256_w_mem.v b/Verilog_Code/tb_sha256_w_mem.v
new file mode 100644
index 0000000..8c929c6
--- /dev/null
+++ b/Verilog_Code/tb_sha256_w_mem.v
@@ -0,0 +1,213 @@
+//======================================================================
+//
+// tb_sha256_w_mem.v
+// -----------------
+// Testbench for the SHA-256 W memory module.
+//
+//
+// Copyright (c) 2013, Secworks Sweden AB
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. 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.
+//
+// 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 OWNER 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.
+//
+//======================================================================
+
+`default_nettype none
+
+module tb_sha256_w_mem();
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter DEBUG = 1;
+ parameter DISPLAY_CYCLES = 0;
+
+ parameter CLK_HALF_PERIOD = 2;
+
+
+ //----------------------------------------------------------------
+ // Wires.
+ //----------------------------------------------------------------
+ reg tb_clk;
+ reg tb_reset_n;
+
+ reg tb_init;
+ reg tb_next;
+ reg [511 : 0] tb_block;
+ wire [31 : 0] tb_w;
+
+ reg [63 : 0] cycle_ctr;
+ reg [31 : 0] error_ctr;
+ reg [31 : 0] tc_ctr;
+
+
+ //----------------------------------------------------------------
+ // Device Under Test.
+ //----------------------------------------------------------------
+ sha256_w_mem dut(
+ .clk(tb_clk),
+ .reset_n(tb_reset_n),
+
+ .block(tb_block),
+
+ .init(tb_init),
+ .next(tb_next),
+
+ .w(tb_w)
+ );
+
+
+ //----------------------------------------------------------------
+ // clk_gen
+ //
+ // Clock generator process.
+ //----------------------------------------------------------------
+ always
+ begin : clk_gen
+ #CLK_HALF_PERIOD tb_clk = !tb_clk;
+ end // clk_gen
+
+
+ //--------------------------------------------------------------------
+ // dut_monitor
+ //
+ // Monitor displaying information every cycle.
+ // Includes the cycle counter.
+ //--------------------------------------------------------------------
+ always @ (posedge tb_clk)
+ begin : dut_monitor
+ cycle_ctr = cycle_ctr + 1;
+
+ if (DISPLAY_CYCLES)
+ begin
+ $display("cycle = %016x:", cycle_ctr);
+ end
+
+ if (DEBUG)
+ begin
+ $display("dut w_ctr = %02x:", dut.w_ctr_reg);
+ $display("dut w_tmp = %02x:", dut.w_tmp);
+ dump_w_state();
+ end
+ end // dut_monitor
+
+
+ //----------------------------------------------------------------
+ // dump_w_state()
+ //
+ // Dump the current state of all W registers.
+ //----------------------------------------------------------------
+ task dump_w_state;
+ begin
+ $display("W state:");
+
+ $display("w0_reg = %08x, w1_reg = %08x, w2_reg = %08x, w3_reg = %08x",
+ dut.w_mem[00], dut.w_mem[01], dut.w_mem[02], dut.w_mem[03]);
+
+ $display("w4_reg = %08x, w5_reg = %08x, w6_reg = %08x, w7_reg = %08x",
+ dut.w_mem[04], dut.w_mem[05], dut.w_mem[06], dut.w_mem[07]);
+
+ $display("w8_reg = %08x, w9_reg = %08x, w10_reg = %08x, w11_reg = %08x",
+ dut.w_mem[08], dut.w_mem[09], dut.w_mem[10], dut.w_mem[11]);
+
+ $display("w12_reg = %08x, w13_reg = %08x, w14_reg = %08x, w15_reg = %08x",
+ dut.w_mem[12], dut.w_mem[13], dut.w_mem[14], dut.w_mem[15]);
+
+ $display("w_new = %08x", dut.w_new);
+ $display("");
+ end
+ endtask // dump_state
+
+
+ //----------------------------------------------------------------
+ // reset_dut
+ //----------------------------------------------------------------
+ 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
+ //----------------------------------------------------------------
+ task init_sim;
+ begin
+ $display("*** Simulation init.");
+ tb_clk = 0;
+ tb_reset_n = 1;
+ cycle_ctr = 0;
+
+ tb_init = 0;
+ tb_block = 512'h0;
+ end
+ endtask // reset_dut
+
+
+ //----------------------------------------------------------------
+ // test_w_schedule()
+ //
+ // Test that W scheduling happens and work correctly.
+ // Note: Currently not a self checking test case.
+ //----------------------------------------------------------------
+ task test_w_schedule;
+ begin
+ $display("*** Test of W schedule processing. --");
+ tb_block = 512'h61626380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018;
+ tb_init = 1;
+ #(4 * CLK_HALF_PERIOD);
+ tb_init = 0;
+ dump_w_state();
+
+ tb_next = 1;
+ #(150 * CLK_HALF_PERIOD);
+ end
+ endtask // test_w_schedule
+
+
+ //----------------------------------------------------------------
+ // The main test functionality.
+ //----------------------------------------------------------------
+ initial
+ begin : w_mem_test
+ $display(" -- Testbench for sha256 w memory started --");
+ init_sim();
+ reset_dut();
+ test_w_schedule();
+
+ $display("*** Simulation done.");
+ $finish;
+ end
+
+endmodule // w_mem_test
+
+//======================================================================
+// EOF tb_sha256_w_mem.v
+//======================================================================
diff --git a/Verilog_Code/tb_top.v b/Verilog_Code/tb_top.v
new file mode 100644
index 0000000..ab6e82f
--- /dev/null
+++ b/Verilog_Code/tb_top.v
@@ -0,0 +1,726 @@
+//======================================================================
+//
+// tb_top_tukka_proj.v
+// -----------
+// Testbench for the SHA-256 and clock mux top level wrapper.
+//
+//
+// Author: Joachim Strombergson
+// Copyright (c) 2013, Secworks Sweden AB
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or
+// without modification, are permitted provided that the following
+// conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. 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.
+//
+// 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 OWNER 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.
+//
+//======================================================================
+
+`default_nettype none
+
+module tb_top_tukka_proj();
+
+ //----------------------------------------------------------------
+ // Internal constant and parameter definitions.
+ //----------------------------------------------------------------
+ parameter DEBUG = 0;
+
+ parameter CLK_HALF_PERIOD1 = 2;
+ parameter CLK_HALF_PERIOD2 = 4;
+ parameter CLK_PERIOD1 = 2 * CLK_HALF_PERIOD1;
+ parameter CLK_PERIOD2 = 2 * CLK_HALF_PERIOD2;
+
+ // The address map.
+ parameter ADDR_NAME0 = 8'h00;
+ parameter ADDR_NAME1 = 8'h01;
+ parameter ADDR_VERSION = 8'h02;
+
+ parameter ADDR_CTRL = 8'h08;
+ parameter CTRL_INIT_VALUE = 8'h01;
+ parameter CTRL_NEXT_VALUE = 8'h02;
+ parameter CTRL_MODE_VALUE = 8'h04;
+
+ parameter ADDR_STATUS = 8'h09;
+ parameter STATUS_READY_BIT = 0;
+ parameter STATUS_VALID_BIT = 1;
+
+ parameter ADDR_BLOCK0 = 8'h10;
+ parameter ADDR_BLOCK1 = 8'h11;
+ parameter ADDR_BLOCK2 = 8'h12;
+ parameter ADDR_BLOCK3 = 8'h13;
+ parameter ADDR_BLOCK4 = 8'h14;
+ parameter ADDR_BLOCK5 = 8'h15;
+ parameter ADDR_BLOCK6 = 8'h16;
+ parameter ADDR_BLOCK7 = 8'h17;
+ parameter ADDR_BLOCK8 = 8'h18;
+ parameter ADDR_BLOCK9 = 8'h19;
+ parameter ADDR_BLOCK10 = 8'h1a;
+ parameter ADDR_BLOCK11 = 8'h1b;
+ parameter ADDR_BLOCK12 = 8'h1c;
+ parameter ADDR_BLOCK13 = 8'h1d;
+ parameter ADDR_BLOCK14 = 8'h1e;
+ parameter ADDR_BLOCK15 = 8'h1f;
+
+ parameter ADDR_DIGEST0 = 8'h20;
+ parameter ADDR_DIGEST1 = 8'h21;
+ parameter ADDR_DIGEST2 = 8'h22;
+ parameter ADDR_DIGEST3 = 8'h23;
+ parameter ADDR_DIGEST4 = 8'h24;
+ parameter ADDR_DIGEST5 = 8'h25;
+ parameter ADDR_DIGEST6 = 8'h26;
+ parameter ADDR_DIGEST7 = 8'h27;
+
+ parameter SHA224_MODE = 0;
+ parameter SHA256_MODE = 1;
+
+
+ //----------------------------------------------------------------
+ // Register and Wire declarations.
+ //----------------------------------------------------------------
+ reg [31 : 0] cycle_ctr;
+ reg [31 : 0] error_ctr;
+ reg [31 : 0] tc_ctr;
+ reg tb_clk1,tb_clk2,tb_sel_clk2;
+ reg tb_clk;
+ reg tb_reset_n;
+ reg tb_cs;
+ reg tb_we;
+ reg [7 : 0] tb_address;
+ reg [31 : 0] tb_write_data;
+ wire [31 : 0] tb_read_data;
+ wire tb_error;
+
+ reg [31 : 0] read_data;
+ reg [255 : 0] digest_data;
+
+
+ //----------------------------------------------------------------
+ // Device Under Test.
+ //----------------------------------------------------------------
+
+top_tukka_proj dut(
+.clk1(tb_clk1),
+.clk2(tb_clk2),
+.reset_n(tb_reset_n),
+.sel_clk2(tb_sel_clk2),
+.cs(tb_cs),
+.we(tb_we),
+.address(tb_address),
+.write_data(tb_write_data),
+.read_data(tb_read_data),
+.error(tb_error)
+);
+
+
+ //----------------------------------------------------------------
+ // clk_gen
+ //
+ // Clock generator process.
+ //----------------------------------------------------------------
+ always
+ begin : clk_gen
+ #CLK_HALF_PERIOD1 tb_clk1 = !tb_clk1;
+ #CLK_HALF_PERIOD2 tb_clk2 = !tb_clk2;
+ end // clk_gen
+
+
+ //----------------------------------------------------------------
+ // sys_monitor
+ //
+ // Generates a cycle counter and displays information about
+ // the dut as needed.
+ //----------------------------------------------------------------
+ always
+ begin : sys_monitor
+ #(2 * CLK_HALF_PERIOD2);
+ cycle_ctr = cycle_ctr + 1;
+ end
+
+
+ //----------------------------------------------------------------
+ // dump_dut_state()
+ //
+ // Dump the state of the dump when needed.
+ //----------------------------------------------------------------
+ /* task dump_dut_state;
+ begin
+ $display("State of DUT");
+ $display("------------");
+ $display("Inputs and outputs:");
+ $display("cs = 0x%01x, we = 0x%01x",
+ dut.cs, dut.we);
+ $display("address = 0x%02x", dut.address);
+ $display("write_data = 0x%08x, read_data = 0x%08x",
+ dut.write_data, dut.read_data);
+ $display("tmp_read_data = 0x%08x", dut.tmp_read_data);
+ $display("");
+
+ $display("Control and status:");
+ $display("ctrl = 0x%02x, status = 0x%02x",
+ {dut.next_reg, dut.init_reg},
+ {dut.digest_valid_reg, dut.ready_reg});
+ $display("");
+
+ $display("Message block:");
+ $display("block0 = 0x%08x, block1 = 0x%08x, block2 = 0x%08x, block3 = 0x%08x",
+ dut.block_reg[00], dut.block_reg[01], dut.block_reg[02], dut.block_reg[03]);
+// $display("block4 = 0x%08x, block5 = 0x%08x, block6 = 0x%08x, block7 = 0x%08x",
+// dut.block_reg[04], dut.block_reg[05], dut.block_reg[06], dut.block_reg[07]);
+
+ $display("block8 = 0x%08x, block9 = 0x%08x, block10 = 0x%08x, block11 = 0x%08x",
+ dut.block_reg[08], dut.block_reg[09], dut.block_reg[10], dut.block_reg[11]);
+ $display("block12 = 0x%08x, block13 = 0x%08x, block14 = 0x%08x, block15 = 0x%08x",
+ dut.block_reg[12], dut.block_reg[13], dut.block_reg[14], dut.block_reg[15]);
+ $display("");
+
+ $display("Digest:");
+ $display("digest = 0x%064x", dut.digest_reg);
+ $display("");
+
+ end
+ endtask // dump_dut_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_PERIOD1);
+ 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;
+ error_ctr = 32'h0;
+ tc_ctr = 32'h0;
+ tb_sel_clk2=1'b0;
+ tb_clk1 = 0;
+ tb_clk2 = 0;
+ tb_reset_n = 0;
+ tb_cs = 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
+
+
+ //----------------------------------------------------------------
+ // wait_ready()
+ //
+ // Wait for the ready flag in the dut to be set.
+ // (Actually we wait for either ready or valid to be set.)
+ //
+ // Note: It is the callers responsibility to call the function
+ // when the dut is actively processing and will in fact at some
+ // point set the flag.
+ //----------------------------------------------------------------
+ task wait_ready;
+ begin
+ read_data = 0;
+
+ while (read_data == 0)
+ begin
+ read_word(ADDR_STATUS);
+ end
+ end
+ endtask // wait_ready
+
+
+ //----------------------------------------------------------------
+ // write_word()
+ //
+ // Write the given word to the DUT using the DUT interface.
+ //----------------------------------------------------------------
+ task write_word(input [7 : 0] address,
+ input [31 : 0] word);
+ begin
+ if (DEBUG)
+ begin
+ $display("*** Writing 0x%08x to 0x%02x.", word, address);
+ $display("");
+ end
+
+ tb_address = address;
+ tb_write_data = word;
+ tb_cs = 1;
+ tb_we = 1;
+ #(CLK_PERIOD2);
+ tb_cs = 0;
+ tb_we = 0;
+ end
+ endtask // write_word
+
+
+ //----------------------------------------------------------------
+ // write_block()
+ //
+ // Write the given block to the dut.
+ //----------------------------------------------------------------
+ task write_block(input [511 : 0] block);
+ begin
+ write_word(ADDR_BLOCK0, block[511 : 480]);
+ write_word(ADDR_BLOCK1, block[479 : 448]);
+ write_word(ADDR_BLOCK2, block[447 : 416]);
+ write_word(ADDR_BLOCK3, block[415 : 384]);
+ write_word(ADDR_BLOCK4, block[383 : 352]);
+ write_word(ADDR_BLOCK5, block[351 : 320]);
+ write_word(ADDR_BLOCK6, block[319 : 288]);
+ write_word(ADDR_BLOCK7, block[287 : 256]);
+ write_word(ADDR_BLOCK8, block[255 : 224]);
+ write_word(ADDR_BLOCK9, block[223 : 192]);
+ write_word(ADDR_BLOCK10, block[191 : 160]);
+ write_word(ADDR_BLOCK11, block[159 : 128]);
+ write_word(ADDR_BLOCK12, block[127 : 96]);
+ write_word(ADDR_BLOCK13, block[95 : 64]);
+ write_word(ADDR_BLOCK14, block[63 : 32]);
+ write_word(ADDR_BLOCK15, block[31 : 0]);
+ end
+ endtask // write_block
+
+
+ //----------------------------------------------------------------
+ // read_word()
+ //
+ // Read a data word from the given address in the DUT.
+ // the word read will be available in the global variable
+ // read_data.
+ //----------------------------------------------------------------
+ task read_word(input [7 : 0] address);
+ begin
+ tb_address = address;
+ tb_cs = 1;
+ tb_we = 0;
+ #(CLK_PERIOD2);
+ read_data = tb_read_data;
+ tb_cs = 0;
+
+ if (DEBUG)
+ begin
+ $display("*** Reading 0x%08x from 0x%02x.", read_data, address);
+ $display("");
+ end
+ end
+ endtask // read_word
+
+
+ //----------------------------------------------------------------
+ // check_name_version()
+ //
+ // Read the name and version from the DUT.
+ //----------------------------------------------------------------
+ task check_name_version;
+ reg [31 : 0] name0;
+ reg [31 : 0] name1;
+ reg [31 : 0] version;
+ begin
+
+ read_word(ADDR_NAME0);
+ name0 = read_data;
+ read_word(ADDR_NAME1);
+ name1 = read_data;
+ read_word(ADDR_VERSION);
+ version = read_data;
+
+ $display("DUT name: %c%c%c%c%c%c%c%c",
+ name0[31 : 24], name0[23 : 16], name0[15 : 8], name0[7 : 0],
+ name1[31 : 24], name1[23 : 16], name1[15 : 8], name1[7 : 0]);
+ $display("DUT version: %c%c%c%c",
+ version[31 : 24], version[23 : 16], version[15 : 8], version[7 : 0]);
+ end
+ endtask // check_name_version
+
+
+ //----------------------------------------------------------------
+ // read_digest()
+ //
+ // Read the digest in the dut. The resulting digest will be
+ // available in the global variable digest_data.
+ //----------------------------------------------------------------
+ task read_digest;
+ begin
+ read_word(ADDR_DIGEST0);
+ digest_data[255 : 224] = read_data;
+ read_word(ADDR_DIGEST1);
+ digest_data[223 : 192] = read_data;
+ read_word(ADDR_DIGEST2);
+ digest_data[191 : 160] = read_data;
+ read_word(ADDR_DIGEST3);
+ digest_data[159 : 128] = read_data;
+ read_word(ADDR_DIGEST4);
+ digest_data[127 : 96] = read_data;
+ read_word(ADDR_DIGEST5);
+ digest_data[95 : 64] = read_data;
+ read_word(ADDR_DIGEST6);
+ digest_data[63 : 32] = read_data;
+ read_word(ADDR_DIGEST7);
+ digest_data[31 : 0] = read_data;
+ end
+ endtask // read_digest
+
+
+ //----------------------------------------------------------------
+ // single_block_test()
+ //
+ //
+ // Perform test of a single block digest.
+ //----------------------------------------------------------------
+ task single_block_test(input mode,
+ input [511 : 0] block,
+ input [255 : 0] expected);
+ begin
+ $display("*** TC%01d - Single block test started.", tc_ctr);
+
+ write_block(block);
+
+ if (mode)
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_INIT_VALUE));
+ else
+ write_word(ADDR_CTRL, CTRL_INIT_VALUE);
+
+ #(CLK_PERIOD1);
+ wait_ready();
+ read_digest();
+
+ // We need to ignore the LSW in SHA224 mode.
+ if (mode == SHA224_MODE)
+ digest_data[31 : 0] = 32'h0;
+
+ if (digest_data == expected)
+ begin
+ $display("TC%01d: OK.", tc_ctr);
+ end
+ else
+ begin
+ $display("TC%01d: ERROR.", tc_ctr);
+ $display("TC%01d: Expected: 0x%064x", tc_ctr, expected);
+ $display("TC%01d: Got: 0x%064x", tc_ctr, digest_data);
+ error_ctr = error_ctr + 1;
+ end
+ $display("*** TC%01d - Single block test done.", tc_ctr);
+ tc_ctr = tc_ctr + 1;
+ end
+ endtask // single_block_test
+
+
+ //----------------------------------------------------------------
+ // double_block_test()
+ //
+ //
+ // Perform test of a double block digest. Note that we check
+ // the digests for both the first and final block.
+ //----------------------------------------------------------------
+ task double_block_test(input mode,
+ input [511 : 0] block0,
+ input [255 : 0] expected0,
+ input [511 : 0] block1,
+ input [255 : 0] expected1
+ );
+ begin
+ $display("*** TC%01d - Double block test started.", tc_ctr);
+
+ // First block
+ write_block(block0);
+
+ if (mode)
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_INIT_VALUE));
+ else
+ write_word(ADDR_CTRL, CTRL_INIT_VALUE);
+
+ #(CLK_PERIOD2);
+ wait_ready();
+ read_digest();
+
+ // We need to ignore the LSW in SHA224 mode.
+ if (mode == SHA224_MODE)
+ digest_data[31 : 0] = 32'h0;
+
+ if (digest_data == expected0)
+ begin
+ $display("TC%01d first block: OK.", tc_ctr);
+ end
+ else
+ begin
+ $display("TC%01d: ERROR in first digest", tc_ctr);
+ $display("TC%01d: Expected: 0x%064x", tc_ctr, expected0);
+ $display("TC%01d: Got: 0x%064x", tc_ctr, digest_data);
+ error_ctr = error_ctr + 1;
+ end
+
+ // Final block
+ write_block(block1);
+
+ if (mode)
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_NEXT_VALUE));
+ else
+ write_word(ADDR_CTRL, CTRL_NEXT_VALUE);
+
+ #(CLK_PERIOD2);
+ wait_ready();
+ read_digest();
+
+ // We need to ignore the LSW in SHA224 mode.
+ if (mode == SHA224_MODE)
+ digest_data[31 : 0] = 32'h0;
+
+ if (digest_data == expected1)
+ begin
+ $display("TC%01d final block: OK.", tc_ctr);
+ end
+ else
+ begin
+ $display("TC%01d: ERROR in final digest", tc_ctr);
+ $display("TC%01d: Expected: 0x%064x", tc_ctr, expected1);
+ $display("TC%01d: Got: 0x%064x", tc_ctr, digest_data);
+ error_ctr = error_ctr + 1;
+ end
+
+ $display("*** TC%01d - Double block test done.", tc_ctr);
+ tc_ctr = tc_ctr + 1;
+ end
+ endtask // double_block_test
+
+
+ //----------------------------------------------------------------
+ // sha224_tests()
+ //
+ // Run test cases for sha224.
+ // Test cases taken from:
+ // http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA224.pdf
+ //----------------------------------------------------------------
+ task sha224_tests;
+ begin : sha224_tests_block
+ reg [511 : 0] tc0;
+ reg [255 : 0] res0;
+
+ reg [511 : 0] tc1_0;
+ reg [255 : 0] res1_0;
+ reg [511 : 0] tc1_1;
+ reg [255 : 0] res1_1;
+
+ $display("*** Testcases for sha224 functionality started.");
+
+ tc0 = 512'h61626380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018;
+
+ res0 = 256'h23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA700000000;
+ single_block_test(SHA224_MODE, tc0, res0);
+
+ tc1_0 = 512'h6162636462636465636465666465666765666768666768696768696A68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F70718000000000000000;
+ res1_0 = 256'h8250e65dbcf62f8466659c3333e5e91a10c8b7b0953927691f1419c200000000;
+ tc1_1 = 512'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C0;
+ res1_1 = 256'h75388b16512776cc5dba5da1fd890150b0c6455cb4f58b195252252500000000;
+ double_block_test(SHA224_MODE, tc1_0, res1_0, tc1_1, res1_1);
+
+ $display("*** Testcases for sha224 functionality completed.");
+ end
+ endtask // sha224_tests
+
+
+ //----------------------------------------------------------------
+ // sha256_tests()
+ //
+ // Run test cases for sha256.
+ // Test cases taken from:
+ // http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA256.pdf
+ //----------------------------------------------------------------
+ task sha256_tests;
+ begin : sha256_tests_block
+ reg [511 : 0] tc0;
+ reg [255 : 0] res0;
+
+ reg [511 : 0] tc1_0;
+ reg [255 : 0] res1_0;
+ reg [511 : 0] tc1_1;
+ reg [255 : 0] res1_1;
+
+ $display("*** Testcases for sha256 functionality started.");
+
+ tc0 = 512'h61626380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018;
+ res0 = 256'hBA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD;
+ single_block_test(SHA256_MODE, tc0, res0);
+
+ tc1_0 = 512'h6162636462636465636465666465666765666768666768696768696A68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F70718000000000000000;
+ res1_0 = 256'h85E655D6417A17953363376A624CDE5C76E09589CAC5F811CC4B32C1F20E533A;
+ tc1_1 = 512'h000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001C0;
+ res1_1 = 256'h248D6A61D20638B8E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1;
+ double_block_test(SHA256_MODE, tc1_0, res1_0, tc1_1, res1_1);
+
+ $display("*** Testcases for sha256 functionality completed.");
+ end
+ endtask // sha256_tests
+
+
+
+ //----------------------------------------------------------------
+ // issue_test()
+ //----------------------------------------------------------------
+ task issue_test;
+ reg [511 : 0] block0;
+ reg [511 : 0] block1;
+ reg [511 : 0] block2;
+ reg [511 : 0] block3;
+ reg [511 : 0] block4;
+ reg [511 : 0] block5;
+ reg [511 : 0] block6;
+ reg [511 : 0] block7;
+ reg [511 : 0] block8;
+ reg [255 : 0] expected;
+ begin : issue_test
+ block0 = 512'h6b900001_496e2074_68652061_72656120_6f662049_6f542028_496e7465_726e6574_206f6620_5468696e_6773292c_206d6f72_6520616e_64206d6f_7265626f_6f6d2c20;
+ block1 = 512'h69742068_61732062_65656e20_6120756e_69766572_73616c20_636f6e73_656e7375_73207468_61742064_61746120_69732074_69732061_206e6577_20746563_686e6f6c;
+ block2 = 512'h6f677920_74686174_20696e74_65677261_74657320_64656365_6e747261_6c697a61_74696f6e_2c496e20_74686520_61726561_206f6620_496f5420_28496e74_65726e65;
+ block3 = 512'h74206f66_20546869_6e677329_2c206d6f_72652061_6e64206d_6f726562_6f6f6d2c_20697420_68617320_6265656e_20612075_6e697665_7273616c_20636f6e_73656e73;
+ block4 = 512'h75732074_68617420_64617461_20697320_74697320_61206e65_77207465_63686e6f_6c6f6779_20746861_7420696e_74656772_61746573_20646563_656e7472_616c697a;
+ block5 = 512'h6174696f_6e2c496e_20746865_20617265_61206f66_20496f54_2028496e_7465726e_6574206f_66205468_696e6773_292c206d_6f726520_616e6420_6d6f7265_626f6f6d;
+ block6 = 512'h2c206974_20686173_20626565_6e206120_756e6976_65727361_6c20636f_6e73656e_73757320_74686174_20646174_61206973_20746973_2061206e_65772074_6563686e;
+ block7 = 512'h6f6c6f67_79207468_61742069_6e746567_72617465_73206465_63656e74_72616c69_7a617469_6f6e2c49_6e207468_65206172_6561206f_6620496f_54202849_6e746572;
+ block8 = 512'h6e657420_6f662054_68696e67_73292c20_6d6f7265_20616e64_206d6f72_65800000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_000010e8;
+
+ expected = 256'h7758a30bbdfc9cd92b284b05e9be9ca3d269d3d149e7e82ab4a9ed5e81fbcf9d;
+
+ $display("Running test for 9 block issue.");
+ tc_ctr = tc_ctr + 1;
+ write_block(block0);
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_INIT_VALUE));
+ #(2*CLK_PERIOD2);
+ wait_ready();
+
+ write_block(block1);
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_NEXT_VALUE));
+ #(2*CLK_PERIOD2);
+ tb_sel_clk2=1'b1;
+ wait_ready();
+
+ write_block(block2);
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_NEXT_VALUE));
+ #(2*CLK_PERIOD2);
+ wait_ready();
+
+ write_block(block3);
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_NEXT_VALUE));
+ #(2*CLK_PERIOD2);
+ wait_ready();
+
+ write_block(block4);
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_NEXT_VALUE));
+ #(2*CLK_PERIOD2);
+ tb_sel_clk2=1'b0;
+ wait_ready();
+
+ write_block(block5);
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_NEXT_VALUE));
+ #(2*CLK_PERIOD2);
+ wait_ready();
+
+ write_block(block6);
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_NEXT_VALUE));
+ #(2*CLK_PERIOD2);
+ tb_sel_clk2=1'b1;
+ wait_ready();
+
+ write_block(block7);
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_NEXT_VALUE));
+ #(2*CLK_PERIOD2);
+ tb_sel_clk2=1'b0;
+ wait_ready();
+
+ write_block(block8);
+ write_word(ADDR_CTRL, (CTRL_MODE_VALUE + CTRL_NEXT_VALUE));
+ #(2*CLK_PERIOD2);
+ wait_ready();
+
+ read_digest();
+ if (digest_data == expected)
+ begin
+ $display("Digest ok.");
+ end
+ else
+ begin
+ $display("ERROR in digest");
+ $display("Expected: 0x%064x", expected);
+ $display("Got: 0x%064x", digest_data);
+ error_ctr = error_ctr + 1;
+ end
+ end
+ endtask // issue_test
+
+
+ //----------------------------------------------------------------
+ // The main test functionality.
+ //----------------------------------------------------------------
+ initial
+ begin : main
+ $display(" -- Testbench for sha256 started --");
+
+ init_sim();
+ reset_dut();
+
+ check_name_version();
+ sha224_tests();
+ sha256_tests();
+ issue_test();
+
+ display_test_result();
+
+ $display(" -- Testbench for sha256 done. --");
+ $finish;
+ end // main
+endmodule // tb_sha256
+
+//======================================================================
+// EOF tb_sha256.v
+//======================================================================
diff --git a/Verilog_Code/top_tukka_proj.v b/Verilog_Code/top_tukka_proj.v
new file mode 100644
index 0000000..ba7fde4
--- /dev/null
+++ b/Verilog_Code/top_tukka_proj.v
@@ -0,0 +1,39 @@
+module top_tukka_proj (clk1,clk2,reset_n,sel_clk2,cs,we,address,write_data,read_data,error);
+
+input clk1; // Clock 1 supposed to be faster
+input clk2; // Clock 2 supposed to be slower
+input reset_n; // System reset
+input sel_clk2; // Select clock2 when high
+//for SHA
+// Control.
+input wire cs;
+input wire we;
+// Data ports.
+input wire [7 : 0] address;
+input wire [31 : 0] write_data;
+output wire [31 : 0] read_data;
+output wire error;
+//output clock
+wire clk1or2; // Selected clock
+
+//clock mux instintiated
+clock_mux clock_mux0(
+.clk1(clk1),
+.clk2(clk2),
+.reset_n(reset_n),
+.sel_clk2(sel_clk2),
+.clk1or2(clk1or2)
+);
+//sha instintiated
+sha256 dut(
+.clk(clk1or2),
+.reset_n(reset_n),
+.cs(cs),
+.we(we),
+.address(address),
+.write_data(write_data),
+.read_data(read_data),
+.error(error)
+);
+
+endmodule