Skip to content

AES Encryption

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)

  1. Key expansion
  2. Initial Round
    • AddRoundKey
  3. Rounds (repeat 9 times)
    • SubBytes
    • ShiftRows
    • MixColumns
    • AddRoundKey
  4. 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