//====================================================================== // // sha512.v // -------- // Top level wrapper for the SHA-512 hash function providing // a simple write()/read() interface with 8 bit data access. // // // Authors: Joachim Strombergson, Paul Selkirk // Copyright (c) 2014, SUNET // 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. // //====================================================================== module sha512( // Clock and reset. input wire clk, input wire reset_n, // SHA-512 mode input wire [1 : 0] mode, // Interface to communication core input wire rx_syn, input wire [7 : 0] rx_data, output wire rx_ack, output wire tx_syn, output wire [7 : 0] tx_data, input wire tx_ack ); //---------------------------------------------------------------- // Internal constant and parameter definitions. //---------------------------------------------------------------- parameter RX_INIT = 0; parameter RX_SYN = 1; parameter RX_ACK = 2; parameter RX_WAIT = 3; parameter TX_INIT = 0; parameter TX_SYN = 1; parameter TX_ACK = 2; parameter MODE_SHA_512_224 = 2'h0; parameter MODE_SHA_512_256 = 2'h1; parameter MODE_SHA_384 = 2'h2; parameter MODE_SHA_512 = 2'h3; parameter BLOCK_BITS = 1024; parameter BLOCK_BYTES = BLOCK_BITS / 8; parameter DIGEST_BITS = 512; parameter DIGEST_BYTES = DIGEST_BITS / 8; parameter DIGEST_BYTES_512_224 = 224 / 8; parameter DIGEST_BYTES_512_256 = 256 / 8; parameter DIGEST_BYTES_384 = 384 / 8; parameter DIGEST_BYTES_512 = 512 / 8; //---------------------------------------------------------------- // Registers including update variables and write enable. //---------------------------------------------------------------- reg rx_ack_reg; reg rx_ack_new; reg rx_ack_we; reg [6 : 0] rx_ptr_reg; reg [7 : 0] rx_ptr_new; reg rx_ptr_we; reg [1 : 0] rx_ctrl_reg; reg [1 : 0] rx_ctrl_new; reg rx_ctrl_we; reg [7 : 0] block_reg [0 : BLOCK_BYTES - 1]; reg [7 : 0] block_new; reg block_we; reg init_reg; reg init_new; reg init_we; reg next_reg; reg next_new; reg next_we; reg initnext_reg; reg initnext_new; reg initnext_we; reg tx_syn_reg; reg tx_syn_new; reg tx_syn_we; reg [6 : 0] tx_ptr_reg; reg [7 : 0] tx_ptr_new; reg tx_ptr_we; reg [1 : 0] tx_ctrl_reg; reg [1 : 0] tx_ctrl_new; reg tx_ctrl_we; reg tx_active_reg; reg tx_active_new; reg tx_active_we; wire [7 : 0] digest_reg [0 : DIGEST_BYTES - 1]; //---------------------------------------------------------------- // Wires. //---------------------------------------------------------------- wire core_init; wire core_next; wire core_ready; wire [BLOCK_BITS - 1 : 0] core_block; wire [DIGEST_BITS - 1 : 0] core_digest; wire core_digest_valid; //---------------------------------------------------------------- // Concurrent connectivity for ports etc. //---------------------------------------------------------------- assign core_init = init_reg; assign core_next = next_reg; assign core_block = {block_reg[0], block_reg[1], block_reg[2], block_reg[3], block_reg[4], block_reg[5], block_reg[6], block_reg[7], block_reg[8], block_reg[9], block_reg[10], block_reg[11], block_reg[12], block_reg[13], block_reg[14], block_reg[15], block_reg[16], block_reg[17], block_reg[18], block_reg[19], block_reg[20], block_reg[21], block_reg[22], block_reg[23], block_reg[24], block_reg[25], block_reg[26], block_reg[27], block_reg[28], block_reg[29], block_reg[30], block_reg[31], block_reg[32], block_reg[33], block_reg[34], block_reg[35], block_reg[36], block_reg[37], block_reg[38], block_reg[39], block_reg[40], block_reg[41], block_reg[42], block_reg[43], block_reg[44], block_reg[45], block_reg[46], block_reg[47], block_reg[48], block_reg[49], block_reg[50], block_reg[51], block_reg[52], block_reg[53], block_reg[54], block_reg[55], block_reg[56], block_reg[57], block_reg[58], block_reg[59], block_reg[60], block_reg[61], block_reg[62], block_reg[63], block_reg[64], block_reg[65], block_reg[66], block_reg[67], block_reg[68], block_reg[69], block_reg[70], block_reg[71], block_reg[72], block_reg[73], block_reg[74], block_reg[75], block_reg[76], block_reg[77], block_reg[78], block_reg[79], block_reg[80], block_reg[81], block_reg[82], block_reg[83], block_reg[84], block_reg[85], block_reg[86], block_reg[87], block_reg[88], block_reg[89], block_reg[90], block_reg[91], block_reg[92], block_reg[93], block_reg[94], block_reg[95], block_reg[96], block_reg[97], block_reg[98], block_reg[99], block_reg[100], block_reg[101], block_reg[102], block_reg[103], block_reg[104], block_reg[105], block_reg[106], block_reg[107], block_reg[108], block_reg[109], block_reg[110], block_reg[111], block_reg[112], block_reg[113], block_reg[114], block_reg[115], block_reg[116], block_reg[117], block_reg[118], block_reg[119], block_reg[120], block_reg[121], block_reg[122], block_reg[123], block_reg[124], block_reg[125], block_reg[126], block_reg[127]}; assign rx_ack = rx_ack_reg; assign tx_syn = tx_syn_reg; assign tx_data = digest_reg[tx_ptr_reg]; assign digest_reg[0] = core_digest[511 : 504]; assign digest_reg[1] = core_digest[503 : 496]; assign digest_reg[2] = core_digest[495 : 488]; assign digest_reg[3] = core_digest[487 : 480]; assign digest_reg[4] = core_digest[479 : 472]; assign digest_reg[5] = core_digest[471 : 464]; assign digest_reg[6] = core_digest[463 : 456]; assign digest_reg[7] = core_digest[455 : 448]; assign digest_reg[8] = core_digest[447 : 440]; assign digest_reg[9] = core_digest[439 : 432]; assign digest_reg[10] = core_digest[431 : 424]; assign digest_reg[11] = core_digest[423 : 416]; assign digest_reg[12] = core_digest[415 : 408]; assign digest_reg[13] = core_digest[407 : 400]; assign digest_reg[14] = core_digest[399 : 392]; assign digest_reg[15] = core_digest[391 : 384]; assign digest_reg[16] = core_digest[383 : 376]; assign digest_reg[17] = core_digest[375 : 368]; assign digest_reg[18] = core_digest[367 : 360]; assign digest_reg[19] = core_digest[359 : 352]; assign digest_reg[20] = core_digest[351 : 344]; assign digest_reg[21] = core_digest[343 : 336]; assign digest_reg[22] = core_digest[335 : 328]; assign digest_reg[23] = core_digest[327 : 320]; assign digest_reg[24] = core_digest[319 : 312]; assign digest_reg[25] = core_digest[311 : 304]; assign digest_reg[26] = core_digest[303 : 296]; assign digest_reg[27] = core_digest[295 : 288]; assign digest_reg[28] = core_digest[287 : 280]; assign digest_reg[29] = core_digest[279 : 272]; assign digest_reg[30] = core_digest[271 : 264]; assign digest_reg[31] = core_digest[263 : 256]; assign digest_reg[32] = core_digest[255 : 248]; assign digest_reg[33] = core_digest[247 : 240]; assign digest_reg[34] = core_digest[239 : 232]; assign digest_reg[35] = core_digest[231 : 224]; assign digest_reg[36] = core_digest[223 : 216]; assign digest_reg[37] = core_digest[215 : 208]; assign digest_reg[38] = core_digest[207 : 200]; assign digest_reg[39] = core_digest[199 : 192]; assign digest_reg[40] = core_digest[191 : 184]; assign digest_reg[41] = core_digest[183 : 176]; assign digest_reg[42] = core_digest[175 : 168]; assign digest_reg[43] = core_digest[167 : 160]; assign digest_reg[44] = core_digest[159 : 152]; assign digest_reg[45] = core_digest[151 : 144]; assign digest_reg[46] = core_digest[143 : 136]; assign digest_reg[47] = core_digest[135 : 128]; assign digest_reg[48] = core_digest[127 : 120]; assign digest_reg[49] = core_digest[119 : 112]; assign digest_reg[50] = core_digest[111 : 104]; assign digest_reg[51] = core_digest[103 : 96]; assign digest_reg[52] = core_digest[95 : 88]; assign digest_reg[53] = core_digest[87 : 80]; assign digest_reg[54] = core_digest[79 : 72]; assign digest_reg[55] = core_digest[71 : 64]; assign digest_reg[56] = core_digest[63 : 56]; assign digest_reg[57] = core_digest[55 : 48]; assign digest_reg[58] = core_digest[47 : 40]; assign digest_reg[59] = core_digest[39 : 32]; assign digest_reg[60] = core_digest[31 : 24]; assign digest_reg[61] = core_digest[23 : 16]; assign digest_reg[62] = core_digest[15 : 8]; assign digest_reg[63] = core_digest[7 : 0]; //---------------------------------------------------------------- // core instantiation. //---------------------------------------------------------------- sha512_core core( .clk(clk), .reset_n(reset_n), .init(core_init), .next(core_next), .mode(mode), .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 synchronous // active low reset. All registers have write enable. //---------------------------------------------------------------- always @ (posedge clk) begin: reg_update if (!reset_n) begin: reset_reg reg[7:0] i; for (i = 0; i < BLOCK_BYTES; i = i + 1) block_reg[i] <= 0; rx_ack_reg <= 0; rx_ptr_reg <= 0; rx_ctrl_reg <= RX_INIT; tx_syn_reg <= 0; tx_ptr_reg <= 0; tx_ctrl_reg <= TX_INIT; initnext_reg <= 0; end else begin if (rx_ack_we) begin rx_ack_reg <= rx_ack_new; end if (rx_ptr_we) begin rx_ptr_reg <= rx_ptr_new[6:0]; end if (rx_ctrl_we) begin rx_ctrl_reg <= rx_ctrl_new; end if (block_we) begin block_reg[rx_ptr_reg] <= block_new; end if (init_we) begin init_reg <= init_new; end if (next_we) begin next_reg <= next_new; end if (initnext_we) begin initnext_reg <= initnext_new; end if (tx_syn_we) begin tx_syn_reg <= tx_syn_new; end if (tx_ptr_we) begin tx_ptr_reg <= tx_ptr_new[6:0]; end if (tx_ctrl_we) begin tx_ctrl_reg <= tx_ctrl_new; end if (tx_active_we) begin tx_active_reg <= tx_active_new; end end end // reg_update //---------------------------------------------------------------- // rx_engine //---------------------------------------------------------------- always @* begin: rx_engine rx_ack_new = 0; rx_ack_we = 0; rx_ptr_new = 0; rx_ptr_we = 0; rx_ctrl_new = 0; rx_ctrl_we = 0; block_new = 0; block_we = 0; init_new = 0; init_we = 0; next_new = 0; next_we = 0; initnext_new = 0; initnext_we = 0; if (tx_active_reg) begin initnext_we = 1; end case (rx_ctrl_reg) RX_INIT: if (core_ready) begin rx_ctrl_new = RX_SYN; rx_ctrl_we = 1; end RX_SYN: if (rx_syn) begin rx_ack_new = 1; rx_ack_we = 1; block_new = rx_data; block_we = 1; rx_ctrl_new = RX_ACK; rx_ctrl_we = 1; end RX_ACK: if (!rx_syn) begin rx_ack_new = 0; rx_ack_we = 1; rx_ptr_new = rx_ptr_reg + 1; rx_ptr_we = 1; rx_ctrl_new = RX_SYN; rx_ctrl_we = 1; if (rx_ptr_new == BLOCK_BYTES) begin rx_ptr_new = 0; rx_ctrl_new = RX_WAIT; if (initnext_reg == 0) begin init_new = 1; init_we = 1; initnext_new = 1; initnext_we = 1; end else begin next_new = 1; next_we = 1; end end end RX_WAIT: if (!core_ready) begin init_new = 0; init_we = 1; next_new = 0; next_we = 1; rx_ctrl_new = RX_INIT; rx_ctrl_we = 1; end endcase // case (rx_ctrl_reg) end // rx_engine //---------------------------------------------------------------- // tx_engine //---------------------------------------------------------------- always @* begin: tx_engine tx_syn_new = 0; tx_syn_we = 0; tx_ptr_new = 0; tx_ptr_we = 0; tx_ctrl_new = 0; tx_ctrl_we = 0; tx_active_new = 0; tx_active_we = 0; case (tx_ctrl_reg) TX_INIT: if (core_digest_valid) begin tx_ctrl_new = TX_SYN; tx_ctrl_we = 1; end TX_SYN: begin tx_syn_new = 1; tx_syn_we = 1; tx_ctrl_new = TX_ACK; tx_ctrl_we = 1; end TX_ACK: if (!core_digest_valid) begin tx_syn_new = 0; tx_syn_we = 1; tx_ptr_new = 0; tx_ptr_we = 1; tx_ctrl_new = TX_INIT; tx_ctrl_we = 1; end else if (tx_ack) begin tx_active_new = 1; tx_active_we = 1; tx_syn_new = 0; tx_syn_we = 1; tx_ptr_new = tx_ptr_reg + 1; tx_ptr_we = 1; tx_ctrl_new = TX_SYN; tx_ctrl_we = 1; if (((mode == MODE_SHA_512_224) && (tx_ptr_new == DIGEST_BYTES_512_224)) || ((mode == MODE_SHA_512_256) && (tx_ptr_new == DIGEST_BYTES_512_256)) || ((mode == MODE_SHA_384) && (tx_ptr_new == DIGEST_BYTES_384)) || ((mode == MODE_SHA_512) && (tx_ptr_new == DIGEST_BYTES_512))) begin tx_active_new = 0; tx_ptr_new = 0; tx_ctrl_new = TX_INIT; end end endcase // case (tx_ctrl_reg) end // tx_engine endmodule // sha512 //====================================================================== // EOF sha512.v //======================================================================