Skip to content

AES From Kilt’s Book

AES CORE Unpipelined

module AES_Enc_core(
					output [32*‘Nb-1:0] oCiphertext, // outputs ciphered text Nb=4
					output oValid, // data at output is valid
					output oKeysValid, //???????? bu neyin ready sinyali? 
					input iClk, iReset, 
					input [32*‘Nb-1:0] iPlaintext, // input data to be encrypted
					input [32*‘Nk-1:0] iKey, // input cipther key
					input iReady, // valid data to encrypt (text'in ready signali)
					input iNewKey// signals new key is input (key'in ready sinyali)
					); 
// registered inputs
wire [32*‘Nk-1:0] wKeyReg; //key'in modullere bağlantısı, key'i taşıyor
wire wNewKeyReg, wReadyReg; //wNewKeyReg hiç kullanılmamış, 
                            // wReadyReg moduller arasında textin ready sinyalini taşıyor
wire [127:0] wPlaintextReg, wBlockOutInit; //wPlaintextReg şifrelenecek teksti bloklar arasında taşıyor
                                           // wBlockOutInit moduller arası ????? taşıyor
wire [127:0] wRoundKeyInit, wRoundKey; // wRoundKeyInit initial key
                                        // wRoundKey round keys 

// register inputs
InputRegsEnc InputRegs( .iClk(iClk), 
						.iReset(iReset),
						.iKey(iKey),
						.iNewKey(iNewKey), 
						.iPlaintext(iPlaintext),
						.oKeysValid(oKeysValid),
						.iReady(iReady),
						.oKey(wKeyReg), 
						.oPlaintext(wPlaintextReg),
						.oReady(wReadyReg)
						);
						
// initial addition of round key
AddRoundKeyEnc InitialKey(  .iClk(iClk), 
							.iReset(iReset),
							.iBlockIn(wPlaintextReg),
							.iRoundKey(wRoundKeyInit),
							.oBlockOut(wBlockOutInit),
							.iReady(wReadyReg),
							.oValid(wValidInit)//wValid init tanımlanmalı
						 );			

// Number of rounds is a function of key size (10, 12, or 14)
// Key expansion block	
KeyExpansionEnc KeyExpansion(   .iClk(iClk), 
								.iReset(iReset),
								.iNkKeys(wKeyReg),
								.iReady(wReadyReg),
								.oRoundKey(wRoundKey)
							 );
							 
							 
RoundsIterEnc RoundsIter(   .iClk(iClk), 
			    .iReset(iReset),
			    .iBlockIn(wBlockOutInit),
			    .oBlockOut(oCiphertext),
			    .iReady(wValidInit),
			    .oValid(oValid),
			    .iRoundKey(wRoundKey)
						 );

‘ifdef Nk4
assign wRoundKeyInit = wKeyReg[128-1:0];
‘endif
‘ifdef Nk6
assign wRoundKeyInit = wKeyReg[192-1:192-128];
‘endif
‘ifdef Nk8
assign wRoundKeyInit = wKeyReg[256-1:256-128];
‘endif
endmodule

 

 

AES CORE Semi-pipelined

module AES_core(
				output [32*‘Nb-1:0] oCiphertext, // output cipthertext
				output oValid, // data at output is valid
				// signals that new key has been completely processed
				output oKeysValid,
				input iClk, iReset,
				input [32*‘Nb-1:0] iPlaintext, // input data to
				be encrypted
				input [32*‘Nk-1:0] iKey, // input cipther key
				input iReady, // valid data to encrypt
				input iNewKey // signals new key is input
				); 
				
wire [32*‘Nb-1:0] 	wRoundKey1, wRoundKey2,
					wRoundKey3, wRoundKey4,
					wRoundKey5, wRoundKey6,
					wRoundKey7, wRoundKey8,
					wRoundKey9, wRoundKeyFinal,
					wRoundKeyInit;
					
wire [32*‘Nb-1:0] 	wBlockOut1, wBlockOut2,
					wBlockOut3, wBlockOut4,
					wBlockOut5, wBlockOut6,
					wBlockOut7, wBlockOut8,
					wBlockOut9, wBlockOutInit;
					
wire 				wValid1, wValid2, wValid3,
					wValid4,
					wValid5, wValid6, wValid7,
					wValid8,
					wValid9, wValidFinal,
					wValidInit;

wire [32*‘Nk-1:0] wNkKeysInit;
wire [3:0] wKeyIterInit;
wire [3:0] wKeyIterModNkInit;
wire [3:0] wKeyIterDivNkInit;

wire wNewKeyInit;
wire [128*(‘Nr+1)-1:0] wKeys; // complete set of round keys

// registered inputs
wire [32*‘Nk-1:0] wKeyReg;
wire wNewKeyReg, wReadyReg;
wire [127:0] wPlaintextReg;
// register inputs

InputRegs InputRegs(.iClk(iClk), 
					.iReset(iReset),
					.iKey(iKey),
					.iNewKey(iNewKey),
					.iPlaintext(iPlaintext),
					.iReady(iReady), 
					.oKey(wKeyReg),
					.oNewKey(wNewKeyReg),
					.oPlaintext(wPlaintextReg),
					.oReady(wReadyReg)
					);
					
// initial key expansion
KeyExpInit KeyExpInit(  .iClk(iClk), 
						.iReset(iReset),
						.iNkKeys(wKeyReg), 
						.iNewKey(wNewKeyReg),
						.oKeyIter(wKeyIterInit),
						.oNewKey(wNewKeyInit),
						.oKeyIterModNk(wKeyIterModNkInit),
						.oNkKeys(wNkKeysInit),
						.oKeyIterDivNk(wKeyIterDivNkInit)
					  );

// initial addition of round key
AddRoundKey InitialKey( .iClk(iClk), 
						.iReset(iReset),
						.iBlockIn(wPlaintextReg),
						.iRoundKey(wRoundKeyInit),
						.oBlockOut(wBlockOutInit),
						.iReady(wReadyReg),
						.oValid(wValidInit)
					   );
					   
// Number of rounds is a function of key size (10, 12, or 14)
// Key expansion block
KeyExpansion KeyExpansion(  .iClk(iClk),
							.iReset(iReset),
							.iKeyIter(wKeyIterInit),
							.iKeyIterModNk(wKeyIterModNkInit),
							.iNkKeys(wNkKeysInit),
							.iKeyIterDivNk(wKeyIterDivNkInit),
							.iNewKey(wNewKeyInit),
							.oKeys(wKeys), 
							.oKeysValid(oKeysValid)
						  );

// round transformation blocks
Round R1( 	.iClk(iClk), 
			.iReset(iReset),
			.iBlockIn(wBlockOutInit),
			.iRoundKey(wRoundKey1),
			.oBlockOut(wBlockOut1),
			.iReady(wValidInit),
			.oValid(wValid1)
		);


Round R9(   .iClk(iClk), 
			.iReset(iReset),
			.iBlockIn(wBlockOut8),
			.iRoundKey(wRoundKey9),
			.oBlockOut(wBlockOut9),
			.iReady(wValid8),
			.oValid(wValid9)
		);

// 10 rounds total
// Initial key addition
assign wRoundKeyFinal = wKeys[128*(‘Nr-7)-1:128*(‘Nr-8)];
// round key assignments
assign wRoundKey9 = wKeys[128*(‘Nr-6)-1: 128*(‘Nr-7)];
assign wRoundKey8 = wKeys[128*(‘Nr-5)-1: 128*(‘Nr-6)];
assign wRoundKey7 = wKeys[128*(‘Nr-4)-1: 128*(‘Nr-5)];
assign wRoundKey6 = wKeys[128*(‘Nr-3)-1: 128*(‘Nr-4)];
assign wRoundKey5 = wKeys[128*(‘Nr-2)-1: 128*(‘Nr-3)];
assign wRoundKey4 = wKeys[128*(‘Nr-1)-1: 128*(‘Nr-2)];
assign wRoundKey3 = wKeys[128*‘Nr-1: 128*(‘Nr-1)];
assign wRoundKey2 = wKeys[128*(‘Nr+1)-1: 128*‘Nr];
assign wRoundKey1 = wNkKeysInit[128-1:0];
assign wRoundKeyInit = iKey[128-1:0];

FinalRound FinalRound(  .iClk(iClk), 
						.iReset(iReset),
						.iBlockIn(wBlockOut9),
						.iRoundKey(wRoundKeyFinal),
						.oBlockOut(oCiphertext),
						.iReady(wValid9), 
						.oValid(oValid)
					 );

endmodule

 

 

AES CORE Fully-pipelined

module AES_core(
				output [32*‘Nb-1:0] oCiphertext, // output cipthertext
				output oValid, // data at output is valid
				input iClk, iReset,
				input [32*‘Nb-1:0] iPlaintext, // input data to be encrypted
				input [32*‘Nk-1:0] iKey, // input cipther key
				input iReady // valid data to encrypt
				); 

wire [32*‘Nb-1:0]	wRoundKey1, wRoundKey2, wRoundKey3, wRoundKey4,
					wRoundKey5, wRoundKey6, wRoundKey7, wRoundKey8,
					wRoundKey9, wRoundKeyFinal,wRoundKeyInit;
					
wire [32*‘Nb-1:0] 	wBlockOut1, wBlockOut2, wBlockOut3, wBlockOut4,
					wBlockOut5, wBlockOut6, wBlockOut7, wBlockOut8,
					wBlockOut9, wBlockOutInit;
					
wire [32*‘Nk-1:0] 	wNkKeys1, wNkKeys2, wNkKeys3, wNkKeys4,
					wNkKeys5, wNkKeys6, wNkKeys7, wNkKeys8,
					wNkKeys9, wNkKeysFinal, wNkKeysInit;
					
wire [3:0] 			wKeyIter1, wKeyIter2, wKeyIter3, wKeyIter4,
					wKeyIter5, wKeyIter6, wKeyIter7, wKeyIter8,
					wKeyIter9, wKeyIterFinal, wKeyIterInit;	
					
wire [3:0] 			wKeyIterModNk1, wKeyIterModNk2, wKeyIterModNk3, wKeyIterModNk4, 
					wKeyIterModNk5, wKeyIterModNk6, wKeyIterModNk7, wKeyIterModNk8,
					wKeyIterModNk9, wKeyIterModNkFinal, wKeyIterModNkInit;

wire [3:0] 			wKeyIterDivNk1, wKeyIterDivNk2, wKeyIterDivNk3, wKeyIterDivNk4, 
					wKeyIterDivNk5, wKeyIterDivNk6, wKeyIterDivNk7, wKeyIterDivNk8,
					wKeyIterDivNk9, wKeyIterDivNkFinal, wKeyIterDivNkInit;
					
wire				wValid1, wValid2, wValid3, wValid4,
					wValid5, wValid6, wValid7, wValid8,
					wValid9, wValidFinal, wValidInit;
					
// registered inputs
wire [32*‘Nk-1:0] wKeyReg;
wire wReadyReg;
wire [127:0] wPlaintextReg;

// Initial key addition
assign wRoundKeyInit = wKeyReg[32*‘Nk-1:32*‘Nk-128];
// round key assignments
assign wRoundKey1 = wNkKeysInit[32*‘Nb-1:0];
assign wRoundKey2 = wNkKeys1[32*‘Nb-1:0];
assign wRoundKey3 = wNkKeys2[32*‘Nb-1:0];
assign wRoundKey4 = wNkKeys3[32*‘Nb-1:0];
assign wRoundKey5 = wNkKeys4[32*‘Nb-1:0];
assign wRoundKey6 = wNkKeys5[32*‘Nb-1:0];
assign wRoundKey7 = wNkKeys6[32*‘Nb-1:0];
assign wRoundKey8 = wNkKeys7[32*‘Nb-1:0];
assign wRoundKey9 = wNkKeys8[32*‘Nb-1:0];


// register inputs
InputRegs InputRegs(.iClk(iClk), 
					.iReset(iReset),
					.iKey(iKey),
					.iPlaintext(iPlaintext),
					.iReady(iReady), 
					.oKey(wKeyReg),
					.oPlaintext(wPlaintextReg),
					.oReady(wReadyReg)
					);

// initial key expansion
KeyExpInit KeyExpInit(  .iClk(iClk), 
						.iReset(iReset),
						.iNkKeys(wKeyReg),
						.oKeyIter(wKeyIterInit),
						.oKeyIterModNk(wKeyIterModNkInit),
						.oNkKeys(wNkKeysInit),
						.oKeyIterDivNk(wKeyIterDivNkInit)
					 );

// initial addition of round key
AddRoundKey InitialKey( .iClk(iClk), 
						.iReset(iReset),
						.iBlockIn(wPlaintextReg),
						.iRoundKey(wRoundKeyInit),
						.oBlockOut(wBlockOutInit),
						.iReady(wReadyReg),
						.oValid(wValidInit)
					   );

// Number of rounds is a function of key size (10, 12, or 14)
// Key expansion blocks
KeyExpBlock KeyExpBlock1(   .iClk(iClk), 
							.iReset(iReset),
							.iKeyIter(wKeyIterInit),
							.iKeyIterModNk(wKeyIterModNkInit),
							.iNkKeys(wNkKeysInit),
							.iKeyIterDivNk(wKeyIterDivNkInit),
							.oKeyIter(wKeyIter1),
							.oKeyIterModNk(wKeyIterModNk1),
							.oNkKeys(wNkKeys1),
							.oKeyIterDivNk(wKeyIterDivNk1)
						);

KeyExpBlock KeyExpBlock8( 	.iClk(iClk), 
							.iReset(iReset),
							.iKeyIter(wKeyIter7),
							.iKeyIterModNk(wKeyIterModNk7),
							.iNkKeys(wNkKeys7),
							.iKeyIterDivNk(wKeyIterDivNk7),
							.oKeyIter(wKeyIter8),
							.oKeyIterModNk(wKeyIterModNk8),
							.oNkKeys(wNkKeys8),
							.oKeyIterDivNk(wKeyIterDivNk8)
						);
// round transformation blocks
Round R1(   .iClk(iClk), 
			.iReset(iReset),
			.iBlockIn(wBlockOutInit),
			.iRoundKey(wRoundKey1),
			.oBlockOut(wBlockOut1),
			.iReady(wValidInit),
			.oValid(wValid1)
		);
//...
Round R9(  	.iClk(iClk), 
			.iReset(iReset),
			.iBlockIn(wBlockOut8),
			.iRoundKey(wRoundKey9),
			.oBlockOut(wBlockOut9),
			.iReady(wValid8),
			.oValid(wValid9)
		);
// 10 rounds total

assign wRoundKeyFinal = wNkKeys9[32*‘Nb-1:0];

KeyExpBlock KeyExpBlock9( 	.iClk(iClk), 
							.iReset(iReset),
							.iKeyIter(wKeyIter8),
							.iKeyIterModNk(wKeyIterModNk8),
							.iNkKeys(wNkKeys8),
							.iKeyIterDivNk(wKeyIterDivNk8),
							.oKeyIter(wKeyIter9),
							.oKeyIterModNk(wKeyIterModNk9),
							.oNkKeys(wNkKeys9),
							.oKeyIterDivNk(wKeyIterDivNk9)
						);
						
FinalRound FinalRound( 	.iClk(iClk), 
						.iReset(iReset),
						.iBlockIn(wBlockOut9),
						.iRoundKey(wRoundKeyFinal),
						.oBlockOut(oCiphertext),
						.iReady(wValid9), 
						.oValid(oValid)
					 );
endmodule




 

InputRegsEnc

// Registers all inputs
module InputRegsEnc(
					output reg [32 *‘Nk - 1:0] oKey,
					output reg oReady, oKeysValid,
					output reg [127:0] oPlaintext,
					input iClk, iReset,
					input [32 *‘Nk - 1:0] iKey,
					input iNewKey, iReady,
					input [127:0] iPlaintext
					);

reg [32 *‘Nk - 1:0] KeyReg;
reg NewKeyReg, ReadyStaged;
reg [127:0] PlaintextStaged;

always @(posedge iClk or negedge iReset)
	if (!iReset) 
		begin
			oKey <= 0;
			oReady <= 0;
			oPlaintext <= 0;
			NewKeyReg <= 0;
			KeyReg <= 0;
			oKeysValid <= 0;
			ReadyStaged <= 0;
			PlaintextStaged <= 0;
		end
	else 
		begin
			NewKeyReg <= iNewKey;
			KeyReg <= iKey;
			if (NewKeyReg) 
				begin
					oKeysValid <= 1;
					oKey <= KeyReg;
				end
			else
				oKeysValid <= 0;
				
			ReadyStaged <= iReady;
			PlaintextStaged <= iPlaintext;
			oReady <= ReadyStaged;
			oPlaintext <= PlaintextStaged;
		end
endmodule

 

ADDRoundKey

// This block performs the AddRoundKey transformation on the iBlockIn data
// and places it on oBlockOut
module AddRoundKeyEnc(
						output reg [32 *‘Nb - 1:0] oBlockOut,
						output reg oValid,
						input iClk, iReset, iReady, 
						// Data input to be transformed
						input [32 *‘Nb - 1:0] iBlockIn, iRoundKey
					 );

reg [32 *‘Nb - 1:0] BlockOutStaged;
reg ValidStaged;

always @(posedge iClk or negedge iReset)
	if (!iReset) 
		begin
			oBlockOut <= 0;
			oValid <= 0;
			BlockOutStaged <= 0;
			ValidStaged <= 0;
		end
	else 
		begin
			BlockOutStaged <= iBlockIn ^ iRoundKey;
			ValidStaged <= iReady;
			oBlockOut <= BlockOutStaged;
			oValid <= ValidStaged;	
		end
endmodule

KeyExpansionEnc
module KeyExpansionEnc(
						output [128-1:0] oRoundKey,
						input iClk, iReset,
						// The last Nk keys generated in initial key expansion
						input [32*‘Nk-1:0] iNkKeys,
						input iReady// signals a new key is input
						); 
wire [3:0] KeyIterIn, KeyIterOut;
wire [3:0] KeyIterDivNkIn, KeyIterDivNkOut;
wire [3:0] KeyIterModNkIn, KeyIterModNkOut;
wire [32*‘Nk-1:0] NkKeysOut, NkKeysIn;
wire wReady;

assign wReady = iReady;
assign KeyIterIn = wReady ? ‘Nk : KeyIterOut;
assign oRoundKey = NkKeysOut[32*‘Nk-1:32*‘Nk-128];
assign KeyIterModNkIn = wReady ? 4’h0 : KeyIterModNkOut;
assign KeyIterDivNkIn = wReady ? 4’h1 : KeyIterDivNkOut;
assign NkKeysIn = wReady ? iNkKeys : NkKeysOut;

KeyExp1Enc KeyExp1( .iClk(iClk), 
					.iReset(iReset),
					.iKeyIter(KeyIterIn),
					.iKeyIterModNk(KeyIterModNkIn),
					.iNkKeys(NkKeysIn), 
					.iKeyIterDivNk(KeyIterDivNkIn),
					.oKeyIter(KeyIterOut),
					.oKeyIterModNk(KeyIterModNkOut),
					.oNkKeys(NkKeysOut),
					.oKeyIterDivNk(KeyIterDivNkOut)
				  );
endmodule

 

KeyExp1Enc

module KeyExp1Enc(
					// updated values to be passed to next iteration
					output [3:0] oKeyIter, oKeyIterModNk,oKeyIterDivNk,
					output [32*‘Nk-1:0] oNkKeys,
					input iClk, iReset,
					// represents total # of iterations and value mod Nk
					input [3:0] iKeyIter, iKeyIterModNk, iKeyIterDivNk,
					// The last Nk keys generated in key expansion
					input [32*‘Nk-1:0] iNkKeys
				  );
				  
// updated values to be passed to next iteration
reg [3:0] oKeyIter, oKeyIterModNk, oKeyIterDivNk;
reg [32*‘Nk-1:0] OldKeys;
reg [31:0] InterKey; // intermediate key value
wire [32*‘Nk-1:0] oNkKeys;
wire [31:0] PrevKey, RotWord, SubWord, NewKeyWord;
wire [31:0] KeyWordNk;
wire [31:0] Rcon;

assign PrevKey = iNkKeys[31:0]; // last word in key array
assign KeyWordNk = OldKeys[32*‘Nk-1:32*‘Nk-32];

// 1 byte cyclic permutation
assign RotWord = {PrevKey[23:0], PrevKey[31:24]};

// new key calculated in this round
assign NewKeyWord = KeyWordNk ^ InterKey;
// calculate new key set
assign oNkKeys = {OldKeys[32*‘Nk-33:0], NewKeyWord};
// calculate Rcon over GF(2^8)
assign Rcon = 	iKeyIterDivNk == 8’h1 ? 32’h01000000:
				iKeyIterDivNk == 8’h2 ? 32’h02000000:
				iKeyIterDivNk == 8’h3 ? 32’h04000000:
				iKeyIterDivNk == 8’h4 ? 32’h08000000:
				iKeyIterDivNk == 8’h5 ? 32’h10000000:
				iKeyIterDivNk == 8’h6 ? 32’h20000000:
				iKeyIterDivNk == 8’h7 ? 32’h40000000:
				iKeyIterDivNk == 8’h8 ? 32’h80000000:
				iKeyIterDivNk == 8’h9 ? 32’h1b000000:
				32’h36000000;

SboxEnc SboxEnc0(.iPreMap(RotWord[31:24]),.oPostMap(SubWord[31:24]));
SboxEnc SboxEnc1(.iPreMap(RotWord[23:16]),.oPostMap(SubWord[23:16]));
SboxEnc SboxEnc2(.iPreMap(RotWord[15:8]), .oPostMap(SubWord[15:8]));
SboxEnc SboxEnc3(.iPreMap(RotWord[7:0]),  .oPostMap(SubWord[7:0]));

‘ifdef Nk8
wire [31:0] SubWordNk8;

// Substitution only when Nk = 8
SboxEnc SboxEncNk8_0(.iPreMap(PrevKey[31:24]),.oPostMap(SubWordNk8[31:24]));
SboxEnc SboxEncNk8_1(.iPreMap(PrevKey[23:16]),.oPostMap(SubWordNk8[23:16]));
SboxEnc SboxEncNk8_2(.iPreMap(PrevKey[15:8]), .oPostMap(SubWordNk8[15:8]));
SboxEnc SboxEncNk8_3(.iPreMap(PrevKey[7:0]),  .oPostMap(SubWordNk8[7:0]));
‘endif

always @(posedge iClk)
	if(!iReset) 
		begin
			oKeyIter <= 0;
			oKeyIterModNk <= 0;
			InterKey <= 0;
			oKeyIterDivNk <= 0;
			OldKeys <= 0;
		end
	else 
		begin
			oKeyIter <= iKeyIter + 1;
			OldKeys <= iNkKeys;
			// update "Key iteration mod Nk" for next iteration
			if(iKeyIterModNk + 1 == ‘Nk) 
				begin
					oKeyIterModNk <= 0;
					oKeyIterDivNk <= iKeyIterDivNk+1;
				end
			else 
				begin
					oKeyIterModNk <= iKeyIterModNk + 1;
					oKeyIterDivNk <= iKeyIterDivNk;
				end
		if(iKeyIterModNk == 0)
			InterKey <= SubWord ^ Rcon;
			‘ifdef Nk8
			// an option only for Nk = 8
		else if(iKeyIterModNk == 4)
				InterKey <= SubWordNk8;
			‘endif
		else
			InterKey <= PrevKey;
	end
endmodule

 

 

RoundsIterEnc

// This module iterates the intermediate data through the round block

module RoundsIterEnc(
						output reg [32*‘Nb-1:0] oBlockOut,
						output reg oValid,
						input iClk, iReset,
						input [32*‘Nb-1:0] iBlockIn,
						input iReady,
						input [127:0] iRoundKey
					);
reg [3:0] round;// keeps track of current round
reg ValidReg;
reg [127:0] BlockOutReg;
wire [127:0] wBlockIn, wBlockOut;
wire wReady, wValid;

assign wBlockIn = iReady ? iBlockIn: wBlockOut;

// ready is asserted when we have a new input or when the
// previous round has completed and we are not done
assign wReady = iReady || (wValid && (round !=‘Nr));

RoundEnc Riter( .iClk(iClk), 
				.iReset(iReset),
				.iBlockIn(wBlockIn), 
				.iRoundKey(iRoundKey),
				.oBlockOut(wBlockOut), 
				.iReady(wReady),
				.oValid(wValid), 
				.iRound(round)
			   );

always @(posedge iClk or negedge iReset)
	if(!iReset) 
		begin
			round <= 0;
			oValid <= 0;
			oBlockOut <= 0;
			ValidReg <= 0;
			BlockOutReg <= 0;
		end
	else 
		begin
			oValid <= ValidReg;
			oBlockOut <= BlockOutReg;
			if(iReady) 
				begin
					round <= 1;
					ValidReg <= 0;
				end
			else if(wValid && (round != 0)) 
				begin
				// rounds continue and data has completed another round
					if(round == ‘Nr) 
						begin
							// data has completed last round
							round <= 0;
							ValidReg <= 1;
							BlockOutReg <= wBlockOut;
						end
					else 
						begin
							// data will continue through rounds
							round <= round + 1;
							ValidReg <= 0;
						end
				end
			else ValidReg <= 0;
		end
endmodule

 

 

RoundEnc

module RoundEnc(
					output [32*‘Nb-1:0] oBlockOut,
					output oValid,
					input iClk, iReset,
					input [32*‘Nb-1:0] iBlockIn, iRoundKey,
					input iReady,
					input [3:0] iRound
				
				);
wire [32*‘Nb-1:0] wSubOut, wShiftOut, wMixOut;
wire wValidSub, wValidShift, wValidMix;

SubBytesEnc sub(.iClk(iClk), 
				.iReset(iReset),
				.iBlockIn(iBlockIn),
				.oBlockOut(wSubOut),
				.iReady(iReady),
				.oValid(wValidSub)
				);
				
ShiftRowsEnc shift( .iBlockIn(wSubOut), 
					.oBlockOut(wShiftOut),
					.iReady(wValidSub), 
					.oValid(wValidShift)
				  );
				  
MixColumnsEnc mixcolumn(.iClk(iClk), 
						.iReset(iReset),
						.iBlockIn(wShiftOut),
						.oBlockOut(wMixOut),
						.iReady(wValidShift),
						.oValid(wValidMix),
						.iRound(iRound)
						);
						
AddRoundKeyEnc addroundkey( .iClk(iClk), 
							.iReset(iReset),
							.iBlockIn(wMixOut),
							.iRoundKey(iRoundKey),
							.oBlockOut(oBlockOut),
							.iReady(wValidMix),
							.oValid(oValid)
						  );
						  
endmodule

 

Subbytes

// This block performs the SboxEnc transformationon the iBlockIn data
// and places it on oBlockOut
module SubBytesEnc(
					output reg [32 *‘Nb - 1:0] oBlockOut,
					output reg oValid,
					input iClk, iReset, iReady,
					input [32 *‘Nb - 1:0] iBlockIn); // Data input to be transformed
					
wire [32 *‘Nb - 1:0] wPostMap;

SboxEnc SboxEnc1(.oPostMap(wPostMap[7:0]),      .iPreMap(iBlockIn[7:0]));
SboxEnc SboxEnc2(.oPostMap(wPostMap[15:8]),     .iPreMap(iBlockIn[15:8]));
SboxEnc SboxEnc3(.oPostMap(wPostMap[23:16]),    .iPreMap(iBlockIn[23:16]));
SboxEnc SboxEnc4(.oPostMap(wPostMap[31:24]),    .iPreMap(iBlockIn[31:24]));
SboxEnc SboxEnc5(.oPostMap(wPostMap[39:32]),    .iPreMap(iBlockIn[39:32]));
SboxEnc SboxEnc6(.oPostMap(wPostMap[47:40]),    .iPreMap(iBlockIn[47:40]));
SboxEnc SboxEnc7(.oPostMap(wPostMap[55:48]),    .iPreMap(iBlockIn[55:48]));
SboxEnc SboxEnc8( .oPostMap(wPostMap[63:56]),   .iPreMap(iBlockIn[63:56]));
SboxEnc SboxEnc9( .oPostMap(wPostMap[71:64]),   .iPreMap(iBlockIn[71:64]));
SboxEnc SboxEnc10(.oPostMap(wPostMap[79:72]),   .iPreMap(iBlockIn[79:72]));
SboxEnc SboxEnc11(.oPostMap(wPostMap[87:80]),   .iPreMap(iBlockIn[87:80]));
SboxEnc SboxEnc12(.oPostMap(wPostMap[95:88]),   .iPreMap(iBlockIn[95:88]));
SboxEnc SboxEnc13(.oPostMap(wPostMap[103:96]),  .iPreMap(iBlockIn[103:96]));
SboxEnc SboxEnc14(.oPostMap(wPostMap[111:104]), .iPreMap(iBlockIn[111:104]));
SboxEnc SboxEnc15(.oPostMap(wPostMap[119:112]), .iPreMap(iBlockIn[119:112]));
SboxEnc SboxEnc16(.oPostMap(wPostMap[127:120]), .iPreMap(iBlockIn[127:120]));

always @(posedge iClk or negedge iReset)
	if (!iReset) 
		begin
			oBlockOut <= 0;
			oValid <= 0;
		end
	else 
		begin
			oBlockOut <= wPostMap;
			oValid <= iReady;
		end
endmodule // SubBytesEnc

 

ShiftRows

module ShiftRowsEnc(
					output [32 *‘Nb - 1:0] oBlockOut,
					output oValid,
					input [32 *‘Nb - 1:0] iBlockIn, // Data input to be transformed
					input iReady
					);
					
assign oValid = iReady;
assign oBlockOut[7:0]     = iBlockIn[39:32];
assign oBlockOut[15:8]    = iBlockIn[79:72];
assign oBlockOut[23:16]   = iBlockIn[119:112];
assign oBlockOut[31:24]   = iBlockIn[31:24];
assign oBlockOut[39:32]   = iBlockIn[71:64];
assign oBlockOut[47:40]   = iBlockIn[111:104];
assign oBlockOut[55:48]   = iBlockIn[23:16];
assign oBlockOut[63:56]   = iBlockIn[63:56];
assign oBlockOut[71:64]   = iBlockIn[103:96];
assign oBlockOut[79:72]   = iBlockIn[15:8];
assign oBlockOut[87:80]   = iBlockIn[55:48];
assign oBlockOut[95:88]   = iBlockIn[95:88];
assign oBlockOut[103:96]  = iBlockIn[7:0];
assign oBlockOut[111:104] = iBlockIn[47:40];
assign oBlockOut[119:112] = iBlockIn[87:80];
assign oBlockOut[127:120] = iBlockIn[127:120];
endmodule // ShiftRowsEnc

 

MixColumn

module MixColumnsEnc(
						output reg [32 * ‘Nb - 1:0] oBlockOut,
						output reg oValid,
						input iClk, iReset,
						input [32 *‘Nb - 1:0] iBlockIn, // Data input to be transformed
						input iReady,
						input [3:0] iRound);
						
reg [32 *‘Nb - 1:0] BlockInHold; // registered output
wire [32 *‘Nb - 1:0] wPostMap;

MapColumnEnc MapColumnEnc0 (.iClk(iClk),
							.iReset(iReset), 
							.iColumnIn({iBlockIn[127:120], iBlockIn[119:112],iBlockIn[111:104],iBlockIn[103:96]}),
							.oColumnOut({wPostMap[127:120],wPostMap[119:112],wPostMap[111:104],wPostMap[103:96]})
						    );
						   
MapColumnEnc MapColumnEnc1 (.iClk(iClk), 
							.iReset(iReset),
							.iColumnIn({iBlockIn[95:88],iBlockIn[87:80],iBlockIn[79:72],iBlockIn[71:64]}),
							.oColumnOut({wPostMap[95:88],wPostMap[87:80],wPostMap[79:72],wPostMap[71:64]})
							);
							
MapColumnEnc MapColumnEnc2 (.iClk(iClk),
							.iReset(iReset),
							.iColumnIn({iBlockIn[63:56],iBlockIn[55:48],iBlockIn[47:40],iBlockIn[39:32]}),
							.oColumnOut({wPostMap[63:56],wPostMap[55:48],wPostMap[47:40],wPostMap[39:32]})
							);
							
MapColumnEnc MapColumnEnc3 (.iClk(iClk), 
							.iReset(iReset),
							.iColumnIn({iBlockIn[31:24],iBlockIn[23:16],iBlockIn[15:8],iBlockIn[7:0]}),
							.oColumnOut({wPostMap[31:24],wPostMap[23:16],wPostMap[15:8],wPostMap[7:0]})
							);
							
always @*
	if (iRound != ‘Nr )
		oBlockOut = wPostMap;
	else
		oBlockOut = BlockInHold;

always @(posedge iClk or negedge iReset)
	if (!iReset) 
		begin
			oValid = 0;
			BlockInHold = 0;
		end
	else 
		begin
			BlockInHold = iBlockIn;
			oValid = iReady;
		end
endmodule

 

MapColumn

// Provides necessary parameters to the
AES implementation
// number of data words (always 32*4 = 128)
‘define Nb 4
// 128 bit key mode
‘define Nk4
// 192 bit key mode
//‘define Nk6
// 256 bit key mode
//‘define Nk8
‘ifdef Nk4
‘define Nk 4
‘define Nr 10
‘endif
‘ifdef Nk6
‘define Nk 6
‘define Nr 12
‘endif
‘ifdef Nk8
‘define Nk 8
‘define Nr 14
‘endif
// Performs the column mapping for MixColumns
module MapColumnEnc(
					output reg [31:0] oColumnOut,
					input iClk, iReset,
					input [31:0] iColumnIn);
// intermediate Poly mult results
wire [7:0]		S0x2, S1x2, S2x2, S3x2;
wire [7:0] 		S0x3, S1x3, S2x3, S3x3;
// Mapped cells in column
wire [7:0]		S0PostMap, S1PostMap,
				S2PostMap, S3PostMap;
				
// Modules that will perform poly mults over GF(2^8)
PolyMultx2Enc PolyMultS0x2(.iPolyIn(iColumnIn[31:24]),.oPolyOut(S0x2));
PolyMultx2Enc PolyMultS1x2(.iPolyIn(iColumnIn[23:16]),.oPolyOut(S1x2));
PolyMultx2Enc PolyMultS2x2(.iPolyIn(iColumnIn[15:8]), .oPolyOut(S2x2));
PolyMultx2Enc PolyMultS3x2(.iPolyIn(iColumnIn[7:0]),  .oPolyOut(S3x2));
PolyMultx3Enc PolyMultS0x3(.iPolyIn(iColumnIn[31:24]),.oPolyOut(S0x3));
PolyMultx3Enc PolyMultS1x3(.iPolyIn(iColumnIn[23:16]),.oPolyOut(S1x3));
PolyMultx3Enc PolyMultS2x3(.iPolyIn(iColumnIn[15:8]), .oPolyOut(S2x3));
PolyMultx3Enc PolyMultS3x3(.iPolyIn(iColumnIn[7:0]),  .oPolyOut(S3x3));				
				
// Sum terms over GF(2)
assign S0PostMap = S0x2 ^ S1x3 ^ iColumnIn[15:8] ^ iColumnIn[7:0];
assign S1PostMap = iColumnIn[31:24] ^ S1x2 ^ S2x3 ^ iColumnIn[7:0];
assign S2PostMap = iColumnIn[31:24] ^ iColumnIn[23:16] ^ S2x2 ^ S3x3;
assign S3PostMap = S0x3 ^ iColumnIn[23:16] ^ iColumnIn[15:8] ^ S3x2;				
				
always @(posedge iClk or negedge iReset) begin
if (!iReset)
	oColumnOut <= 0;
else // output is combination of post mapped cells
	oColumnOut <= {S0PostMap, S1PostMap, S2PostMap,S3PostMap};
end
endmodule		

 

MixColumnsEnc

module MixColumnsEnc(
						output reg [32 * ‘Nb - 1:0] oBlockOut,
						output reg oValid,
						input iClk, iReset,
						input [32 *‘Nb - 1:0] iBlockIn, // Data input to be transformed
						input iReady,
						input [3:0] iRound);
						
reg [32 *‘Nb - 1:0] BlockInHold; // registered output
wire [32 *‘Nb - 1:0] wPostMap;

MapColumnEnc MapColumnEnc0 (.iClk(iClk),
							.iReset(iReset), 
							.iColumnIn({iBlockIn[127:120], iBlockIn[119:112],iBlockIn[111:104],iBlockIn[103:96]}),
							.oColumnOut({wPostMap[127:120],wPostMap[119:112],wPostMap[111:104],wPostMap[103:96]})
						    );
						   
MapColumnEnc MapColumnEnc1 (.iClk(iClk), 
							.iReset(iReset),
							.iColumnIn({iBlockIn[95:88],iBlockIn[87:80],iBlockIn[79:72],iBlockIn[71:64]}),
							.oColumnOut({wPostMap[95:88],wPostMap[87:80],wPostMap[79:72],wPostMap[71:64]})
							);
							
MapColumnEnc MapColumnEnc2 (.iClk(iClk),
							.iReset(iReset),
							.iColumnIn({iBlockIn[63:56],iBlockIn[55:48],iBlockIn[47:40],iBlockIn[39:32]}),
							.oColumnOut({wPostMap[63:56],wPostMap[55:48],wPostMap[47:40],wPostMap[39:32]})
							);
							
MapColumnEnc MapColumnEnc3 (.iClk(iClk), 
							.iReset(iReset),
							.iColumnIn({iBlockIn[31:24],iBlockIn[23:16],iBlockIn[15:8],iBlockIn[7:0]}),
							.oColumnOut({wPostMap[31:24],wPostMap[23:16],wPostMap[15:8],wPostMap[7:0]})
							);
							
always @*
	if (iRound != ‘Nr )
		oBlockOut = wPostMap;
	else
		oBlockOut = BlockInHold;

always @(posedge iClk or negedge iReset)
	if (!iReset) 
		begin
			oValid = 0;
			BlockInHold = 0;
		end
	else 
		begin
			BlockInHold = iBlockIn;
			oValid = iReady;
		end
endmodule

 

PolyMultx2Enc

// Multiplies input poly by {02} over GF(2^8) and reduces
// mod m(x) = x^8 + x^4 + x^3 + x + 1
module PolyMultx2Enc(
					  output [7:0] oPolyOut,
					  input [7:0] iPolyIn
					 );
wire [8:0] PolyPreShift, PolyPostShift, PolyReduced;

assign PolyPreShift = {1’b0, iPolyIn};
assign PolyPostShift = PolyPreShift << 1;
assign PolyReduced = PolyPostShift[8] ? (PolyPostShift ^ (9’b100011011)): PolyPostShift;
assign oPolyOut = PolyReduced[7:0];

endmodule // PolyMultx2Enc

 

PolyMultx3Enc

// Multiplies input poly by {03} over GF(2^8) and reduces
// mod m(x) = x^8 + x^4 + x^3 + x + 1
module PolyMultx3Enc (
						output [7:0] oPolyOut,
						input [7:0] iPolyIn
					 );
wire [8:0] PolyPreShift, PolyPostShift, PolyReduced;

assign PolyPreShift = {1’b0, iPolyIn};
assign PolyPostShift = (PolyPreShift << 1) ^ PolyPreShift;
assign PolyReduced = PolyPostShift[8] ? (PolyPostShift ^ (9’b100011011)): PolyPostShift;
assign oPolyOut = PolyReduced[7:0];
endmodule // PolyMultx3Enc