| // Copyright lowRISC contributors. |
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| // SPDX-License-Identifier: Apache-2.0 |
| // |
| // AES main control FSM |
| // |
| // This module contains the main control FSM handling the interplay of input/output registers and |
| // the AES cipher core. This version operates on and produces the negated values of important |
| // control signals. This is achieved by: |
| // - instantiating the regular main control FSM operating on and producing the positive values of |
| // these signals, and |
| // - inverting these signals between the regular FSM and the prim_buf synthesis barriers. |
| // Synthesis tools will then push the inverters into the actual FSM. |
| |
| `include "prim_assert.sv" |
| |
| module aes_control_fsm_n |
| import aes_pkg::*; |
| import aes_reg_pkg::*; |
| #( |
| parameter bit SecMasking = 0 |
| ) ( |
| input logic clk_i, |
| input logic rst_ni, |
| |
| // Main control signals |
| input logic ctrl_qe_i, |
| output logic ctrl_we_o, |
| input logic ctrl_phase_i, |
| input logic ctrl_err_storage_i, |
| input aes_op_e op_i, |
| input aes_mode_e mode_i, |
| input ciph_op_e cipher_op_i, |
| input logic sideload_i, |
| input prs_rate_e prng_reseed_rate_i, |
| input logic manual_operation_i, |
| input logic key_touch_forces_reseed_i, |
| input logic start_i, |
| input logic key_iv_data_in_clear_i, |
| input logic data_out_clear_i, |
| input logic prng_reseed_i, |
| input logic mux_sel_err_i, |
| input logic sp_enc_err_i, |
| input lc_ctrl_pkg::lc_tx_t lc_escalate_en_i, |
| input logic alert_fatal_i, |
| output logic alert_o, |
| |
| // I/O register read/write enables |
| input logic key_sideload_valid_i, |
| input logic [NumSharesKey-1:0][NumRegsKey-1:0] key_init_qe_i, |
| input logic [NumRegsIv-1:0] iv_qe_i, |
| input logic [NumRegsData-1:0] data_in_qe_i, |
| input logic [NumRegsData-1:0] data_out_re_i, |
| output logic data_in_we_o, |
| output logic data_out_we_no, // Sparsify |
| |
| // Previous input data register |
| output dip_sel_e data_in_prev_sel_o, |
| output logic data_in_prev_we_no, // Sparsify |
| |
| // Cipher I/O muxes |
| output si_sel_e state_in_sel_o, |
| output add_si_sel_e add_state_in_sel_o, |
| output add_so_sel_e add_state_out_sel_o, |
| |
| // Counter |
| output logic ctr_incr_no, // Sparsify |
| input logic ctr_ready_ni, // Sparsify |
| input logic [NumSlicesCtr-1:0] ctr_we_ni, // Sparsify |
| |
| // Cipher core control and sync |
| output logic cipher_in_valid_no, // Sparsify |
| input logic cipher_in_ready_ni, // Sparsify |
| input logic cipher_out_valid_ni, // Sparsify |
| output logic cipher_out_ready_no, // Sparsify |
| output logic cipher_crypt_no, // Sparsify |
| input logic cipher_crypt_ni, // Sparsify |
| output logic cipher_dec_key_gen_no, // Sparsify |
| input logic cipher_dec_key_gen_ni, // Sparsify |
| output logic cipher_prng_reseed_o, |
| input logic cipher_prng_reseed_i, |
| output logic cipher_key_clear_o, |
| input logic cipher_key_clear_i, |
| output logic cipher_data_out_clear_o, |
| input logic cipher_data_out_clear_i, |
| |
| // Initial key registers |
| output key_init_sel_e key_init_sel_o, |
| output logic [NumSharesKey-1:0][NumRegsKey-1:0] key_init_we_no, // Sparsify |
| |
| // IV registers |
| output iv_sel_e iv_sel_o, |
| output logic [NumSlicesCtr-1:0] iv_we_no, // Sparsify |
| |
| // Pseudo-random number generator interface |
| output logic prng_data_req_o, |
| input logic prng_data_ack_i, |
| output logic prng_reseed_req_o, |
| input logic prng_reseed_ack_i, |
| |
| // Trigger register |
| output logic start_we_o, |
| output logic key_iv_data_in_clear_we_o, |
| output logic data_out_clear_we_o, |
| output logic prng_reseed_o, |
| output logic prng_reseed_we_o, |
| |
| // Status register |
| output logic idle_o, |
| output logic idle_we_o, |
| output logic stall_o, |
| output logic stall_we_o, |
| input logic output_lost_i, |
| output logic output_lost_o, |
| output logic output_lost_we_o, |
| output logic output_valid_o, |
| output logic output_valid_we_o, |
| output logic input_ready_o, |
| output logic input_ready_we_o |
| ); |
| |
| ///////////////////// |
| // Input Buffering // |
| ///////////////////// |
| |
| localparam int NumInBufBits = $bits({ |
| ctrl_qe_i, |
| ctrl_phase_i, |
| ctrl_err_storage_i, |
| op_i, |
| mode_i, |
| cipher_op_i, |
| sideload_i, |
| prng_reseed_rate_i, |
| manual_operation_i, |
| key_touch_forces_reseed_i, |
| start_i, |
| key_iv_data_in_clear_i, |
| data_out_clear_i, |
| prng_reseed_i, |
| mux_sel_err_i, |
| sp_enc_err_i, |
| lc_escalate_en_i, |
| alert_fatal_i, |
| key_sideload_valid_i, |
| key_init_qe_i, |
| iv_qe_i, |
| data_in_qe_i, |
| data_out_re_i, |
| ctr_ready_ni, |
| ctr_we_ni, |
| cipher_in_ready_ni, |
| cipher_out_valid_ni, |
| cipher_crypt_ni, |
| cipher_dec_key_gen_ni, |
| cipher_prng_reseed_i, |
| cipher_key_clear_i, |
| cipher_data_out_clear_i, |
| prng_data_ack_i, |
| prng_reseed_ack_i, |
| output_lost_i |
| }); |
| |
| logic [NumInBufBits-1:0] in, in_buf; |
| |
| assign in = { |
| ctrl_qe_i, |
| ctrl_phase_i, |
| ctrl_err_storage_i, |
| op_i, |
| mode_i, |
| cipher_op_i, |
| sideload_i, |
| prng_reseed_rate_i, |
| manual_operation_i, |
| key_touch_forces_reseed_i, |
| start_i, |
| key_iv_data_in_clear_i, |
| data_out_clear_i, |
| prng_reseed_i, |
| mux_sel_err_i, |
| sp_enc_err_i, |
| lc_escalate_en_i, |
| alert_fatal_i, |
| key_sideload_valid_i, |
| key_init_qe_i, |
| iv_qe_i, |
| data_in_qe_i, |
| data_out_re_i, |
| ctr_ready_ni, |
| ctr_we_ni, |
| cipher_in_ready_ni, |
| cipher_out_valid_ni, |
| cipher_crypt_ni, |
| cipher_dec_key_gen_ni, |
| cipher_prng_reseed_i, |
| cipher_key_clear_i, |
| cipher_data_out_clear_i, |
| prng_data_ack_i, |
| prng_reseed_ack_i, |
| output_lost_i |
| }; |
| |
| // This primitive is used to place a size-only constraint on the |
| // buffers to act as a synthesis optimization barrier. |
| prim_buf #( |
| .Width(NumInBufBits) |
| ) u_prim_buf_in ( |
| .in_i(in), |
| .out_o(in_buf) |
| ); |
| |
| logic ctrl_qe; |
| logic ctrl_phase; |
| logic ctrl_err_storage; |
| aes_op_e op; |
| aes_mode_e mode; |
| ciph_op_e cipher_op; |
| logic [$bits(cipher_op)-1:0] cipher_op_raw; |
| logic sideload; |
| prs_rate_e prng_reseed_rate; |
| logic manual_operation; |
| logic key_touch_forces_reseed; |
| logic start; |
| logic key_iv_data_in_clear; |
| logic data_out_clear; |
| logic prng_reseed_in_buf; |
| logic mux_sel_err; |
| logic sp_enc_err; |
| lc_ctrl_pkg::lc_tx_t lc_escalate_en; |
| logic alert_fatal; |
| logic key_sideload_valid; |
| logic [NumSharesKey-1:0][NumRegsKey-1:0] key_init_qe; |
| logic [NumRegsIv-1:0] iv_qe; |
| logic [NumRegsData-1:0] data_in_qe; |
| logic [NumRegsData-1:0] data_out_re; |
| logic ctr_ready_n; |
| logic [NumSlicesCtr-1:0] ctr_we_n; |
| logic cipher_in_ready_n; |
| logic cipher_out_valid_n; |
| logic cipher_crypt_in_buf_n; |
| logic cipher_dec_key_gen_in_buf_n; |
| logic cipher_prng_reseed_in_buf; |
| logic cipher_key_clear_in_buf; |
| logic cipher_data_out_clear_in_buf; |
| logic prng_data_ack; |
| logic prng_reseed_ack; |
| logic output_lost_in_buf; |
| |
| assign {ctrl_qe, |
| ctrl_phase, |
| ctrl_err_storage, |
| op, |
| mode, |
| cipher_op_raw, |
| sideload, |
| prng_reseed_rate, |
| manual_operation, |
| key_touch_forces_reseed, |
| start, |
| key_iv_data_in_clear, |
| data_out_clear, |
| prng_reseed_in_buf, |
| mux_sel_err, |
| sp_enc_err, |
| lc_escalate_en, |
| alert_fatal, |
| key_sideload_valid, |
| key_init_qe, |
| iv_qe, |
| data_in_qe, |
| data_out_re, |
| ctr_ready_n, |
| ctr_we_n, |
| cipher_in_ready_n, |
| cipher_out_valid_n, |
| cipher_crypt_in_buf_n, |
| cipher_dec_key_gen_in_buf_n, |
| cipher_prng_reseed_in_buf, |
| cipher_key_clear_in_buf, |
| cipher_data_out_clear_in_buf, |
| prng_data_ack, |
| prng_reseed_ack, |
| output_lost_in_buf} = in_buf; |
| |
| assign cipher_op = ciph_op_e'(cipher_op_raw); |
| |
| // Intermediate output signals |
| logic ctrl_we; |
| logic alert; |
| logic data_in_we; |
| logic data_out_we; |
| dip_sel_e data_in_prev_sel; |
| logic data_in_prev_we; |
| si_sel_e state_in_sel; |
| add_si_sel_e add_state_in_sel; |
| add_so_sel_e add_state_out_sel; |
| logic ctr_incr; |
| logic cipher_in_valid; |
| logic cipher_out_ready; |
| logic cipher_crypt_out_buf; |
| logic cipher_dec_key_gen_out_buf; |
| logic cipher_prng_reseed_out_buf; |
| logic cipher_key_clear_out_buf; |
| logic cipher_data_out_clear_out_buf; |
| key_init_sel_e key_init_sel; |
| logic [NumSharesKey-1:0][NumRegsKey-1:0] key_init_we; |
| iv_sel_e iv_sel; |
| logic [NumSlicesCtr-1:0] iv_we; |
| logic prng_data_req; |
| logic prng_reseed_req; |
| logic start_we; |
| logic key_iv_data_in_clear_we; |
| logic data_out_clear_we; |
| logic prng_reseed_out_buf; |
| logic prng_reseed_we; |
| logic idle; |
| logic idle_we; |
| logic stall; |
| logic stall_we; |
| logic output_lost_out_buf; |
| logic output_lost_we; |
| logic output_valid; |
| logic output_valid_we; |
| logic input_ready; |
| logic input_ready_we; |
| |
| ///////////////// |
| // Regular FSM // |
| ///////////////// |
| |
| // The regular FSM operates on and produces the positive values of important control signals. |
| // Invert *_n input signals here to get the positive values for the regular FSM. To obtain the |
| // negated outputs, important output signals are inverted further below. Thanks to the prim_buf |
| // synthesis optimization barriers, tools will push the inverters into the regular FSM. |
| aes_control_fsm #( |
| .SecMasking ( SecMasking ) |
| ) u_aes_control_fsm ( |
| .clk_i ( clk_i ), |
| .rst_ni ( rst_ni ), |
| |
| .ctrl_qe_i ( ctrl_qe ), |
| .ctrl_we_o ( ctrl_we ), |
| .ctrl_phase_i ( ctrl_phase ), |
| .ctrl_err_storage_i ( ctrl_err_storage ), |
| .op_i ( op ), |
| .mode_i ( mode ), |
| .cipher_op_i ( cipher_op ), |
| .sideload_i ( sideload ), |
| .prng_reseed_rate_i ( prng_reseed_rate ), |
| .manual_operation_i ( manual_operation ), |
| .key_touch_forces_reseed_i ( key_touch_forces_reseed ), |
| .start_i ( start ), |
| .key_iv_data_in_clear_i ( key_iv_data_in_clear ), |
| .data_out_clear_i ( data_out_clear ), |
| .prng_reseed_i ( prng_reseed_in_buf ), |
| .mux_sel_err_i ( mux_sel_err ), |
| .sp_enc_err_i ( sp_enc_err ), |
| .lc_escalate_en_i ( lc_escalate_en ), |
| .alert_fatal_i ( alert_fatal ), |
| .alert_o ( alert ), |
| |
| .key_sideload_valid_i ( key_sideload_valid ), |
| .key_init_qe_i ( key_init_qe ), |
| .iv_qe_i ( iv_qe ), |
| .data_in_qe_i ( data_in_qe ), |
| .data_out_re_i ( data_out_re ), |
| .data_in_we_o ( data_in_we ), |
| .data_out_we_o ( data_out_we ), // Invert below for _n output. |
| |
| .data_in_prev_sel_o ( data_in_prev_sel ), |
| .data_in_prev_we_o ( data_in_prev_we ), // Invert below for _n output. |
| |
| .state_in_sel_o ( state_in_sel ), |
| .add_state_in_sel_o ( add_state_in_sel ), |
| .add_state_out_sel_o ( add_state_out_sel ), |
| |
| .ctr_incr_o ( ctr_incr ), // Invert below for _n output. |
| .ctr_ready_i ( ~ctr_ready_n ), // Invert for regular FSM. |
| .ctr_we_i ( ~ctr_we_n ), // Invert for regular FSM. |
| |
| .cipher_in_valid_o ( cipher_in_valid ), // Invert below for _n output. |
| .cipher_in_ready_i ( ~cipher_in_ready_n ), // Invert for regular FSM. |
| .cipher_out_valid_i ( ~cipher_out_valid_n ), // Invert for regular FSM. |
| .cipher_out_ready_o ( cipher_out_ready ), // Invert below for _n output. |
| .cipher_crypt_o ( cipher_crypt_out_buf ), // Invert below for _n output. |
| .cipher_crypt_i ( ~cipher_crypt_in_buf_n ), // Invert for regular FSM. |
| .cipher_dec_key_gen_o ( cipher_dec_key_gen_out_buf ), // Invert below for _n output. |
| .cipher_dec_key_gen_i ( ~cipher_dec_key_gen_in_buf_n ), // Invert for regular FSM. |
| .cipher_prng_reseed_o ( cipher_prng_reseed_out_buf ), |
| .cipher_prng_reseed_i ( cipher_prng_reseed_in_buf ), |
| .cipher_key_clear_o ( cipher_key_clear_out_buf ), |
| .cipher_key_clear_i ( cipher_key_clear_in_buf ), |
| .cipher_data_out_clear_o ( cipher_data_out_clear_out_buf ), |
| .cipher_data_out_clear_i ( cipher_data_out_clear_in_buf ), |
| |
| .key_init_sel_o ( key_init_sel ), |
| .key_init_we_o ( key_init_we ), // Invert below for _n output. |
| |
| .iv_sel_o ( iv_sel ), |
| .iv_we_o ( iv_we ), // Invert below for _n output. |
| |
| .prng_data_req_o ( prng_data_req ), |
| .prng_data_ack_i ( prng_data_ack ), |
| .prng_reseed_req_o ( prng_reseed_req ), |
| .prng_reseed_ack_i ( prng_reseed_ack ), |
| |
| .start_we_o ( start_we ), |
| .key_iv_data_in_clear_we_o ( key_iv_data_in_clear_we ), |
| .data_out_clear_we_o ( data_out_clear_we ), |
| .prng_reseed_o ( prng_reseed_out_buf ), |
| .prng_reseed_we_o ( prng_reseed_we ), |
| |
| .idle_o ( idle ), |
| .idle_we_o ( idle_we ), |
| .stall_o ( stall ), |
| .stall_we_o ( stall_we ), |
| .output_lost_i ( output_lost_in_buf ), |
| .output_lost_o ( output_lost_out_buf ), |
| .output_lost_we_o ( output_lost_we ), |
| .output_valid_o ( output_valid ), |
| .output_valid_we_o ( output_valid_we ), |
| .input_ready_o ( input_ready ), |
| .input_ready_we_o ( input_ready_we ) |
| ); |
| |
| ////////////////////// |
| // Output Buffering // |
| ////////////////////// |
| |
| localparam int NumOutBufBits = $bits({ |
| ctrl_we_o, |
| alert_o, |
| data_in_we_o, |
| data_out_we_no, |
| data_in_prev_sel_o, |
| data_in_prev_we_no, |
| state_in_sel_o, |
| add_state_in_sel_o, |
| add_state_out_sel_o, |
| ctr_incr_no, |
| cipher_in_valid_no, |
| cipher_out_ready_no, |
| cipher_crypt_no, |
| cipher_dec_key_gen_no, |
| cipher_prng_reseed_o, |
| cipher_key_clear_o, |
| cipher_data_out_clear_o, |
| key_init_sel_o, |
| key_init_we_no, |
| iv_sel_o, |
| iv_we_no, |
| prng_data_req_o, |
| prng_reseed_req_o, |
| start_we_o, |
| key_iv_data_in_clear_we_o, |
| data_out_clear_we_o, |
| prng_reseed_o, |
| prng_reseed_we_o, |
| idle_o, |
| idle_we_o, |
| stall_o, |
| stall_we_o, |
| output_lost_o, |
| output_lost_we_o, |
| output_valid_o, |
| output_valid_we_o, |
| input_ready_o, |
| input_ready_we_o |
| }); |
| |
| logic [NumOutBufBits-1:0] out, out_buf; |
| |
| // Important output control signals need to be inverted here. Synthesis tools will push the |
| // inverters back into the regular FSM. |
| assign out = { |
| ctrl_we, |
| alert, |
| data_in_we, |
| ~data_out_we, |
| data_in_prev_sel, |
| ~data_in_prev_we, |
| state_in_sel, |
| add_state_in_sel, |
| add_state_out_sel, |
| ~ctr_incr, |
| ~cipher_in_valid, |
| ~cipher_out_ready, |
| ~cipher_crypt_out_buf, |
| ~cipher_dec_key_gen_out_buf, |
| cipher_prng_reseed_out_buf, |
| cipher_key_clear_out_buf, |
| cipher_data_out_clear_out_buf, |
| key_init_sel, |
| ~key_init_we, |
| iv_sel, |
| ~iv_we, |
| prng_data_req, |
| prng_reseed_req, |
| start_we, |
| key_iv_data_in_clear_we, |
| data_out_clear_we, |
| prng_reseed_out_buf, |
| prng_reseed_we, |
| idle, |
| idle_we, |
| stall, |
| stall_we, |
| output_lost_out_buf, |
| output_lost_we, |
| output_valid, |
| output_valid_we, |
| input_ready, |
| input_ready_we |
| }; |
| |
| // This primitive is used to place a size-only constraint on the |
| // buffers to act as a synthesis optimization barrier. |
| prim_buf #( |
| .Width(NumOutBufBits) |
| ) u_prim_buf_out ( |
| .in_i(out), |
| .out_o(out_buf) |
| ); |
| |
| assign {ctrl_we_o, |
| alert_o, |
| data_in_we_o, |
| data_out_we_no, |
| data_in_prev_sel_o, |
| data_in_prev_we_no, |
| state_in_sel_o, |
| add_state_in_sel_o, |
| add_state_out_sel_o, |
| ctr_incr_no, |
| cipher_in_valid_no, |
| cipher_out_ready_no, |
| cipher_crypt_no, |
| cipher_dec_key_gen_no, |
| cipher_prng_reseed_o, |
| cipher_key_clear_o, |
| cipher_data_out_clear_o, |
| key_init_sel_o, |
| key_init_we_no, |
| iv_sel_o, |
| iv_we_no, |
| prng_data_req_o, |
| prng_reseed_req_o, |
| start_we_o, |
| key_iv_data_in_clear_we_o, |
| data_out_clear_we_o, |
| prng_reseed_o, |
| prng_reseed_we_o, |
| idle_o, |
| idle_we_o, |
| stall_o, |
| stall_we_o, |
| output_lost_o, |
| output_lost_we_o, |
| output_valid_o, |
| output_valid_we_o, |
| input_ready_o, |
| input_ready_we_o} = out_buf; |
| |
| endmodule |