../src/lowrisc_ip_aes_0.6/rtl/aes_cipher_control.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 control
6: //
7: // This module controls the AES cipher core including the key expand module.
8:
9: `include "prim_assert.sv"
10:
11: module aes_cipher_control (
12: input logic clk_i,
13: input logic rst_ni,
14:
15: // Input handshake signals
16: input logic in_valid_i,
17: output logic in_ready_o,
18:
19: // Output handshake signals
20: output logic out_valid_o,
21: input logic out_ready_i,
22:
23: // Control and sync signals
24: input aes_pkg::ciph_op_e op_i,
25: input aes_pkg::key_len_e key_len_i,
26: input logic crypt_i,
27: output logic crypt_o,
28: input logic dec_key_gen_i,
29: output logic dec_key_gen_o,
30: input logic key_clear_i,
31: output logic key_clear_o,
32: input logic data_out_clear_i,
33: output logic data_out_clear_o,
34:
35: // Control outputs cipher data path
36: output aes_pkg::state_sel_e state_sel_o,
37: output logic state_we_o,
38: output aes_pkg::add_rk_sel_e add_rk_sel_o,
39:
40: // Control outputs key expand data path
41: output aes_pkg::ciph_op_e key_expand_op_o,
42: output aes_pkg::key_full_sel_e key_full_sel_o,
43: output logic key_full_we_o,
44: output aes_pkg::key_dec_sel_e key_dec_sel_o,
45: output logic key_dec_we_o,
46: output logic key_expand_step_o,
47: output logic key_expand_clear_o,
48: output logic [3:0] key_expand_round_o,
49: output aes_pkg::key_words_sel_e key_words_sel_o,
50: output aes_pkg::round_key_sel_e round_key_sel_o
51: );
52:
53: import aes_pkg::*;
54:
55: // Types
56: typedef enum logic [2:0] {
57: IDLE, INIT, ROUND, FINISH, CLEAR_S, CLEAR_KD
58: } aes_cipher_ctrl_e;
59:
60: aes_cipher_ctrl_e aes_cipher_ctrl_ns, aes_cipher_ctrl_cs;
61:
62: // Signals
63: logic [3:0] round_d, round_q;
64: logic [3:0] num_rounds_d, num_rounds_q;
65: logic [3:0] num_rounds_regular;
66: logic crypt_d, crypt_q;
67: logic dec_key_gen_d, dec_key_gen_q;
68: logic key_clear_d, key_clear_q;
69: logic data_out_clear_d, data_out_clear_q;
70:
71: // FSM
72: always_comb begin : aes_cipher_ctrl_fsm
73:
74: // Handshake signals
75: in_ready_o = 1'b0;
76: out_valid_o = 1'b0;
77:
78: // Cipher data path
79: state_sel_o = STATE_ROUND;
80: state_we_o = 1'b0;
81: add_rk_sel_o = ADD_RK_ROUND;
82:
83: // Key expand data path
84: key_full_sel_o = KEY_FULL_ROUND;
85: key_full_we_o = 1'b0;
86: key_dec_sel_o = KEY_DEC_EXPAND;
87: key_dec_we_o = 1'b0;
88: key_expand_step_o = 1'b0;
89: key_expand_clear_o = 1'b0;
90: key_words_sel_o = KEY_WORDS_ZERO;
91: round_key_sel_o = ROUND_KEY_DIRECT;
92:
93: // FSM
94: aes_cipher_ctrl_ns = aes_cipher_ctrl_cs;
95: round_d = round_q;
96: num_rounds_d = num_rounds_q;
97: crypt_d = crypt_q;
98: dec_key_gen_d = dec_key_gen_q;
99: key_clear_d = key_clear_q;
100: data_out_clear_d = data_out_clear_q;
101:
102: unique case (aes_cipher_ctrl_cs)
103:
104: IDLE: begin
105: dec_key_gen_d = 1'b0;
106:
107: // Signal that we are ready, wait for handshake.
108: in_ready_o = 1'b1;
109: if (in_valid_i) begin
110: if (key_clear_i || data_out_clear_i) begin
111: // Clear internal key registers. The cipher core muxes are used to clear the data
112: // output registers.
113: key_clear_d = key_clear_i;
114: data_out_clear_d = data_out_clear_i;
115:
116: // To clear the data output registers, we must first clear the state.
117: aes_cipher_ctrl_ns = data_out_clear_i ? CLEAR_S : CLEAR_KD;
118:
119: end else if (dec_key_gen_i || crypt_i) begin
120: // Start encryption/decryption or generation of start key for decryption.
121: crypt_d = ~dec_key_gen_i;
122: dec_key_gen_d = dec_key_gen_i;
123:
124: // Load input data to state
125: state_sel_o = dec_key_gen_d ? STATE_CLEAR : STATE_INIT;
126: state_we_o = 1'b1;
127:
128: // Init key expand
129: key_expand_clear_o = 1'b1;
130:
131: // Load full key
132: key_full_sel_o = dec_key_gen_d ? KEY_FULL_ENC_INIT :
133: (op_i == CIPH_FWD) ? KEY_FULL_ENC_INIT :
134: KEY_FULL_DEC_INIT;
135: key_full_we_o = 1'b1;
136:
137: // Load num_rounds, clear round
138: round_d = '0;
139: num_rounds_d = (key_len_i == AES_128) ? 4'd10 :
140: (key_len_i == AES_192) ? 4'd12 :
141: 4'd14;
142: aes_cipher_ctrl_ns = INIT;
143: end
144: end
145: end
146:
147: INIT: begin
148: // Initial round: just add key to state
149: state_we_o = ~dec_key_gen_q;
150: add_rk_sel_o = ADD_RK_INIT;
151:
152: // Select key words for initial add_round_key
153: key_words_sel_o = dec_key_gen_q ? KEY_WORDS_ZERO :
154: (key_len_i == AES_128) ? KEY_WORDS_0123 :
155: (key_len_i == AES_192 && op_i == CIPH_FWD) ? KEY_WORDS_0123 :
156: (key_len_i == AES_192 && op_i == CIPH_INV) ? KEY_WORDS_2345 :
157: (key_len_i == AES_256 && op_i == CIPH_FWD) ? KEY_WORDS_0123 :
158: (key_len_i == AES_256 && op_i == CIPH_INV) ? KEY_WORDS_4567 : KEY_WORDS_ZERO;
159:
160: // Make key expand advance - AES-256 has two round keys available right from beginning.
161: if (key_len_i != AES_256) begin
162: key_expand_step_o = 1'b1;
163: key_full_we_o = 1'b1;
164: end
165:
166: aes_cipher_ctrl_ns = ROUND;
167: end
168:
169: ROUND: begin
170: // Normal rounds
171: state_we_o = ~dec_key_gen_q;
172:
173: // Select key words for add_round_key
174: key_words_sel_o = dec_key_gen_q ? KEY_WORDS_ZERO :
175: (key_len_i == AES_128) ? KEY_WORDS_0123 :
176: (key_len_i == AES_192 && op_i == CIPH_FWD) ? KEY_WORDS_2345 :
177: (key_len_i == AES_192 && op_i == CIPH_INV) ? KEY_WORDS_0123 :
178: (key_len_i == AES_256 && op_i == CIPH_FWD) ? KEY_WORDS_4567 :
179: (key_len_i == AES_256 && op_i == CIPH_INV) ? KEY_WORDS_0123 : KEY_WORDS_ZERO;
180:
181: // Make key expand advance
182: key_expand_step_o = 1'b1;
183: key_full_we_o = 1'b1;
184:
185: // Select round key: direct or mixed (equivalent inverse cipher)
186: round_key_sel_o = (op_i == CIPH_FWD) ? ROUND_KEY_DIRECT : ROUND_KEY_MIXED;
187:
188: // Update round
189: round_d = round_q + 4'b1;
190:
191: // Are we doing the last regular round?
192: if (round_q == num_rounds_regular) begin
193: aes_cipher_ctrl_ns = FINISH;
194:
195: if (dec_key_gen_q) begin
196: // Write decryption key.
197: key_dec_we_o = 1'b1;
198:
199: // Indicate that we are done, try to perform the handshake. But we don't wait here
200: // as the decryption key is valid only during one cycle. If we don't get the
201: // handshake now, we will wait in the finish state.
202: out_valid_o = 1'b1;
203: if (out_ready_i) begin
204: // Go to idle state directly.
205: dec_key_gen_d = 1'b0;
206: aes_cipher_ctrl_ns = IDLE;
207: end
208: end
209: end
210: end
211:
212: FINISH: begin
213: // Final round
214:
215: // Select key words for add_round_key
216: key_words_sel_o = dec_key_gen_q ? KEY_WORDS_ZERO :
217: (key_len_i == AES_128) ? KEY_WORDS_0123 :
218: (key_len_i == AES_192 && op_i == CIPH_FWD) ? KEY_WORDS_2345 :
219: (key_len_i == AES_192 && op_i == CIPH_INV) ? KEY_WORDS_0123 :
220: (key_len_i == AES_256 && op_i == CIPH_FWD) ? KEY_WORDS_4567 :
221: (key_len_i == AES_256 && op_i == CIPH_INV) ? KEY_WORDS_0123 : KEY_WORDS_ZERO;
222:
223: // Skip mix_columns
224: add_rk_sel_o = ADD_RK_FINAL;
225:
226: // Indicate that we are done, wait for handshake.
227: out_valid_o = 1'b1;
228: if (out_ready_i) begin
229: // We don't need the state anymore, clear it.
230: state_we_o = 1'b1;
231: state_sel_o = STATE_CLEAR;
232: crypt_d = 1'b0;
233: // If we were generating the decryption key and didn't get the handshake in the last
234: // regular round, we should clear dec_key_gen now.
235: dec_key_gen_d = 1'b0;
236: aes_cipher_ctrl_ns = IDLE;
237: end
238: end
239:
240: CLEAR_S: begin
241: // Clear the state with pseudo-random data.
242: state_we_o = 1'b1;
243: state_sel_o = STATE_CLEAR;
244: aes_cipher_ctrl_ns = CLEAR_KD;
245: end
246:
247: CLEAR_KD: begin
248: // Clear internal key registers and/or external data output registers.
249: if (key_clear_q) begin
250: key_full_sel_o = KEY_FULL_CLEAR;
251: key_full_we_o = 1'b1;
252: key_dec_sel_o = KEY_DEC_CLEAR;
253: key_dec_we_o = 1'b1;
254: end
255: if (data_out_clear_q) begin
256: // Forward the state (previously cleared with psuedo-random data).
257: add_rk_sel_o = ADD_RK_INIT;
258: key_words_sel_o = KEY_WORDS_ZERO;
259: round_key_sel_o = ROUND_KEY_DIRECT;
260: end
261: // Indicate that we are done, wait for handshake.
262: out_valid_o = 1'b1;
263: if (out_ready_i) begin
264: key_clear_d = 1'b0;
265: data_out_clear_d = 1'b0;
266: aes_cipher_ctrl_ns = IDLE;
267: end
268: end
269:
270: default: aes_cipher_ctrl_ns = IDLE;
271: endcase
272: end
273:
274: always_ff @(posedge clk_i or negedge rst_ni) begin : reg_fsm
275: if (!rst_ni) begin
276: aes_cipher_ctrl_cs <= IDLE;
277: round_q <= '0;
278: num_rounds_q <= '0;
279: crypt_q <= 1'b0;
280: dec_key_gen_q <= 1'b0;
281: key_clear_q <= 1'b0;
282: data_out_clear_q <= 1'b0;
283: end else begin
284: aes_cipher_ctrl_cs <= aes_cipher_ctrl_ns;
285: round_q <= round_d;
286: num_rounds_q <= num_rounds_d;
287: crypt_q <= crypt_d;
288: dec_key_gen_q <= dec_key_gen_d;
289: key_clear_q <= key_clear_d;
290: data_out_clear_q <= data_out_clear_d;
291: end
292: end
293:
294: // Use separate signal for number of regular rounds.
295: assign num_rounds_regular = num_rounds_q - 4'd2;
296:
297: // Use separate signals for key expand operation and round.
298: assign key_expand_op_o = (dec_key_gen_d || dec_key_gen_q) ? CIPH_FWD : op_i;
299: assign key_expand_round_o = round_d;
300:
301: // Let the main controller know whate we are doing.
302: assign crypt_o = crypt_q;
303: assign dec_key_gen_o = dec_key_gen_q;
304: assign key_clear_o = key_clear_q;
305: assign data_out_clear_o = data_out_clear_q;
306:
307: ////////////////
308: // Assertions //
309: ////////////////
310:
311: // Selectors must be known/valid
312: `ASSERT_KNOWN(AesCiphOpKnown, op_i)
313: `ASSERT(AesKeyLenValid, key_len_i inside {
314: AES_128,
315: AES_192,
316: AES_256
317: })
318: `ASSERT(AesControlStateValid, aes_cipher_ctrl_cs inside {
319: IDLE,
320: INIT,
321: ROUND,
322: FINISH,
323: CLEAR_S,
324: CLEAR_KD
325: })
326:
327: endmodule
328: