../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: