Advanced Encryption Standard Cipher
From Gezel2
aes.fdl
The design below is based on the core by Rudolf Usselman, available from OpenCores.
dp sbox_us00(in din : ns(8); out dout : ns(8)) {
lookup T : ns(9) = {
99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118,
202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192,
183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21,
4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117,
9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132,
83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207,
208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168,
81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210,
205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115,
96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121,
231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8,
186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138,
112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158,
225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22};
always {
dout = T(din);
}
}
dp sbox_us01 : sbox_us00
dp sbox_us02 : sbox_us00
dp sbox_us03 : sbox_us00
dp sbox_us10 : sbox_us00
dp sbox_us11 : sbox_us00
dp sbox_us12 : sbox_us00
dp sbox_us13 : sbox_us00
dp sbox_us20 : sbox_us00
dp sbox_us21 : sbox_us00
dp sbox_us22 : sbox_us00
dp sbox_us23 : sbox_us00
dp sbox_us30 : sbox_us00
dp sbox_us31 : sbox_us00
dp sbox_us32 : sbox_us00
dp sbox_us33 : sbox_us00
dp sbox_u0 : sbox_us00
dp sbox_u1 : sbox_us00
dp sbox_u2 : sbox_us00
dp sbox_u3 : sbox_us00
dp aes_rcon(in kld : ns(1);
out res : ns(32)) {
reg rcnt : ns(4);
sig rcnt_next : ns(4);
always {
res = kld ? 0x01000000 :
(rcnt == 0) ? 0x01000000 :
(rcnt == 1) ? 0x02000000 :
(rcnt == 2) ? 0x04000000 :
(rcnt == 3) ? 0x08000000 :
(rcnt == 4) ? 0x10000000 :
(rcnt == 5) ? 0x20000000 :
(rcnt == 6) ? 0x40000000 :
(rcnt == 7) ? 0x80000000 :
(rcnt == 8) ? 0x1b000000 :
(rcnt == 9) ? 0x36000000 :
0x00000000 ;
rcnt_next = rcnt + 1;
rcnt = kld ? 0 : ((rcnt == 10) ? rcnt : rcnt_next);
}
}
dp aes_key_expand_128(in kld : ns(1);
in key : ns(128);
out wo_0 : ns(32);
out wo_1 : ns(32);
out wo_2 : ns(32);
out wo_3 : ns(32)) {
reg w3, w2, w1, w0 : ns(32);
sig tmp_w0, tmp_w1, tmp_w2, tmp_w3 : ns(8);
sig subword : ns(32);
sig subword0 : ns (8);
sig subword1 : ns (8);
sig subword2 : ns (8);
sig subword3 : ns (8);
sig rcon : ns(32);
use sbox_u0 (tmp_w3, subword3); // should be able to use indices here
use sbox_u1 (tmp_w2, subword2);
use sbox_u2 (tmp_w1, subword1);
use sbox_u3 (tmp_w0, subword0);
use aes_rcon(kld, rcon);
always {
subword = (subword3 << 24) | (subword2 << 16) | (subword1 << 8) | subword0;
w0 = kld ? key[127: 96] : (w0 ^ subword ^ rcon);
w1 = kld ? key[ 95: 64] : (w0 ^ w1 ^ subword ^ rcon);
w2 = kld ? key[ 63: 32] : (w0 ^ w2 ^ w1 ^ subword ^ rcon);
w3 = kld ? key[ 31: 0] : (w0 ^ w3 ^ w2 ^ w1 ^ subword ^ rcon);
tmp_w0 = w3[31:24];
tmp_w1 = w3[ 7: 0];
tmp_w2 = w3[15: 8];
tmp_w3 = w3[23:16];
wo_0 = w0;
wo_1 = w1;
wo_2 = w2;
wo_3 = w3;
}
}
dp aes_mix_col_0(in s0 : ns(8);
in s1 : ns(8);
in s2 : ns(8);
in s3 : ns(8);
out s0_o : ns(8);
out s1_o : ns(8);
out s2_o : ns(8);
out s3_o : ns(8)) {
sig fpr : ns(8);
always {
fpr = 0x1b;
s0_o = (s0 << 1) ^ (s0[7] ? fpr : 0) ^ (s1 << 1) ^ (s1[7] ? fpr : 0) ^ s1 ^ s2 ^ s3;
s1_o = (s1 << 1) ^ (s1[7] ? fpr : 0) ^ (s2 << 1) ^ (s2[7] ? fpr : 0) ^ s0 ^ s2 ^ s3;
s2_o = (s2 << 1) ^ (s2[7] ? fpr : 0) ^ (s3 << 1) ^ (s3[7] ? fpr : 0) ^ s0 ^ s1 ^ s3;
s3_o = (s3 << 1) ^ (s3[7] ? fpr : 0) ^ (s0 << 1) ^ (s0[7] ? fpr : 0) ^ s0 ^ s1 ^ s2;
}
}
dp aes_mix_col_1 : aes_mix_col_0
dp aes_mix_col_2 : aes_mix_col_0
dp aes_mix_col_3 : aes_mix_col_0
dp aes_top(in rstaes : ns(1);
in ld : ns(1);
out done : ns(1);
in key : ns(128);
in text_in : ns(128);
out text_out : ns(128)) {
sig w0, w1, w2, w3 : ns(32);
reg text_in_r : ns(128);
reg text_out_r : ns(128);
reg ld_r : ns(1);
reg sa00, sa01, sa02, sa03 : ns(8);
reg sa10, sa11, sa12, sa13 : ns(8);
reg sa20, sa21, sa22, sa23 : ns(8);
reg sa30, sa31, sa32, sa33 : ns(8);
sig sa00_next, sa01_next, sa02_next, sa03_next : ns(8);
sig sa10_next, sa11_next, sa12_next, sa13_next : ns(8);
sig sa20_next, sa21_next, sa22_next, sa23_next : ns(8);
sig sa30_next, sa31_next, sa32_next, sa33_next : ns(8);
sig sa00_sub, sa01_sub, sa02_sub, sa03_sub : ns(8);
sig sa10_sub, sa11_sub, sa12_sub, sa13_sub : ns(8);
sig sa20_sub, sa21_sub, sa22_sub, sa23_sub : ns(8);
sig sa30_sub, sa31_sub, sa32_sub, sa33_sub : ns(8);
sig sa00_sr, sa01_sr, sa02_sr, sa03_sr : ns(8);
sig sa10_sr, sa11_sr, sa12_sr, sa13_sr : ns(8);
sig sa20_sr, sa21_sr, sa22_sr, sa23_sr : ns(8);
sig sa30_sr, sa31_sr, sa32_sr, sa33_sr : ns(8);
sig sa00_mc, sa01_mc, sa02_mc, sa03_mc : ns(8);
sig sa10_mc, sa11_mc, sa12_mc, sa13_mc : ns(8);
sig sa20_mc, sa21_mc, sa22_mc, sa23_mc : ns(8);
sig sa30_mc, sa31_mc, sa32_mc, sa33_mc : ns(8);
sig text_out00, text_out01, text_out02, text_out03 : ns(8);
sig text_out04, text_out05, text_out06, text_out07 : ns(8);
sig text_out08, text_out09, text_out10, text_out11 : ns(8);
sig text_out12, text_out13, text_out14, text_out15 : ns(8);
reg dcnt : ns(4);
use aes_mix_col_0(sa00_sr,sa10_sr,sa20_sr,sa30_sr,sa00_mc,sa10_mc,sa20_mc,sa30_mc);
use aes_mix_col_1(sa01_sr,sa11_sr,sa21_sr,sa31_sr,sa01_mc,sa11_mc,sa21_mc,sa31_mc);
use aes_mix_col_2(sa02_sr,sa12_sr,sa22_sr,sa32_sr,sa02_mc,sa12_mc,sa22_mc,sa32_mc);
use aes_mix_col_3(sa03_sr,sa13_sr,sa23_sr,sa33_sr,sa03_mc,sa13_mc,sa23_mc,sa33_mc);
use sbox_us00(sa00,sa00_sub);
use sbox_us01(sa01,sa01_sub);
use sbox_us02(sa02,sa02_sub);
use sbox_us03(sa03,sa03_sub);
use sbox_us10(sa10,sa10_sub);
use sbox_us11(sa11,sa11_sub);
use sbox_us12(sa12,sa12_sub);
use sbox_us13(sa13,sa13_sub);
use sbox_us20(sa20,sa20_sub);
use sbox_us21(sa21,sa21_sub);
use sbox_us22(sa22,sa22_sub);
use sbox_us23(sa23,sa23_sub);
use sbox_us30(sa30,sa30_sub);
use sbox_us31(sa31,sa31_sub);
use sbox_us32(sa32,sa32_sub);
use sbox_us33(sa33,sa33_sub);
use aes_key_expand_128(ld, key, w0, w1, w2, w3);
always {
// control
dcnt = rstaes ? 0 : (ld ? 11 : (dcnt ? dcnt - 1 : dcnt));
done = ~(dcnt[3] | dcnt[2] | dcnt[1]) & dcnt[0] & ~ld;
text_in_r = ld ? text_in : text_in_r;
ld_r = ld;
// addroundkey
sa33 = ld_r ? text_in[ 7: 0] ^ w3[ 7: 0] : sa33_next;
sa23 = ld_r ? text_in[ 15: 8] ^ w3[15: 8] : sa23_next;
sa13 = ld_r ? text_in[ 23: 16] ^ w3[23:16] : sa13_next;
sa03 = ld_r ? text_in[ 31: 24] ^ w3[31:24] : sa03_next;
sa32 = ld_r ? text_in[ 39: 32] ^ w2[ 7: 0] : sa32_next;
sa22 = ld_r ? text_in[ 47: 40] ^ w2[15: 8] : sa22_next;
sa12 = ld_r ? text_in[ 55: 48] ^ w2[23:16] : sa12_next;
sa02 = ld_r ? text_in[ 63: 56] ^ w2[31:24] : sa02_next;
sa31 = ld_r ? text_in[ 71: 64] ^ w1[ 7: 0] : sa31_next;
sa21 = ld_r ? text_in[ 79: 72] ^ w1[15: 8] : sa21_next;
sa11 = ld_r ? text_in[ 87: 80] ^ w1[23:16] : sa11_next;
sa01 = ld_r ? text_in[ 95: 88] ^ w1[31:24] : sa01_next;
sa30 = ld_r ? text_in[103:096] ^ w0[ 7: 0] : sa30_next;
sa20 = ld_r ? text_in[111:104] ^ w0[15: 8] : sa20_next;
sa10 = ld_r ? text_in[119:112] ^ w0[23:16] : sa10_next;
sa00 = ld_r ? text_in[127:120] ^ w0[31:24] : sa00_next;
// round permutations
sa00_sr = sa00_sub;
sa01_sr = sa01_sub;
sa02_sr = sa02_sub;
sa03_sr = sa03_sub;
sa10_sr = sa11_sub;
sa11_sr = sa12_sub;
sa12_sr = sa13_sub;
sa13_sr = sa10_sub;
sa20_sr = sa22_sub;
sa21_sr = sa23_sub;
sa22_sr = sa20_sub;
sa23_sr = sa21_sub;
sa30_sr = sa33_sub;
sa31_sr = sa30_sub;
sa32_sr = sa31_sub;
sa33_sr = sa32_sub;
// add roundkey
sa00_next = sa00_mc ^ w0[31:24];
sa01_next = sa01_mc ^ w1[31:24];
sa02_next = sa02_mc ^ w2[31:24];
sa03_next = sa03_mc ^ w3[31:24];
sa10_next = sa10_mc ^ w0[23:16];
sa11_next = sa11_mc ^ w1[23:16];
sa12_next = sa12_mc ^ w2[23:16];
sa13_next = sa13_mc ^ w3[23:16];
sa20_next = sa20_mc ^ w0[15: 8];
sa21_next = sa21_mc ^ w1[15: 8];
sa22_next = sa22_mc ^ w2[15: 8];
sa23_next = sa23_mc ^ w3[15: 8];
sa30_next = sa30_mc ^ w0[ 7: 0];
sa31_next = sa31_mc ^ w1[ 7: 0];
sa32_next = sa32_mc ^ w2[ 7: 0];
sa33_next = sa33_mc ^ w3[ 7: 0];
// final text output
text_out00 = sa00_sr ^ w0[31:24];
text_out01 = sa01_sr ^ w1[31:24];
text_out02 = sa02_sr ^ w2[31:24];
text_out03 = sa03_sr ^ w3[31:24];
text_out04 = sa10_sr ^ w0[23:16];
text_out05 = sa11_sr ^ w1[23:16];
text_out06 = sa12_sr ^ w2[23:16];
text_out07 = sa13_sr ^ w3[23:16];
text_out08 = sa20_sr ^ w0[15: 8];
text_out09 = sa21_sr ^ w1[15: 8];
text_out10 = sa22_sr ^ w2[15: 8];
text_out11 = sa23_sr ^ w3[15: 8];
text_out12 = sa30_sr ^ w0[ 7: 0];
text_out13 = sa31_sr ^ w1[ 7: 0];
text_out14 = sa32_sr ^ w2[ 7: 0];
text_out15 = sa33_sr ^ w3[ 7: 0];
text_out = (text_out00 << 120) |
(text_out01 << 88) |
(text_out02 << 56) |
(text_out03 << 24) |
(text_out04 << 112) |
(text_out05 << 80) |
(text_out06 << 48) |
(text_out07 << 16) |
(text_out08 << 104) |
(text_out09 << 72) |
(text_out10 << 40) |
(text_out11 << 8) |
(text_out12 << 96) |
(text_out13 << 64) |
(text_out14 << 32) |
(text_out15 << 0);
$display(done, " ", text_out);
}
}
dp testbench(out rstaes : ns(1); out ld : ns(1); in done : ns(1);
out key : ns(128); out text_in : ns(128); in text_out : ns(128)) {
reg ddone : ns(1);
reg dtext_out : ns(128);
sfg reset_1 { rstaes = 1; }
sfg reset_0 { rstaes = 0; }
sfg ld_1 { ld = 1; }
sfg ld_0 { ld = 0; }
always { key = 0x000102030405060708090a0b0c0d0e0f;
text_in = 0x00112233445566778899aabbccddeeff;
ddone = done;
dtext_out = text_out;
}
}
fsm ftestbench(testbench) {
initial s0;
state s1, s2;
@s0 (reset_1, ld_0) -> s1;
@s1 (reset_0, ld_1) -> s2;
@s2 if (ddone) then (reset_0, ld_1) -> s2;
else (reset_0, ld_0) -> s2;
}
dp aes_sys {
sig rstaes, ld, done : ns(1);
sig key, text_in, text_out : ns(128);
use testbench(rstaes, ld, done, key, text_in, text_out);
use aes_top (rstaes, ld, done, key, text_in, text_out);
}
system S {
aes_sys;
}
Simulation Output
>fdlsim aes.fdl 25 0 63636363636363636363636363636363 0 99989898999898989998989899989898 0 ee474445ea434041e64f4c4de24b4849 0 b5f99471dbcf93fe17d6cfa06c61a619 0 112cd562f390ce6a66520f457751389f 0 8d2656262eb632cc3b3ec75fc430b16c 0 6a9a894caa06dd37f05a3061a6fe9f3a 0 a993eb8502aa4cdcfdfa67a69b64f89 0 b6e3b9ede3d146f398a2c823ede4c224 0 a0a162568be9688d0f93276311bc956a 0 795fa5f512e0dacf6dbeea9358a87e47 0 40a2709b25cddd862819921f3de761 1 69c4e0d86a7b0430d8cdb78070b4c55a 0 d7cd9a21d2c7c4effd4464bc2b425345 0 85d8b509c8b5c83e7d2fe25371f1341c 0 b5f99471dbcf93fe17d6cfa06c61a619 0 112cd562f390ce6a66520f457751389f 0 8d2656262eb632cc3b3ec75fc430b16c 0 6a9a894caa06dd37f05a3061a6fe9f3a 0 a993eb8502aa4cdcfdfa67a69b64f89 0 b6e3b9ede3d146f398a2c823ede4c224 0 a0a162568be9688d0f93276311bc956a 0 795fa5f512e0dacf6dbeea9358a87e47 0 40a2709b25cddd862819921f3de761 1 69c4e0d86a7b0430d8cdb78070b4c55a
