hw/ip/aes/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: module aes_core #(
8: parameter bit AES192Enable = 1,
9: parameter SBoxImpl = "lut"
10: ) (
11: input clk_i,
12: input rst_ni,
13:
14: // Bus Interface
15: input aes_reg_pkg::aes_reg2hw_t reg2hw,
16: output aes_reg_pkg::aes_hw2reg_t hw2reg
17: );
18:
19: import aes_reg_pkg::*;
20: import aes_pkg::*;
21:
22: // Signals
23: logic [3:0][31:0] data_in;
24: logic [3:0] data_in_qe;
25: logic data_in_we;
26: logic [7:0][31:0] key_init;
27: logic [7:0] key_init_qe;
28:
29: logic ctrl_qe;
30: logic ctrl_we;
31: mode_e mode_d, mode_q;
32: key_len_e key_len;
33: key_len_e key_len_d, key_len_q;
34: logic manual_start_trigger_q;
35: logic force_data_overwrite_q;
36:
37: logic [3:0][3:0][7:0] state_init;
38: logic [3:0][3:0][7:0] state_d;
39: logic [3:0][3:0][7:0] state_q;
40: logic state_we;
41: state_sel_e state_sel;
42:
43: logic [3:0][3:0][7:0] sub_bytes_out;
44: logic [3:0][3:0][7:0] shift_rows_out;
45: logic [3:0][3:0][7:0] mix_columns_out;
46: logic [3:0][3:0][7:0] add_round_key_in;
47: logic [3:0][3:0][7:0] add_round_key_out;
48: add_rk_sel_e add_round_key_in_sel;
49:
50: logic [7:0][31:0] key_init_d;
51: logic [7:0][31:0] key_init_q;
52: logic [7:0] key_init_we;
53: key_init_sel_e key_init_sel;
54: logic [7:0][31:0] key_full_d;
55: logic [7:0][31:0] key_full_q;
56: logic key_full_we;
57: key_full_sel_e key_full_sel;
58: logic [7:0][31:0] key_dec_d;
59: logic [7:0][31:0] key_dec_q;
60: logic key_dec_we;
61: key_dec_sel_e key_dec_sel;
62: logic [7:0][31:0] key_expand_out;
63: mode_e key_expand_mode;
64: logic key_expand_step;
65: logic key_expand_clear;
66: logic [3:0] key_expand_round;
67: key_words_sel_e key_words_sel;
68: logic [3:0][31:0] key_words;
69: logic [3:0][3:0][7:0] key_bytes;
70: logic [3:0][3:0][7:0] key_mix_columns_out;
71: logic [3:0][3:0][7:0] round_key;
72: round_key_sel_e round_key_sel;
73:
74: logic [3:0][31:0] data_out_d;
75: logic [3:0][31:0] data_out_q;
76: logic data_out_we;
77: logic [3:0] data_out_re;
78:
79: // Unused signals
80: logic [3:0][31:0] unused_data_out_q;
81:
82: ////////////
83: // Inputs //
84: ////////////
85:
86: // Inputs
87: always_comb begin : key_init_get
88: for (int i=0; i<8; i++) begin
89: key_init[i] = reg2hw.key[i].q;
90: key_init_qe[i] = reg2hw.key[i].qe;
91: end
92: end
93:
94: always_comb begin : data_in_get
95: for (int i=0; i<4; i++) begin
96: data_in[i] = reg2hw.data_in[i].q;
97: data_in_qe[i] = reg2hw.data_in[i].qe;
98: end
99: end
100:
101: always_comb begin : data_out_get
102: for (int i=0; i<4; i++) begin
103: // data_out is actually hwo, but we need hrw for hwre
104: unused_data_out_q[i] = reg2hw.data_out[i].q;
105: data_out_re[i] = reg2hw.data_out[i].re;
106: end
107: end
108:
109: assign mode_d = mode_e'(reg2hw.ctrl.mode.q);
110:
111: assign key_len = key_len_e'(reg2hw.ctrl.key_len.q);
112: always_comb begin : get_key_len
113: unique case (key_len)
114: AES_128: key_len_d = AES_128;
115: AES_256: key_len_d = AES_256;
116: AES_192: key_len_d = AES192Enable ? AES_192 : AES_128;
117: default: key_len_d = AES_128; // unsupported values are mapped to AES_128
118: endcase
119: end
120:
121: assign ctrl_qe = reg2hw.ctrl.mode.qe & reg2hw.ctrl.key_len.qe &
122: reg2hw.ctrl.manual_start_trigger.qe & reg2hw.ctrl.force_data_overwrite.qe;
123:
124: //////////
125: // Data //
126: //////////
127:
128: // Convert input data to state (every input data word contains one state column)
129: assign state_init = aes_transpose(data_in);
130:
131: // State registers
132: always_comb begin : state_mux
133: unique case (state_sel)
134: STATE_INIT: state_d = state_init;
135: STATE_ROUND: state_d = add_round_key_out;
136: STATE_CLEAR: state_d = '0;
137: default: state_d = state_init;
138: endcase
139: end
140:
141: always_ff @(posedge clk_i or negedge rst_ni) begin : state_reg
142: if (!rst_ni) begin
143: state_q <= '0;
144: end else if (state_we) begin
145: state_q <= state_d;
146: end
147: end
148:
149: // Cipher data path
150: aes_sub_bytes #(
151: .SBoxImpl ( SBoxImpl )
152: ) aes_sub_bytes (
153: .mode_i ( mode_q ),
154: .data_i ( state_q ),
155: .data_o ( sub_bytes_out )
156: );
157:
158: aes_shift_rows aes_shift_rows (
159: .mode_i ( mode_q ),
160: .data_i ( sub_bytes_out ),
161: .data_o ( shift_rows_out )
162: );
163:
164: aes_mix_columns aes_mix_columns (
165: .mode_i ( mode_q ),
166: .data_i ( shift_rows_out ),
167: .data_o ( mix_columns_out )
168: );
169:
170: always_comb begin : add_round_key_in_mux
171: unique case (add_round_key_in_sel)
172: ADD_RK_INIT: add_round_key_in = state_q;
173: ADD_RK_ROUND: add_round_key_in = mix_columns_out;
174: ADD_RK_FINAL: add_round_key_in = shift_rows_out;
175: default: add_round_key_in = state_q;
176: endcase
177: end
178:
179: assign add_round_key_out = add_round_key_in ^ round_key;
180:
181: /////////
182: // Key //
183: /////////
184:
185: // Initial Key registers
186: always_comb begin : key_init_mux
187: unique case (key_init_sel)
188: KEY_INIT_INPUT: key_init_d = key_init;
189: KEY_INIT_CLEAR: key_init_d = '0;
190: default: key_init_d = key_init;
191: endcase
192: end
193:
194: always_ff @(posedge clk_i or negedge rst_ni) begin : key_init_reg
195: if (!rst_ni) begin
196: key_init_q <= '0;
197: end else begin
198: for (int i=0; i<8; i++) begin
199: if (key_init_we[i]) begin
200: key_init_q[i] <= key_init_d[i];
201: end
202: end
203: end
204: end
205:
206: // Full Key registers
207: always_comb begin : key_full_mux
208: unique case (key_full_sel)
209: KEY_FULL_ENC_INIT: key_full_d = key_init_q;
210: KEY_FULL_DEC_INIT: key_full_d = key_dec_q;
211: KEY_FULL_ROUND: key_full_d = key_expand_out;
212: KEY_FULL_CLEAR: key_full_d = '0;
213: default: key_full_d = key_init_q;
214: endcase
215: end
216:
217: always_ff @(posedge clk_i or negedge rst_ni) begin : key_full_reg
218: if (!rst_ni) begin
219: key_full_q <= '0;
220: end else if (key_full_we) begin
221: key_full_q <= key_full_d;
222: end
223: end
224:
225: // Decryption Key registers
226: always_comb begin : key_dec_mux
227: unique case (key_dec_sel)
228: KEY_DEC_EXPAND: key_dec_d = key_expand_out;
229: KEY_DEC_CLEAR: key_dec_d = '0;
230: default: key_dec_d = key_expand_out;
231: endcase
232: end
233:
234: always_ff @(posedge clk_i or negedge rst_ni) begin : key_dec_reg
235: if (!rst_ni) begin
236: key_dec_q <= '0;
237: end else if (key_dec_we) begin
238: key_dec_q <= key_dec_d;
239: end
240: end
241:
242: // Key expand data path
243: aes_key_expand #(
244: .AES192Enable ( AES192Enable ),
245: .SBoxImpl ( SBoxImpl )
246: ) aes_key_expand (
247: .clk_i ( clk_i ),
248: .rst_ni ( rst_ni ),
249: .mode_i ( key_expand_mode ),
250: .step_i ( key_expand_step ),
251: .clear_i ( key_expand_clear ),
252: .round_i ( key_expand_round ),
253: .key_len_i ( key_len_q ),
254: .key_i ( key_full_q ),
255: .key_o ( key_expand_out )
256: );
257:
258: always_comb begin : key_words_mux
259: unique case (key_words_sel)
260: KEY_WORDS_0123: key_words = key_full_q[3:0];
261: KEY_WORDS_2345: key_words = AES192Enable ? key_full_q[5:2] : key_full_q[3:0];
262: KEY_WORDS_4567: key_words = key_full_q[7:4];
263: KEY_WORDS_ZERO: key_words = '0;
264: default: key_words = key_full_q[3:0];
265: endcase
266: end
267:
268: // Convert words to bytes (every key word contains one column)
269: assign key_bytes = aes_transpose(key_words);
270:
271: aes_mix_columns aes_key_mix_columns (
272: .mode_i ( AES_DEC ),
273: .data_i ( key_bytes ),
274: .data_o ( key_mix_columns_out )
275: );
276:
277: always_comb begin : round_key_mux
278: unique case (round_key_sel)
279: ROUND_KEY_DIRECT: round_key = key_bytes;
280: ROUND_KEY_MIXED: round_key = key_mix_columns_out;
281: default: round_key = key_bytes;
282: endcase
283: end
284:
285: /////////////
286: // Control //
287: /////////////
288:
289: // Control
290: aes_control aes_control (
291: .clk_i ( clk_i ),
292: .rst_ni ( rst_ni ),
293:
294: .mode_i ( mode_q ),
295: .key_len_i ( key_len_q ),
296: .manual_start_trigger_i ( manual_start_trigger_q ),
297: .force_data_overwrite_i ( force_data_overwrite_q ),
298: .start_i ( reg2hw.trigger.start.q ),
299: .key_clear_i ( reg2hw.trigger.key_clear.q ),
300: .data_in_clear_i ( reg2hw.trigger.data_in_clear.q ),
301: .data_out_clear_i ( reg2hw.trigger.data_out_clear.q ),
302:
303: .data_in_qe_i ( data_in_qe ),
304: .key_init_qe_i ( key_init_qe ),
305: .data_out_re_i ( data_out_re ),
306:
307: .state_sel_o ( state_sel ),
308: .state_we_o ( state_we ),
309: .add_rk_sel_o ( add_round_key_in_sel ),
310:
311: .key_expand_mode_o ( key_expand_mode ),
312: .key_init_sel_o ( key_init_sel ),
313: .key_init_we_o ( key_init_we ),
314: .key_full_sel_o ( key_full_sel ),
315: .key_full_we_o ( key_full_we ),
316: .key_dec_sel_o ( key_dec_sel ),
317: .key_dec_we_o ( key_dec_we ),
318: .key_expand_step_o ( key_expand_step ),
319: .key_expand_clear_o ( key_expand_clear ),
320: .key_expand_round_o ( key_expand_round ),
321: .key_words_sel_o ( key_words_sel ),
322: .round_key_sel_o ( round_key_sel ),
323:
324: .data_in_we_o ( data_in_we ),
325: .data_out_we_o ( data_out_we ),
326:
327: .start_o ( hw2reg.trigger.start.d ),
328: .start_we_o ( hw2reg.trigger.start.de ),
329: .key_clear_o ( hw2reg.trigger.key_clear.d ),
330: .key_clear_we_o ( hw2reg.trigger.key_clear.de ),
331: .data_in_clear_o ( hw2reg.trigger.data_in_clear.d ),
332: .data_in_clear_we_o ( hw2reg.trigger.data_in_clear.de ),
333: .data_out_clear_o ( hw2reg.trigger.data_out_clear.d ),
334: .data_out_clear_we_o ( hw2reg.trigger.data_out_clear.de ),
335:
336: .output_valid_o ( hw2reg.status.output_valid.d ),
337: .output_valid_we_o ( hw2reg.status.output_valid.de ),
338: .input_ready_o ( hw2reg.status.input_ready.d ),
339: .input_ready_we_o ( hw2reg.status.input_ready.de ),
340: .idle_o ( hw2reg.status.idle.d ),
341: .idle_we_o ( hw2reg.status.idle.de ),
342: .stall_o ( hw2reg.status.stall.d ),
343: .stall_we_o ( hw2reg.status.stall.de )
344: );
345:
346: // Input data register clear
347: always_comb begin : data_in_reg_clear
348: for (int i=0; i<4; i++) begin
349: hw2reg.data_in[i].d = '0;
350: hw2reg.data_in[i].de = data_in_we;
351: end
352: end
353:
354: // Control register
355: assign ctrl_we = ctrl_qe & hw2reg.status.idle.d;
356:
357: always_ff @(posedge clk_i or negedge rst_ni) begin : ctrl_reg
358: if (!rst_ni) begin
359: mode_q <= AES_ENC;
360: key_len_q <= AES_128;
361: manual_start_trigger_q <= '0;
362: force_data_overwrite_q <= '0;
363: end else if (ctrl_we) begin
364: mode_q <= mode_d;
365: key_len_q <= key_len_d;
366: manual_start_trigger_q <= reg2hw.ctrl.manual_start_trigger.q;
367: force_data_overwrite_q <= reg2hw.ctrl.force_data_overwrite.q;
368: end
369: end
370:
371: /////////////
372: // Outputs //
373: /////////////
374:
375: // Convert output state to output data (every state column corresponds to one output word)
376: assign data_out_d = aes_transpose(add_round_key_out);
377:
378: always_ff @(posedge clk_i or negedge rst_ni) begin : data_out_reg
379: if (!rst_ni) begin
380: data_out_q <= '0;
381: end else if (data_out_we) begin
382: data_out_q <= data_out_d;
383: end
384: end
385:
386: // Outputs
387: always_comb begin : key_reg_put
388: for (int i=0; i<8; i++) begin
389: hw2reg.key[i].d = key_init_q[i];
390: end
391: end
392:
393: always_comb begin : data_out_put
394: for (int i=0; i<4; i++) begin
395: hw2reg.data_out[i].d = data_out_q[i];
396: end
397: end
398:
399: assign hw2reg.ctrl.key_len.d = {key_len_q};
400:
401: ////////////////
402: // Assertions //
403: ////////////////
404:
405: // Selectors must be known/valid
406: `ASSERT_KNOWN(AesModeKnown, mode_q, clk_i, !rst_ni)
407: `ASSERT(AesKeyLenValid, key_len_q inside {
408: AES_128,
409: AES_192,
410: AES_256
411: }, clk_i, !rst_ni)
412: `ASSERT(AesStateSelValid, state_sel inside {
413: STATE_INIT,
414: STATE_ROUND,
415: STATE_CLEAR
416: }, clk_i, !rst_ni)
417: `ASSERT(AesAddRKSelValid, add_round_key_in_sel inside {
418: ADD_RK_INIT,
419: ADD_RK_ROUND,
420: ADD_RK_FINAL
421: }, clk_i, !rst_ni)
422: `ASSERT_KNOWN(AesKeyInitSelKnown, key_init_sel, clk_i, !rst_ni)
423: `ASSERT_KNOWN(AesKeyFullSelKnown, key_full_sel, clk_i, !rst_ni)
424: `ASSERT_KNOWN(AesKeyDecSelKnown, key_dec_sel, clk_i, !rst_ni)
425: `ASSERT_KNOWN(AesKeyWordsSelKnown, key_words_sel, clk_i, !rst_ni)
426: `ASSERT_KNOWN(AesRoundKeySelKnown, round_key_sel, clk_i, !rst_ni)
427:
428: endmodule
429: