hw/ip/aes/rtl/aes_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 core implementation
   6: 
   7: module aes_core #(
   8:   parameter bit AES192Enable = 1,
   9:   parameter     SBoxImpl     = "lut"
  10: ) (
  11:   input                            clk_i,
  12:   input                            rst_ni,
  13: 
  14:   // Bus Interface
  15:   input  aes_reg_pkg::aes_reg2hw_t reg2hw,
  16:   output aes_reg_pkg::aes_hw2reg_t hw2reg
  17: );
  18: 
  19:   import aes_reg_pkg::*;
  20:   import aes_pkg::*;
  21: 
  22:   // Signals
  23:   logic     [3:0][31:0] data_in;
  24:   logic     [3:0]       data_in_qe;
  25:   logic                 data_in_we;
  26:   logic     [7:0][31:0] key_init;
  27:   logic     [7:0]       key_init_qe;
  28: 
  29:   logic                 ctrl_qe;
  30:   logic                 ctrl_we;
  31:   mode_e                mode_d, mode_q;
  32:   key_len_e             key_len;
  33:   key_len_e             key_len_d, key_len_q;
  34:   logic                 manual_start_trigger_q;
  35:   logic                 force_data_overwrite_q;
  36: 
  37:   logic [3:0][3:0][7:0] state_init;
  38:   logic [3:0][3:0][7:0] state_d;
  39:   logic [3:0][3:0][7:0] state_q;
  40:   logic                 state_we;
  41:   state_sel_e           state_sel;
  42: 
  43:   logic [3:0][3:0][7:0] sub_bytes_out;
  44:   logic [3:0][3:0][7:0] shift_rows_out;
  45:   logic [3:0][3:0][7:0] mix_columns_out;
  46:   logic [3:0][3:0][7:0] add_round_key_in;
  47:   logic [3:0][3:0][7:0] add_round_key_out;
  48:   add_rk_sel_e          add_round_key_in_sel;
  49: 
  50:   logic     [7:0][31:0] key_init_d;
  51:   logic     [7:0][31:0] key_init_q;
  52:   logic     [7:0]       key_init_we;
  53:   key_init_sel_e        key_init_sel;
  54:   logic     [7:0][31:0] key_full_d;
  55:   logic     [7:0][31:0] key_full_q;
  56:   logic                 key_full_we;
  57:   key_full_sel_e        key_full_sel;
  58:   logic     [7:0][31:0] key_dec_d;
  59:   logic     [7:0][31:0] key_dec_q;
  60:   logic                 key_dec_we;
  61:   key_dec_sel_e         key_dec_sel;
  62:   logic     [7:0][31:0] key_expand_out;
  63:   mode_e                key_expand_mode;
  64:   logic                 key_expand_step;
  65:   logic                 key_expand_clear;
  66:   logic           [3:0] key_expand_round;
  67:   key_words_sel_e       key_words_sel;
  68:   logic     [3:0][31:0] key_words;
  69:   logic [3:0][3:0][7:0] key_bytes;
  70:   logic [3:0][3:0][7:0] key_mix_columns_out;
  71:   logic [3:0][3:0][7:0] round_key;
  72:   round_key_sel_e       round_key_sel;
  73: 
  74:   logic     [3:0][31:0] data_out_d;
  75:   logic     [3:0][31:0] data_out_q;
  76:   logic                 data_out_we;
  77:   logic           [3:0] data_out_re;
  78: 
  79:   // Unused signals
  80:   logic     [3:0][31:0] unused_data_out_q;
  81: 
  82:   ////////////
  83:   // Inputs //
  84:   ////////////
  85: 
  86:   // Inputs
  87:   always_comb begin : key_init_get
  88:     for (int i=0; i<8; i++) begin
  89:       key_init[i]    = reg2hw.key[i].q;
  90:       key_init_qe[i] = reg2hw.key[i].qe;
  91:     end
  92:   end
  93: 
  94:   always_comb begin : data_in_get
  95:     for (int i=0; i<4; i++) begin
  96:       data_in[i]    = reg2hw.data_in[i].q;
  97:       data_in_qe[i] = reg2hw.data_in[i].qe;
  98:     end
  99:   end
 100: 
 101:   always_comb begin : data_out_get
 102:     for (int i=0; i<4; i++) begin
 103:       // data_out is actually hwo, but we need hrw for hwre
 104:       unused_data_out_q[i] = reg2hw.data_out[i].q;
 105:       data_out_re[i]       = reg2hw.data_out[i].re;
 106:     end
 107:   end
 108: 
 109:   assign mode_d = mode_e'(reg2hw.ctrl.mode.q);
 110: 
 111:   assign key_len = key_len_e'(reg2hw.ctrl.key_len.q);
 112:   always_comb begin : get_key_len
 113:     unique case (key_len)
 114:       AES_128: key_len_d = AES_128;
 115:       AES_256: key_len_d = AES_256;
 116:       AES_192: key_len_d = AES192Enable ? AES_192 : AES_128;
 117:       default: key_len_d = AES_128; // unsupported values are mapped to AES_128
 118:     endcase
 119:   end
 120: 
 121:   assign ctrl_qe = reg2hw.ctrl.mode.qe & reg2hw.ctrl.key_len.qe &
 122:       reg2hw.ctrl.manual_start_trigger.qe & reg2hw.ctrl.force_data_overwrite.qe;
 123: 
 124:   //////////
 125:   // Data //
 126:   //////////
 127: 
 128:   // Convert input data to state (every input data word contains one state column)
 129:   assign state_init = aes_transpose(data_in);
 130: 
 131:   // State registers
 132:   always_comb begin : state_mux
 133:     unique case (state_sel)
 134:       STATE_INIT:  state_d = state_init;
 135:       STATE_ROUND: state_d = add_round_key_out;
 136:       STATE_CLEAR: state_d = '0;
 137:       default:     state_d = state_init;
 138:     endcase
 139:   end
 140: 
 141:   always_ff @(posedge clk_i or negedge rst_ni) begin : state_reg
 142:     if (!rst_ni) begin
 143:       state_q <= '0;
 144:     end else if (state_we) begin
 145:       state_q <= state_d;
 146:     end
 147:   end
 148: 
 149:   // Cipher data path
 150:   aes_sub_bytes #(
 151:   .SBoxImpl     ( SBoxImpl )
 152:   ) aes_sub_bytes (
 153:     .mode_i ( mode_q        ),
 154:     .data_i ( state_q       ),
 155:     .data_o ( sub_bytes_out )
 156:   );
 157: 
 158:   aes_shift_rows aes_shift_rows (
 159:     .mode_i ( mode_q         ),
 160:     .data_i ( sub_bytes_out  ),
 161:     .data_o ( shift_rows_out )
 162:   );
 163: 
 164:   aes_mix_columns aes_mix_columns (
 165:     .mode_i ( mode_q          ),
 166:     .data_i ( shift_rows_out  ),
 167:     .data_o ( mix_columns_out )
 168:   );
 169: 
 170:   always_comb begin : add_round_key_in_mux
 171:     unique case (add_round_key_in_sel)
 172:       ADD_RK_INIT:  add_round_key_in = state_q;
 173:       ADD_RK_ROUND: add_round_key_in = mix_columns_out;
 174:       ADD_RK_FINAL: add_round_key_in = shift_rows_out;
 175:       default:      add_round_key_in = state_q;
 176:     endcase
 177:   end
 178: 
 179:   assign add_round_key_out = add_round_key_in ^ round_key;
 180: 
 181:   /////////
 182:   // Key //
 183:   /////////
 184: 
 185:   // Initial Key registers
 186:   always_comb begin : key_init_mux
 187:     unique case (key_init_sel)
 188:       KEY_INIT_INPUT: key_init_d = key_init;
 189:       KEY_INIT_CLEAR: key_init_d = '0;
 190:       default:        key_init_d = key_init;
 191:     endcase
 192:   end
 193: 
 194:   always_ff @(posedge clk_i or negedge rst_ni) begin : key_init_reg
 195:     if (!rst_ni) begin
 196:       key_init_q <= '0;
 197:     end else begin
 198:       for (int i=0; i<8; i++) begin
 199:         if (key_init_we[i]) begin
 200:           key_init_q[i] <= key_init_d[i];
 201:         end
 202:       end
 203:     end
 204:   end
 205: 
 206:   // Full Key registers
 207:   always_comb begin : key_full_mux
 208:     unique case (key_full_sel)
 209:       KEY_FULL_ENC_INIT: key_full_d = key_init_q;
 210:       KEY_FULL_DEC_INIT: key_full_d = key_dec_q;
 211:       KEY_FULL_ROUND:    key_full_d = key_expand_out;
 212:       KEY_FULL_CLEAR:    key_full_d = '0;
 213:       default:           key_full_d = key_init_q;
 214:     endcase
 215:   end
 216: 
 217:   always_ff @(posedge clk_i or negedge rst_ni) begin : key_full_reg
 218:     if (!rst_ni) begin
 219:       key_full_q <= '0;
 220:     end else if (key_full_we) begin
 221:       key_full_q <= key_full_d;
 222:     end
 223:   end
 224: 
 225:   // Decryption Key registers
 226:   always_comb begin : key_dec_mux
 227:     unique case (key_dec_sel)
 228:       KEY_DEC_EXPAND: key_dec_d = key_expand_out;
 229:       KEY_DEC_CLEAR:  key_dec_d = '0;
 230:       default:        key_dec_d = key_expand_out;
 231:     endcase
 232:   end
 233: 
 234:   always_ff @(posedge clk_i or negedge rst_ni) begin : key_dec_reg
 235:     if (!rst_ni) begin
 236:       key_dec_q <= '0;
 237:     end else if (key_dec_we) begin
 238:       key_dec_q <= key_dec_d;
 239:     end
 240:   end
 241: 
 242:   // Key expand data path
 243:   aes_key_expand #(
 244:   .AES192Enable ( AES192Enable ),
 245:   .SBoxImpl     ( SBoxImpl     )
 246:   ) aes_key_expand (
 247:     .clk_i     ( clk_i            ),
 248:     .rst_ni    ( rst_ni           ),
 249:     .mode_i    ( key_expand_mode  ),
 250:     .step_i    ( key_expand_step  ),
 251:     .clear_i   ( key_expand_clear ),
 252:     .round_i   ( key_expand_round ),
 253:     .key_len_i ( key_len_q        ),
 254:     .key_i     ( key_full_q       ),
 255:     .key_o     ( key_expand_out   )
 256:   );
 257: 
 258:   always_comb begin : key_words_mux
 259:     unique case (key_words_sel)
 260:       KEY_WORDS_0123: key_words = key_full_q[3:0];
 261:       KEY_WORDS_2345: key_words = AES192Enable ? key_full_q[5:2] : key_full_q[3:0];
 262:       KEY_WORDS_4567: key_words = key_full_q[7:4];
 263:       KEY_WORDS_ZERO: key_words = '0;
 264:       default:        key_words = key_full_q[3:0];
 265:     endcase
 266:   end
 267: 
 268:   // Convert words to bytes (every key word contains one column)
 269:   assign key_bytes = aes_transpose(key_words);
 270: 
 271:   aes_mix_columns aes_key_mix_columns (
 272:     .mode_i ( AES_DEC             ),
 273:     .data_i ( key_bytes           ),
 274:     .data_o ( key_mix_columns_out )
 275:   );
 276: 
 277:   always_comb begin : round_key_mux
 278:     unique case (round_key_sel)
 279:       ROUND_KEY_DIRECT: round_key = key_bytes;
 280:       ROUND_KEY_MIXED:  round_key = key_mix_columns_out;
 281:       default:          round_key = key_bytes;
 282:     endcase
 283:   end
 284: 
 285:   /////////////
 286:   // Control //
 287:   /////////////
 288: 
 289:   // Control
 290:   aes_control aes_control (
 291:     .clk_i                  ( clk_i                              ),
 292:     .rst_ni                 ( rst_ni                             ),
 293: 
 294:     .mode_i                 ( mode_q                             ),
 295:     .key_len_i              ( key_len_q                          ),
 296:     .manual_start_trigger_i ( manual_start_trigger_q             ),
 297:     .force_data_overwrite_i ( force_data_overwrite_q             ),
 298:     .start_i                ( reg2hw.trigger.start.q             ),
 299:     .key_clear_i            ( reg2hw.trigger.key_clear.q         ),
 300:     .data_in_clear_i        ( reg2hw.trigger.data_in_clear.q     ),
 301:     .data_out_clear_i       ( reg2hw.trigger.data_out_clear.q    ),
 302: 
 303:     .data_in_qe_i           ( data_in_qe                         ),
 304:     .key_init_qe_i          ( key_init_qe                        ),
 305:     .data_out_re_i          ( data_out_re                        ),
 306: 
 307:     .state_sel_o            ( state_sel                          ),
 308:     .state_we_o             ( state_we                           ),
 309:     .add_rk_sel_o           ( add_round_key_in_sel               ),
 310: 
 311:     .key_expand_mode_o      ( key_expand_mode                    ),
 312:     .key_init_sel_o         ( key_init_sel                       ),
 313:     .key_init_we_o          ( key_init_we                        ),
 314:     .key_full_sel_o         ( key_full_sel                       ),
 315:     .key_full_we_o          ( key_full_we                        ),
 316:     .key_dec_sel_o          ( key_dec_sel                        ),
 317:     .key_dec_we_o           ( key_dec_we                         ),
 318:     .key_expand_step_o      ( key_expand_step                    ),
 319:     .key_expand_clear_o     ( key_expand_clear                   ),
 320:     .key_expand_round_o     ( key_expand_round                   ),
 321:     .key_words_sel_o        ( key_words_sel                      ),
 322:     .round_key_sel_o        ( round_key_sel                      ),
 323: 
 324:     .data_in_we_o           ( data_in_we                         ),
 325:     .data_out_we_o          ( data_out_we                        ),
 326: 
 327:     .start_o                ( hw2reg.trigger.start.d             ),
 328:     .start_we_o             ( hw2reg.trigger.start.de            ),
 329:     .key_clear_o            ( hw2reg.trigger.key_clear.d         ),
 330:     .key_clear_we_o         ( hw2reg.trigger.key_clear.de        ),
 331:     .data_in_clear_o        ( hw2reg.trigger.data_in_clear.d     ),
 332:     .data_in_clear_we_o     ( hw2reg.trigger.data_in_clear.de    ),
 333:     .data_out_clear_o       ( hw2reg.trigger.data_out_clear.d    ),
 334:     .data_out_clear_we_o    ( hw2reg.trigger.data_out_clear.de   ),
 335: 
 336:     .output_valid_o         ( hw2reg.status.output_valid.d       ),
 337:     .output_valid_we_o      ( hw2reg.status.output_valid.de      ),
 338:     .input_ready_o          ( hw2reg.status.input_ready.d        ),
 339:     .input_ready_we_o       ( hw2reg.status.input_ready.de       ),
 340:     .idle_o                 ( hw2reg.status.idle.d               ),
 341:     .idle_we_o              ( hw2reg.status.idle.de              ),
 342:     .stall_o                ( hw2reg.status.stall.d              ),
 343:     .stall_we_o             ( hw2reg.status.stall.de             )
 344:   );
 345: 
 346:   // Input data register clear
 347:   always_comb begin : data_in_reg_clear
 348:     for (int i=0; i<4; i++) begin
 349:       hw2reg.data_in[i].d  = '0;
 350:       hw2reg.data_in[i].de = data_in_we;
 351:     end
 352:   end
 353: 
 354:   // Control register
 355:   assign ctrl_we = ctrl_qe & hw2reg.status.idle.d;
 356: 
 357:   always_ff @(posedge clk_i or negedge rst_ni) begin : ctrl_reg
 358:     if (!rst_ni) begin
 359:       mode_q                 <= AES_ENC;
 360:       key_len_q              <= AES_128;
 361:       manual_start_trigger_q <= '0;
 362:       force_data_overwrite_q <= '0;
 363:     end else if (ctrl_we) begin
 364:       mode_q                 <= mode_d;
 365:       key_len_q              <= key_len_d;
 366:       manual_start_trigger_q <= reg2hw.ctrl.manual_start_trigger.q;
 367:       force_data_overwrite_q <= reg2hw.ctrl.force_data_overwrite.q;
 368:     end
 369:   end
 370: 
 371:   /////////////
 372:   // Outputs //
 373:   /////////////
 374: 
 375:   // Convert output state to output data (every state column corresponds to one output word)
 376:   assign data_out_d = aes_transpose(add_round_key_out);
 377: 
 378:   always_ff @(posedge clk_i or negedge rst_ni) begin : data_out_reg
 379:     if (!rst_ni) begin
 380:       data_out_q <= '0;
 381:     end else if (data_out_we) begin
 382:       data_out_q <= data_out_d;
 383:     end
 384:   end
 385: 
 386:   // Outputs
 387:   always_comb begin : key_reg_put
 388:     for (int i=0; i<8; i++) begin
 389:       hw2reg.key[i].d  = key_init_q[i];
 390:     end
 391:   end
 392: 
 393:   always_comb begin : data_out_put
 394:     for (int i=0; i<4; i++) begin
 395:       hw2reg.data_out[i].d = data_out_q[i];
 396:     end
 397:   end
 398: 
 399:   assign hw2reg.ctrl.key_len.d  = {key_len_q};
 400: 
 401:   ////////////////
 402:   // Assertions //
 403:   ////////////////
 404: 
 405:   // Selectors must be known/valid
 406:   `ASSERT_KNOWN(AesModeKnown, mode_q, clk_i, !rst_ni)
 407:   `ASSERT(AesKeyLenValid, key_len_q inside {
 408:       AES_128,
 409:       AES_192,
 410:       AES_256
 411:       }, clk_i, !rst_ni)
 412:   `ASSERT(AesStateSelValid, state_sel inside {
 413:       STATE_INIT,
 414:       STATE_ROUND,
 415:       STATE_CLEAR
 416:       }, clk_i, !rst_ni)
 417:   `ASSERT(AesAddRKSelValid, add_round_key_in_sel inside {
 418:       ADD_RK_INIT,
 419:       ADD_RK_ROUND,
 420:       ADD_RK_FINAL
 421:       }, clk_i, !rst_ni)
 422:   `ASSERT_KNOWN(AesKeyInitSelKnown, key_init_sel, clk_i, !rst_ni)
 423:   `ASSERT_KNOWN(AesKeyFullSelKnown, key_full_sel, clk_i, !rst_ni)
 424:   `ASSERT_KNOWN(AesKeyDecSelKnown, key_dec_sel, clk_i, !rst_ni)
 425:   `ASSERT_KNOWN(AesKeyWordsSelKnown, key_words_sel, clk_i, !rst_ni)
 426:   `ASSERT_KNOWN(AesRoundKeySelKnown, round_key_sel, clk_i, !rst_ni)
 427: 
 428: endmodule
 429: