aboutsummaryrefslogblamecommitdiff
path: root/rtl/src/verilog/sha256.v
blob: d6fb133472582ee740d0fb846f49bd21cb7b0e77 (plain) (tree)











































































































































































































                                                                              
//======================================================================
//
// sha256.v
// ------
// Top level wrapper for the SHA-256 hash function providing
// a simple memory like interface with 32 bit data access.
//
// Authors: Joachim Strömbergson, Paul Selkirk
// Copyright (c) 2014, NORDUnet A/S All rights reserved.
// 
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// - Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
//
// - Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
//
// - Neither the name of the NORDUnet nor the names of its contributors may
//   be used to endorse or promote products derived from this software
//   without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//======================================================================

module 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
            );

   //----------------------------------------------------------------
   // Internal constant and parameter definitions.
   //----------------------------------------------------------------
   parameter ADDR_NAME0       = 8'h00;
   parameter ADDR_NAME1       = 8'h01;
   parameter ADDR_VERSION     = 8'h02;

   parameter ADDR_CTRL        = 8'h08;
   parameter CTRL_INIT_BIT    = 0;
   parameter CTRL_NEXT_BIT    = 1;

   parameter ADDR_STATUS      = 8'h09;
   parameter STATUS_READY_BIT = 0;
   parameter STATUS_VALID_BIT = 1;

   parameter ADDR_BLOCK       = 8'h10;

   parameter ADDR_DIGEST      = 8'h20;

   parameter CORE_NAME0       = 32'h73686132; // "sha2"
   parameter CORE_NAME1       = 32'h2d323536; // "-256"
   parameter CORE_VERSION     = 32'h302e3830; // "0.80"

   parameter BLOCK_BITS       = 512;
   parameter DIGEST_BITS      = 256;
   parameter BLOCK_WORDS      = BLOCK_BITS / 32;
   parameter DIGEST_WORDS     = DIGEST_BITS / 32;

   //----------------------------------------------------------------
   // Registers.
   //----------------------------------------------------------------
   reg [0 : BLOCK_BITS - 1]    block_reg;
   reg [0 : DIGEST_BITS - 1]   digest_reg;
   reg                         init_reg;
   reg                         next_reg;

   reg [31 : 0] 	       tmp_read_data;
   reg [31 : 0] 	       tmp_read_data_reg;

   //----------------------------------------------------------------
   // Wires.
   //----------------------------------------------------------------
   wire                        core_init;
   wire                        core_next;
   wire                        core_ready;
   wire [0 : BLOCK_BITS - 1]   core_block;
   wire [0 : DIGEST_BITS - 1]  core_digest;
   wire                        core_digest_valid;

   wire [31 : 0]               core_name0   = CORE_NAME0;
   wire [31 : 0]               core_name1   = CORE_NAME1;
   wire [31 : 0]               core_version = CORE_VERSION;
   wire [31 : 0]               core_ctrl;
   wire [31 : 0]               core_status;

   //----------------------------------------------------------------
   // Concurrent connectivity for ports etc.
   //----------------------------------------------------------------
   assign core_init   = init_reg;
   assign core_next   = next_reg;
   assign core_ctrl   = { 30'b0, next_reg, init_reg };
   assign core_status = { 30'b0, core_digest_valid, core_ready };
   assign core_block  = block_reg;

   assign read_data   = tmp_read_data_reg;

   //----------------------------------------------------------------
   // core instantiation.
   //----------------------------------------------------------------
   sha256_core core(
                  .clk(clk),
                  .reset_n(reset_n),

                  .init(core_init),
                  .next(core_next),

                  .block(core_block),

                  .ready(core_ready),

                  .digest(core_digest),
                  .digest_valid(core_digest_valid)
                  );


   //----------------------------------------------------------------
   // latch in digest when ready
   //----------------------------------------------------------------
   always @(posedge clk)
      begin
         if (core_digest_valid)
           digest_reg <= core_digest;
      end

   //----------------------------------------------------------------
   // storage registers for mapping memory to core interface
   //----------------------------------------------------------------
   always @(posedge clk)
     begin
	init_reg <= 0;
	next_reg <= 0;

	if (cs && we)
	  begin
	     // write operations
	     if ((address >= ADDR_BLOCK) &&
		 (address < ADDR_BLOCK + BLOCK_WORDS))
	       block_reg[((address - ADDR_BLOCK) * 32)+:32] <= write_data;
	     else if (address == ADDR_CTRL)
	       begin
		  init_reg <= write_data[CTRL_INIT_BIT];
		  next_reg <= write_data[CTRL_NEXT_BIT];
	       end
	  end
     end

   always @*
     begin
	tmp_read_data = 32'h00000000;

	if (cs && !we)
	  begin
	     // read operations
	     if ((address >= ADDR_BLOCK) &&
		 (address < ADDR_BLOCK + BLOCK_WORDS))
	       tmp_read_data = block_reg[((address - ADDR_BLOCK) * 32)+:32];
	     else if ((address >= ADDR_DIGEST) &&
		      (address < ADDR_DIGEST + DIGEST_WORDS))
	       tmp_read_data = digest_reg[((address - ADDR_DIGEST) * 32)+:32];
	     else
	       case (address)
		 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 = core_ctrl;
		 ADDR_STATUS:
		   tmp_read_data = core_status;
	       endcase
	  end
     end

   always @(posedge clk)
     begin
	tmp_read_data_reg <= tmp_read_data;
     end

endmodule // sha256