../src/lowrisc_ip_aes_0.6/rtl/aes_ctr.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 counter for CTR mode
   6: //
   7: // This module uses a 16-bit counter to iteratively increment the 128-bit counter value.
   8: 
   9: `include "prim_assert.sv"
  10: 
  11: module aes_ctr(
  12:   input  logic             clk_i,
  13:   input  logic             rst_ni,
  14: 
  15:   input  logic             incr_i,
  16:   output logic             ready_o,
  17: 
  18:   input  logic [7:0][15:0] ctr_i, // 8 times 2 bytes
  19:   output logic [7:0][15:0] ctr_o, // 8 times 2 bytes
  20:   output logic [7:0]       ctr_we_o
  21: );
  22: 
  23:   // Reverse byte order
  24:   function automatic logic [15:0][7:0] aes_rev_order_byte(logic [15:0][7:0] in);
  25:     logic [15:0][7:0] out;
  26:     for (int i=0; i<16; i++) begin
  27:       out[i] = in[15-i];
  28:     end
  29:     return out;
  30:   endfunction
  31: 
  32:   // Reverse bit order
  33:   function automatic logic [7:0] aes_rev_order_bit(logic [7:0] in);
  34:     logic [7:0] out;
  35:     for (int i=0; i<8; i++) begin
  36:       out[i] = in[7-i];
  37:     end
  38:     return out;
  39:   endfunction
  40: 
  41:   // Types
  42:   typedef enum logic {
  43:     IDLE, INCR
  44:   } aes_ctr_e;
  45: 
  46:   // Signals
  47:   aes_ctr_e         aes_ctr_ns, aes_ctr_cs;
  48:   logic       [2:0] ctr_slice_idx_d, ctr_slice_idx_q;
  49:   logic             ctr_carry_d, ctr_carry_q;
  50: 
  51:   logic [7:0][15:0] ctr_i_rev; // 8 times 2 bytes
  52:   logic [7:0][15:0] ctr_o_rev; // 8 times 2 bytes
  53:   logic [7:0]       ctr_we_o_rev;
  54:   logic             ctr_we;
  55: 
  56:   logic      [15:0] ctr_i_slice;
  57:   logic      [15:0] ctr_o_slice;
  58:   logic      [16:0] ctr_value;
  59: 
  60:   ////////////
  61:   // Inputs //
  62:   ////////////
  63: 
  64:   // Reverse byte order
  65:   assign ctr_i_rev = aes_rev_order_byte(ctr_i);
  66: 
  67:   /////////////
  68:   // Counter //
  69:   /////////////
  70: 
  71:   // We do 16 bits at a time.
  72:   assign ctr_i_slice = ctr_i_rev[ctr_slice_idx_q];
  73:   assign ctr_value   = ctr_i_slice + {15'b0, ctr_carry_q};
  74:   assign ctr_o_slice = ctr_value[15:0];
  75: 
  76:   /////////////
  77:   // Control //
  78:   /////////////
  79: 
  80:   // FSM
  81:   always_comb begin : aes_ctr_fsm
  82: 
  83:     // Outputs
  84:     ready_o         = 1'b0;
  85:     ctr_we          = 1'b0;
  86: 
  87:     // FSM
  88:     aes_ctr_ns      = aes_ctr_cs;
  89:     ctr_slice_idx_d = ctr_slice_idx_q;
  90:     ctr_carry_d     = ctr_carry_q;
  91: 
  92:     unique case (aes_ctr_cs)
  93:       IDLE: begin
  94:         ready_o = 1'b1;
  95:         if (incr_i) begin
  96:           // Initialize slice index and carry bit.
  97:           ctr_slice_idx_d = '0;
  98:           ctr_carry_d     = 1'b1;
  99:           aes_ctr_ns      = INCR;
 100:         end
 101:       end
 102: 
 103:       INCR: begin
 104:         // Increment slice index.
 105:         ctr_slice_idx_d = ctr_slice_idx_q + 3'b1;
 106:         ctr_carry_d     = ctr_value[16];
 107:         ctr_we          = 1'b1;
 108: 
 109:         if (ctr_slice_idx_q == 3'b111) begin
 110:           aes_ctr_ns = IDLE;
 111:         end
 112:       end
 113: 
 114:       default: aes_ctr_ns = IDLE;
 115:     endcase
 116:   end
 117: 
 118:   // Registers
 119:   always_ff @(posedge clk_i or negedge rst_ni) begin
 120:     if (!rst_ni) begin
 121:       aes_ctr_cs      <= IDLE;
 122:       ctr_slice_idx_q <= '0;
 123:       ctr_carry_q     <= '0;
 124:     end else begin
 125:       aes_ctr_cs      <= aes_ctr_ns;
 126:       ctr_slice_idx_q <= ctr_slice_idx_d;
 127:       ctr_carry_q     <= ctr_carry_d;
 128:     end
 129:   end
 130: 
 131:   /////////////
 132:   // Outputs //
 133:   /////////////
 134: 
 135:   // Combine input and counter output.
 136:   always_comb begin
 137:     ctr_o_rev                  = ctr_i_rev;
 138:     ctr_o_rev[ctr_slice_idx_q] = ctr_o_slice;
 139:   end
 140: 
 141:   // Generate the sliced write enable.
 142:   always_comb begin
 143:     ctr_we_o_rev                  = '0;
 144:     ctr_we_o_rev[ctr_slice_idx_q] = ctr_we;
 145:   end
 146: 
 147:   // Reverse byte and bit order.
 148:   assign ctr_o    = aes_rev_order_byte(ctr_o_rev);
 149:   assign ctr_we_o = aes_rev_order_bit(ctr_we_o_rev);
 150: 
 151:   ////////////////
 152:   // Assertions //
 153:   ////////////////
 154:   `ASSERT_KNOWN(AesCtrStateKnown, aes_ctr_cs)
 155: 
 156: endmodule
 157: