Introduction
AES (Advanced Encryption Standard)
In this work, AES is a variant of Rijndael, with a fixed block size of 128 bits, and a key size of 128 bits.
The 16-byte data b0,b1,…,b15 will be represented as
$$\begin{bmatrix}
b_0 & b_4 & b_8& b_{12} \\
b_1 & b_5 & b_9& b_{13} \\
b_2 & b_6 & b_{10}& b_{14} \\
b_3 & b_7 & b_{11}& b_{15} \\
\end{bmatrix} $$

Before starting to encrypt the message we need some initialization steps; key expansion and initial round.

The size of the key dictates how many rounds that we have to perform to get encrypted message. In this work key is 128 bits and we need 10 cycles. In each round a modified version of the original key will be used and that will be created by performing “AES Key Expansion” operation.
Stages: (will be performed for the first 16 byte of message, then next 16 byte will be taken, and continue on this way up to end of the message)
- Key expansion
- Initial Round
- AddRoundKey
- Rounds (repeat 9 times)
- SubBytes
- ShiftRows
- MixColumns
- AddRoundKey
- Final Round
- SubBytes
- ShiftRows
- AddRoundKey

Lets Assume the message is “AES Advanced Encryption Standard!”.
First 16 bytes (or characters) “AES Advanced Enc” will be taken (their ASCII values) for encryption and place in 4×4 matrix. It will be called as state.
$$\begin{bmatrix}
A & A & n & \\
E & d & c & E \\
S & v & e & n \\
& a & d & c \\
\end{bmatrix} = \begin{bmatrix}
41 & 41 & 6E & 20 \\
45 & 64 & 63 & 45 \\
53 & 76 & 65 & 6E \\
20 & 61 & 64 & 63 \\
\end{bmatrix} $$
and lets assume Cipher Key is
$$\begin{bmatrix}
2B & 28 & AB & 09 \\
7E & AE & F7 & CF \\
15 & D2 & 15 & 4F \\
16 & A6 & 88 & 3C \\
\end{bmatrix}$$
AddRoundKey Step
In this step each byte of the state will be XORed with the KEY.
For initial Round (Round 0)
$$\begin{bmatrix}
41 & 41 & 6E & 20 \\
45 & 64 & 63 & 45 \\
53 & 76 & 65 & 6E \\
20 & 61 & 64 & 63 \\
\end{bmatrix} XOR \begin{bmatrix}
2B & 28 & AB & 09 \\
7E & AE & F7 & CF \\
15 & D2 & 15 & 4F \\
16 & A6 & 88 & 3C \\
\end{bmatrix} =\begin{bmatrix}
6A & 69 & C5 & 29 \\
3B & CA & 94 & 8A \\
46 & A4 & 70 & 21 \\
36 & C7 & EC & 5F \\
\end{bmatrix} $$
After Round 0, the output of key expansion step will be used as round key.
SubBytes Step
Replace each byte of the state (16 byte chunk) with another byte by using Rijndael S-Box (Substitution Box). (details)
$$\begin{bmatrix}
6A & 69 & C5 & 29 \\
3B & CA & 94 & 8A \\
46 & A4 & 70 & 21 \\
36 & C7 & EC & 5F \\
\end{bmatrix} Replace with S-BOX \begin{bmatrix}
02 & F9 & A6 & A5 \\
E2 & 74 & 22 & 7E \\
5A & 49 & 51 & FD \\
05 & C6 & CE & CF \\
\end{bmatrix} $$
ShiftRows Step
The output of SubBytes step will be taken and the rows of the matrix will be rotated.
First row remains same,
Second row will be rotated left once,
Third row will be rotated left twice,
Fourth row will be rotated left 3 times.
$$ShiftRows\left(\begin{bmatrix}
02 & F9 & A6 & A5 \\
E2 & 74 & 22 & 7E \\
5A & 49 & 51 & FD \\
05 & C6 & CE & CF\\
\end{bmatrix} \right)= \begin{bmatrix}
02 & F9 & A6 & A5 \\
74 & 22 & 7E & E2 \\
51 & FD & 5A & 49 \\
CF & 05 & C6 & CE\\
\end{bmatrix}$$
MixColumns Step
The state will be modulo multiplied with Rijndael’s Galois Field Matrix.
The Galois Field Matrix is
$$\begin{bmatrix}
02 & 03 & 01 & 01 \\
01 & 02 & 03 & 01 \\
01 & 01 & 02 & 03 \\
03 & 01 & 01 & 02\\
\end{bmatrix}$$
The multiplication
$$\begin{bmatrix}
02 & 03 & 01 & 01 \\
01 & 02 & 03 & 01 \\
01 & 01 & 02 & 03 \\
03 & 01 & 01 & 02\\
\end{bmatrix}*\begin{bmatrix}
02 & F9 & A6 & A5 \\
74 & 22 & 7E & E2 \\
51 & FD & 5A & 49 \\
CF & 05 & C6 & CE\\
\end{bmatrix}=\begin{bmatrix}
06 & 77 & 49 & EB \\
D6 & A4 & 72 & 6F \\
9E & 35 & 3D & 9C \\
A6 & C5 & 42 & D8\\
\end{bmatrix}$$
b0 of the result matrix will be calculated as (02*02)⊕(03*74)⊕(01*51)⊕(01*CF)
For the multiplication;
If the Galois field value is 1: no need to calculate, ie, 51 and CF
If the Galois field value is 2: shift the value left once and if the leftmost bit of the value before shifting is 1 then xor the result of shift operation with 0x1B, otherwise leave it;
for (02*02): 00000010 will be shifted left once, the leftmost bit is not 1 so, the result is 00000100=4.
If the Galois field value is 3: perform GF(2) then xor it with the value,
for (03*74): 01110100 will be shifted left once, the leftmost bit is not 1 so, 11101000⊕01110100=9C.
and last: 04⊕9C⊕51⊕CF=06
At this point AddRoundKey step will be performed again with the key that is produced from the original key.
The steps SubBytes, ShiftRows, MixColumns and AddRoundKey steps will be repeated 9 times.
At the final round, SubBytes, ShiftRows and AddRoundKey steps will be performed. (no MixColumns step)
KEY EXPANSION
It is expansion of Chipher key. 11 keys will be used. The initial key in initial round, 10 keys, produced from initial key, will be used for 9 main rounds and the final round.
The initial chipher key
$$\begin{bmatrix}
2B & 28 & AB & 09 \\
7E & AE & F7 & CF \\
15 & D2 & 15 & 4F \\
16 & A6 & 88 & 3C \\
\end{bmatrix}$$
To produce a round key;
Last column will be taken from previous round key.
The column will be rotated up once.
Perform SubBytes operation.
$$\begin{bmatrix}
09 \\
CF\\
4F\\
3C\\
\end{bmatrix} rotate-up\begin{bmatrix}
CF\\
4F\\
3C\\
09\\
\end{bmatrix}Subbytes\begin{bmatrix}
8A\\
84\\
EB\\
01\\
\end{bmatrix}
$$
The next step is to use Rcon table. For the first round key, the first column of Rcon table will be used, for second round key the second column of Rcon tablewill be used and goes on in this way.
The Rcon table table is
$$\begin{bmatrix}
01 & 02 & 04 & 08 & 10 & 20 & 40 & 80 & 1B & 36\\
00 & 00 & 00 & 00 & 00 & 00 & 00 & 00 & 00 & 00\\
00 & 00 & 00 & 00 & 00 & 00 & 00 & 00 & 00 & 00\\
00 & 00 & 00 & 00 & 00 & 00 & 00 & 00 & 00 & 00\\
\end{bmatrix}$$
For each first column of round key, the first column of the previous round key, the column that we have calculated and associated Rcon column will be XORed.
$$\begin{bmatrix}
2B \\
7E\\
15\\
16\\
\end{bmatrix} ⊕\begin{bmatrix}
8A\\
84\\
EB\\
01\\
\end{bmatrix}⊕\begin{bmatrix}
01\\
00\\
00\\
00\\
\end{bmatrix}=\begin{bmatrix}
A0\\
FA\\
FE\\
17\\
\end{bmatrix}
$$
For the second column of the current round key, the second column of previous round key and the first column of the current round key will be XORed.
$$\begin{bmatrix}
28\\
AE\\
D2\\
A6\\
\end{bmatrix}⊕\begin{bmatrix}
A0\\
FA\\
FE\\
17\\
\end{bmatrix}=\begin{bmatrix}
88\\
54\\
2C\\
B1\\
\end{bmatrix}
$$
For the third column of current round key, the third column of previous round key and second column of current round key will be XORed.
$$\begin{bmatrix}
AB\\
F7\\
15\\
88\\
\end{bmatrix}⊕\begin{bmatrix}
88\\
54\\
2C\\
B1\\
\end{bmatrix}=\begin{bmatrix}
23\\
A3\\
39\\
39\\
\end{bmatrix}
$$
For the fourth column of current round key, the fourth column of previous round key and third column of current round key will be XORed.
$$\begin{bmatrix}
09\\
CF\\
4F\\
3C\\
\end{bmatrix}⊕\begin{bmatrix}
23\\
A3\\
39\\
39\\
\end{bmatrix}=\begin{bmatrix}
2A\\
6C\\
76\\
05\\
\end{bmatrix}
$$
The round key will be
$$\begin{bmatrix}
A0 & 88 & 23 & 2A \\
FA & 54 & A3 & 6C \\
FE & 2C & 39 & 76 \\
17 & B1 & 39 & 05 \\
\end{bmatrix}$$
For the keys of next rounds, same operations will be repeated with associated Rcon column. (10 Times)
Original source code can be found at https://github.com/secworks/aes
Main AES Module
//======================================================================
//
// aes.v
// --------
// Top level wrapper for the AES block cipher core.
//
//
// Author: Joachim Strombergson
// Copyright (c) 2013, 2014 Secworks Sweden AB
// All rights reserved.
`default_nettype none
module aes(
// Clock and reset.
input wire clk,
input wire reset_n,
// Control.
input wire cs, //comes from cpu --chip select
input wire we, //comes from cpu --write enable
// Data ports.
input wire [7 : 0] address, //8 bit controls local params defined
// ADDCTRL
input wire [31 : 0] write_data, //test kodundan geliyor, ana test modülünde tb_write_data ile connected
// hem data hem de control sinyalleri bunun üzerinde geliyor, address kontrol
// edilip karar veriliyor
output wire [31 : 0] read_data
);
//----------------------------------------------------------------
// Internal constant and parameter definitions.
//----------------------------------------------------------------
//sisteme geri gönderilecek mesajın adres aralığı, by using read_data
//questioning by outside agent
localparam ADDR_NAME0 = 8'h00;
localparam ADDR_NAME1 = 8'h01;
localparam ADDR_VERSION = 8'h02;
//questioning by outside agent
localparam ADDR_CTRL = 8'h08;
localparam CTRL_INIT_BIT = 0;
localparam CTRL_NEXT_BIT = 1;
//questioning by outside agent
localparam ADDR_STATUS = 8'h09;
localparam STATUS_READY_BIT = 0;
localparam STATUS_VALID_BIT = 1;
localparam ADDR_CONFIG = 8'h0a;
localparam CTRL_ENCDEC_BIT = 0;
localparam CTRL_KEYLEN_BIT = 1;
// key_reg 8*32 array key için
localparam ADDR_KEY0 = 8'h10;
localparam ADDR_KEY7 = 8'h17;
//block_reg 4*32 array data için
localparam ADDR_BLOCK0 = 8'h20;
localparam ADDR_BLOCK3 = 8'h23;
//dış agent sonucu almak için bu adres aralığını kullanıyor
localparam ADDR_RESULT0 = 8'h30;
localparam ADDR_RESULT3 = 8'h33;
//these are written to output read_data (first written into temp_read_data)
localparam CORE_NAME0 = 32'h61657320; // "aes "
localparam CORE_NAME1 = 32'h20202020; // " "
localparam CORE_VERSION = 32'h302e3630; // "0.60"
//----------------------------------------------------------------
// Registers including update variables and write enable.
//----------------------------------------------------------------
reg init_reg; // initial state stored value (current state)
reg init_new; // initial state new value (next state)
reg next_reg; //current next
reg next_new; // next "next" state
reg encdec_reg; //encode or decode
reg keylen_reg; // 128 or 256 bit encryption
reg config_we; //????
reg [31 : 0] block_reg [0 : 3]; //4 * 32 bit data
reg block_we; //block control
reg [31 : 0] key_reg [0 : 7]; // 8 * 32 bit key value
reg key_we; //key kontrol
reg [127 : 0] result_reg; //128 bit result
reg valid_reg; //
reg ready_reg;
//----------------------------------------------------------------
// Wires.
//----------------------------------------------------------------
reg [31 : 0] tmp_read_data ; // data at every iteration ????
//all are aes_core connection
wire core_encdec;
wire core_init; //initial state value sent to aes_core
wire core_next; //next state value sent to aes_core
wire core_ready; // ready signal sent to aes_core
wire [255 : 0] core_key; //256 bit key value
wire core_keylen; // key is 128 or 256 bit
wire [127 : 0] core_block; // 128 bit block sent to aes_core
wire [127 : 0] core_result; //comes from aes_core as result
wire core_valid; // core output is valid, read it from core_result
//----------------------------------------------------------------
// Concurrent connectivity for ports etc.
//----------------------------------------------------------------
assign read_data = tmp_read_data; //read_data dışarıya bilgi göndermek için kullanılıyor
assign core_key = {key_reg[0], key_reg[1], key_reg[2], key_reg[3], // 8 32 bitlik key birleştirip 256 bitlik key oluşturuyor...
key_reg[4], key_reg[5], key_reg[6], key_reg[7]}; //ama 128 bi key kullanılıyorsa sadece yarısını employ ediyor..
assign core_block = {block_reg[0], block_reg[1],
block_reg[2], block_reg[3]}; //128 bitlik data oluşturuyor.
assign core_init = init_reg; // init signal is assigned to core module
assign core_next = next_reg; // next signal is assigned to core module
assign core_encdec = encdec_reg; // enc or dec
assign core_keylen = keylen_reg; // key length is assigned to core module
//----------------------------------------------------------------
// core instantiation.
//----------------------------------------------------------------
aes_core core(
.clk(clk),
.reset_n(reset_n),
.encdec(core_encdec),
.init(core_init), //goes to core. am I in an initial state? if so, go to initial state. write_data[0] ı gönderdi
.next(core_next), //goes to core. should I pass to the next state? write_data[1] ı gönderdi
.ready(core_ready), //comes from core. core is ready for the next step.
.key(core_key), //key goes to core
.keylen(core_keylen), //keylen goes to core
.block(core_block), //goes to core
.result(core_result), //comes from core. our main 128-bit result
.result_valid(core_valid) //core output is valid???
);
//----------------------------------------------------------------
// reg_update
// Update functionality for all registers in the core.
// All registers are positive edge triggered with asynchronous
// active low reset.
//----------------------------------------------------------------
always @ (posedge clk or negedge reset_n)
begin : reg_update
integer i;
if (!reset_n) // if reset
begin // clear blocks and key
for (i = 0 ; i < 4 ; i = i + 1)
block_reg[i] <= 32'h0;
for (i = 0 ; i < 8 ; i = i + 1)
key_reg[i] <= 32'h0;
init_reg <= 1'b0; // clear all control signals
next_reg <= 1'b0;
encdec_reg <= 1'b0;
keylen_reg <= 1'b0;
result_reg <= 128'h0;
valid_reg <= 1'b0;
ready_reg <= 1'b0;
end
else
begin // if not reset, start
ready_reg <= core_ready; // read ready signal from aes_core, aes core da enchiper bloktan geliyor enc_ready'ye bağlı
valid_reg <= core_valid; //read valid signal from aes_core (defined as result_valid in aes_core)
result_reg <= core_result; // read result(128bit) from aes_core
init_reg <= init_new; // assign init_reg to init signal of aes_core
next_reg <= next_new; // assign next_reg to next signal of aes_core
if (config_we) // Gelen adres ADDR_CONFIG 0x0A ise configürasyon bilgileri alınıyor
begin
encdec_reg <= write_data[CTRL_ENCDEC_BIT];// write_data içinde encription veya decription yapacağı bilgisi geliyor
keylen_reg <= write_data[CTRL_KEYLEN_BIT];// write_data içinde 128 veya 256 bit key kullanılacağı bilgisi geliyor
end
if (key_we) // eğer adres 0x10-0x17 arasındaysa
key_reg[address[2 : 0]] <= write_data; //dışardan input edilen address in lsb 3 bitine bakıyor.
// writedata da dışarıdan geliyor (input)
// key 8 defa da geliyor (8*32)
if (block_we) // eğer adres 0x20 - 0x23 arasındaysa
block_reg[address[1 : 0]] <= write_data;
end
end // reg_update
//----------------------------------------------------------------
// api
//
// The interface command decoding logic.
//----------------------------------------------------------------
always @*
begin : api
init_new = 1'b0;
next_new = 1'b0;
config_we = 1'b0;
key_we = 1'b0;
block_we = 1'b0;
tmp_read_data = 32'h0;
if (cs)
begin
if (we)
begin //we=1
if (address == ADDR_CTRL)//adres 0x08 gelirse aes_core parametreleri set ediliyor
begin
init_new = write_data[CTRL_INIT_BIT]; //write_datanın 0 ıncı biti init'e atanacak, init de core'a gönderiliyor
next_new = write_data[CTRL_NEXT_BIT]; //write_datanın 1 ıncı biti next'e atanacak, next de core'a gönderiliyor
end
if (address == ADDR_CONFIG) //adres 0x0a gelirse, config_we 1 olacak, write_data'nın 0 ve 1inci biti encdec_reg ve
// keylen_reg değerlerini belirlemek için kullanılacak
config_we = 1'b1;
if ((address >= ADDR_KEY0) && (address <= ADDR_KEY7)) //adres key ile ilgili aralıktaysa key_we 1 olacak
key_we = 1'b1;
if ((address >= ADDR_BLOCK0) && (address <= ADDR_BLOCK3)) // adress blok ile ilgili aralıktaysa block_we 1 olacak
block_we = 1'b1;
end // if (we)
else // we=0
begin //questioning by outside agent
case (address) //read_data ile dışarıya bilgi gönderiliyor (statü, control, data )
ADDR_NAME0: tmp_read_data = CORE_NAME0; //"aes"
ADDR_NAME1: tmp_read_data = CORE_NAME1; // " "
ADDR_VERSION: tmp_read_data = CORE_VERSION; //"0.60"
ADDR_CTRL: tmp_read_data = {28'h0, keylen_reg, encdec_reg, next_reg, init_reg};
ADDR_STATUS: tmp_read_data = {30'h0, valid_reg, ready_reg};
default:
begin
end
endcase // case (address)
if ((address >= ADDR_RESULT0) && (address <= ADDR_RESULT3))
tmp_read_data = result_reg[(3 - (address - ADDR_RESULT0)) * 32 +: 32]; // indexed part-select.
// 128 bitlik resultı gelen adrese göre
// 32 bitlik 4 parçaya bölüp read_data
//ile gönderiyor
end
end
end // addr_decoder
endmodule // aes
//======================================================================
// EOF aes.v
//======================================================================
AES Core Module
`default_nettype none
module aes_core( // instantiated by aes.v
input wire clk, //clock
input wire reset_n, //reset
input wire encdec, //encrpt or decryt
input wire init, //initial state or not
input wire next, //next state
output wire ready, //ready signal
input wire [255 : 0] key, //key
input wire keylen, //128 or 256 bit key
input wire [127 : 0] block, //data block to be encrpted
output wire [127 : 0] result, // encryipted data to be printed
output wire result_valid // to update the result
);
//----------------------------------------------------------------
// Internal constant and parameter definitions.
//----------------------------------------------------------------
localparam CTRL_IDLE = 2'h0; //parameters for finite state machine Main FSM
localparam CTRL_INIT = 2'h1;
localparam CTRL_NEXT = 2'h2;
//----------------------------------------------------------------
// Registers including update variables and write enable.
//----------------------------------------------------------------
reg [1 : 0] aes_core_ctrl_reg; //stores state values
reg [1 : 0] aes_core_ctrl_new; //
reg aes_core_ctrl_we;
reg result_valid_reg;
reg result_valid_new;
reg result_valid_we;
reg ready_reg;
reg ready_new;
reg ready_we;
//----------------------------------------------------------------
// Wires.
//----------------------------------------------------------------
reg init_state;
wire [127 : 0] round_key;
wire key_ready;
reg enc_next;
wire [3 : 0] enc_round_nr;
wire [127 : 0] enc_new_block;
wire enc_ready;
wire [31 : 0] enc_sboxw;
reg dec_next;
wire [3 : 0] dec_round_nr;
wire [127 : 0] dec_new_block;
wire dec_ready;
reg [127 : 0] muxed_new_block;
reg [3 : 0] muxed_round_nr;
reg muxed_ready;
wire [31 : 0] keymem_sboxw;
/* verilator lint_off UNOPTFLAT */
reg [31 : 0] muxed_sboxw;
wire [31 : 0] new_sboxw;
/* verilator lint_on UNOPTFLAT */
//----------------------------------------------------------------
// Instantiations.
//----------------------------------------------------------------
aes_encipher_block enc_block(
.clk(clk),// input clock
.reset_n(reset_n), // input reset
.next(enc_next), // enchipher modüle gönderilen next sinyali
.keylen(keylen), // key length 128 veya 256 bit işlem yapıldığını gösteriyor
.round(enc_round_nr), // enchipher module kaçıncı raund'da olduğunun bilgisini gönderiyor, bu bilgi key_mem modüle iletilecek
.round_key(round_key),//input 128 bit key for this round, keym_mem'den geliyor
.sboxw(enc_sboxw), //output to sbox module to get new value
.new_sboxw(new_sboxw), // input 32 bit new sbox value
.block(block), // input 128 byte block data, şifrelenecek data
.new_block(enc_new_block), //result of encription,
.ready(enc_ready) //ready signal, ENCHIPHER Module sends it
);
aes_decipher_block dec_block( // part for decryption
.clk(clk),
.reset_n(reset_n),
.next(dec_next),
.keylen(keylen),
.round(dec_round_nr),
.round_key(round_key),
.block(block),
.new_block(dec_new_block),
.ready(dec_ready)
);
aes_key_mem keymem(
.clk(clk), // input clock
.reset_n(reset_n), // input reset
.key(key), // input 256 bit key, AES main'den gelen buraya gönderiliyor
.keylen(keylen), //key length
.init(init), //input initial state or not, Aes main'den geliyor buraya gönderiliyor
.round_key(round_key), //input 128 bit key for this round, buradan gelen ENCHIPHER modüle gönderiliyor
.ready(key_ready), //output ready signal for keymem, keymem sends it AES_CORE
.sboxw(keymem_sboxw), //output to sbox module to get new value
.new_sboxw(new_sboxw) //input 32 bit new value
);
aes_sbox sbox_inst(.sboxw(muxed_sboxw), //input for sbox operations
.new_sboxw(new_sboxw) // output
);
//----------------------------------------------------------------
// Concurrent connectivity for ports etc.
//----------------------------------------------------------------
assign ready = ready_reg; //Aes maine gönderilen işlem yapmaya hazır sinyali
assign result = muxed_new_block; // AES_ENCIPHER modulden gelen şifrelenmiş veri AES Main'e muxed_new_block üzerinden gönderiliyor
assign result_valid = result_valid_reg; //Aes main'e gönderilen sonucun hazır olduğuna dair kontrol sinyali
//----------------------------------------------------------------
// reg_update
//
// Update functionality for all registers in the core.
// All registers are positive edge triggered with asynchronous
// active low reset. All registers have write enable.
//----------------------------------------------------------------
always @ (posedge clk or negedge reset_n)
begin: reg_update
if (!reset_n) //reset
begin
result_valid_reg <= 1'b0; // sonucun hazır olmadığını belirtiyor
ready_reg <= 1'b1; // işlem yapmaya hazır olduğunun sinyalini Aes main'e göndermek için hazırlıyor
aes_core_ctrl_reg <= CTRL_IDLE; //ilk state IDLE olarak ayarlanıyor
end
else
begin //run the hardware
if (result_valid_we) // 1 olduğunda result_valid değişiyor, result_valid=1 ise AES main Result'ın hazır olduğunu anlıyor
result_valid_reg <= result_valid_new;
if (ready_we) //1 olduğunda ready sinyali değişiyor,
ready_reg <= ready_new;
if (aes_core_ctrl_we) //1 olduğunda state değişikliği gerçekleşiyor
aes_core_ctrl_reg <= aes_core_ctrl_new;
end
end // reg_update
//----------------------------------------------------------------
// sbox_mux
//
// Controls which of the encipher datapath or the key memory
// that gets access to the sbox.
//----------------------------------------------------------------
always @*
begin : sbox_mux
if (init_state) // if it is initial state then read data from key_mem else read it from enchipher block
begin
muxed_sboxw = keymem_sboxw; //sbox'ı keymem mi yoksa encipher modül mü kullanacak karar veriliyor
end
else
begin
muxed_sboxw = enc_sboxw;
end
end // sbox_mux
//----------------------------------------------------------------
// encdex_mux
//
// Controls which of the datapaths that get the next signal, have
// access to the memory as well as the block processing result.
//----------------------------------------------------------------
always @*
begin : encdec_mux //encription or decription initialization, decide whether enc or dec
enc_next = 1'b0;
dec_next = 1'b0;
if (encdec)
begin
// Encipher operations
enc_next = next; // aes main'den gelen next sinyali enchipher modüle aktarılıyor
muxed_round_nr = enc_round_nr; //ENCHIPHER modülden gelen raund number alınıyor
muxed_new_block = enc_new_block; // sbox'a gönderilecek olan 32 bit data enchipher modulden alınıyor
muxed_ready = enc_ready; //enchipher modülden gelen ready sinyali alınıyor
end
else
begin
// Decipher operations
dec_next = next;
muxed_round_nr = dec_round_nr;
muxed_new_block = dec_new_block;
muxed_ready = dec_ready;
end
end // encdec_mux
//----------------------------------------------------------------
// aes_core_ctrl
//
// Control FSM for aes core. Basically tracks if we are in
// key init, encipher or decipher modes and connects the
// different submodules to shared resources and interface ports.
//----------------------------------------------------------------
always @*
begin : aes_core_ctrl //initialization, first state is idle, every signal is assigned as 0
init_state = 1'b0; // stateler içinde değiştirilmeyen değişkenler için default değerler
ready_new = 1'b0;
ready_we = 1'b0;
result_valid_new = 1'b0;
result_valid_we = 1'b0;
aes_core_ctrl_new = CTRL_IDLE;
aes_core_ctrl_we = 1'b0;
case (aes_core_ctrl_reg) // aes_core_ctrl_reg stateleri kontrol eden sinyal
CTRL_IDLE:
begin
if (init) // AES Mainden geliyor. 1 ise initial işlem.
begin //if init=1
init_state = 1'b1; //init_state is 1 so muxed_sboxw = keymem_sboxw;
ready_new = 1'b0; //ready sinyali kapatılıyor, aes main yeni bir blok gönderemeyecek
ready_we = 1'b1; //ready sinyalinin yazılmasını izin veriliyor
result_valid_new = 1'b0; // CTRL_NEXT sonunda 1 olacak, aes main'e result'ın hazır olduğunu bildirmek için kullanılıyor
result_valid_we = 1'b1; // result_valid'in yazılmasını kontrol ediyor
aes_core_ctrl_new = CTRL_INIT; // next state INIT olarak atandı
aes_core_ctrl_we = 1'b1; //state değişikliğine izin veren sinyal
end
else if (next) // init 1 değil ve next 1 ise bir sonraki işlem ile devam ediyor
begin
init_state = 1'b0; // bu durumda sbox'ı encipher module kullanacak
ready_new = 1'b0; //ready sinyali kapatılıyor, aes main yeni bir blok gönderemeyecek
ready_we = 1'b1; //ready sinyalinin yazılmasını izin veriliyor
result_valid_new = 1'b0; // result hazır değil
result_valid_we = 1'b1; // result_valid'in üzerine yeni değerin yazılmasına izin veriliyor
aes_core_ctrl_new = CTRL_NEXT; //next state CTRL_NEXT olarak ayarlandı
aes_core_ctrl_we = 1'b1; // state control register'ının üzerine yazılmasına izin verildi
end
end
CTRL_INIT:
begin
init_state = 1'b1; //sbox'ı key modülü kullanacak
if (key_ready) //eğer key_mem modülünden key'in hazır olduğuna dair sinyal geldiyse
begin
ready_new = 1'b1; //ready sinyali 1 olacak ve AES main'e ready sinyali gönderilecek, bu durumda yeni data okunabilir
ready_we = 1'b1;
aes_core_ctrl_new = CTRL_IDLE; //State IDLE olarak ayarlanacak
aes_core_ctrl_we = 1'b1;
end
end
CTRL_NEXT:
begin
init_state = 1'b0; //sbox'ı encipher modülü kullancak
if (muxed_ready) //muxed_ready encipher ya da dechipher yapılmasına göre set ediliyor,
begin //ben encipher varsaydım, bu durumda encipher işini bitirdiyse 1 olacak
ready_new = 1'b1; // CTRL_INIT'teki işlemlerin aynıları yapılıyor
ready_we = 1'b1;
result_valid_new = 1'b1;
result_valid_we = 1'b1;
aes_core_ctrl_new = CTRL_IDLE;
aes_core_ctrl_we = 1'b1;
end
end
default:
begin
end
endcase // case (aes_core_ctrl_reg)
end // aes_core_ctrl
endmodule // aes_core
//======================================================================
// EOF aes_core.v
//======================================================================
AES Key Module
`default_nettype none
module aes_key_mem(
input wire clk,
input wire reset_n,
input wire [255 : 0] key, // key AES_CORE'dan geliyor
input wire keylen, // 128 veya 256 bit
input wire init, // başlangıç sinyali
input wire [3 : 0] round, //round bilgisi AES_ENCIPHER ile senkronize ilerliyor
output wire [127 : 0] round_key, //O raundun keyi gönderiliyor
output wire ready, //Keyin hazır olduğu bilgisi
output wire [31 : 0] sboxw, //subbytes işlemi için 32bitlik blok gönderiliyor
input wire [31 : 0] new_sboxw //subbyte yapılan sonuç geliyor
);
//----------------------------------------------------------------
// Parameters.
//----------------------------------------------------------------
localparam AES_128_BIT_KEY = 1'h0;
localparam AES_256_BIT_KEY = 1'h1;
localparam AES_128_NUM_ROUNDS = 10;
localparam AES_256_NUM_ROUNDS = 14;
localparam CTRL_IDLE = 3'h0; // main fsm için stateler
localparam CTRL_INIT = 3'h1;
localparam CTRL_GENERATE = 3'h2;
localparam CTRL_DONE = 3'h3;
//----------------------------------------------------------------
// Registers.
//----------------------------------------------------------------
reg [127 : 0] key_mem [0 : 14];
reg [127 : 0] key_mem_new;
reg key_mem_we;
reg [127 : 0] prev_key0_reg;
reg [127 : 0] prev_key0_new;
reg prev_key0_we;
reg [127 : 0] prev_key1_reg;
reg [127 : 0] prev_key1_new;
reg prev_key1_we;
reg [3 : 0] round_ctr_reg;
reg [3 : 0] round_ctr_new;
reg round_ctr_rst;
reg round_ctr_inc;
reg round_ctr_we;
reg [2 : 0] key_mem_ctrl_reg;
reg [2 : 0] key_mem_ctrl_new;
reg key_mem_ctrl_we;
reg ready_reg;
reg ready_new;
reg ready_we;
reg [7 : 0] rcon_reg;
reg [7 : 0] rcon_new;
reg rcon_we;
reg rcon_set;
reg rcon_next;
//----------------------------------------------------------------
// Wires.
//----------------------------------------------------------------
reg [31 : 0] tmp_sboxw;
reg round_key_update;
reg [127 : 0] tmp_round_key;
//----------------------------------------------------------------
// Concurrent assignments for ports.
//----------------------------------------------------------------
assign round_key = tmp_round_key; //output portlarına bağlantılar
assign ready = ready_reg;
assign sboxw = tmp_sboxw;
//----------------------------------------------------------------
// reg_update
//
// Update functionality for all registers in the core.
// All registers are positive edge triggered with asynchronous
// active low reset. All registers have write enable.
//----------------------------------------------------------------
always @ (posedge clk or negedge reset_n)
begin: reg_update
integer i;
if (!reset_n) //reset sinyali geldiyse, her şey 0'lanıp IDLE state'e geçiyor. init sinyalini beklemeye başlıyor
begin
for (i = 0 ; i <= AES_256_NUM_ROUNDS ; i = i + 1)
key_mem [i] <= 128'h0;
ready_reg <= 1'b0;
rcon_reg <= 8'h0;
round_ctr_reg <= 4'h0;
prev_key0_reg <= 128'h0;
prev_key1_reg <= 128'h0;
key_mem_ctrl_reg <= CTRL_IDLE;
end
else
begin
if (ready_we) //key hazır olduğunda CTRL_DONE State'inde 1 yapılıyor
ready_reg <= ready_new; //keyin hazır olduğu bilgisi reg'e atanıyor, buradan AES_CORE'a gönderilecek
if (rcon_we) //bir sonraki rcon kolonu değerinin yazılmasına ya da 0'lanmasına izin veriyor
rcon_reg <= rcon_new;
if (round_ctr_we) // round counter'ı arttığında ya da 0'lanması gerektiğinde 1 oluyor ve yeni değeri reg'e yazılıyor
round_ctr_reg <= round_ctr_new;
if (key_mem_we) //round key update edileceği zaman round_key_update kont içinde 1 yapılıyor
key_mem[round_ctr_reg] <= key_mem_new; // oluşturulan round keyi key_mem'in gösterdiği round'un olduğu yere yazılıyor
if (prev_key0_we) //256 bit olduğunda kullanıyoruz
prev_key0_reg <= prev_key0_new;
if (prev_key1_we) //yeni key oluştuğu zaman 1 yapılıyor,
prev_key1_reg <= prev_key1_new; //böylelikle yeni keyin yedeği alınıyor, bir sonraki state'te kullanılacak
if (key_mem_ctrl_we) // 1 olduğunda state değişikliği yapılacak
key_mem_ctrl_reg <= key_mem_ctrl_new;
end
end // reg_update
//----------------------------------------------------------------
// key_mem_read
//
// Combinational read port for the key memory.
//----------------------------------------------------------------
always @* //key_mem içinde bütün raundlara ait keyler var, round değerine göre tmp_round_key'e alınıyor
begin : key_mem_read //round_key üzerinden AES_CORE'a gönderiliyor (128 bit)
tmp_round_key = key_mem[round];
end // key_mem_read
//----------------------------------------------------------------
// round_key_gen
//
// The round key generator logic for AES-128 and AES-256.
//----------------------------------------------------------------
always @*
begin: round_key_gen
reg [31 : 0] w0, w1, w2, w3, w4, w5, w6, w7;
reg [31 : 0] k0, k1, k2, k3;
reg [31 : 0] rconw, rotstw, tw, trw;
// Default assignments.
key_mem_new = 128'h0;
key_mem_we = 1'b0;
prev_key0_new = 128'h0;
prev_key0_we = 1'b0;
prev_key1_new = 128'h0;
prev_key1_we = 1'b0;
k0 = 32'h0;
k1 = 32'h0;
k2 = 32'h0;
k3 = 32'h0;
rcon_set = 1'b1;
rcon_next = 1'b0;
// Extract words and calculate intermediate values.
// Perform rotation of sbox word etc.
w0 = prev_key0_reg[127 : 096];//bu kısım 256 bit için
w1 = prev_key0_reg[095 : 064];
w2 = prev_key0_reg[063 : 032];
w3 = prev_key0_reg[031 : 000];
w4 = prev_key1_reg[127 : 096];//128 bit key için bu kısımdan itibaren kullanılıyor
w5 = prev_key1_reg[095 : 064];// bir önceki roundun keyi 4 kolon halinde alınıyor
w6 = prev_key1_reg[063 : 032];
w7 = prev_key1_reg[031 : 000];
rconw = {rcon_reg, 24'h0}; // rcon matrix için kolonların değeri oluşturuluyor. rcon_reg içindeki değer 01,02,04,08 şeklinde artacak
tmp_sboxw = w7; //bir önceki keyin son kolonu subbytes işlemi için sbox module gönderiliyor
rotstw = {new_sboxw[23 : 00], new_sboxw[31 : 24]}; // subbytes sonucu geldikten sonra column rotate yapılıyor
trw = rotstw ^ rconw; //rotate sonrası xor işlemi, yeni keyin hesaplanması için gereken kolon hazırlanıyor
tw = new_sboxw;
// Generate the specific round keys.
if (round_key_update) // CTRL_GENERATE state'inde 1 yapılıyor, bu noktada yeni roundun keyi oluşturulmaya başlanıyor
begin
rcon_set = 1'b0; //rcon matrisinin ilk satırındaki değerlerin sırasıyla 1 2 4 8 şeklinde artışını kontrol eden sinyal, default 0
key_mem_we = 1'b1; //keyin yazılmasına izin veren sinyal, değişiklikler bu sinyal 1 olduğunda yapılıyor
case (keylen) //keyin büyüklüğü
AES_128_BIT_KEY: //128 bit key için
begin
if (round_ctr_reg == 0) //eğer ilk roundsa
begin
key_mem_new = key[255 : 128]; //AES_CORE'dan gelen key alınıyor, 128 bit olduğu için 128-256 arası bitler kullanılıyor
prev_key1_new = key[255 : 128]; //bir önceki state'teki kolonlar yeni keyin oluşturulması sırasında kullanılacak
// o yüzden bir yedeği alınıyor
prev_key1_we = 1'b1; // prev_key'in yazılması için izin sinyali
rcon_next = 1'b1; // bir sonraki rcon değerinin hesaplanması için izin sinyali
end
else // eğer ilk round değilse bir önceki roundda oluşturulan keyin son kolonu alınarak yeni key oluşturulmaya başlanıyor
begin
k0 = w4 ^ trw; //yeni keyin ilk kolonu için hesaplanan kolon(trw'de) önceki keyin ilk kolonu(w4'te) ile xorlanıyor, yeni keyin ilk kolonu oluşuyor
k1 = w5 ^ w4 ^ trw; //yeni keyin ilk kolonu ile (k0=w4^trv) eski keyin 2. kolonu xorlanıp yeni keyin 2. kolonu oluşturuluyor
k2 = w6 ^ w5 ^ w4 ^ trw; // yeni keyin 2. kolonu ile (k1=w5^w4^trw), eski keyin 3. kolonu xorlanıp yeni keyin 3. kolonu oluşturuluyor
k3 = w7 ^ w6 ^ w5 ^ w4 ^ trw;// yeni keyin 3. kolonu ile (k2=w6^w5^w4^trw), eski keyin 4. kolonu xorlanıp yeni keyin 4. kolonu oluşturuluyor
key_mem_new = {k0, k1, k2, k3}; // kolonlar birleştiriliyor ve yeni key tamamlanıyor
prev_key1_new = {k0, k1, k2, k3}; //yeni keyin yedeği bir sonraki state'te kullanılmak için yedekleniyor
prev_key1_we = 1'b1; //previous key yedeğinin yapılması için izin sinyali
rcon_next = 1'b1; // bir sonraki rcon değerinin hesaplanması için izin sinyali
end
end
AES_256_BIT_KEY:
begin
if (round_ctr_reg == 0) //0 ve 1 initial roundlar
begin
key_mem_new = key[255 : 128];
prev_key0_new = key[255 : 128];
prev_key0_we = 1'b1;
end
else if (round_ctr_reg == 1)
begin
key_mem_new = key[127 : 0];
prev_key1_new = key[127 : 0];
prev_key1_we = 1'b1;
rcon_next = 1'b1;
end
else
begin
if (round_ctr_reg[0] == 0) //roundun tek veya çift sayıda olmasına bağlı olarak ilk 128 ve ikinci 128 bitlik
begin //kısım üzerinde işlem yapıyor
k0 = w0 ^ trw;
k1 = w1 ^ w0 ^ trw;
k2 = w2 ^ w1 ^ w0 ^ trw;
k3 = w3 ^ w2 ^ w1 ^ w0 ^ trw;
end
else
begin
k0 = w0 ^ tw;
k1 = w1 ^ w0 ^ tw;
k2 = w2 ^ w1 ^ w0 ^ tw;
k3 = w3 ^ w2 ^ w1 ^ w0 ^ tw;
rcon_next = 1'b1; //ikinci 128bitlik kısım üzerinde işlem yaptıktan sonra bir sonraki rcon değerine geçmesine izin veriyor
end
// Store the generated round keys.
key_mem_new = {k0, k1, k2, k3};
prev_key1_new = {k0, k1, k2, k3};
prev_key1_we = 1'b1;
prev_key0_new = prev_key1_reg;
prev_key0_we = 1'b1;
end
end
default:
begin
end
endcase // case (keylen)
end
end // round_key_gen
//----------------------------------------------------------------
// rcon_logic
//
// Caclulates the rcon value for the different key expansion
// iterations.
//----------------------------------------------------------------
always @*
begin : rcon_logic
reg [7 : 0] tmp_rcon;
rcon_new = 8'h00; //initial değerler
rcon_we = 1'b0; //rcon_Set ya da rcon_next sinyali 1 olmadıkça değişmiyor,
tmp_rcon = {rcon_reg[6 : 0], 1'b0} ^ (8'h1b & {8{rcon_reg[7]}});// MSB 0 iken sadece bir kere sola shift eder (2 ile çarpma)
//MSB 1 olduğunda 0x1b ile xorlanıyor
if (rcon_set)
begin
rcon_new = 8'h8d; //rcon ilk değer 01 olması lazım bunu burada sağlıyor. bu şekilde initial ediliyor 1000 1101
rcon_we = 1'b1; // ilk tmp_rcon hesabında(283. satır) {rcon_reg[6 : 0], 1'b0} = 0001 1010
end // {8{rcon_reg[7]} -->(1111 1111) bu değer 0001 1011 ile & --> 0001 1011
// 283 satır bu durumda 0001 1010 ^ 0001 1011 = 0000 0001
if (rcon_next) // her bir state için gereken 01 02 04 08 değerleri tmp_rcon içinde üretilmişti, burada next sinyali geldiyese
begin // we 1 yapılarak rcon_new'un üzerine yazılmasını sağlanıyor
rcon_new = tmp_rcon[7 : 0];
rcon_we = 1'b1; //değişiklik sinyali gelmedikçe bu always bloğu içinde 0 olarak assign ediliyor
end
end
//----------------------------------------------------------------
// round_ctr
//
// The round counter logic with increase and reset.
//----------------------------------------------------------------
always @*
begin : round_ctr
round_ctr_new = 4'h0;
round_ctr_we = 1'b0;
if (round_ctr_rst) // CTRL_INIT state'inde 1 yapılıyor, böylelikle yeni blok için counter 0'lanıyor
begin
round_ctr_new = 4'h0;
round_ctr_we = 1'b1;
end
else if (round_ctr_inc) //her bir roundda işlem bittikten ve o raundun keyi hazır olduğunda CTRL_GENERATE statei 1 yapıyor
begin
round_ctr_new = round_ctr_reg + 1'b1; //counter arttırılıyor
round_ctr_we = 1'b1; // yazılmasına izin veriyor
end
end
//----------------------------------------------------------------
// key_mem_ctrl
//
//
// The FSM that controls the round key generation.
//----------------------------------------------------------------
always @* // main FSM
begin: key_mem_ctrl
reg [3 : 0] num_rounds;
// Default assignments. // caseler içinde değiştirilmeyen kontrol sinyalleri için default değerler
ready_new = 1'b0;
ready_we = 1'b0;
round_key_update = 1'b0;
round_ctr_rst = 1'b0;
round_ctr_inc = 1'b0;
key_mem_ctrl_new = CTRL_IDLE;
key_mem_ctrl_we = 1'b0;
if (keylen == AES_128_BIT_KEY) // 128 veya 256 bit keye göre round sayısı
num_rounds = AES_128_NUM_ROUNDS; //10 round
else
num_rounds = AES_256_NUM_ROUNDS; //14 round
case(key_mem_ctrl_reg) //key_mem_ctrl_reg fsm'nin statelerini belirleyen ana değişken
CTRL_IDLE:
begin
if (init) //init sinyali geldiyse. IDLE state içerisindeyse init sinyali önemli, diğer durumlarda gelen sinyale bakmıyor
begin
ready_new = 1'b0; //ready 0 yapılarak keyin hazır olmadığı belirtiliyor
ready_we = 1'b1; //we 1 yapılarak ready sinyalinin yazılmasına izin veriyor
key_mem_ctrl_new = CTRL_INIT; //state INIT olarak ayarlanıyor
key_mem_ctrl_we = 1'b1; // state değişikliği için we sinyali 1 yapılıyor
end
end
CTRL_INIT: //initialization state
begin
round_ctr_rst = 1'b1; //round counter'ın sıfırlanması için control sinyali. 1 olduğunda, yeni counter değeri 0
// olarak ayarlanacak ve round_ctr_we sinyali 1 yapılıp reg'e yazılacak
key_mem_ctrl_new = CTRL_GENERATE; //state CTRL_GENERATE olarak ayarlanacak
key_mem_ctrl_we = 1'b1; //state değişikliği için we sinyali 1 yapılacak
end
CTRL_GENERATE: //key generation state
begin
round_ctr_inc = 1'b1; //round counter'ın artmasına izin verecek
round_key_update = 1'b1; //roundun keyinin oluşturulmasına başlanması için kontrol sinyali. 1 olduğunda işlemler başlayacak
if (round_ctr_reg == num_rounds) //10 round olup olmadığının kontrolu burada
begin
key_mem_ctrl_new = CTRL_DONE; //10 round olduğunda state CTRL_DONE olarak değişecek
key_mem_ctrl_we = 1'b1; // state değişikliğine izin verecek
end
end
CTRL_DONE: // bu round için keyin bittiğini gösteren state
begin
ready_new = 1'b1;//keyin hazır olduğunu belirtiyor, AES_CORE'a gönderilecek
ready_we = 1'b1;//ready sinyalinin yazılmasına izin veren kontrol sinyali
key_mem_ctrl_new = CTRL_IDLE; //yeni rounda başlamak için IDLE state'e geri dönüyor
key_mem_ctrl_we = 1'b1; //state değişikliğine izin verecek
end
default:
begin
end
endcase // case (key_mem_ctrl_reg)
end // key_mem_ctrl
endmodule // aes_key_mem
//======================================================================
// EOF aes_key_mem.v
//======================================================================
AES Encipher Module
//======================================================================
//
// aes_encipher_block.v
// --------------------
// The AES encipher round. A pure combinational module that implements
// the initial round, main round and final round logic for
// enciper operations.
//
//
// Author: Joachim Strombergson
// Copyright (c) 2013, 2014, Secworks Sweden AB
// All rights reserved.
//
`default_nettype none
module aes_encipher_block(
input wire clk,
input wire reset_n,
input wire next, //AES_CORE'dan geliyor, yeni işleme başlama komutu
input wire keylen, // key 128 bit mi 256 bit mi olacak
output wire [3 : 0] round, // round bilgisini AES_CORE'a gönderiyor, ona göre
input wire [127 : 0] round_key, //round key gelecek
output wire [31 : 0] sboxw, // Subbytes için AES_CORE'a 32 bit veri gidiyor
input wire [31 : 0] new_sboxw, // Subbytes yapılmış veri geliyor
input wire [127 : 0] block, //şifrelenecek 128 bit veri geliyor
output wire [127 : 0] new_block, //şifrelenmiş hali AES_CORE'a gönderiliyor
output wire ready // yeni 128 bitlik blok için hazır sinyali
);
//----------------------------------------------------------------
// Internal constant and parameter definitions.
//----------------------------------------------------------------
localparam AES_128_BIT_KEY = 1'h0;
localparam AES_256_BIT_KEY = 1'h1;
localparam AES128_ROUNDS = 4'ha;
localparam AES256_ROUNDS = 4'he;
localparam NO_UPDATE = 3'h0; //yapılan işlemler için stateler
localparam INIT_UPDATE = 3'h1;
localparam SBOX_UPDATE = 3'h2;
localparam MAIN_UPDATE = 3'h3;
localparam FINAL_UPDATE = 3'h4;
localparam CTRL_IDLE = 2'h0; //main FSM stateleri
localparam CTRL_INIT = 2'h1;
localparam CTRL_SBOX = 2'h2;
localparam CTRL_MAIN = 2'h3;
//----------------------------------------------------------------
// Round functions with sub functions.
//----------------------------------------------------------------
function [7 : 0] gm2(input [7 : 0] op); //galois field matrixte 2 ile çarpma işlemi için gerekli, mixcolumns stepte kullanılıyor
begin
gm2 = {op[6 : 0], 1'b0} ^ (8'h1b & {8{op[7]}});// ({8{op[7]}}--> 8 tane op[7]), op[7] 1'se 0x1b ile xorla değilse xorlama
end
endfunction // gm2
function [7 : 0] gm3(input [7 : 0] op); //galois field matrixte 3 ile çarpma işlemi için gerekli, mixcolumns stepte kullanılıyor
begin // gf(2) hesaplanıp kendisi ile xorlanıyor
gm3 = gm2(op) ^ op;
end
endfunction // gm3
function [31 : 0] mixw(input [31 : 0] w); //mixcolumns step için yapılan galois field matrix çarpımı
reg [7 : 0] b0, b1, b2, b3; //b kolon içindeki satırlar
reg [7 : 0] mb0, mb1, mb2, mb3; //w içinde kolon alınıyor
begin
b0 = w[31 : 24];
b1 = w[23 : 16];
b2 = w[15 : 08];
b3 = w[07 : 00];
mb0 = gm2(b0) ^ gm3(b1) ^ b2 ^ b3;
mb1 = b0 ^ gm2(b1) ^ gm3(b2) ^ b3;
mb2 = b0 ^ b1 ^ gm2(b2) ^ gm3(b3);
mb3 = gm3(b0) ^ b1 ^ b2 ^ gm2(b3);
mixw = {mb0, mb1, mb2, mb3}; // sonuç tekrar kolona çevriliyor
end
endfunction // mixw
function [127 : 0] mixcolumns(input [127 : 0] data); //mixcolumns step
reg [31 : 0] w0, w1, w2, w3; //w içerisinde 4 kolon alınıyor mixw functiona gönderilip
reg [31 : 0] ws0, ws1, ws2, ws3; // galois field ile çarpımı yapılıyor
begin
w0 = data[127 : 096]; //128 bit data 32 bitlik 4 kolona çevriliyor
w1 = data[095 : 064];
w2 = data[063 : 032];
w3 = data[031 : 000];
ws0 = mixw(w0);
ws1 = mixw(w1);
ws2 = mixw(w2);
ws3 = mixw(w3);
mixcolumns = {ws0, ws1, ws2, ws3}; // mixcolumns işlemi sonunda 32 bitlik kolonlar birleştiriliyor
end
endfunction // mixcolumns
function [127 : 0] shiftrows(input [127 : 0] data); //shiftrows step
reg [31 : 0] w0, w1, w2, w3; // 1. satır aynı kalıyor
reg [31 : 0] ws0, ws1, ws2, ws3; // 2. satır 1 kere, 3. satır 2 kere, 4. satır 3 kere rotate ediliyor
begin
w0 = data[127 : 096];
w1 = data[095 : 064];
w2 = data[063 : 032];
w3 = data[031 : 000];
ws0 = {w0[31 : 24], w1[23 : 16], w2[15 : 08], w3[07 : 00]};
ws1 = {w1[31 : 24], w2[23 : 16], w3[15 : 08], w0[07 : 00]};
ws2 = {w2[31 : 24], w3[23 : 16], w0[15 : 08], w1[07 : 00]};
ws3 = {w3[31 : 24], w0[23 : 16], w1[15 : 08], w2[07 : 00]};
shiftrows = {ws0, ws1, ws2, ws3}; // rotate edilen satırlar birleştiriliyor
end
endfunction // shiftrows
function [127 : 0] addroundkey(input [127 : 0] data, input [127 : 0] rkey); //addroundkey step
begin
addroundkey = data ^ rkey; // o raundun keyi ile data xorlanıyor
end
endfunction // addroundkey
//----------------------------------------------------------------
// Registers including update variables and write enable.
//----------------------------------------------------------------
reg [1 : 0] sword_ctr_reg;
reg [1 : 0] sword_ctr_new;
reg sword_ctr_we;
reg sword_ctr_inc;
reg sword_ctr_rst;
reg [3 : 0] round_ctr_reg;
reg [3 : 0] round_ctr_new;
reg round_ctr_we;
reg round_ctr_rst;
reg round_ctr_inc;
reg [127 : 0] block_new;
reg [31 : 0] block_w0_reg;
reg [31 : 0] block_w1_reg;
reg [31 : 0] block_w2_reg;
reg [31 : 0] block_w3_reg;
reg block_w0_we;
reg block_w1_we;
reg block_w2_we;
reg block_w3_we;
reg ready_reg;
reg ready_new;
reg ready_we;
reg [1 : 0] enc_ctrl_reg;
reg [1 : 0] enc_ctrl_new;
reg enc_ctrl_we;
//----------------------------------------------------------------
// Wires.
//----------------------------------------------------------------
reg [2 : 0] update_type;
reg [31 : 0] muxed_sboxw; //32 bitlik geçici sbox registerı, bunun üzerinden subbytes işlemi yapılıyor.
//----------------------------------------------------------------
// Concurrent connectivity for ports etc.
//----------------------------------------------------------------
assign round = round_ctr_reg;
assign sboxw = muxed_sboxw;
assign new_block = {block_w0_reg, block_w1_reg, block_w2_reg, block_w3_reg};
assign ready = ready_reg;
//----------------------------------------------------------------
// reg_update
//
// Update functionality for all registers in the core.
// All registers are positive edge triggered with asynchronous
// active low reset. All registers have write enable.
//----------------------------------------------------------------
always @ (posedge clk or negedge reset_n)
begin: reg_update
if (!reset_n)
begin
block_w0_reg <= 32'h0;
block_w1_reg <= 32'h0;
block_w2_reg <= 32'h0;
block_w3_reg <= 32'h0;
sword_ctr_reg <= 2'h0;
round_ctr_reg <= 4'h0;
ready_reg <= 1'b1;
enc_ctrl_reg <= CTRL_IDLE;
end
else
begin
if (block_w0_we) //4 parçaya bölünen block her bir işlemden sonra we 1 olduğunda sonucun yazılması
block_w0_reg <= block_new[127 : 096]; // sağlanıyor
//SBOX_UPDATE adımında bu 4'e bölünen her kısımda aynı veri var
if (block_w1_we) // hangi bloğun we sinyali 1 ise ona yazılacak
block_w1_reg <= block_new[095 : 064]; // diğer adımlarda 128 bit birden işleme alındığında bütün we sinyalleri 1 olduğundan
// tek seferde 4 blok da yazılıyor
if (block_w2_we)
block_w2_reg <= block_new[063 : 032];
if (block_w3_we)
block_w3_reg <= block_new[031 : 000];
if (sword_ctr_we) // 1 olduğunda SBOX için yeni counter değeri reg'e atanıyor. 0'lanıyor ya da arttırılan yeni değeri atanıyor
sword_ctr_reg <= sword_ctr_new;
if (round_ctr_we) //counter arttıktan sonra ya da 0'landığında we 1 olacak, yeni counter değeri reg'e atanabilecek
round_ctr_reg <= round_ctr_new;
if (ready_we) //eğer we 1 olursa ready_reg üzerinden AES_CORE'a ready signalinin yeni değerinin gönderilmesini sağlayacak
ready_reg <= ready_new;
if (enc_ctrl_we) //FSM'de bir sonraki state'i belirliyor we 1 olduğunda state değişiyor
enc_ctrl_reg <= enc_ctrl_new;
end
end // reg_update
//----------------------------------------------------------------
// round_logic
//
// The logic needed to implement init, main and final rounds.
//----------------------------------------------------------------
always @*
begin : round_logic
reg [127 : 0] old_block, shiftrows_block, mixcolumns_block;
reg [127 : 0] addkey_init_block, addkey_main_block, addkey_final_block;
block_new = 128'h0;
muxed_sboxw = 32'h0;
block_w0_we = 1'b0;
block_w1_we = 1'b0;
block_w2_we = 1'b0;
block_w3_we = 1'b0;
old_block = {block_w0_reg, block_w1_reg, block_w2_reg, block_w3_reg};
shiftrows_block = shiftrows(old_block);
mixcolumns_block = mixcolumns(shiftrows_block);
addkey_init_block = addroundkey(block, round_key); //128 bitlik gelen ilk data addroundkey'e gönderiliyor, sonuç addkey_init_block'ta saklanıyor
addkey_main_block = addroundkey(mixcolumns_block, round_key);
addkey_final_block = addroundkey(shiftrows_block, round_key);
case (update_type)
INIT_UPDATE:
begin
block_new = addkey_init_block; // eğer initial stepse bu stepte addroundkey işlemi sonucunda çıkan addkey_init_block'taki veri block_new'e aktarılıyor
//gelen 128bitlik main block, round için gelen key ile xorlanıyor (AddRoundKey step)
//128 bitlik blok "block" değişkeni içinde geldi. addroundkey functionına gönderildi.
//addkey_init_block içerisinde işlemin sonucu tutuluyor, o da burada block_new'e aktarıldı
block_w0_we = 1'b1; //SBOX işlemini 32bitlik 4 blok halinde yapacak o yüzden block 4 parçaya bölünecek
block_w1_we = 1'b1; // sonuç 4 parça halinde w0-w3 içinde tutulacak, sonrasında birleştirilecek, üzerine yazılabilmesi için
block_w2_we = 1'b1; //we sinyalleri 1 yapıldı
block_w3_we = 1'b1;
end
SBOX_UPDATE: //eğer subbytes step ise block_new'e sbox'ta değiştirilen değerler yükleniyor
begin //new_sboxw AES_CORE'dan gelen Subbytes yapılmış 32bitlik veri
block_new = {new_sboxw, new_sboxw, new_sboxw, new_sboxw}; //32 bitlik 4 block halinde değişim yapılıyor
// burada Subbytes yapılıp gelen 32bitlik değerin aynısı 4 bloğa da yazılıyor
case (sword_ctr_reg) //Counter değerine göre her seferinde 1 tane 32 bitlik kısmın Subbytes yapmasını sağlıyor
2'h0:
begin
muxed_sboxw = block_w0_reg; //muxed_sboxw AES_CORE'e bağlı olan sboxw'a assign ediliyor. AES_CORE bunu AES_SBOX'a
block_w0_we = 1'b1; // gönderip subbytes işleminin yapılmasını sağlıyor
end
2'h1:
begin
muxed_sboxw = block_w1_reg; // hangi blok işleme alınacaksa onun we signali 1 oluyor
block_w1_we = 1'b1; // diğerlerine bu always bloğunun başında default değer olarak 1 atanıyor
end
2'h2:
begin
muxed_sboxw = block_w2_reg;
block_w2_we = 1'b1;
end
2'h3:
begin
muxed_sboxw = block_w3_reg;
block_w3_we = 1'b1;
end
endcase // case (sbox_mux_ctrl_reg)
end
MAIN_UPDATE: //initial step sonrası 9 defa tekrar edecek kısım için, block_new'e addkey_main_block yükleniyor
begin
block_new = addkey_main_block;
//muxed_sboxw'tan gelen subbytes yapılış değerler, ilk olarak block_w0-w3_reg üzerinden old_block'a yazılıyor
// old_block shiftrows function'a gönderiliyor, shift işlemi sonrası sonuç shiftrows_block'ta tutuluyor
// shiftrows_block mixcolumns function'a gönderiliyor, sonuç mixcolumns_block'ta tutuluyor
//mixcolumns_block addroundkey function'a gönderiliyor, sonuç addkey_main_block'a geliyor
//burada da sonuç block_new'e atanıyor,
block_w0_we = 1'b1; //4 we sinyali de 1 yapılıyor, böylelikle block_new 4 parçaya bölünerek block_w0-w3_reg'e atanabilecek
block_w1_we = 1'b1; //bir sonraki adımda block_w0-w3_reg'den alınan 4 parça kullanılacak
block_w2_we = 1'b1;
block_w3_we = 1'b1;
end
FINAL_UPDATE: // main step sonrası son adım için block_new'e addkey_final_block yükleniyor
begin
block_new = addkey_final_block; // mixcolumns yapmadan addroundkey function'ı shiftrows_block'ta saklı sonuç üzerinden çağırıyor
block_w0_we = 1'b1; // geri kalan kısımlar MAIN_UPDATE ile aynı çalışıyor
block_w1_we = 1'b1;
block_w2_we = 1'b1;
block_w3_we = 1'b1;
end
default:
begin
end
endcase // case (update_type)
end // round_logic
//----------------------------------------------------------------
// sword_ctr
//
// The subbytes word counter with reset and increase logic.
//----------------------------------------------------------------
always @*
begin : sword_ctr
sword_ctr_new = 2'h0;
sword_ctr_we = 1'b0;
if (sword_ctr_rst) //Eğer Sbox işlemi için ilk 32 bit alınacaksa counter resetleniyor
begin
sword_ctr_new = 2'h0; //Counterın yeni değeri 0 olarak set ediliyor
sword_ctr_we = 1'b1; // we 1 yapılarak 0 olarak set edilen counter değerinin reg'e yazılmasına izin veriyor
end
else if (sword_ctr_inc) //SBOX_UPDATE kısmında sırası ile 4 bloğun da işleme alınması için gereken counterın artmasını sağlayan kontrol sinyali
begin
sword_ctr_new = sword_ctr_reg + 1'b1;
sword_ctr_we = 1'b1;
end
end // sword_ctr
//----------------------------------------------------------------
// round_ctr
//
// The round counter with reset and increase logic.
//----------------------------------------------------------------
always @*
begin : round_ctr
round_ctr_new = 4'h0;
round_ctr_we = 1'b0;
if (round_ctr_rst)
begin
round_ctr_new = 4'h0;
round_ctr_we = 1'b1;
end
else if (round_ctr_inc) // sinyal 1 geldiğinde counter reg içinde olan bir önceki değerin üzerine 1 ekleyip new'e atıyor.
begin
round_ctr_new = round_ctr_reg + 1'b1;
round_ctr_we = 1'b1; // we 1 olunca'da yeni değerin reg'e yazılması sağlanıyor
end
end // round_ctr
//----------------------------------------------------------------
// encipher_ctrl
//
// The FSM that controls the encipher operations.
//----------------------------------------------------------------
always @* // Main FSM
begin: encipher_ctrl
reg [3 : 0] num_rounds; //counts the rounds (128 bit için 10)
// Default assignments. // enc_ctrl_reg FSM'nin statelerini kontrol eden variable
sword_ctr_inc = 1'b0; // enc_ctrl_reg'e göre assign edilen variablelar dışındakiler buradaki değerleri alıyor
sword_ctr_rst = 1'b0;
round_ctr_inc = 1'b0;
round_ctr_rst = 1'b0;
ready_new = 1'b0;
ready_we = 1'b0;
update_type = NO_UPDATE;
enc_ctrl_new = CTRL_IDLE;
enc_ctrl_we = 1'b0;
if (keylen == AES_256_BIT_KEY)
begin
num_rounds = AES256_ROUNDS;
end
else
begin
num_rounds = AES128_ROUNDS; //128 bit için raund sayısı 10
end
case(enc_ctrl_reg)
CTRL_IDLE:
begin
if (next) //1 ise işlem başlayacak
begin
round_ctr_rst = 1'b1; //işleme başladığı zaman round counter 0'lanıyor
ready_new = 1'b0; // dışarıya ready signalinin 0 olarak gönderilmesini sağlıyor, böylece AES_CORE'dan yeni
ready_we = 1'b1; //bilgi gelmeyecek, ready sinyalinin yeni değerinin yazılabilmesi için we signali 1 yapıldı
enc_ctrl_new = CTRL_INIT; //IDLE stateten INIT state geçişi saglıyor
enc_ctrl_we = 1'b1; //kontrol sinyali, 1 olduğunda yeni state enc_ctrl_reg'e new üzerinden yazılacak
end
end
CTRL_INIT:
begin
round_ctr_inc = 1'b1; //round counterın artması için gereken kontrol sinyali, 1 olduğunda counter'ı 1 arttıracak işlemi yapacak
sword_ctr_rst = 1'b1; // SBOX işlemi 4 stepte yapılıyor, 32 bitlik 4 blok şeklinde. burada counter 0'lanarak ilk adımdan başlaması sağlanıyor
// sbox Counter'ını 0'lamak için gereken sinyal
update_type = INIT_UPDATE; //yapılan işlemin hangisi olduğunu tutan control değişkeni. Initial stepte ilk init update'i yapacağı bloğa gidecek
enc_ctrl_new = CTRL_SBOX; //INIT stateten SBOX statee geçişi sağlıyor
enc_ctrl_we = 1'b1; //kontrol sinyali, 1 olduğunda yeni state enc_ctrl_reg'e new üzerinden yazılacak
end
CTRL_SBOX:
begin
sword_ctr_inc = 1'b1; //SBOX 4 adımda yapılacak, INIT state'te counter 0'lanmıştı, burada counter arttırılacak
update_type = SBOX_UPDATE; //yapılacak işi SBOX_UPDATE olarak ayarladı
if (sword_ctr_reg == 2'h3) //4 sbox da bitince bir sonraki state CTRL_MAIN'e geçecek. Diğer durumda CTRL_SBOX state devam edecek
begin //SBOX_UPDATE işlemi de yapılmaya devam edecek
enc_ctrl_new = CTRL_MAIN;
enc_ctrl_we = 1'b1; //kontrol sinyali, 1 olduğunda yeni state enc_ctrl_reg'e new üzerinden yazılacak
end
end
CTRL_MAIN:// Subbytes, shiftrows, mixcolumns ve addroundkey 10 defa tekrar edilecek, 10 tekrarda mixcolumns işlemi olmayacak
begin
sword_ctr_rst = 1'b1; // her round başında sbox counterı sıfırlanacak, o yüzden reset sinyali 1 oluyor
round_ctr_inc = 1'b1; // her roundda counter 1 arttırılacak, increment sinyali 1 oluyor
if (round_ctr_reg < num_rounds) //num_rounds=10 ilk 9da MAIN_UPDATE yapılacak, sonuncu adımda FINAL_UPDATE yapılacak
begin
update_type = MAIN_UPDATE; // ilk 9 işlem için MAIN_UPDATE'de yapılacak işler için state ayarlandı
enc_ctrl_new = CTRL_SBOX; // 1 round MAIN_UPDATE yapıldıktan sonra SBOX statee dönüp Subbytes işlemi yapacak
enc_ctrl_we = 1'b1;
end
else
begin
update_type = FINAL_UPDATE; // son adımda FINAL_UPDATE yapılacak
ready_new = 1'b1; // yeni 128'bitlik blok alınabilmesi için ready sinyali 1 yapıldı
ready_we = 1'b1; // yeni ready sinyalinin yazılabilmesi için we sinyali 1 oldu
enc_ctrl_new = CTRL_IDLE; // IDLE statee dönüp yeni 128 bitlik bloğun gelmesini bekleyecek
enc_ctrl_we = 1'b1;
end
end
default:
begin
// Empty. Just here to make the synthesis tool happy.
end
endcase // case (enc_ctrl_reg)
end // encipher_ctrl
endmodule // aes_encipher_block
//======================================================================
// EOF aes_encipher_block.v
//======================================================================
AES SBOX Module
`default_nettype none
module aes_sbox(
input wire [31 : 0] sboxw,
output wire [31 : 0] new_sboxw
);
//----------------------------------------------------------------
// The sbox array.
//----------------------------------------------------------------
wire [7 : 0] sbox [0 : 255];
//----------------------------------------------------------------
// Four parallel muxes.
//----------------------------------------------------------------
assign new_sboxw[31 : 24] = sbox[sboxw[31 : 24]];
assign new_sboxw[23 : 16] = sbox[sboxw[23 : 16]];
assign new_sboxw[15 : 08] = sbox[sboxw[15 : 08]];
assign new_sboxw[07 : 00] = sbox[sboxw[07 : 00]];
//----------------------------------------------------------------
// Creating the sbox array contents.
//----------------------------------------------------------------
assign sbox[8'h00] = 8'h63;
assign sbox[8'h01] = 8'h7c;
assign sbox[8'h02] = 8'h77;
assign sbox[8'h03] = 8'h7b;
assign sbox[8'h04] = 8'hf2;
assign sbox[8'h05] = 8'h6b;
assign sbox[8'h06] = 8'h6f;
assign sbox[8'h07] = 8'hc5;
assign sbox[8'h08] = 8'h30;
assign sbox[8'h09] = 8'h01;
assign sbox[8'h0a] = 8'h67;
assign sbox[8'h0b] = 8'h2b;
assign sbox[8'h0c] = 8'hfe;
assign sbox[8'h0d] = 8'hd7;
assign sbox[8'h0e] = 8'hab;
assign sbox[8'h0f] = 8'h76;
assign sbox[8'h10] = 8'hca;
assign sbox[8'h11] = 8'h82;
assign sbox[8'h12] = 8'hc9;
assign sbox[8'h13] = 8'h7d;
assign sbox[8'h14] = 8'hfa;
assign sbox[8'h15] = 8'h59;
assign sbox[8'h16] = 8'h47;
assign sbox[8'h17] = 8'hf0;
assign sbox[8'h18] = 8'had;
assign sbox[8'h19] = 8'hd4;
assign sbox[8'h1a] = 8'ha2;
assign sbox[8'h1b] = 8'haf;
assign sbox[8'h1c] = 8'h9c;
assign sbox[8'h1d] = 8'ha4;
assign sbox[8'h1e] = 8'h72;
assign sbox[8'h1f] = 8'hc0;
assign sbox[8'h20] = 8'hb7;
assign sbox[8'h21] = 8'hfd;
assign sbox[8'h22] = 8'h93;
assign sbox[8'h23] = 8'h26;
assign sbox[8'h24] = 8'h36;
assign sbox[8'h25] = 8'h3f;
assign sbox[8'h26] = 8'hf7;
assign sbox[8'h27] = 8'hcc;
assign sbox[8'h28] = 8'h34;
assign sbox[8'h29] = 8'ha5;
assign sbox[8'h2a] = 8'he5;
assign sbox[8'h2b] = 8'hf1;
assign sbox[8'h2c] = 8'h71;
assign sbox[8'h2d] = 8'hd8;
assign sbox[8'h2e] = 8'h31;
assign sbox[8'h2f] = 8'h15;
assign sbox[8'h30] = 8'h04;
assign sbox[8'h31] = 8'hc7;
assign sbox[8'h32] = 8'h23;
assign sbox[8'h33] = 8'hc3;
assign sbox[8'h34] = 8'h18;
assign sbox[8'h35] = 8'h96;
assign sbox[8'h36] = 8'h05;
assign sbox[8'h37] = 8'h9a;
assign sbox[8'h38] = 8'h07;
assign sbox[8'h39] = 8'h12;
assign sbox[8'h3a] = 8'h80;
assign sbox[8'h3b] = 8'he2;
assign sbox[8'h3c] = 8'heb;
assign sbox[8'h3d] = 8'h27;
assign sbox[8'h3e] = 8'hb2;
assign sbox[8'h3f] = 8'h75;
assign sbox[8'h40] = 8'h09;
assign sbox[8'h41] = 8'h83;
assign sbox[8'h42] = 8'h2c;
assign sbox[8'h43] = 8'h1a;
assign sbox[8'h44] = 8'h1b;
assign sbox[8'h45] = 8'h6e;
assign sbox[8'h46] = 8'h5a;
assign sbox[8'h47] = 8'ha0;
assign sbox[8'h48] = 8'h52;
assign sbox[8'h49] = 8'h3b;
assign sbox[8'h4a] = 8'hd6;
assign sbox[8'h4b] = 8'hb3;
assign sbox[8'h4c] = 8'h29;
assign sbox[8'h4d] = 8'he3;
assign sbox[8'h4e] = 8'h2f;
assign sbox[8'h4f] = 8'h84;
assign sbox[8'h50] = 8'h53;
assign sbox[8'h51] = 8'hd1;
assign sbox[8'h52] = 8'h00;
assign sbox[8'h53] = 8'hed;
assign sbox[8'h54] = 8'h20;
assign sbox[8'h55] = 8'hfc;
assign sbox[8'h56] = 8'hb1;
assign sbox[8'h57] = 8'h5b;
assign sbox[8'h58] = 8'h6a;
assign sbox[8'h59] = 8'hcb;
assign sbox[8'h5a] = 8'hbe;
assign sbox[8'h5b] = 8'h39;
assign sbox[8'h5c] = 8'h4a;
assign sbox[8'h5d] = 8'h4c;
assign sbox[8'h5e] = 8'h58;
assign sbox[8'h5f] = 8'hcf;
assign sbox[8'h60] = 8'hd0;
assign sbox[8'h61] = 8'hef;
assign sbox[8'h62] = 8'haa;
assign sbox[8'h63] = 8'hfb;
assign sbox[8'h64] = 8'h43;
assign sbox[8'h65] = 8'h4d;
assign sbox[8'h66] = 8'h33;
assign sbox[8'h67] = 8'h85;
assign sbox[8'h68] = 8'h45;
assign sbox[8'h69] = 8'hf9;
assign sbox[8'h6a] = 8'h02;
assign sbox[8'h6b] = 8'h7f;
assign sbox[8'h6c] = 8'h50;
assign sbox[8'h6d] = 8'h3c;
assign sbox[8'h6e] = 8'h9f;
assign sbox[8'h6f] = 8'ha8;
assign sbox[8'h70] = 8'h51;
assign sbox[8'h71] = 8'ha3;
assign sbox[8'h72] = 8'h40;
assign sbox[8'h73] = 8'h8f;
assign sbox[8'h74] = 8'h92;
assign sbox[8'h75] = 8'h9d;
assign sbox[8'h76] = 8'h38;
assign sbox[8'h77] = 8'hf5;
assign sbox[8'h78] = 8'hbc;
assign sbox[8'h79] = 8'hb6;
assign sbox[8'h7a] = 8'hda;
assign sbox[8'h7b] = 8'h21;
assign sbox[8'h7c] = 8'h10;
assign sbox[8'h7d] = 8'hff;
assign sbox[8'h7e] = 8'hf3;
assign sbox[8'h7f] = 8'hd2;
assign sbox[8'h80] = 8'hcd;
assign sbox[8'h81] = 8'h0c;
assign sbox[8'h82] = 8'h13;
assign sbox[8'h83] = 8'hec;
assign sbox[8'h84] = 8'h5f;
assign sbox[8'h85] = 8'h97;
assign sbox[8'h86] = 8'h44;
assign sbox[8'h87] = 8'h17;
assign sbox[8'h88] = 8'hc4;
assign sbox[8'h89] = 8'ha7;
assign sbox[8'h8a] = 8'h7e;
assign sbox[8'h8b] = 8'h3d;
assign sbox[8'h8c] = 8'h64;
assign sbox[8'h8d] = 8'h5d;
assign sbox[8'h8e] = 8'h19;
assign sbox[8'h8f] = 8'h73;
assign sbox[8'h90] = 8'h60;
assign sbox[8'h91] = 8'h81;
assign sbox[8'h92] = 8'h4f;
assign sbox[8'h93] = 8'hdc;
assign sbox[8'h94] = 8'h22;
assign sbox[8'h95] = 8'h2a;
assign sbox[8'h96] = 8'h90;
assign sbox[8'h97] = 8'h88;
assign sbox[8'h98] = 8'h46;
assign sbox[8'h99] = 8'hee;
assign sbox[8'h9a] = 8'hb8;
assign sbox[8'h9b] = 8'h14;
assign sbox[8'h9c] = 8'hde;
assign sbox[8'h9d] = 8'h5e;
assign sbox[8'h9e] = 8'h0b;
assign sbox[8'h9f] = 8'hdb;
assign sbox[8'ha0] = 8'he0;
assign sbox[8'ha1] = 8'h32;
assign sbox[8'ha2] = 8'h3a;
assign sbox[8'ha3] = 8'h0a;
assign sbox[8'ha4] = 8'h49;
assign sbox[8'ha5] = 8'h06;
assign sbox[8'ha6] = 8'h24;
assign sbox[8'ha7] = 8'h5c;
assign sbox[8'ha8] = 8'hc2;
assign sbox[8'ha9] = 8'hd3;
assign sbox[8'haa] = 8'hac;
assign sbox[8'hab] = 8'h62;
assign sbox[8'hac] = 8'h91;
assign sbox[8'had] = 8'h95;
assign sbox[8'hae] = 8'he4;
assign sbox[8'haf] = 8'h79;
assign sbox[8'hb0] = 8'he7;
assign sbox[8'hb1] = 8'hc8;
assign sbox[8'hb2] = 8'h37;
assign sbox[8'hb3] = 8'h6d;
assign sbox[8'hb4] = 8'h8d;
assign sbox[8'hb5] = 8'hd5;
assign sbox[8'hb6] = 8'h4e;
assign sbox[8'hb7] = 8'ha9;
assign sbox[8'hb8] = 8'h6c;
assign sbox[8'hb9] = 8'h56;
assign sbox[8'hba] = 8'hf4;
assign sbox[8'hbb] = 8'hea;
assign sbox[8'hbc] = 8'h65;
assign sbox[8'hbd] = 8'h7a;
assign sbox[8'hbe] = 8'hae;
assign sbox[8'hbf] = 8'h08;
assign sbox[8'hc0] = 8'hba;
assign sbox[8'hc1] = 8'h78;
assign sbox[8'hc2] = 8'h25;
assign sbox[8'hc3] = 8'h2e;
assign sbox[8'hc4] = 8'h1c;
assign sbox[8'hc5] = 8'ha6;
assign sbox[8'hc6] = 8'hb4;
assign sbox[8'hc7] = 8'hc6;
assign sbox[8'hc8] = 8'he8;
assign sbox[8'hc9] = 8'hdd;
assign sbox[8'hca] = 8'h74;
assign sbox[8'hcb] = 8'h1f;
assign sbox[8'hcc] = 8'h4b;
assign sbox[8'hcd] = 8'hbd;
assign sbox[8'hce] = 8'h8b;
assign sbox[8'hcf] = 8'h8a;
assign sbox[8'hd0] = 8'h70;
assign sbox[8'hd1] = 8'h3e;
assign sbox[8'hd2] = 8'hb5;
assign sbox[8'hd3] = 8'h66;
assign sbox[8'hd4] = 8'h48;
assign sbox[8'hd5] = 8'h03;
assign sbox[8'hd6] = 8'hf6;
assign sbox[8'hd7] = 8'h0e;
assign sbox[8'hd8] = 8'h61;
assign sbox[8'hd9] = 8'h35;
assign sbox[8'hda] = 8'h57;
assign sbox[8'hdb] = 8'hb9;
assign sbox[8'hdc] = 8'h86;
assign sbox[8'hdd] = 8'hc1;
assign sbox[8'hde] = 8'h1d;
assign sbox[8'hdf] = 8'h9e;
assign sbox[8'he0] = 8'he1;
assign sbox[8'he1] = 8'hf8;
assign sbox[8'he2] = 8'h98;
assign sbox[8'he3] = 8'h11;
assign sbox[8'he4] = 8'h69;
assign sbox[8'he5] = 8'hd9;
assign sbox[8'he6] = 8'h8e;
assign sbox[8'he7] = 8'h94;
assign sbox[8'he8] = 8'h9b;
assign sbox[8'he9] = 8'h1e;
assign sbox[8'hea] = 8'h87;
assign sbox[8'heb] = 8'he9;
assign sbox[8'hec] = 8'hce;
assign sbox[8'hed] = 8'h55;
assign sbox[8'hee] = 8'h28;
assign sbox[8'hef] = 8'hdf;
assign sbox[8'hf0] = 8'h8c;
assign sbox[8'hf1] = 8'ha1;
assign sbox[8'hf2] = 8'h89;
assign sbox[8'hf3] = 8'h0d;
assign sbox[8'hf4] = 8'hbf;
assign sbox[8'hf5] = 8'he6;
assign sbox[8'hf6] = 8'h42;
assign sbox[8'hf7] = 8'h68;
assign sbox[8'hf8] = 8'h41;
assign sbox[8'hf9] = 8'h99;
assign sbox[8'hfa] = 8'h2d;
assign sbox[8'hfb] = 8'h0f;
assign sbox[8'hfc] = 8'hb0;
assign sbox[8'hfd] = 8'h54;
assign sbox[8'hfe] = 8'hbb;
assign sbox[8'hff] = 8'h16;
endmodule // aes_sbox
//======================================================================
// EOF aes_sbox.v
//======================================================================
The original source codes are taken from https://github.com/secworks/aes
