../src/lowrisc_ip_aes_0.6/rtl/aes_cipher_control.sv Cov: 100%

   1: // Copyright lowRISC contributors.
   2: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
   3: // SPDX-License-Identifier: Apache-2.0
   4: //
   5: // AES cipher core control
   6: //
   7: // This module controls the AES cipher core including the key expand module.
   8: 
   9: `include "prim_assert.sv"
  10: 
  11: module aes_cipher_control (
  12:   input  logic                    clk_i,
  13:   input  logic                    rst_ni,
  14: 
  15:   // Input handshake signals
  16:   input  logic                    in_valid_i,
  17:   output logic                    in_ready_o,
  18: 
  19:   // Output handshake signals
  20:   output logic                    out_valid_o,
  21:   input  logic                    out_ready_i,
  22: 
  23:   // Control and sync signals
  24:   input  aes_pkg::ciph_op_e       op_i,
  25:   input  aes_pkg::key_len_e       key_len_i,
  26:   input  logic                    crypt_i,
  27:   output logic                    crypt_o,
  28:   input  logic                    dec_key_gen_i,
  29:   output logic                    dec_key_gen_o,
  30:   input  logic                    key_clear_i,
  31:   output logic                    key_clear_o,
  32:   input  logic                    data_out_clear_i,
  33:   output logic                    data_out_clear_o,
  34: 
  35:   // Control outputs cipher data path
  36:   output aes_pkg::state_sel_e     state_sel_o,
  37:   output logic                    state_we_o,
  38:   output aes_pkg::add_rk_sel_e    add_rk_sel_o,
  39: 
  40:   // Control outputs key expand data path
  41:   output aes_pkg::ciph_op_e       key_expand_op_o,
  42:   output aes_pkg::key_full_sel_e  key_full_sel_o,
  43:   output logic                    key_full_we_o,
  44:   output aes_pkg::key_dec_sel_e   key_dec_sel_o,
  45:   output logic                    key_dec_we_o,
  46:   output logic                    key_expand_step_o,
  47:   output logic                    key_expand_clear_o,
  48:   output logic [3:0]              key_expand_round_o,
  49:   output aes_pkg::key_words_sel_e key_words_sel_o,
  50:   output aes_pkg::round_key_sel_e round_key_sel_o
  51: );
  52: 
  53:   import aes_pkg::*;
  54: 
  55:   // Types
  56:   typedef enum logic [2:0] {
  57:     IDLE, INIT, ROUND, FINISH, CLEAR_S, CLEAR_KD
  58:   } aes_cipher_ctrl_e;
  59: 
  60:   aes_cipher_ctrl_e aes_cipher_ctrl_ns, aes_cipher_ctrl_cs;
  61: 
  62:   // Signals
  63:   logic [3:0] round_d, round_q;
  64:   logic [3:0] num_rounds_d, num_rounds_q;
  65:   logic [3:0] num_rounds_regular;
  66:   logic       crypt_d, crypt_q;
  67:   logic       dec_key_gen_d, dec_key_gen_q;
  68:   logic       key_clear_d, key_clear_q;
  69:   logic       data_out_clear_d, data_out_clear_q;
  70: 
  71:   // FSM
  72:   always_comb begin : aes_cipher_ctrl_fsm
  73: 
  74:     // Handshake signals
  75:     in_ready_o         = 1'b0;
  76:     out_valid_o        = 1'b0;
  77: 
  78:     // Cipher data path
  79:     state_sel_o        = STATE_ROUND;
  80:     state_we_o         = 1'b0;
  81:     add_rk_sel_o       = ADD_RK_ROUND;
  82: 
  83:     // Key expand data path
  84:     key_full_sel_o     = KEY_FULL_ROUND;
  85:     key_full_we_o      = 1'b0;
  86:     key_dec_sel_o      = KEY_DEC_EXPAND;
  87:     key_dec_we_o       = 1'b0;
  88:     key_expand_step_o  = 1'b0;
  89:     key_expand_clear_o = 1'b0;
  90:     key_words_sel_o    = KEY_WORDS_ZERO;
  91:     round_key_sel_o    = ROUND_KEY_DIRECT;
  92: 
  93:     // FSM
  94:     aes_cipher_ctrl_ns = aes_cipher_ctrl_cs;
  95:     round_d            = round_q;
  96:     num_rounds_d       = num_rounds_q;
  97:     crypt_d            = crypt_q;
  98:     dec_key_gen_d      = dec_key_gen_q;
  99:     key_clear_d        = key_clear_q;
 100:     data_out_clear_d   = data_out_clear_q;
 101: 
 102:     unique case (aes_cipher_ctrl_cs)
 103: 
 104:       IDLE: begin
 105:         dec_key_gen_d = 1'b0;
 106: 
 107:         // Signal that we are ready, wait for handshake.
 108:         in_ready_o = 1'b1;
 109:         if (in_valid_i) begin
 110:           if (key_clear_i || data_out_clear_i) begin
 111:             // Clear internal key registers. The cipher core muxes are used to clear the data
 112:             // output registers.
 113:             key_clear_d      = key_clear_i;
 114:             data_out_clear_d = data_out_clear_i;
 115: 
 116:             // To clear the data output registers, we must first clear the state.
 117:             aes_cipher_ctrl_ns = data_out_clear_i ? CLEAR_S : CLEAR_KD;
 118: 
 119:           end else if (dec_key_gen_i || crypt_i) begin
 120:             // Start encryption/decryption or generation of start key for decryption.
 121:             crypt_d       = ~dec_key_gen_i;
 122:             dec_key_gen_d =  dec_key_gen_i;
 123: 
 124:             // Load input data to state
 125:             state_sel_o = dec_key_gen_d ? STATE_CLEAR : STATE_INIT;
 126:             state_we_o  = 1'b1;
 127: 
 128:             // Init key expand
 129:             key_expand_clear_o = 1'b1;
 130: 
 131:             // Load full key
 132:             key_full_sel_o = dec_key_gen_d ? KEY_FULL_ENC_INIT :
 133:                         (op_i == CIPH_FWD) ? KEY_FULL_ENC_INIT :
 134:                                              KEY_FULL_DEC_INIT;
 135:             key_full_we_o  = 1'b1;
 136: 
 137:             // Load num_rounds, clear round
 138:             round_d      = '0;
 139:             num_rounds_d = (key_len_i == AES_128) ? 4'd10 :
 140:                            (key_len_i == AES_192) ? 4'd12 :
 141:                                                     4'd14;
 142:             aes_cipher_ctrl_ns = INIT;
 143:           end
 144:         end
 145:       end
 146: 
 147:       INIT: begin
 148:         // Initial round: just add key to state
 149:         state_we_o   = ~dec_key_gen_q;
 150:         add_rk_sel_o = ADD_RK_INIT;
 151: 
 152:         // Select key words for initial add_round_key
 153:         key_words_sel_o = dec_key_gen_q                ? KEY_WORDS_ZERO :
 154:             (key_len_i == AES_128)                     ? KEY_WORDS_0123 :
 155:             (key_len_i == AES_192 && op_i == CIPH_FWD) ? KEY_WORDS_0123 :
 156:             (key_len_i == AES_192 && op_i == CIPH_INV) ? KEY_WORDS_2345 :
 157:             (key_len_i == AES_256 && op_i == CIPH_FWD) ? KEY_WORDS_0123 :
 158:             (key_len_i == AES_256 && op_i == CIPH_INV) ? KEY_WORDS_4567 : KEY_WORDS_ZERO;
 159: 
 160:         // Make key expand advance - AES-256 has two round keys available right from beginning.
 161:         if (key_len_i != AES_256) begin
 162:           key_expand_step_o = 1'b1;
 163:           key_full_we_o     = 1'b1;
 164:         end
 165: 
 166:         aes_cipher_ctrl_ns = ROUND;
 167:       end
 168: 
 169:       ROUND: begin
 170:         // Normal rounds
 171:         state_we_o = ~dec_key_gen_q;
 172: 
 173:         // Select key words for add_round_key
 174:         key_words_sel_o = dec_key_gen_q                ? KEY_WORDS_ZERO :
 175:             (key_len_i == AES_128)                     ? KEY_WORDS_0123 :
 176:             (key_len_i == AES_192 && op_i == CIPH_FWD) ? KEY_WORDS_2345 :
 177:             (key_len_i == AES_192 && op_i == CIPH_INV) ? KEY_WORDS_0123 :
 178:             (key_len_i == AES_256 && op_i == CIPH_FWD) ? KEY_WORDS_4567 :
 179:             (key_len_i == AES_256 && op_i == CIPH_INV) ? KEY_WORDS_0123 : KEY_WORDS_ZERO;
 180: 
 181:         // Make key expand advance
 182:         key_expand_step_o = 1'b1;
 183:         key_full_we_o     = 1'b1;
 184: 
 185:         // Select round key: direct or mixed (equivalent inverse cipher)
 186:         round_key_sel_o = (op_i == CIPH_FWD) ? ROUND_KEY_DIRECT : ROUND_KEY_MIXED;
 187: 
 188:         // Update round
 189:         round_d = round_q + 4'b1;
 190: 
 191:         // Are we doing the last regular round?
 192:         if (round_q == num_rounds_regular) begin
 193:           aes_cipher_ctrl_ns = FINISH;
 194: 
 195:           if (dec_key_gen_q) begin
 196:             // Write decryption key.
 197:             key_dec_we_o = 1'b1;
 198: 
 199:             // Indicate that we are done, try to perform the handshake. But we don't wait here
 200:             // as the decryption key is valid only during one cycle. If we don't get the
 201:             // handshake now, we will wait in the finish state.
 202:             out_valid_o = 1'b1;
 203:             if (out_ready_i) begin
 204:               // Go to idle state directly.
 205:               dec_key_gen_d      = 1'b0;
 206:               aes_cipher_ctrl_ns = IDLE;
 207:             end
 208:           end
 209:         end
 210:       end
 211: 
 212:       FINISH: begin
 213:         // Final round
 214: 
 215:         // Select key words for add_round_key
 216:         key_words_sel_o = dec_key_gen_q                ? KEY_WORDS_ZERO :
 217:             (key_len_i == AES_128)                     ? KEY_WORDS_0123 :
 218:             (key_len_i == AES_192 && op_i == CIPH_FWD) ? KEY_WORDS_2345 :
 219:             (key_len_i == AES_192 && op_i == CIPH_INV) ? KEY_WORDS_0123 :
 220:             (key_len_i == AES_256 && op_i == CIPH_FWD) ? KEY_WORDS_4567 :
 221:             (key_len_i == AES_256 && op_i == CIPH_INV) ? KEY_WORDS_0123 : KEY_WORDS_ZERO;
 222: 
 223:         // Skip mix_columns
 224:         add_rk_sel_o = ADD_RK_FINAL;
 225: 
 226:         // Indicate that we are done, wait for handshake.
 227:         out_valid_o = 1'b1;
 228:         if (out_ready_i) begin
 229:           // We don't need the state anymore, clear it.
 230:           state_we_o         = 1'b1;
 231:           state_sel_o        = STATE_CLEAR;
 232:           crypt_d            = 1'b0;
 233:           // If we were generating the decryption key and didn't get the handshake in the last
 234:           // regular round, we should clear dec_key_gen now.
 235:           dec_key_gen_d      = 1'b0;
 236:           aes_cipher_ctrl_ns = IDLE;
 237:         end
 238:       end
 239: 
 240:       CLEAR_S: begin
 241:         // Clear the state with pseudo-random data.
 242:         state_we_o         = 1'b1;
 243:         state_sel_o        = STATE_CLEAR;
 244:         aes_cipher_ctrl_ns = CLEAR_KD;
 245:       end
 246: 
 247:       CLEAR_KD: begin
 248:         // Clear internal key registers and/or external data output registers.
 249:         if (key_clear_q) begin
 250:           key_full_sel_o = KEY_FULL_CLEAR;
 251:           key_full_we_o  = 1'b1;
 252:           key_dec_sel_o  = KEY_DEC_CLEAR;
 253:           key_dec_we_o   = 1'b1;
 254:         end
 255:         if (data_out_clear_q) begin
 256:           // Forward the state (previously cleared with psuedo-random data).
 257:           add_rk_sel_o    = ADD_RK_INIT;
 258:           key_words_sel_o = KEY_WORDS_ZERO;
 259:           round_key_sel_o = ROUND_KEY_DIRECT;
 260:         end
 261:         // Indicate that we are done, wait for handshake.
 262:         out_valid_o = 1'b1;
 263:         if (out_ready_i) begin
 264:           key_clear_d        = 1'b0;
 265:           data_out_clear_d   = 1'b0;
 266:           aes_cipher_ctrl_ns = IDLE;
 267:         end
 268:       end
 269: 
 270:       default: aes_cipher_ctrl_ns = IDLE;
 271:     endcase
 272:   end
 273: 
 274:   always_ff @(posedge clk_i or negedge rst_ni) begin : reg_fsm
 275:     if (!rst_ni) begin
 276:       aes_cipher_ctrl_cs <= IDLE;
 277:       round_q            <= '0;
 278:       num_rounds_q       <= '0;
 279:       crypt_q            <= 1'b0;
 280:       dec_key_gen_q      <= 1'b0;
 281:       key_clear_q        <= 1'b0;
 282:       data_out_clear_q   <= 1'b0;
 283:     end else begin
 284:       aes_cipher_ctrl_cs <= aes_cipher_ctrl_ns;
 285:       round_q            <= round_d;
 286:       num_rounds_q       <= num_rounds_d;
 287:       crypt_q            <= crypt_d;
 288:       dec_key_gen_q      <= dec_key_gen_d;
 289:       key_clear_q        <= key_clear_d;
 290:       data_out_clear_q   <= data_out_clear_d;
 291:     end
 292:   end
 293: 
 294:   // Use separate signal for number of regular rounds.
 295:   assign num_rounds_regular = num_rounds_q - 4'd2;
 296: 
 297:   // Use separate signals for key expand operation and round.
 298:   assign key_expand_op_o    = (dec_key_gen_d || dec_key_gen_q) ? CIPH_FWD : op_i;
 299:   assign key_expand_round_o = round_d;
 300: 
 301:   // Let the main controller know whate we are doing.
 302:   assign crypt_o          = crypt_q;
 303:   assign dec_key_gen_o    = dec_key_gen_q;
 304:   assign key_clear_o      = key_clear_q;
 305:   assign data_out_clear_o = data_out_clear_q;
 306: 
 307:   ////////////////
 308:   // Assertions //
 309:   ////////////////
 310: 
 311:   // Selectors must be known/valid
 312:   `ASSERT_KNOWN(AesCiphOpKnown, op_i)
 313:   `ASSERT(AesKeyLenValid, key_len_i inside {
 314:       AES_128,
 315:       AES_192,
 316:       AES_256
 317:       })
 318:   `ASSERT(AesControlStateValid, aes_cipher_ctrl_cs inside {
 319:       IDLE,
 320:       INIT,
 321:       ROUND,
 322:       FINISH,
 323:       CLEAR_S,
 324:       CLEAR_KD
 325:       })
 326: 
 327: endmodule
 328: