[aes/rtl] Implement MixColumns operation
diff --git a/hw/ip/aes/aes.core b/hw/ip/aes/aes.core
index 20db757..32cab00 100644
--- a/hw/ip/aes/aes.core
+++ b/hw/ip/aes/aes.core
@@ -18,6 +18,9 @@
- rtl/aes_sbox_lut.sv
- rtl/aes_shift_rows.sv
- rtl/aes_mix_columns.sv
+ - rtl/aes_mix_single_column.sv
+ - rtl/aes_mul2.sv
+ - rtl/aes_mul4.sv
- rtl/aes_key_expand.sv
- rtl/aes_control.sv
- rtl/aes.sv
diff --git a/hw/ip/aes/rtl/aes_mix_columns.sv b/hw/ip/aes/rtl/aes_mix_columns.sv
index 715ced0..0541649 100644
--- a/hw/ip/aes/rtl/aes_mix_columns.sv
+++ b/hw/ip/aes/rtl/aes_mix_columns.sv
@@ -10,11 +10,13 @@
output logic [7:0] data_o [16]
);
-import aes_pkg::*;
-
-// dummy only
-mode_e unused_mode;
-assign unused_mode = mode_i;
-assign data_o = data_i;
+ // Individually mix columns
+ for (genvar i = 0; i < 4; i++) begin : gen_mix_column
+ aes_mix_single_column aes_mix_column_i (
+ .mode_i ( mode_i ),
+ .data_i ( data_i[4*i:4*i+3] ),
+ .data_o ( data_o[4*i:4*i+3] )
+ );
+ end
endmodule
diff --git a/hw/ip/aes/rtl/aes_mix_single_column.sv b/hw/ip/aes/rtl/aes_mix_single_column.sv
new file mode 100644
index 0000000..345c66b
--- /dev/null
+++ b/hw/ip/aes/rtl/aes_mix_single_column.sv
@@ -0,0 +1,77 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// AES MixColumns for one single column of the state matrix
+//
+// For details, see Equations 4-7 of:
+// Satoh et al., "A Compact Rijndael Hardware Architecture with S-Box Optimization"
+
+module aes_mix_single_column (
+ input aes_pkg::mode_e mode_i,
+ input logic [7:0] data_i [4],
+ output logic [7:0] data_o [4]
+);
+
+ import aes_pkg::*;
+
+ logic [7:0] x[4];
+ logic [7:0] y[2];
+ logic [7:0] z[2];
+
+ logic [7:0] x_mul2[4];
+ logic [7:0] y_pre_mul4[2];
+ logic [7:0] y2, y2_pre_mul2;
+
+ logic [7:0] z_muxed[2];
+
+ // Drive x
+ assign x[0] = data_i[0] ^ data_i[3];
+ assign x[1] = data_i[3] ^ data_i[2];
+ assign x[2] = data_i[2] ^ data_i[1];
+ assign x[3] = data_i[1] ^ data_i[0];
+
+ // Mul2 blocks for x
+ for (genvar i = 0; i < 4; i++) begin : gen_x_mul2
+ aes_mul2 x_mul2_i (
+ .data_i ( x[i] ),
+ .data_o ( x_mul2[i] )
+ );
+ end
+
+ // Drive y_pre_mul4
+ assign y_pre_mul4[0] = data_i[3] ^ data_i[1];
+ assign y_pre_mul4[1] = data_i[2] ^ data_i[0];
+
+ // Mul4 blocks for y
+ for (genvar i = 0; i < 2; i++) begin : gen_mul4
+ aes_mul4 y_mul4_i (
+ .data_i ( y_pre_mul4[i] ),
+ .data_o ( y[i] )
+ );
+ end
+
+ // Drive y2_pre_mul2
+ assign y2_pre_mul2 = y[0] ^ y[1];
+
+ // Mul2 block for y
+ aes_mul2 y_mul2 (
+ .data_i ( y2_pre_mul2 ),
+ .data_o ( y2 )
+ );
+
+ // Drive z
+ assign z[0] = y2 ^ y[0];
+ assign z[1] = y2 ^ y[1];
+
+ // Mux z
+ assign z_muxed[0] = (mode_i == AES_ENC) ? 8'b0 : z[0];
+ assign z_muxed[1] = (mode_i == AES_ENC) ? 8'b0 : z[1];
+
+ // Drive outputs
+ assign data_o[0] = data_i[1] ^ x_mul2[3] ^ x[1] ^ z_muxed[1];
+ assign data_o[1] = data_i[0] ^ x_mul2[2] ^ x[1] ^ z_muxed[0];
+ assign data_o[2] = data_i[3] ^ x_mul2[1] ^ x[3] ^ z_muxed[1];
+ assign data_o[3] = data_i[2] ^ x_mul2[0] ^ x[3] ^ z_muxed[0];
+
+endmodule
diff --git a/hw/ip/aes/rtl/aes_mul2.sv b/hw/ip/aes/rtl/aes_mul2.sv
new file mode 100644
index 0000000..dc19cd0
--- /dev/null
+++ b/hw/ip/aes/rtl/aes_mul2.sv
@@ -0,0 +1,21 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// AES mul2 implements a constant multiplication by 2 on GF(2^8).
+
+module aes_mul2 (
+ input logic [7:0] data_i,
+ output logic [7:0] data_o
+);
+
+ assign data_o[7] = data_i[6];
+ assign data_o[6] = data_i[5];
+ assign data_o[5] = data_i[4];
+ assign data_o[4] = data_i[3] ^ data_i[7];
+ assign data_o[3] = data_i[2] ^ data_i[7];
+ assign data_o[2] = data_i[1];
+ assign data_o[1] = data_i[0] ^ data_i[7];
+ assign data_o[0] = data_i[7];
+
+endmodule
diff --git a/hw/ip/aes/rtl/aes_mul4.sv b/hw/ip/aes/rtl/aes_mul4.sv
new file mode 100644
index 0000000..b43ca63
--- /dev/null
+++ b/hw/ip/aes/rtl/aes_mul4.sv
@@ -0,0 +1,21 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// AES mul4 implements a constant multiplication by 4 on GF(2^8).
+
+module aes_mul4 (
+ input logic [7:0] data_i,
+ output logic [7:0] data_o
+);
+
+ assign data_o[7] = data_i[5];
+ assign data_o[6] = data_i[4];
+ assign data_o[5] = data_i[3] ^ data_i[7];
+ assign data_o[4] = data_i[2] ^ data_i[7] ^ data_i[6];
+ assign data_o[3] = data_i[1] ^ data_i[6];
+ assign data_o[2] = data_i[0] ^ data_i[7];
+ assign data_o[1] = data_i[7] ^ data_i[6];
+ assign data_o[0] = data_i[6];
+
+endmodule