../src/lowrisc_ip_aes_0.6/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: `include "prim_assert.sv"
   8: 
   9: module aes_core #(
  10:   parameter bit AES192Enable = 1,
  11:   parameter     SBoxImpl     = "lut"
  12: ) (
  13:   input  logic                     clk_i,
  14:   input  logic                     rst_ni,
  15: 
  16:   // PRNG Interface
  17:   output logic                     prng_data_req_o,
  18:   input  logic                     prng_data_ack_i,
  19:   input  logic [63:0]              prng_data_i,
  20: 
  21:   output logic                     prng_reseed_req_o,
  22:   input  logic                     prng_reseed_ack_i,
  23: 
  24:   // Bus Interface
  25:   input  aes_reg_pkg::aes_reg2hw_t reg2hw,
  26:   output aes_reg_pkg::aes_hw2reg_t hw2reg
  27: );
  28: 
  29:   import aes_reg_pkg::*;
  30:   import aes_pkg::*;
  31: 
  32:   // Signals
  33:   logic                 ctrl_qe;
  34:   logic                 ctrl_we;
  35:   aes_op_e              aes_op_d, aes_op_q;
  36:   aes_mode_e            aes_mode;
  37:   aes_mode_e            aes_mode_d, aes_mode_q;
  38:   ciph_op_e             cipher_op;
  39:   key_len_e             key_len;
  40:   key_len_e             key_len_d, key_len_q;
  41:   logic                 manual_operation_q;
  42: 
  43:   logic [3:0][3:0][7:0] state_in;
  44:   si_sel_e              state_in_sel;
  45:   logic [3:0][3:0][7:0] add_state_in;
  46:   add_si_sel_e          add_state_in_sel;
  47: 
  48:   logic [3:0][3:0][7:0] state_init;
  49:   logic [3:0][3:0][7:0] state_done;
  50: 
  51:   logic     [7:0][31:0] key_init;
  52:   logic     [7:0]       key_init_qe;
  53:   logic     [7:0][31:0] key_init_d;
  54:   logic     [7:0][31:0] key_init_q;
  55:   logic     [7:0]       key_init_we;
  56:   key_init_sel_e        key_init_sel;
  57: 
  58:   logic     [3:0][31:0] iv;
  59:   logic     [3:0]       iv_qe;
  60:   logic     [7:0][15:0] iv_d;
  61:   logic     [7:0][15:0] iv_q;
  62:   logic     [7:0]       iv_we;
  63:   iv_sel_e              iv_sel;
  64: 
  65:   logic     [7:0][15:0] ctr;
  66:   logic     [7:0]       ctr_we;
  67:   logic                 ctr_incr;
  68:   logic                 ctr_ready;
  69: 
  70:   logic     [3:0][31:0] data_in_prev_d;
  71:   logic     [3:0][31:0] data_in_prev_q;
  72:   logic                 data_in_prev_we;
  73:   dip_sel_e             data_in_prev_sel;
  74: 
  75:   logic     [3:0][31:0] data_in;
  76:   logic     [3:0]       data_in_qe;
  77:   logic                 data_in_we;
  78: 
  79:   logic [3:0][3:0][7:0] add_state_out;
  80:   add_so_sel_e          add_state_out_sel;
  81: 
  82:   logic     [3:0][31:0] data_out_d;
  83:   logic     [3:0][31:0] data_out_q;
  84:   logic                 data_out_we;
  85:   logic           [3:0] data_out_re;
  86: 
  87:   logic                 cipher_in_valid;
  88:   logic                 cipher_in_ready;
  89:   logic                 cipher_out_valid;
  90:   logic                 cipher_out_ready;
  91:   logic                 cipher_crypt;
  92:   logic                 cipher_crypt_busy;
  93:   logic                 cipher_dec_key_gen;
  94:   logic                 cipher_dec_key_gen_busy;
  95:   logic                 cipher_key_clear;
  96:   logic                 cipher_key_clear_busy;
  97:   logic                 cipher_data_out_clear;
  98:   logic                 cipher_data_out_clear_busy;
  99: 
 100:   // Unused signals
 101:   logic     [3:0][31:0] unused_data_out_q;
 102: 
 103:   ////////////
 104:   // Inputs //
 105:   ////////////
 106: 
 107:   always_comb begin : key_init_get
 108:     for (int i=0; i<8; i++) begin
 109:       key_init[i]    = reg2hw.key[i].q;
 110:       key_init_qe[i] = reg2hw.key[i].qe;
 111:     end
 112:   end
 113: 
 114:   always_comb begin : iv_get
 115:     for (int i=0; i<4; i++) begin
 116:       iv[i]    = reg2hw.iv[i].q;
 117:       iv_qe[i] = reg2hw.iv[i].qe;
 118:     end
 119:   end
 120: 
 121:   always_comb begin : data_in_get
 122:     for (int i=0; i<4; i++) begin
 123:       data_in[i]    = reg2hw.data_in[i].q;
 124:       data_in_qe[i] = reg2hw.data_in[i].qe;
 125:     end
 126:   end
 127: 
 128:   always_comb begin : data_out_get
 129:     for (int i=0; i<4; i++) begin
 130:       // data_out is actually hwo, but we need hrw for hwre
 131:       unused_data_out_q[i] = reg2hw.data_out[i].q;
 132:       data_out_re[i]       = reg2hw.data_out[i].re;
 133:     end
 134:   end
 135: 
 136:   assign aes_op_d = aes_op_e'(reg2hw.ctrl.operation.q);
 137: 
 138:   assign aes_mode = aes_mode_e'(reg2hw.ctrl.mode.q);
 139:   always_comb begin : mode_get
 140:     unique case (aes_mode)
 141:       AES_ECB: aes_mode_d = AES_ECB;
 142:       AES_CBC: aes_mode_d = AES_CBC;
 143:       AES_CTR: aes_mode_d = AES_CTR;
 144:       default: aes_mode_d = AES_ECB; // unsupported values are mapped to AES_ECB
 145:     endcase
 146:   end
 147: 
 148:   assign key_len = key_len_e'(reg2hw.ctrl.key_len.q);
 149:   always_comb begin : key_len_get
 150:     unique case (key_len)
 151:       AES_128: key_len_d = AES_128;
 152:       AES_256: key_len_d = AES_256;
 153:       AES_192: key_len_d = AES192Enable ? AES_192 : AES_128;
 154:       default: key_len_d = AES_128; // unsupported values are mapped to AES_128
 155:     endcase
 156:   end
 157: 
 158:   assign ctrl_qe = reg2hw.ctrl.operation.qe & reg2hw.ctrl.mode.qe & reg2hw.ctrl.key_len.qe &
 159:       reg2hw.ctrl.manual_operation.qe;
 160: 
 161:   //////////////////////
 162:   // Key, IV and Data //
 163:   //////////////////////
 164: 
 165:   // Initial Key registers
 166:   always_comb begin : key_init_mux
 167:     unique case (key_init_sel)
 168:       KEY_INIT_INPUT: key_init_d = key_init;
 169:       KEY_INIT_CLEAR: key_init_d = {prng_data_i, prng_data_i, prng_data_i, prng_data_i};
 170:       default:        key_init_d = {prng_data_i, prng_data_i, prng_data_i, prng_data_i};
 171:     endcase
 172:   end
 173: 
 174:   always_ff @(posedge clk_i) begin : key_init_reg
 175:     for (int i=0; i<8; i++) begin
 176:       if (key_init_we[i]) begin
 177:         key_init_q[i] <= key_init_d[i];
 178:       end
 179:     end
 180:   end
 181: 
 182:   // IV registers
 183:   always_comb begin : iv_mux
 184:     unique case (iv_sel)
 185:       IV_INPUT:        iv_d = iv;
 186:       IV_DATA_OUT:     iv_d = data_out_d;
 187:       IV_DATA_IN_PREV: iv_d = data_in_prev_q;
 188:       IV_CTR:          iv_d = ctr;
 189:       IV_CLEAR:        iv_d = {prng_data_i, prng_data_i};
 190:       default:         iv_d = {prng_data_i, prng_data_i};
 191:     endcase
 192:   end
 193: 
 194:   always_ff @(posedge clk_i) begin : iv_reg
 195:     for (int i=0; i<8; i++) begin
 196:       if (iv_we[i]) begin
 197:         iv_q[i] <= iv_d[i];
 198:       end
 199:     end
 200:   end
 201: 
 202:   // Previous input data register
 203:   always_comb begin : data_in_prev_mux
 204:     unique case (data_in_prev_sel)
 205:       DIP_DATA_IN: data_in_prev_d = data_in;
 206:       DIP_CLEAR:   data_in_prev_d = {prng_data_i, prng_data_i};
 207:       default:     data_in_prev_d = {prng_data_i, prng_data_i};
 208:     endcase
 209:   end
 210: 
 211:   always_ff @(posedge clk_i) begin : data_in_prev_reg
 212:     if (data_in_prev_we) begin
 213:       data_in_prev_q <= data_in_prev_d;
 214:     end
 215:   end
 216: 
 217:   /////////////
 218:   // Counter //
 219:   /////////////
 220: 
 221:   aes_ctr aes_ctr (
 222:     .clk_i    ( clk_i     ),
 223:     .rst_ni   ( rst_ni    ),
 224: 
 225:     .incr_i   ( ctr_incr  ),
 226:     .ready_o  ( ctr_ready ),
 227: 
 228:     .ctr_i    ( iv_q      ),
 229:     .ctr_o    ( ctr       ),
 230:     .ctr_we_o ( ctr_we    )
 231:   );
 232: 
 233:   /////////////////
 234:   // Cipher Core //
 235:   /////////////////
 236: 
 237:   // Cipher core operation
 238:   assign cipher_op = (aes_mode_q == AES_ECB && aes_op_q == AES_ENC) ? CIPH_FWD :
 239:                      (aes_mode_q == AES_ECB && aes_op_q == AES_DEC) ? CIPH_INV :
 240:                      (aes_mode_q == AES_CBC && aes_op_q == AES_ENC) ? CIPH_FWD :
 241:                      (aes_mode_q == AES_CBC && aes_op_q == AES_DEC) ? CIPH_INV :
 242:                      (aes_mode_q == AES_CTR)                        ? CIPH_FWD : CIPH_FWD;
 243: 
 244:   // Mux for state input
 245:   always_comb begin : state_in_mux
 246:     unique case (state_in_sel)
 247:       SI_ZERO: state_in = '0;
 248:       SI_DATA: state_in = aes_transpose(data_in);
 249:       default: state_in = '0;
 250:     endcase
 251:   end
 252: 
 253:   // Mux for addition to state input
 254:   always_comb begin : add_state_in_mux
 255:     unique case (add_state_in_sel)
 256:       ADD_SI_ZERO: add_state_in = '0;
 257:       ADD_SI_IV:   add_state_in = aes_transpose(iv_q);
 258:       default:     add_state_in = '0;
 259:     endcase
 260:   end
 261: 
 262:   // Convert input data to state format (every input data word contains one state column)
 263:   assign state_init = state_in ^ add_state_in;
 264: 
 265:   // Cipher core
 266:   aes_cipher_core #(
 267:     .AES192Enable ( AES192Enable ),
 268:     .SBoxImpl     ( SBoxImpl     )
 269:   ) aes_cipher_core (
 270:     .clk_i            ( clk_i                      ),
 271:     .rst_ni           ( rst_ni                     ),
 272: 
 273:     .in_valid_i       ( cipher_in_valid            ),
 274:     .in_ready_o       ( cipher_in_ready            ),
 275:     .out_valid_o      ( cipher_out_valid           ),
 276:     .out_ready_i      ( cipher_out_ready           ),
 277:     .op_i             ( cipher_op                  ),
 278:     .key_len_i        ( key_len_q                  ),
 279:     .crypt_i          ( cipher_crypt               ),
 280:     .crypt_o          ( cipher_crypt_busy          ),
 281:     .dec_key_gen_i    ( cipher_dec_key_gen         ),
 282:     .dec_key_gen_o    ( cipher_dec_key_gen_busy    ),
 283:     .key_clear_i      ( cipher_key_clear           ),
 284:     .key_clear_o      ( cipher_key_clear_busy      ),
 285:     .data_out_clear_i ( cipher_data_out_clear      ),
 286:     .data_out_clear_o ( cipher_data_out_clear_busy ),
 287: 
 288:     .prng_data_i      ( prng_data_i                ),
 289: 
 290:     .state_init_i     ( state_init                 ),
 291:     .key_init_i       ( key_init_q                 ),
 292:     .state_o          ( state_done                 )
 293:   );
 294: 
 295:   // Mux for addition to state output
 296:   always_comb begin : add_state_out_mux
 297:     unique case (add_state_out_sel)
 298:       ADD_SO_ZERO: add_state_out = '0;
 299:       ADD_SO_IV:   add_state_out = aes_transpose(iv_q);
 300:       ADD_SO_DIP:  add_state_out = aes_transpose(data_in_prev_q);
 301:       default:     add_state_out = '0;
 302:     endcase
 303:   end
 304: 
 305:   // Convert output state to output data format (every state column corresponds to one output word)
 306:   assign data_out_d = aes_transpose(state_done ^ add_state_out);
 307: 
 308:   /////////////
 309:   // Control //
 310:   /////////////
 311: 
 312:   // Control
 313:   aes_control aes_control (
 314:     .clk_i                   ( clk_i                            ),
 315:     .rst_ni                  ( rst_ni                           ),
 316: 
 317:     .op_i                    ( aes_op_q                         ),
 318:     .mode_i                  ( aes_mode_q                       ),
 319:     .cipher_op_i             ( cipher_op                        ),
 320:     .manual_operation_i      ( manual_operation_q               ),
 321:     .start_i                 ( reg2hw.trigger.start.q           ),
 322:     .key_clear_i             ( reg2hw.trigger.key_clear.q       ),
 323:     .iv_clear_i              ( reg2hw.trigger.iv_clear.q        ),
 324:     .data_in_clear_i         ( reg2hw.trigger.data_in_clear.q   ),
 325:     .data_out_clear_i        ( reg2hw.trigger.data_out_clear.q  ),
 326:     .prng_reseed_i           ( reg2hw.trigger.prng_reseed.q     ),
 327: 
 328:     .key_init_qe_i           ( key_init_qe                      ),
 329:     .iv_qe_i                 ( iv_qe                            ),
 330:     .data_in_qe_i            ( data_in_qe                       ),
 331:     .data_out_re_i           ( data_out_re                      ),
 332:     .data_in_we_o            ( data_in_we                       ),
 333:     .data_out_we_o           ( data_out_we                      ),
 334: 
 335:     .data_in_prev_sel_o      ( data_in_prev_sel                 ),
 336:     .data_in_prev_we_o       ( data_in_prev_we                  ),
 337: 
 338:     .state_in_sel_o          ( state_in_sel                     ),
 339:     .add_state_in_sel_o      ( add_state_in_sel                 ),
 340:     .add_state_out_sel_o     ( add_state_out_sel                ),
 341: 
 342:     .ctr_incr_o              ( ctr_incr                         ),
 343:     .ctr_ready_i             ( ctr_ready                        ),
 344:     .ctr_we_i                ( ctr_we                           ),
 345: 
 346:     .cipher_in_valid_o       ( cipher_in_valid                  ),
 347:     .cipher_in_ready_i       ( cipher_in_ready                  ),
 348:     .cipher_out_valid_i      ( cipher_out_valid                 ),
 349:     .cipher_out_ready_o      ( cipher_out_ready                 ),
 350:     .cipher_crypt_o          ( cipher_crypt                     ),
 351:     .cipher_crypt_i          ( cipher_crypt_busy                ),
 352:     .cipher_dec_key_gen_o    ( cipher_dec_key_gen               ),
 353:     .cipher_dec_key_gen_i    ( cipher_dec_key_gen_busy          ),
 354:     .cipher_key_clear_o      ( cipher_key_clear                 ),
 355:     .cipher_key_clear_i      ( cipher_key_clear_busy            ),
 356:     .cipher_data_out_clear_o ( cipher_data_out_clear            ),
 357:     .cipher_data_out_clear_i ( cipher_data_out_clear_busy       ),
 358: 
 359:     .key_init_sel_o          ( key_init_sel                     ),
 360:     .key_init_we_o           ( key_init_we                      ),
 361:     .iv_sel_o                ( iv_sel                           ),
 362:     .iv_we_o                 ( iv_we                            ),
 363: 
 364:     .prng_data_req_o         ( prng_data_req_o                  ),
 365:     .prng_data_ack_i         ( prng_data_ack_i                  ),
 366:     .prng_reseed_req_o       ( prng_reseed_req_o                ),
 367:     .prng_reseed_ack_i       ( prng_reseed_ack_i                ),
 368: 
 369:     .start_o                 ( hw2reg.trigger.start.d           ),
 370:     .start_we_o              ( hw2reg.trigger.start.de          ),
 371:     .key_clear_o             ( hw2reg.trigger.key_clear.d       ),
 372:     .key_clear_we_o          ( hw2reg.trigger.key_clear.de      ),
 373:     .iv_clear_o              ( hw2reg.trigger.iv_clear.d        ),
 374:     .iv_clear_we_o           ( hw2reg.trigger.iv_clear.de       ),
 375:     .data_in_clear_o         ( hw2reg.trigger.data_in_clear.d   ),
 376:     .data_in_clear_we_o      ( hw2reg.trigger.data_in_clear.de  ),
 377:     .data_out_clear_o        ( hw2reg.trigger.data_out_clear.d  ),
 378:     .data_out_clear_we_o     ( hw2reg.trigger.data_out_clear.de ),
 379:     .prng_reseed_o           ( hw2reg.trigger.prng_reseed.d     ),
 380:     .prng_reseed_we_o        ( hw2reg.trigger.prng_reseed.de    ),
 381: 
 382:     .output_valid_o          ( hw2reg.status.output_valid.d     ),
 383:     .output_valid_we_o       ( hw2reg.status.output_valid.de    ),
 384:     .input_ready_o           ( hw2reg.status.input_ready.d      ),
 385:     .input_ready_we_o        ( hw2reg.status.input_ready.de     ),
 386:     .idle_o                  ( hw2reg.status.idle.d             ),
 387:     .idle_we_o               ( hw2reg.status.idle.de            ),
 388:     .stall_o                 ( hw2reg.status.stall.d            ),
 389:     .stall_we_o              ( hw2reg.status.stall.de           )
 390:   );
 391: 
 392:   // Input data register clear
 393:   always_comb begin : data_in_reg_clear
 394:     for (int i=0; i<4; i++) begin
 395:       hw2reg.data_in[i].d  = '0;
 396:       hw2reg.data_in[i].de = data_in_we;
 397:     end
 398:   end
 399: 
 400:   // Control register
 401:   assign ctrl_we = ctrl_qe & hw2reg.status.idle.d;
 402: 
 403:   always_ff @(posedge clk_i or negedge rst_ni) begin : ctrl_reg
 404:     if (!rst_ni) begin
 405:       aes_op_q           <= AES_ENC;
 406:       aes_mode_q         <= AES_ECB;
 407:       key_len_q          <= AES_128;
 408:       manual_operation_q <= '0;
 409:     end else if (ctrl_we) begin
 410:       aes_op_q           <= aes_op_d;
 411:       aes_mode_q         <= aes_mode_d;
 412:       key_len_q          <= key_len_d;
 413:       manual_operation_q <= reg2hw.ctrl.manual_operation.q;
 414:     end
 415:   end
 416: 
 417:   /////////////
 418:   // Outputs //
 419:   /////////////
 420: 
 421:   always_ff @(posedge clk_i) begin : data_out_reg
 422:     if (data_out_we) begin
 423:       data_out_q <= data_out_d;
 424:     end
 425:   end
 426: 
 427:   always_comb begin : key_reg_put
 428:     for (int i=0; i<8; i++) begin
 429:       hw2reg.key[i].d  = key_init_q[i];
 430:     end
 431:   end
 432: 
 433:   always_comb begin : iv_reg_put
 434:     for (int i=0; i<4; i++) begin
 435:       hw2reg.iv[i].d  = {iv_q[2*i+1], iv_q[2*i]};
 436:     end
 437:   end
 438: 
 439:   always_comb begin : data_out_put
 440:     for (int i=0; i<4; i++) begin
 441:       hw2reg.data_out[i].d = data_out_q[i];
 442:     end
 443:   end
 444: 
 445:   assign hw2reg.ctrl.mode.d    = {aes_mode_q};
 446:   assign hw2reg.ctrl.key_len.d = {key_len_q};
 447: 
 448:   // These fields are actually hro. But software must be able observe the current value (rw).
 449:   assign hw2reg.ctrl.operation.d        = {aes_op_q};
 450:   assign hw2reg.ctrl.manual_operation.d = manual_operation_q;
 451: 
 452:   ////////////////
 453:   // Assertions //
 454:   ////////////////
 455: 
 456:   // Selectors must be known/valid
 457:   `ASSERT_KNOWN(AesKeyInitSelKnown, key_init_sel)
 458:   `ASSERT(AesIvSelValid, iv_sel inside {
 459:       IV_INPUT,
 460:       IV_DATA_OUT,
 461:       IV_DATA_IN_PREV,
 462:       IV_CTR,
 463:       IV_CLEAR
 464:       })
 465:   `ASSERT_KNOWN(AesDataInPrevSelKnown, data_in_prev_sel)
 466:   `ASSERT(AesModeValid, aes_mode_q inside {
 467:       AES_ECB,
 468:       AES_CBC,
 469:       AES_CTR
 470:       })
 471:   `ASSERT_KNOWN(AesOpKnown, aes_op_q)
 472:   `ASSERT_KNOWN(AesStateInSelKnown, state_in_sel)
 473:   `ASSERT_KNOWN(AesAddStateInSelKnown, add_state_in_sel)
 474:   `ASSERT(AesAddStateOutSelValid, add_state_out_sel inside {
 475:       ADD_SO_ZERO,
 476:       ADD_SO_IV,
 477:       ADD_SO_DIP
 478:       })
 479: 
 480: endmodule
 481: