//====================================================================== // // keywrap.v // -------- // Top level wrapper for the KEY WRAP core. // // // Author: Joachim Strombergson // Copyright (c) 2018, 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 keywrap( // 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 ADDR_STATUS = 8'h09; localparam STATUS_READY_BIT = 0; localparam STATUS_VALID_BIT = 1; localparam ADDR_CONFIG = 8'h0a; localparam CTRL_ENCDEC_BIT = 0; localparam CTRL_KEYLEN_BIT = 1; localparam ADDR_RLEN = 8'h0c; localparam ADDR_A_LSB = 8'h0e; localparam ADDR_A_MSB = 8'h0f; localparam ADDR_KEY0 = 8'h10; localparam ADDR_KEY7 = 8'h17; localparam ADDR_WRITE_DATA = 8'h20; localparam ADDR_READ_DATA = 8'h30; localparam CORE_NAME0 = 32'h6b657920; // "key " localparam CORE_NAME1 = 32'h77726170; // "wrap" localparam CORE_VERSION = 32'h302e3230; // "0.20" //---------------------------------------------------------------- // Registers including update variables and write enable. //---------------------------------------------------------------- reg init_reg; reg init_new; reg next_reg; reg next_new; reg encdec_reg; reg keylen_reg; reg config_we; reg api_cs_reg; reg api_cs_new; reg api_we_reg; reg api_we_new; reg [12 : 0] rlen_reg; reg rlen_we; reg [31 : 0] a0_reg; reg a0_we; reg [31 : 0] a1_reg; reg a1_we; reg [31 : 0] key_reg [0 : 7]; reg key_we; reg valid_reg; reg ready_reg; //---------------------------------------------------------------- // Wires. //---------------------------------------------------------------- reg [31 : 0] tmp_read_data; reg tmp_error; wire core_ready; wire core_valid; wire [255 : 0] core_key; wire [31 : 0] core_api_rd_data; wire [63 : 0] core_a_result; //---------------------------------------------------------------- // Concurrent connectivity for ports etc. //---------------------------------------------------------------- assign read_data = tmp_read_data; assign error = tmp_error; assign core_key = {key_reg[0], key_reg[1], key_reg[2], key_reg[3], key_reg[4], key_reg[5], key_reg[6], key_reg[7]}; //---------------------------------------------------------------- // core instantiation. //---------------------------------------------------------------- keywrap_core core( .clk(clk), .reset_n(reset_n), .init(init_reg), .next(next_reg), .encdec(encdec_reg), .ready(core_ready), .valid(core_valid), .rlen(rlen_reg), .key(core_key), .keylen(keylen_reg), .a_init({a1_reg, a0_reg}), .a_result(core_a_result), .api_cs(api_cs_reg), .api_we(api_we_reg), .api_wr_data(write_data), .api_rd_data(core_api_rd_data) ); //---------------------------------------------------------------- // reg_update //---------------------------------------------------------------- always @ (posedge clk or negedge reset_n) begin : reg_update integer i; if (!reset_n) begin for (i = 0 ; i < 8 ; i = i + 1) key_reg[i] <= 32'h0; init_reg <= 1'h0; next_reg <= 1'h0; encdec_reg <= 1'h0; keylen_reg <= 1'h0; rlen_reg <= 13'h0; valid_reg <= 1'h0; ready_reg <= 1'h0; api_cs_reg <= 1'h0; api_we_reg <= 1'h0; a0_reg <= 32'h0; a1_reg <= 32'h0; end else begin ready_reg <= core_ready; valid_reg <= core_valid; init_reg <= init_new; next_reg <= next_new; api_cs_reg <= api_cs_new; api_we_reg <= api_we_new; if (config_we) begin encdec_reg <= write_data[CTRL_ENCDEC_BIT]; keylen_reg <= write_data[CTRL_KEYLEN_BIT]; end if (rlen_we) rlen_reg <= write_data[12 : 0]; if (a0_we) a0_reg <= write_data; if (a1_we) a1_reg <= write_data; if (key_we) key_reg[address[2 : 0]] <= write_data; end end // reg_update //---------------------------------------------------------------- // api // // The interface command decoding logic. //---------------------------------------------------------------- always @* begin : api init_new = 1'h0; next_new = 1'h0; config_we = 1'h0; rlen_we = 1'h0; key_we = 1'h0; api_cs_new = 1'h0; api_we_new = 1'h0; a0_we = 1'h1; a1_we = 1'h1; tmp_read_data = 32'h0; tmp_error = 1'h0; 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]; end if (address == ADDR_CONFIG) config_we = 1'h1; if (address == ADDR_RLEN) config_we = 1'h1; if (address == ADDR_A_LSB) a0_we = 1'h1; if (address == ADDR_A_MSB) a1_we = 1'h1; if ((address >= ADDR_KEY0) && (address <= ADDR_KEY7)) key_we = 1'h1; if (address == ADDR_WRITE_DATA) begin api_cs_new = 1'h1; api_we_new = 1'h1; end end // if (we) else begin 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 = {28'h0, keylen_reg, encdec_reg, next_reg, init_reg}; ADDR_STATUS: tmp_read_data = {30'h0, valid_reg, ready_reg}; default: begin end endcase // case (address) if (address == ADDR_A_LSB) tmp_read_data = core_a_result[31 : 0]; if (address == ADDR_A_MSB) tmp_read_data = core_a_result[63 : 32]; if (address == ADDR_READ_DATA) begin api_cs_new = 1'h1; tmp_read_data = core_api_rd_data; end end end end // addr_decoder endmodule // keywrap //====================================================================== // EOF keywrap.v //======================================================================