[aes/rtl] Remove X assignments, add SVAs for selector signals
This commit replaces all X assignments in the AES RTL with defined
values. In addition, SystemVerilog Assertions are added to catch
invalid signal values in simulation.
This is related to lowRISC/opentitan#366.
Signed-off-by: Pirmin Vogel <vogelpi@lowrisc.org>
diff --git a/hw/ip/aes/rtl/aes_control.sv b/hw/ip/aes/rtl/aes_control.sv
index a05acdb..48d569f 100644
--- a/hw/ip/aes/rtl/aes_control.sv
+++ b/hw/ip/aes/rtl/aes_control.sv
@@ -215,10 +215,10 @@
unique case (mode_i)
AES_ENC: key_words_sel_o = KEY_WORDS_0123;
AES_DEC: key_words_sel_o = KEY_WORDS_2345;
- default: key_words_sel_o = key_words_sel_e'(1'bX);
+ default: key_words_sel_o = KEY_WORDS_ZERO;
endcase
end else begin
- key_words_sel_o = key_words_sel_e'(1'bX);
+ key_words_sel_o = KEY_WORDS_ZERO;
end
end
@@ -226,11 +226,11 @@
unique case (mode_i)
AES_ENC: key_words_sel_o = KEY_WORDS_0123;
AES_DEC: key_words_sel_o = KEY_WORDS_4567;
- default: key_words_sel_o = key_words_sel_e'(1'bX);
+ default: key_words_sel_o = KEY_WORDS_ZERO;
endcase
end
- default: key_words_sel_o = key_words_sel_e'(1'bX);
+ default: key_words_sel_o = KEY_WORDS_ZERO;
endcase
end
@@ -263,10 +263,10 @@
unique case (mode_i)
AES_ENC: key_words_sel_o = KEY_WORDS_2345;
AES_DEC: key_words_sel_o = KEY_WORDS_0123;
- default: key_words_sel_o = key_words_sel_e'(1'bX);
+ default: key_words_sel_o = KEY_WORDS_ZERO;
endcase
end else begin
- key_words_sel_o = key_words_sel_e'(1'bX);
+ key_words_sel_o = KEY_WORDS_ZERO;
end
end
@@ -274,11 +274,11 @@
unique case (mode_i)
AES_ENC: key_words_sel_o = KEY_WORDS_4567;
AES_DEC: key_words_sel_o = KEY_WORDS_0123;
- default: key_words_sel_o = key_words_sel_e'(1'bX);
+ default: key_words_sel_o = KEY_WORDS_ZERO;
endcase
end
- default: key_words_sel_o = key_words_sel_e'(1'bX);
+ default: key_words_sel_o = KEY_WORDS_ZERO;
endcase
end
@@ -320,10 +320,10 @@
unique case (mode_i)
AES_ENC: key_words_sel_o = KEY_WORDS_2345;
AES_DEC: key_words_sel_o = KEY_WORDS_0123;
- default: key_words_sel_o = key_words_sel_e'(1'bX);
+ default: key_words_sel_o = KEY_WORDS_ZERO;
endcase
end else begin
- key_words_sel_o = key_words_sel_e'(1'bX);
+ key_words_sel_o = KEY_WORDS_ZERO;
end
end
@@ -331,11 +331,11 @@
unique case (mode_i)
AES_ENC: key_words_sel_o = KEY_WORDS_4567;
AES_DEC: key_words_sel_o = KEY_WORDS_0123;
- default: key_words_sel_o = key_words_sel_e'(1'bX);
+ default: key_words_sel_o = KEY_WORDS_ZERO;
endcase
end
- default: key_words_sel_o = key_words_sel_e'(1'bX);
+ default: key_words_sel_o = KEY_WORDS_ZERO;
endcase
end
@@ -381,7 +381,7 @@
aes_ctrl_ns = IDLE;
end
- default: aes_ctrl_ns = aes_ctrl_e'(1'bX);
+ default: aes_ctrl_ns = IDLE;
endcase
end
@@ -451,4 +451,19 @@
assign data_in_clear_o = 1'b0;
assign data_out_clear_o = 1'b0;
+ // Selectors must be known/valid
+ `ASSERT_KNOWN(AesModeKnown, mode_i, clk_i, !rst_ni)
+ `ASSERT(AesKeyLenValid, key_len_i inside {
+ AES_128,
+ AES_192,
+ AES_256
+ }, clk_i, !rst_ni)
+ `ASSERT(AesControlStateValid, aes_ctrl_cs inside {
+ IDLE,
+ INIT,
+ ROUND,
+ FINISH,
+ CLEAR
+ }, clk_i, !rst_ni)
+
endmodule
diff --git a/hw/ip/aes/rtl/aes_core.sv b/hw/ip/aes/rtl/aes_core.sv
index b4afff3..148e7a0 100644
--- a/hw/ip/aes/rtl/aes_core.sv
+++ b/hw/ip/aes/rtl/aes_core.sv
@@ -133,7 +133,7 @@
STATE_INIT: state_d = state_init;
STATE_ROUND: state_d = add_round_key_out;
STATE_CLEAR: state_d = '0;
- default: state_d = 'X;
+ default: state_d = state_init;
endcase
end
@@ -169,7 +169,7 @@
ADD_RK_INIT: add_round_key_in = state_q;
ADD_RK_ROUND: add_round_key_in = mix_columns_out;
ADD_RK_FINAL: add_round_key_in = shift_rows_out;
- default: add_round_key_in = 'X;
+ default: add_round_key_in = state_q;
endcase
end
@@ -184,7 +184,7 @@
unique case (key_init_sel)
KEY_INIT_INPUT: key_init_d = key_init;
KEY_INIT_CLEAR: key_init_d = '0;
- default: key_init_d = 'X;
+ default: key_init_d = key_init;
endcase
end
@@ -207,7 +207,7 @@
KEY_FULL_DEC_INIT: key_full_d = key_dec_q;
KEY_FULL_ROUND: key_full_d = key_expand_out;
KEY_FULL_CLEAR: key_full_d = '0;
- default: key_full_d = 'X;
+ default: key_full_d = key_init_q;
endcase
end
@@ -224,7 +224,7 @@
unique case (key_dec_sel)
KEY_DEC_EXPAND: key_dec_d = key_expand_out;
KEY_DEC_CLEAR: key_dec_d = '0;
- default: key_dec_d = 'X;
+ default: key_dec_d = key_expand_out;
endcase
end
@@ -254,10 +254,10 @@
always_comb begin : key_words_mux
unique case (key_words_sel)
KEY_WORDS_0123: key_words = key_full_q[3:0];
- KEY_WORDS_2345: key_words = AES192Enable ? key_full_q[5:2] : 'X;
+ KEY_WORDS_2345: key_words = AES192Enable ? key_full_q[5:2] : key_full_q[3:0];
KEY_WORDS_4567: key_words = key_full_q[7:4];
KEY_WORDS_ZERO: key_words = '0;
- default: key_words = 'X;
+ default: key_words = key_full_q[3:0];
endcase
end
@@ -274,7 +274,7 @@
unique case (round_key_sel)
ROUND_KEY_DIRECT: round_key = key_bytes;
ROUND_KEY_MIXED: round_key = key_mix_columns_out;
- default: round_key = 'X;
+ default: round_key = key_bytes;
endcase
end
@@ -396,4 +396,31 @@
assign hw2reg.ctrl.key_len.d = {key_len_q};
+ ////////////////
+ // Assertions //
+ ////////////////
+
+ // Selectors must be known/valid
+ `ASSERT_KNOWN(AesModeKnown, mode_q, clk_i, !rst_ni)
+ `ASSERT(AesKeyLenValid, key_len_q inside {
+ AES_128,
+ AES_192,
+ AES_256
+ }, clk_i, !rst_ni)
+ `ASSERT(AesStateSelValid, state_sel inside {
+ STATE_INIT,
+ STATE_ROUND,
+ STATE_CLEAR
+ }, clk_i, !rst_ni)
+ `ASSERT(AesAddRKSelValid, add_round_key_in_sel inside {
+ ADD_RK_INIT,
+ ADD_RK_ROUND,
+ ADD_RK_FINAL
+ }, clk_i, !rst_ni)
+ `ASSERT_KNOWN(AesKeyInitSelKnown, key_init_sel, clk_i, !rst_ni)
+ `ASSERT_KNOWN(AesKeyFullSelKnown, key_full_sel, clk_i, !rst_ni)
+ `ASSERT_KNOWN(AesKeyDecSelKnown, key_dec_sel, clk_i, !rst_ni)
+ `ASSERT_KNOWN(AesKeyWordsSelKnown, key_words_sel, clk_i, !rst_ni)
+ `ASSERT_KNOWN(AesRoundKeySelKnown, round_key_sel, clk_i, !rst_ni)
+
endmodule
diff --git a/hw/ip/aes/rtl/aes_key_expand.sv b/hw/ip/aes/rtl/aes_key_expand.sv
index 0728b15..d15ea42 100644
--- a/hw/ip/aes/rtl/aes_key_expand.sv
+++ b/hw/ip/aes/rtl/aes_key_expand.sv
@@ -83,10 +83,10 @@
rcon_d = (mode_i == AES_ENC) ? 8'h01 :
((mode_i == AES_DEC) && (key_len_i == AES_128)) ? 8'h36 :
((mode_i == AES_DEC) && (key_len_i == AES_192)) ? 8'h80 :
- ((mode_i == AES_DEC) && (key_len_i == AES_256)) ? 8'h40 : 8'hXX;
+ ((mode_i == AES_DEC) && (key_len_i == AES_256)) ? 8'h40 : 8'h01;
end else begin
rcon_d = (mode_i == AES_ENC) ? aes_mul2(rcon_q) :
- (mode_i == AES_DEC) ? aes_div2(rcon_q) : 8'hXX;
+ (mode_i == AES_DEC) ? aes_div2(rcon_q) : 8'h01;
end
end
@@ -116,7 +116,7 @@
unique case (mode_i)
AES_ENC: rot_word_in = key_i[3];
AES_DEC: rot_word_in = spec_in_128;
- default: rot_word_in = 'X;
+ default: rot_word_in = key_i[3];
endcase
end
@@ -129,16 +129,16 @@
AES_ENC: begin
rot_word_in = rnd_type[0] ? key_i[5] :
rnd_type[2] ? key_i[5] :
- rnd_type[3] ? spec_in_192 : 'X;
+ rnd_type[3] ? spec_in_192 : key_i[3];
end
AES_DEC: begin
rot_word_in = rnd_type[1] ? key_i[3] :
- rnd_type[2] ? key_i[1] : 'X;
+ rnd_type[2] ? key_i[1] : key_i[3];
end
- default: rot_word_in = 'X;
+ default: rot_word_in = key_i[3];
endcase
end else begin
- rot_word_in = 'X;
+ rot_word_in = key_i[3];
end
end
@@ -149,11 +149,11 @@
unique case (mode_i)
AES_ENC: rot_word_in = key_i[7];
AES_DEC: rot_word_in = key_i[3];
- default: rot_word_in = 'X;
+ default: rot_word_in = key_i[7];
endcase
end
- default: rot_word_in = 'X;
+ default: rot_word_in = key_i[3];
endcase
end
@@ -183,6 +183,9 @@
///////////////////////////
// The more regular part //
///////////////////////////
+
+ // To reduce muxing resources, we re-use existing
+ // connections for unused words and default cases.
always_comb begin : drive_regular
unique case (key_len_i)
@@ -191,7 +194,7 @@
/////////////
AES_128: begin
// key_o[7:4] not used
- regular[7:4] = 'X;
+ regular[7:4] = key_i[3:0];
regular[0] = irregular ^ key_i[0];
unique case (mode_i)
@@ -207,7 +210,7 @@
end
end
- default: regular = 'X;
+ default: regular = {key_i[3:0], key_i[7:4]};
endcase
end
@@ -216,7 +219,7 @@
/////////////
AES_192: begin
// key_o[7:6] not used
- regular[7:6] = 'X;
+ regular[7:6] = key_i[3:2];
if (AES192Enable) begin
unique case (mode_i)
@@ -265,11 +268,11 @@
end // rnd_type[0]
end
- default: regular = 'X;
+ default: regular = {key_i[3:0], key_i[7:4]};
endcase
end else begin
- regular = 'X;
+ regular = {key_i[3:0], key_i[7:4]};
end // AES192Enable
end
@@ -281,7 +284,8 @@
AES_ENC: begin
if (rnd == 0) begin
// Round 0: Nothing to be done
- regular = key_i;
+ // The Full Key registers are not updated
+ regular = {key_i[3:0], key_i[7:4]};
end else begin
// Shift down old upper half
regular[3:0] = key_i[7:4];
@@ -296,7 +300,8 @@
AES_DEC: begin
if (rnd == 0) begin
// Round 0: Nothing to be done
- regular = key_i;
+ // The Full Key registers are not updated
+ regular = {key_i[3:0], key_i[7:4]};
end else begin
// Shift up old lower half
regular[7:4] = key_i[3:0];
@@ -308,15 +313,23 @@
end // rnd == 0
end
- default: regular = 'X;
+ default: regular = {key_i[3:0], key_i[7:4]};
endcase
end
- default: regular = 'X;
+ default: regular = {key_i[3:0], key_i[7:4]};
endcase // key_len_i
end
// Drive output
assign key_o = regular;
+ // Selectors must be known/valid
+ `ASSERT_KNOWN(AesModeKnown, mode_i, clk_i, !rst_ni)
+ `ASSERT(AesKeyLenValid, key_len_i inside {
+ AES_128,
+ AES_192,
+ AES_256
+ }, clk_i, !rst_ni)
+
endmodule