| // Copyright lowRISC contributors. |
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| // SPDX-License-Identifier: Apache-2.0 |
| // |
| // Key manager operation state control |
| // |
| |
| `include "prim_assert.sv" |
| |
| module keymgr_op_state_ctrl |
| import keymgr_pkg::*; |
| import keymgr_reg_pkg::*; |
| ( |
| input clk_i, |
| input rst_ni, |
| |
| input adv_req_i, |
| input dis_req_i, |
| input id_req_i, |
| input gen_req_i, |
| input [CdiWidth-1:0] cnt_i, |
| output logic op_ack_o, |
| output logic op_busy_o, |
| output logic op_update_o, |
| |
| input kmac_done_i, |
| output logic adv_en_o, |
| output logic id_en_o, |
| output logic gen_en_o, |
| |
| output logic op_fsm_err_o |
| |
| ); |
| |
| localparam int OpStateWidth = 8; |
| typedef enum logic [OpStateWidth-1:0] { |
| StIdle = 8'b10010101, |
| StAdv = 8'b00101000, |
| StAdvAck = 8'b01000011, |
| StWait = 8'b11111110 |
| } state_e; |
| |
| state_e state_q, state_d; |
| logic [OpStateWidth-1:0] state_raw_q; |
| |
| assign state_q = state_e'(state_raw_q); |
| prim_sparse_fsm_flop #( |
| .StateEnumT(state_e), |
| .Width(OpStateWidth), |
| .ResetValue(OpStateWidth'(StIdle)) |
| ) u_state_regs ( |
| .clk_i, |
| .rst_ni, |
| .state_i ( state_d ), |
| .state_o ( state_raw_q ) |
| ); |
| |
| logic gen_en; |
| assign id_en_o = gen_en & id_req_i; |
| assign gen_en_o = gen_en & gen_req_i; |
| |
| always_comb begin |
| state_d = state_q; |
| op_update_o = 1'b0; |
| op_ack_o = 1'b0; |
| op_busy_o = 1'b1; |
| |
| // output to kmac interface |
| adv_en_o = 1'b0; |
| |
| gen_en = 1'b0; |
| op_fsm_err_o = 1'b0; |
| |
| unique case (state_q) |
| StIdle: begin |
| op_busy_o = '0; |
| if (adv_req_i || dis_req_i) begin |
| state_d = StAdv; |
| end else if (id_req_i || gen_req_i) begin |
| state_d = StWait; |
| end |
| end |
| |
| StAdv: begin |
| adv_en_o = 1'b1; |
| |
| if (kmac_done_i && (cnt_i == CDIs-1)) begin |
| op_ack_o = 1'b1; |
| state_d = StIdle; |
| end else if (kmac_done_i && (cnt_i < CDIs-1)) begin |
| op_update_o = 1'b1; |
| state_d = StAdvAck; |
| end |
| end |
| |
| // drop adv_en_o to allow kmac interface handshake |
| StAdvAck: begin |
| state_d = StAdv; |
| end |
| |
| // Not an advanced operation |
| StWait: begin |
| gen_en = 1'b1; |
| |
| if (kmac_done_i) begin |
| op_ack_o = 1'b1; |
| state_d = StIdle; |
| end |
| end |
| |
| // error state |
| default: begin |
| // allow completion of transaction |
| op_ack_o = 1'b1; |
| op_fsm_err_o = 1'b1; |
| end |
| |
| endcase // unique case (adv_state_q) |
| end |
| |
| |
| endmodule // keymgr_op_state_ctrl |