../src/lowrisc_ip_aes_0.6/rtl/aes_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 main control
6: //
7: // This module controls the interplay of input/output registers and the AES cipher core.
8:
9: `include "prim_assert.sv"
10:
11: module aes_control (
12: input logic clk_i,
13: input logic rst_ni,
14:
15: // Main control inputs
16: input aes_pkg::aes_op_e op_i,
17: input aes_pkg::aes_mode_e mode_i,
18: input aes_pkg::ciph_op_e cipher_op_i,
19: input logic manual_operation_i,
20: input logic start_i,
21: input logic key_clear_i,
22: input logic iv_clear_i,
23: input logic data_in_clear_i,
24: input logic data_out_clear_i,
25: input logic prng_reseed_i,
26:
27: // I/O register read/write enables
28: input logic [7:0] key_init_qe_i,
29: input logic [3:0] iv_qe_i,
30: input logic [3:0] data_in_qe_i,
31: input logic [3:0] data_out_re_i,
32: output logic data_in_we_o,
33: output logic data_out_we_o,
34:
35: // Previous input data register
36: output aes_pkg::dip_sel_e data_in_prev_sel_o,
37: output logic data_in_prev_we_o,
38:
39: // Cipher I/O muxes
40: output aes_pkg::si_sel_e state_in_sel_o,
41: output aes_pkg::add_si_sel_e add_state_in_sel_o,
42: output aes_pkg::add_so_sel_e add_state_out_sel_o,
43:
44: // Counter
45: output logic ctr_incr_o,
46: input logic ctr_ready_i,
47: input logic [7:0] ctr_we_i,
48:
49: // Cipher core control and sync
50: output logic cipher_in_valid_o,
51: input logic cipher_in_ready_i,
52: input logic cipher_out_valid_i,
53: output logic cipher_out_ready_o,
54: output logic cipher_crypt_o,
55: input logic cipher_crypt_i,
56: output logic cipher_dec_key_gen_o,
57: input logic cipher_dec_key_gen_i,
58: output logic cipher_key_clear_o,
59: input logic cipher_key_clear_i,
60: output logic cipher_data_out_clear_o,
61: input logic cipher_data_out_clear_i,
62:
63: // Initial key registers
64: output aes_pkg::key_init_sel_e key_init_sel_o,
65: output logic [7:0] key_init_we_o,
66:
67: // IV registers
68: output aes_pkg::iv_sel_e iv_sel_o,
69: output logic [7:0] iv_we_o,
70:
71: // Pseudo-random number generator interface
72: output logic prng_data_req_o,
73: input logic prng_data_ack_i,
74: output logic prng_reseed_req_o,
75: input logic prng_reseed_ack_i,
76:
77: // Trigger register
78: output logic start_o,
79: output logic start_we_o,
80: output logic key_clear_o,
81: output logic key_clear_we_o,
82: output logic iv_clear_o,
83: output logic iv_clear_we_o,
84: output logic data_in_clear_o,
85: output logic data_in_clear_we_o,
86: output logic data_out_clear_o,
87: output logic data_out_clear_we_o,
88: output logic prng_reseed_o,
89: output logic prng_reseed_we_o,
90:
91: // Status register
92: output logic output_valid_o,
93: output logic output_valid_we_o,
94: output logic input_ready_o,
95: output logic input_ready_we_o,
96: output logic idle_o,
97: output logic idle_we_o,
98: output logic stall_o,
99: output logic stall_we_o
100: );
101:
102: import aes_pkg::*;
103:
104: // Types
105: typedef enum logic [2:0] {
106: IDLE, LOAD, UPDATE_PRNG, FINISH, CLEAR
107: } aes_ctrl_e;
108:
109: aes_ctrl_e aes_ctrl_ns, aes_ctrl_cs;
110:
111: // Signals
112: logic key_init_clear;
113: logic [7:0] key_init_new_d, key_init_new_q;
114: logic key_init_new;
115: logic dec_key_gen;
116:
117: logic [7:0] iv_qe;
118: logic iv_clear;
119: logic [7:0] iv_new_d, iv_new_q;
120: logic iv_new;
121: logic iv_clean;
122: logic iv_load;
123: logic iv_ready_d, iv_ready_q;
124:
125: logic [3:0] data_in_new_d, data_in_new_q;
126: logic data_in_new;
127: logic data_in_load;
128:
129: logic [3:0] data_out_read_d, data_out_read_q;
130: logic data_out_read;
131: logic output_valid_q;
132:
133: logic start, finish;
134: logic cipher_crypt;
135: logic doing_cbc_enc, doing_cbc_dec;
136: logic doing_ctr;
137:
138: // Software updates IV in chunks of 32 bits, the counter updates 16 bits at a time.
139: // Convert word write enable to internal half-word write enable.
140: assign iv_qe = {iv_qe_i[3], iv_qe_i[3], iv_qe_i[2], iv_qe_i[2],
141: iv_qe_i[1], iv_qe_i[1], iv_qe_i[0], iv_qe_i[0]};
142:
143: // If set to start manually, we just wait for the trigger. Otherwise, we start once we have valid
144: // data available. If the IV (and counter) is needed, we only start if also the IV (and counter)
145: // is ready.
146: assign start = manual_operation_i ? start_i :
147: (mode_i == AES_ECB) ? data_in_new :
148: (mode_i == AES_CBC) ? (data_in_new & iv_ready_q) :
149: (mode_i == AES_CTR) ? (data_in_new & iv_ready_q & ctr_ready_i) : 1'b0;
150:
151: // If not set to overwrite data, we wait for any previous output data to be read. data_out_read
152: // synchronously clears output_valid_q, unless new output data is written in the exact same
153: // clock cycle.
154: assign finish = manual_operation_i ? 1'b1 : ~output_valid_q | data_out_read;
155:
156: // Helper signals for FSM
157: assign cipher_crypt = cipher_crypt_o | cipher_crypt_i;
158: assign doing_cbc_enc = cipher_crypt & (mode_i == AES_CBC) & (op_i == AES_ENC);
159: assign doing_cbc_dec = cipher_crypt & (mode_i == AES_CBC) & (op_i == AES_DEC);
160: assign doing_ctr = cipher_crypt & (mode_i == AES_CTR);
161:
162: // FSM
163: always_comb begin : aes_ctrl_fsm
164:
165: // Previous input data register control
166: data_in_prev_sel_o = DIP_CLEAR;
167: data_in_prev_we_o = 1'b0;
168:
169: // Cipher I/O mux control
170: state_in_sel_o = SI_DATA;
171: add_state_in_sel_o = ADD_SI_ZERO;
172: add_state_out_sel_o = ADD_SO_ZERO;
173:
174: // Counter control
175: ctr_incr_o = 1'b0;
176:
177: // Cipher core control
178: cipher_in_valid_o = 1'b0;
179: cipher_out_ready_o = 1'b0;
180: cipher_crypt_o = 1'b0;
181: cipher_dec_key_gen_o = 1'b0;
182: cipher_key_clear_o = 1'b0;
183: cipher_data_out_clear_o = 1'b0;
184:
185: // Initial key registers
186: key_init_sel_o = KEY_INIT_INPUT;
187: key_init_we_o = 8'h00;
188:
189: // IV registers
190: iv_sel_o = IV_INPUT;
191: iv_we_o = 8'h00;
192: iv_load = 1'b0;
193:
194: // Pseudo-random number generator control
195: prng_data_req_o = 1'b0;
196: prng_reseed_req_o = 1'b0;
197:
198: // Trigger register control
199: start_we_o = 1'b0;
200: key_clear_we_o = 1'b0;
201: iv_clear_we_o = 1'b0;
202: data_in_clear_we_o = 1'b0;
203: data_out_clear_we_o = 1'b0;
204: prng_reseed_we_o = 1'b0;
205:
206: // Status register
207: idle_o = 1'b0;
208: idle_we_o = 1'b0;
209: stall_o = 1'b0;
210: stall_we_o = 1'b0;
211:
212: // Key, data I/O register control
213: dec_key_gen = 1'b0;
214: data_in_load = 1'b0;
215: data_in_we_o = 1'b0;
216: data_out_we_o = 1'b0;
217:
218: // Edge detector control
219: key_init_clear = 1'b0;
220: iv_clear = 1'b0;
221:
222: // FSM
223: aes_ctrl_ns = aes_ctrl_cs;
224:
225: unique case (aes_ctrl_cs)
226:
227: IDLE: begin
228: idle_o = (start || key_clear_i || iv_clear_i ||
229: data_in_clear_i || data_out_clear_i || prng_reseed_i) ? 1'b0 : 1'b1;
230: idle_we_o = 1'b1;
231:
232: // Initial key and IV updates are ignored if we are not idle.
233: key_init_we_o = idle_o ? key_init_qe_i : 8'h00;
234: iv_we_o = idle_o ? iv_qe : 8'h00;
235:
236: if (prng_reseed_i) begin
237: // Request a reseed of the PRNG, perform handshake.
238: prng_reseed_req_o = 1'b1;
239: if (prng_reseed_ack_i) begin
240: // Clear the trigger.
241: prng_reseed_we_o = 1'b1;
242: end
243:
244: end else if (key_clear_i || data_out_clear_i || iv_clear_i || data_in_clear_i) begin
245: // To clear registers, we must first request fresh pseudo-random data.
246: aes_ctrl_ns = UPDATE_PRNG;
247:
248: end else if (start) begin
249: // Signal that we want to start encryption/decryption.
250: cipher_crypt_o = 1'b1;
251:
252: // We got a new initial key, but want to do decryption. The cipher core must first
253: // generate the start key for decryption.
254: cipher_dec_key_gen_o = key_init_new & (cipher_op_i == CIPH_INV);
255:
256: // Previous input data register control
257: data_in_prev_sel_o = doing_cbc_dec ? DIP_DATA_IN :
258: doing_ctr ? DIP_DATA_IN : DIP_CLEAR;
259: data_in_prev_we_o = doing_cbc_dec ? 1'b1 :
260: doing_ctr ? 1'b1 : 1'b0;
261:
262: // State input mux control
263: state_in_sel_o = doing_ctr ? SI_ZERO : SI_DATA;
264:
265: // State input additon mux control
266: add_state_in_sel_o = doing_cbc_enc ? ADD_SI_IV :
267: doing_ctr ? ADD_SI_IV : ADD_SI_ZERO;
268:
269: // We have work for the cipher core, perform handshake.
270: cipher_in_valid_o = 1'b1;
271: if (cipher_in_ready_i) begin
272: // Do not yet clear a possible start trigger if we are just starting the generation of
273: // the start key for decryption.
274: start_we_o = ~cipher_dec_key_gen_o;
275: aes_ctrl_ns = LOAD;
276: end
277: end
278: end
279:
280: LOAD: begin
281: // Clear key_init_new, iv_new, data_in_new
282: dec_key_gen = cipher_dec_key_gen_i;
283: iv_load = ~cipher_dec_key_gen_i;
284: data_in_load = ~cipher_dec_key_gen_i;
285:
286: // Trigger counter increment.
287: ctr_incr_o = doing_ctr ? 1'b1 : 1'b0;
288:
289: // Unless we are just generating the start key for decryption, we must update the PRNG.
290: aes_ctrl_ns = ~cipher_dec_key_gen_i ? UPDATE_PRNG : FINISH;
291: end
292:
293: UPDATE_PRNG: begin
294: // Fresh pseudo-random data is used to:
295: // - clear the state in the final cipher round,
296: // - clear any other registers in the CLEAR state.
297:
298: // IV control in case of ongoing encryption/decryption
299: // - CTR: IV registers are updated by counter during cipher operation
300: iv_sel_o = doing_ctr ? IV_CTR : IV_INPUT;
301: iv_we_o = doing_ctr ? ctr_we_i : 8'h00;
302:
303: // Request fresh pseudo-random data, perform handshake.
304: prng_data_req_o = 1'b1;
305: if (prng_data_ack_i) begin
306:
307: // Ongoing encryption/decryption operations have the highest priority. The clear triggers
308: // might have become asserted after the handshake with the cipher core.
309: if (cipher_crypt_i) begin
310: aes_ctrl_ns = FINISH;
311:
312: end else if (key_clear_i || data_out_clear_i) begin
313: // To clear the output data registers, we re-use the muxing resources of the cipher
314: // core. To clear all key material, some key registers inside the cipher core need to
315: // be cleared.
316: cipher_key_clear_o = key_clear_i;
317: cipher_data_out_clear_o = data_out_clear_i;
318:
319: // We have work for the cipher core, perform handshake.
320: cipher_in_valid_o = 1'b1;
321: if (cipher_in_ready_i) begin
322: aes_ctrl_ns = CLEAR;
323: end
324: end else begin // (iv_clear_i || data_in_clear_i)
325: // To clear the IV or input data registers, no handshake with the cipher core is
326: // needed.
327: aes_ctrl_ns = CLEAR;
328: end
329: end
330: end
331:
332: FINISH: begin
333: // Wait for cipher core to finish.
334:
335: if (cipher_dec_key_gen_i) begin
336: // We are ready.
337: cipher_out_ready_o = 1'b1;
338: if (cipher_out_valid_i) begin
339: aes_ctrl_ns = IDLE;
340: end
341: end else begin
342: // Signal if the cipher core is stalled (because previous output has not yet been read).
343: stall_o = ~finish & cipher_out_valid_i;
344: stall_we_o = 1'b1;
345:
346: // State out addition mux control
347: add_state_out_sel_o = doing_cbc_dec ? ADD_SO_IV :
348: doing_ctr ? ADD_SO_DIP : ADD_SO_ZERO;
349:
350: // IV control
351: // - CBC: IV registers can only be updated when cipher finishes
352: // - CTR: IV registers are updated by counter during cipher operation
353: iv_sel_o = doing_cbc_enc ? IV_DATA_OUT :
354: doing_cbc_dec ? IV_DATA_IN_PREV :
355: doing_ctr ? IV_CTR : IV_INPUT;
356: iv_we_o = (doing_cbc_enc || doing_cbc_dec) ? {8{finish & cipher_out_valid_i}} :
357: doing_ctr ? ctr_we_i : 8'h00;
358:
359: // We are ready once the output data registers can be written.
360: cipher_out_ready_o = finish;
361: if (finish & cipher_out_valid_i) begin
362: data_out_we_o = 1'b1;
363: aes_ctrl_ns = IDLE;
364: end
365: end
366: end
367:
368: CLEAR: begin
369: // The IV and input data registers can be cleared independently of the cipher core.
370: if (iv_clear_i) begin
371: iv_sel_o = IV_CLEAR;
372: iv_we_o = 8'hFF;
373: iv_clear_we_o = 1'b1;
374: iv_clear = 1'b1;
375: end
376: if (data_in_clear_i) begin
377: data_in_we_o = 1'b1;
378: data_in_clear_we_o = 1'b1;
379: data_in_prev_sel_o = DIP_CLEAR;
380: data_in_prev_we_o = 1'b1;
381: end
382:
383: // To clear the output data registers, we re-use the muxing resources of the cipher core.
384: // To clear all key material, some key registers inside the cipher core need to be cleared.
385: if (cipher_key_clear_i || cipher_data_out_clear_i) begin
386:
387: // Perform handshake.
388: cipher_out_ready_o = 1'b1;
389: if (cipher_out_valid_i) begin
390:
391: if (cipher_key_clear_i) begin
392: key_init_sel_o = KEY_INIT_CLEAR;
393: key_init_we_o = 8'hFF;
394: key_clear_we_o = 1'b1;
395: key_init_clear = 1'b1;
396: end
397:
398: if (cipher_data_out_clear_i) begin
399: data_out_we_o = 1'b1;
400: data_out_clear_we_o = 1'b1;
401: end
402: aes_ctrl_ns = IDLE;
403: end
404:
405: end else begin
406: aes_ctrl_ns = IDLE;
407: end
408: end
409:
410: default: aes_ctrl_ns = IDLE;
411: endcase
412: end
413:
414: always_ff @(posedge clk_i or negedge rst_ni) begin : reg_fsm
415: if (!rst_ni) begin
416: aes_ctrl_cs <= IDLE;
417: end else begin
418: aes_ctrl_cs <= aes_ctrl_ns;
419: end
420: end
421:
422: // Detect new key, new IV, new input, output read.
423: // Edge detectors are cleared by the FSM.
424: assign key_init_new_d = (dec_key_gen || key_init_clear) ? '0 : (key_init_new_q | key_init_we_o);
425: assign key_init_new = &key_init_new_d;
426:
427: // The IV regs can be updated by both software or the counter.
428: assign iv_new_d = (iv_load || iv_clear) ? '0 : (iv_new_q | iv_we_o);
429: assign iv_new = &iv_new_d; // All of the IV regs have been updated.
430: assign iv_clean = ~(|iv_new_d); // None of the IV regs have been updated.
431:
432: assign data_in_new_d = (data_in_load || data_in_we_o) ? '0 : (data_in_new_q | data_in_qe_i);
433: assign data_in_new = &data_in_new_d;
434:
435: // data_out_read is high for one clock cycle only. It clears output_valid_q unless new output
436: // data is written in the exact same cycle.
437: assign data_out_read_d = &data_out_read_q ? '0 : data_out_read_q | data_out_re_i;
438: assign data_out_read = &data_out_read_d;
439:
440: always_ff @(posedge clk_i or negedge rst_ni) begin : reg_edge_detection
441: if (!rst_ni) begin
442: key_init_new_q <= '0;
443: iv_new_q <= '0;
444: data_in_new_q <= '0;
445: data_out_read_q <= '0;
446: end else begin
447: key_init_new_q <= key_init_new_d;
448: iv_new_q <= iv_new_d;
449: data_in_new_q <= data_in_new_d;
450: data_out_read_q <= data_out_read_d;
451: end
452: end
453:
454: // We only use complete IVs. Either software/counter has updated
455: // - all IV registers (iv_new), or
456: // - none of the IV registers (iv_clean), but the registers were updated in the past.
457: assign iv_ready_d = (iv_load || iv_clear) ? 1'b0 : iv_new | (iv_clean & iv_ready_q);
458:
459: always_ff @(posedge clk_i or negedge rst_ni) begin : reg_iv_ready
460: if (!rst_ni) begin
461: iv_ready_q <= 1'b0;
462: end else begin
463: iv_ready_q <= iv_ready_d;
464: end
465: end
466:
467: // Clear once all output regs have been read, or when output is cleared
468: assign output_valid_o = data_out_we_o & ~data_out_clear_we_o;
469: assign output_valid_we_o = data_out_we_o | data_out_read | data_out_clear_we_o;
470:
471: always_ff @(posedge clk_i or negedge rst_ni) begin : reg_output_valid
472: if (!rst_ni) begin
473: output_valid_q <= '0;
474: end else if (output_valid_we_o) begin
475: output_valid_q <= output_valid_o;
476: end
477: end
478:
479: // Clear once all input regs have been written, or when input clear is requested
480: assign input_ready_o = ~data_in_new;
481: assign input_ready_we_o = data_in_new | data_in_load | data_in_we_o;
482:
483: // Trigger register, the control only ever clears these
484: assign start_o = 1'b0;
485: assign key_clear_o = 1'b0;
486: assign iv_clear_o = 1'b0;
487: assign data_in_clear_o = 1'b0;
488: assign data_out_clear_o = 1'b0;
489: assign prng_reseed_o = 1'b0;
490:
491: // Selectors must be known/valid
492: `ASSERT(AesModeValid, mode_i inside {
493: AES_ECB,
494: AES_CBC,
495: AES_CTR
496: })
497: `ASSERT_KNOWN(AesOpKnown, op_i)
498: `ASSERT_KNOWN(AesCiphOpKnown, cipher_op_i)
499: `ASSERT_KNOWN(AesControlStateValid, aes_ctrl_cs)
500:
501: endmodule
502: