../src/lowrisc_ip_aes_0.6/rtl/aes_cipher_core.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 implementation
   6: //
   7: // This module contains the AES cipher core including, state register, full key and decryption key
   8: // registers as well as key expand module and control unit.
   9: 
  10: `include "prim_assert.sv"
  11: 
  12: module aes_cipher_core #(
  13:   parameter bit AES192Enable = 1,
  14:   parameter     SBoxImpl     = "lut"
  15: ) (
  16:   input  logic                 clk_i,
  17:   input  logic                 rst_ni,
  18: 
  19:   // Input handshake signals
  20:   input  logic                 in_valid_i,
  21:   output logic                 in_ready_o,
  22: 
  23:   // Output handshake signals
  24:   output logic                 out_valid_o,
  25:   input  logic                 out_ready_i,
  26: 
  27:   // Control and sync signals
  28:   input  aes_pkg::ciph_op_e    op_i,
  29:   input  aes_pkg::key_len_e    key_len_i,
  30:   input  logic                 crypt_i,
  31:   output logic                 crypt_o,
  32:   input  logic                 dec_key_gen_i,
  33:   output logic                 dec_key_gen_o,
  34:   input  logic                 key_clear_i,
  35:   output logic                 key_clear_o,
  36:   input  logic                 data_out_clear_i, // Re-use the cipher core muxes.
  37:   output logic                 data_out_clear_o,
  38: 
  39:   // Pseudo-random data
  40:   input  logic          [63:0] prng_data_i,
  41: 
  42:   // I/O data & initial key
  43:   input  logic [3:0][3:0][7:0] state_init_i,
  44:   input  logic     [7:0][31:0] key_init_i,
  45:   output logic [3:0][3:0][7:0] state_o
  46: );
  47: 
  48:   import aes_pkg::*;
  49: 
  50:   // Signals
  51:   logic [3:0][3:0][7:0] state_d;
  52:   logic [3:0][3:0][7:0] state_q;
  53:   logic                 state_we;
  54:   state_sel_e           state_sel;
  55: 
  56:   logic [3:0][3:0][7:0] sub_bytes_out;
  57:   logic [3:0][3:0][7:0] shift_rows_out;
  58:   logic [3:0][3:0][7:0] mix_columns_out;
  59:   logic [3:0][3:0][7:0] add_round_key_in;
  60:   logic [3:0][3:0][7:0] add_round_key_out;
  61:   add_rk_sel_e          add_round_key_in_sel;
  62: 
  63:   logic     [7:0][31:0] key_full_d;
  64:   logic     [7:0][31:0] key_full_q;
  65:   logic                 key_full_we;
  66:   key_full_sel_e        key_full_sel;
  67:   logic     [7:0][31:0] key_dec_d;
  68:   logic     [7:0][31:0] key_dec_q;
  69:   logic                 key_dec_we;
  70:   key_dec_sel_e         key_dec_sel;
  71:   logic     [7:0][31:0] key_expand_out;
  72:   ciph_op_e             key_expand_op;
  73:   logic                 key_expand_step;
  74:   logic                 key_expand_clear;
  75:   logic           [3:0] key_expand_round;
  76:   key_words_sel_e       key_words_sel;
  77:   logic     [3:0][31:0] key_words;
  78:   logic [3:0][3:0][7:0] key_bytes;
  79:   logic [3:0][3:0][7:0] key_mix_columns_out;
  80:   logic [3:0][3:0][7:0] round_key;
  81:   round_key_sel_e       round_key_sel;
  82: 
  83:   //////////
  84:   // Data //
  85:   //////////
  86: 
  87:   // State registers
  88:   always_comb begin : state_mux
  89:     unique case (state_sel)
  90:       STATE_INIT:  state_d = state_init_i;
  91:       STATE_ROUND: state_d = add_round_key_out;
  92:       STATE_CLEAR: state_d = {prng_data_i, prng_data_i};
  93:       default:     state_d = {prng_data_i, prng_data_i};
  94:     endcase
  95:   end
  96: 
  97:   always_ff @(posedge clk_i) begin : state_reg
  98:     if (state_we) begin
  99:       state_q <= state_d;
 100:     end
 101:   end
 102: 
 103:   // Cipher data path
 104:   aes_sub_bytes #(
 105:     .SBoxImpl ( SBoxImpl )
 106:   ) aes_sub_bytes (
 107:     .op_i   ( op_i          ),
 108:     .data_i ( state_q       ),
 109:     .data_o ( sub_bytes_out )
 110:   );
 111: 
 112:   aes_shift_rows aes_shift_rows (
 113:     .op_i   ( op_i           ),
 114:     .data_i ( sub_bytes_out  ),
 115:     .data_o ( shift_rows_out )
 116:   );
 117: 
 118:   aes_mix_columns aes_mix_columns (
 119:     .op_i   ( op_i            ),
 120:     .data_i ( shift_rows_out  ),
 121:     .data_o ( mix_columns_out )
 122:   );
 123: 
 124:   always_comb begin : add_round_key_in_mux
 125:     unique case (add_round_key_in_sel)
 126:       ADD_RK_INIT:  add_round_key_in = state_q;
 127:       ADD_RK_ROUND: add_round_key_in = mix_columns_out;
 128:       ADD_RK_FINAL: add_round_key_in = shift_rows_out;
 129:       default:      add_round_key_in = state_q;
 130:     endcase
 131:   end
 132: 
 133:   assign add_round_key_out = add_round_key_in ^ round_key;
 134: 
 135:   /////////
 136:   // Key //
 137:   /////////
 138: 
 139:   // Full Key registers
 140:   always_comb begin : key_full_mux
 141:     unique case (key_full_sel)
 142:       KEY_FULL_ENC_INIT: key_full_d = key_init_i;
 143:       KEY_FULL_DEC_INIT: key_full_d = key_dec_q;
 144:       KEY_FULL_ROUND:    key_full_d = key_expand_out;
 145:       KEY_FULL_CLEAR:    key_full_d = {prng_data_i, prng_data_i, prng_data_i, prng_data_i};
 146:       default:           key_full_d = {prng_data_i, prng_data_i, prng_data_i, prng_data_i};
 147:     endcase
 148:   end
 149: 
 150:   always_ff @(posedge clk_i) begin : key_full_reg
 151:     if (key_full_we) begin
 152:       key_full_q <= key_full_d;
 153:     end
 154:   end
 155: 
 156:   // Decryption Key registers
 157:   always_comb begin : key_dec_mux
 158:     unique case (key_dec_sel)
 159:       KEY_DEC_EXPAND: key_dec_d = key_expand_out;
 160:       KEY_DEC_CLEAR:  key_dec_d = {prng_data_i, prng_data_i, prng_data_i, prng_data_i};
 161:       default:        key_dec_d = {prng_data_i, prng_data_i, prng_data_i, prng_data_i};
 162:     endcase
 163:   end
 164: 
 165:   always_ff @(posedge clk_i) begin : key_dec_reg
 166:     if (key_dec_we) begin
 167:       key_dec_q <= key_dec_d;
 168:     end
 169:   end
 170: 
 171:   // Key expand data path
 172:   aes_key_expand #(
 173:     .AES192Enable ( AES192Enable ),
 174:     .SBoxImpl     ( SBoxImpl     )
 175:   ) aes_key_expand (
 176:     .clk_i     ( clk_i            ),
 177:     .rst_ni    ( rst_ni           ),
 178:     .op_i      ( key_expand_op    ),
 179:     .step_i    ( key_expand_step  ),
 180:     .clear_i   ( key_expand_clear ),
 181:     .round_i   ( key_expand_round ),
 182:     .key_len_i ( key_len_i        ),
 183:     .key_i     ( key_full_q       ),
 184:     .key_o     ( key_expand_out   )
 185:   );
 186: 
 187:   always_comb begin : key_words_mux
 188:     unique case (key_words_sel)
 189:       KEY_WORDS_0123: key_words = key_full_q[3:0];
 190:       KEY_WORDS_2345: key_words = AES192Enable ? key_full_q[5:2] : '0;
 191:       KEY_WORDS_4567: key_words = key_full_q[7:4];
 192:       KEY_WORDS_ZERO: key_words = '0;
 193:       default:        key_words = '0;
 194:     endcase
 195:   end
 196: 
 197:   // Convert words to bytes (every key word contains one column)
 198:   assign key_bytes = aes_transpose(key_words);
 199: 
 200:   aes_mix_columns aes_key_mix_columns (
 201:     .op_i   ( CIPH_INV            ),
 202:     .data_i ( key_bytes           ),
 203:     .data_o ( key_mix_columns_out )
 204:   );
 205: 
 206:   always_comb begin : round_key_mux
 207:     unique case (round_key_sel)
 208:       ROUND_KEY_DIRECT: round_key = key_bytes;
 209:       ROUND_KEY_MIXED:  round_key = key_mix_columns_out;
 210:       default:          round_key = key_bytes;
 211:     endcase
 212:   end
 213: 
 214:   /////////////
 215:   // Control //
 216:   /////////////
 217: 
 218:   // Control
 219:   aes_cipher_control aes_cipher_control (
 220:     .clk_i                  ( clk_i                ),
 221:     .rst_ni                 ( rst_ni               ),
 222: 
 223:     .in_valid_i             ( in_valid_i           ),
 224:     .in_ready_o             ( in_ready_o           ),
 225:     .out_valid_o            ( out_valid_o          ),
 226:     .out_ready_i            ( out_ready_i          ),
 227:     .op_i                   ( op_i                 ),
 228:     .key_len_i              ( key_len_i            ),
 229:     .crypt_i                ( crypt_i              ),
 230:     .crypt_o                ( crypt_o              ),
 231:     .dec_key_gen_i          ( dec_key_gen_i        ),
 232:     .dec_key_gen_o          ( dec_key_gen_o        ),
 233:     .key_clear_i            ( key_clear_i          ),
 234:     .key_clear_o            ( key_clear_o          ),
 235:     .data_out_clear_i       ( data_out_clear_i     ),
 236:     .data_out_clear_o       ( data_out_clear_o     ),
 237: 
 238:     .state_sel_o            ( state_sel            ),
 239:     .state_we_o             ( state_we             ),
 240:     .add_rk_sel_o           ( add_round_key_in_sel ),
 241:     .key_expand_op_o        ( key_expand_op        ),
 242:     .key_full_sel_o         ( key_full_sel         ),
 243:     .key_full_we_o          ( key_full_we          ),
 244:     .key_dec_sel_o          ( key_dec_sel          ),
 245:     .key_dec_we_o           ( key_dec_we           ),
 246:     .key_expand_step_o      ( key_expand_step      ),
 247:     .key_expand_clear_o     ( key_expand_clear     ),
 248:     .key_expand_round_o     ( key_expand_round     ),
 249:     .key_words_sel_o        ( key_words_sel        ),
 250:     .round_key_sel_o        ( round_key_sel        )
 251:   );
 252: 
 253:   /////////////
 254:   // Outputs //
 255:   /////////////
 256: 
 257:   // The output of the last round is not stored into the state register but forwarded directly.
 258:   assign state_o = add_round_key_out;
 259: 
 260:   ////////////////
 261:   // Assertions //
 262:   ////////////////
 263: 
 264:   // Selectors must be known/valid
 265:   `ASSERT(AesStateSelValid, state_sel inside {
 266:       STATE_INIT,
 267:       STATE_ROUND,
 268:       STATE_CLEAR
 269:       })
 270:   `ASSERT(AesAddRKSelValid, add_round_key_in_sel inside {
 271:       ADD_RK_INIT,
 272:       ADD_RK_ROUND,
 273:       ADD_RK_FINAL
 274:       })
 275:   `ASSERT_KNOWN(AesKeyFullSelKnown, key_full_sel)
 276:   `ASSERT_KNOWN(AesKeyDecSelKnown, key_dec_sel)
 277:   `ASSERT_KNOWN(AesKeyWordsSelKnown, key_words_sel)
 278:   `ASSERT_KNOWN(AesRoundKeySelKnown, round_key_sel)
 279: 
 280: endmodule
 281: