//======================================================================
//
// keywrap_mkmif.v
// ---------------
// Wrapper for the mkmif_core. This allow us to simplify the
// integration of the mkmif in keywrap_core.
//
//
// Author: Joachim Strombergson
// Copyright (c) 2018, NORDUnet A/S All rights reserved.
// Copyright: 2020, The Commons Conservancy Cryptech Project
// SPDX-License-Identifier: BSD-3-Clause
//
// 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_mkmif (
input wire clk,
input wire reset_n,
output wire mkm_spi_sclk,
output wire mkm_spi_cs_n,
input wire mkm_spi_do,
output wire mkm_spi_di,
input wire init,
input wire read,
input wire write,
input wire key_status,
output wire ready,
input wire [31 : 0] wr_status,
output wire [31 : 0] rd_status,
input wire [255 : 0] wr_key,
output wire [255 : 0] rd_key
);
//----------------------------------------------------------------
// Paramenters and local defines.
//----------------------------------------------------------------
localparam CTRL_IDLE = 4'h0;
localparam CTRL_WAIT = 4'h1;
localparam CTRL_INIT = 4'h2;
localparam CTRL_READ = 4'h3;
localparam CTRL_READ_STATUS_WAIT = 4'h4;
localparam CTRL_READ_KEY = 4'h5;
localparam CTRL_READ_KEY_WAIT = 4'h6;
localparam CTRL_WRITE = 4'h8;
localparam CTRL_WRITE_KEY = 4'h9;
localparam CTRL_WRITE_KEY_WAIT = 4'ha;
// Addresses for storage in the mkm
localparam MKM_STATUS_WORD = 16'h00;
localparam MKM_KEY_BASE_WORD = 16'h04;
localparam DEFAULT_SCLK_DIV = 16'h0020;
//----------------------------------------------------------------
// Registers and memories including control signals.
//----------------------------------------------------------------
reg [31 : 0] key_reg [0 : 7];
reg key_we;
reg [3 : 0] key_word_ctr_reg;
reg [3 : 0] key_word_ctr_new;
reg key_word_ctr_we;
reg key_word_ctr_rst;
reg key_word_ctr_inc;
reg [15 : 0] mkm_addr_reg;
reg [15 : 0] mkm_addr_new;
reg mkm_addr_we;
reg [31 : 0] mkm_write_data_reg;
reg [31 : 0] mkm_write_data_new;
reg mkm_write_data_we;
reg [31 : 0] status_reg;
reg [31 : 0] status_new;
reg status_we;
reg ready_reg;
reg ready_new;
reg ready_we;
reg [3 : 0] keywrap_mkmif_ctrl_reg;
reg [3 : 0] keywrap_mkmif_ctrl_new;
reg keywrap_mkmif_ctrl_we;
reg init_op_reg;
reg read_op_reg;
reg write_op_reg;
//----------------------------------------------------------------
// Wires.
//----------------------------------------------------------------
reg mkm_init_op;
reg mkm_read_op;
reg mkm_write_op;
wire mkm_ready;
wire mkm_valid;
reg [15 : 0] mkm_addr;
wire [31 : 0] mkm_read_data;
//----------------------------------------------------------------
// Instantiations.
//----------------------------------------------------------------
mkmif_core mkm(
.clk(clk),
.reset_n(reset_n),
.spi_sclk(mkm_spi_sclk),
.spi_cs_n(mkm_spi_cs_n),
.spi_do(mkm_spi_do),
.spi_di(mkm_spi_di),
.init_op(init_op_reg),
.read_op(read_op_reg),
.write_op(write_op_reg),
.ready(mkm_ready),
.valid(mkm_valid),
.sclk_div(DEFAULT_SCLK_DIV),
.addr(mkm_addr_reg),
.write_data(mkm_write_data_reg),
.read_data(mkm_read_data)
);
//----------------------------------------------------------------
// Assignments for ports.
//----------------------------------------------------------------
assign ready = ready_reg;
assign rd_status = status_reg;
assign rd_key = {key_reg[7], key_reg[6], key_reg[5], key_reg[4],
key_reg[3], key_reg[2], key_reg[1], key_reg[0]};
//----------------------------------------------------------------
// 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;
ready_reg <= 1'h0;
status_reg <= 32'h0;
mkm_addr_reg <= 16'h0;
mkm_write_data_reg <= 32'h0;
key_word_ctr_reg <= 4'h0;
init_op_reg <= 1'h0;
read_op_reg <= 1'h0;
write_op_reg <= 1'h0;
keywrap_mkmif_ctrl_reg <= CTRL_INIT;
end
else
begin
init_op_reg <= mkm_init_op;
read_op_reg <= mkm_read_op;
write_op_reg <= mkm_write_op;
if (ready_we)
ready_reg <= ready_new;
if (mkm_addr_we)
mkm_addr_reg <= mkm_addr_new;
if (mkm_write_data_we)
mkm_write_data_reg <= mkm_write_data_new;
if (key_we)
key_reg[key_word_ctr_reg] <= mkm_read_data;
if (status_we)
status_reg <= mkm_read_data;
if (key_word_ctr_we)
key_word_ctr_reg <= key_word_ctr_new;
if (keywrap_mkmif_ctrl_we)
keywrap_mkmif_ctrl_reg <= keywrap_mkmif_ctrl_new;
end
end // reg_update
//----------------------------------------------------------------
// key_word_ctr
//----------------------------------------------------------------
always @*
begin : key_word_ctr
key_word_ctr_new = 4'h0;
key_word_ctr_we = 1'h0;
if (key_word_ctr_rst)
begin
key_word_ctr_new = 4'h0;
key_word_ctr_we = 1'h1;
end
if (key_word_ctr_inc)
begin
key_word_ctr_new = key_word_ctr_reg + 1'h1;
key_word_ctr_we = 1'h1;
end
end
//----------------------------------------------------------------
// keywrap_mkmif_ctrl
//----------------------------------------------------------------
always @*
begin : keywrap_mkmif_ctrl
ready_new = 1'h0;
ready_we = 1'h0;
key_we = 1'h0;
key_word_ctr_rst = 1'h0;
key_word_ctr_inc = 1'h0;
status_we = 1'h0;
mkm_init_op = 1'h0;
mkm_read_op = 1'h0;
mkm_write_op = 1'h0;
mkm_addr_new = 16'h0;
mkm_addr_we = 1'h0;
mkm_write_data_new = 32'h0;
mkm_write_data_we = 1'h0;
keywrap_mkmif_ctrl_new = CTRL_IDLE;
keywrap_mkmif_ctrl_we = 1'h0;
case (keywrap_mkmif_ctrl_reg)
CTRL_IDLE:
begin
if (init)
begin
mkm_init_op = 1'h1;
ready_new = 1'h0;
ready_we = 1'h1;
keywrap_mkmif_ctrl_new = CTRL_INIT;
keywrap_mkmif_ctrl_we = 1'h1;
end
if (read)
begin
ready_new = 1'h0;
ready_we = 1'h1;
keywrap_mkmif_ctrl_new = CTRL_READ;
keywrap_mkmif_ctrl_we = 1'h1;
end
if (write)
begin
ready_new = 1'h0;
ready_we = 1'h1;
keywrap_mkmif_ctrl_new = CTRL_WRITE;
keywrap_mkmif_ctrl_we = 1'h1;
end
end
CTRL_INIT:
begin
keywrap_mkmif_ctrl_new = CTRL_WAIT;
keywrap_mkmif_ctrl_we = 1'h1;
end
CTRL_READ:
begin
if (key_status)
begin
key_word_ctr_rst = 1'h1;
keywrap_mkmif_ctrl_new = CTRL_READ_KEY;
keywrap_mkmif_ctrl_we = 1'h1;
end
else
begin
mkm_read_op = 1'h1;
mkm_addr_new = MKM_STATUS_WORD;
mkm_addr_we = 1'h1;
keywrap_mkmif_ctrl_new = CTRL_READ_STATUS_WAIT;
keywrap_mkmif_ctrl_we = 1'h1;
end
end
CTRL_WAIT:
begin
if (mkm_ready)
begin
ready_new = 1'h1;
ready_we = 1'h1;
keywrap_mkmif_ctrl_new = CTRL_IDLE;
keywrap_mkmif_ctrl_we = 1'h1;
end
end
CTRL_READ_STATUS_WAIT:
begin
if (mkm_ready)
begin
status_we = 1'h1;
ready_new = 1'h1;
ready_we = 1'h1;
keywrap_mkmif_ctrl_new = CTRL_IDLE;
keywrap_mkmif_ctrl_we = 1'h1;
end
end
CTRL_READ_KEY:
begin
if (key_word_ctr_reg < 8)
begin
mkm_read_op = 1'h1;
mkm_addr_new = MKM_KEY_BASE_WORD + {key_word_ctr_reg, 2'h0};
mkm_addr_we = 1'h1;
keywrap_mkmif_ctrl_new = CTRL_READ_KEY_WAIT;
keywrap_mkmif_ctrl_we = 1'h1;
end
else
begin
ready_new = 1'h1;
ready_we = 1'h1;
keywrap_mkmif_ctrl_new = CTRL_IDLE;
keywrap_mkmif_ctrl_we = 1'h1;
end
end
CTRL_READ_KEY_WAIT:
begin
if (mkm_ready)
begin
key_we = 1'h1;
key_word_ctr_inc = 1'h1;
keywrap_mkmif_ctrl_new = CTRL_READ_KEY;
keywrap_mkmif_ctrl_we = 1'h1;
end
end
CTRL_WRITE:
begin
if (key_status)
begin
key_word_ctr_rst = 1'h1;
keywrap_mkmif_ctrl_new = CTRL_WRITE_KEY;
keywrap_mkmif_ctrl_we = 1'h1;
end
else
begin
mkm_write_op = 1'h1;
mkm_addr_new = MKM_STATUS_WORD;
mkm_addr_we = 1'h1;
mkm_write_data_new = wr_status;
mkm_write_data_we = 1'h1;
keywrap_mkmif_ctrl_new = CTRL_WAIT;
keywrap_mkmif_ctrl_we = 1'h1;
end
end
CTRL_WRITE_KEY:
begin
if (key_word_ctr_reg < 8)
begin
mkm_write_op = 1'h1;
mkm_addr_new = MKM_KEY_BASE_WORD + {key_word_ctr_reg, 2'h0};
mkm_addr_we = 1'h1;
mkm_write_data_new = wr_key[key_word_ctr_reg * 32 +: 32];
mkm_write_data_we = 1'h1;
keywrap_mkmif_ctrl_new = CTRL_WRITE_KEY_WAIT;
keywrap_mkmif_ctrl_we = 1'h1;
end
else
begin
ready_new = 1'h1;
ready_we = 1'h1;
keywrap_mkmif_ctrl_new = CTRL_IDLE;
keywrap_mkmif_ctrl_we = 1'h1;
end
end
CTRL_WRITE_KEY_WAIT:
begin
if (mkm_ready)
begin
key_word_ctr_inc = 1'h1;
keywrap_mkmif_ctrl_new = CTRL_WRITE_KEY;
keywrap_mkmif_ctrl_we = 1'h1;
end
end
default:
begin
end
endcase // case (keywrap_mkmif_ctrl_reg)
end // keywrap_mkmif_ctrl
endmodule // keywrap_mkmif
//======================================================================
// EOF keywrap_mkmif.v
//======================================================================