最近学习了AES加密算法的Verilog实现,在此记录一下学习心得,以及将代码分享给大家

算法原理:AES加密算法的详细介绍与实现_TimeShatter的博客-CSDN博客_aes加密

感谢这位大佬的文章,讲的非常详细,帮了我不少忙

之前在网上到处找代码,发现找的并不容易,注释也写的很少。在学习了其他大佬的代码后,我完成了自己的代码,在此分享给大家。

我只是一个Verilog的初学者,代码水平不高。代码只以正确实现功能为目的,并没有考虑到资源的占用、延时等等实际工程问题,还请批评指正。不过我写代码就很喜欢写注释,希望这能帮助和我一样刚入门的同学更容易看懂。

目录

Verilog代码

一、AES module

二、S盒module

三、测试代码

modelsim仿真

一些小tips


Verilog代码

一、AES module

基本思路:

1.为了方便,s盒单独写为一个module,在AES module中例化使用

2.程序共4个always。always本来是并行的,但我需要它们顺序执行,所以定义了一些寄存器作为标志位:state(表示工作状态)和finish_state(表示结束状态)。rst=0时,令finish_state=0;rst=1时,令state=1。只有在state=1且finish=0时,一个always才执行。当一个always执行完成后,令finish=1,这样这个always便不会再继续执行。不过,这样必须在测试文件中先令rst=0,这样才能使finish=0从而开始执行always

3.一些always里面的内容也需要顺序执行,所以我使用case语句块。case执行之前先令case=0,在case=0相关语句中令case=1,这样就会依次执行完所有的case状态

4.128字节的密钥,需要加密10次,我使用if来达到循环的效果

注:第二个always应该是密钥扩展,下面代码里写成了轮密钥加

module AES_2 (rst,clk,

            a00,a01,a02,a03,
				a10,a11,a12,a13,
				a20,a21,a22,a23,
				a30,a31,a32,a33,
				
				k00,k01,k02,k03,
				k10,k11,k12,k13,
				k20,k21,k22,k23,
				k30,k31,k32,k33,
				
				z);

input rst,clk;

input [7:0] a00,a01,a02,a03,
				a10,a11,a12,a13,
				a20,a21,a22,a23,
				a30,a31,a32,a33;
				
input [7:0] k00,k01,k02,k03,
				k10,k11,k12,k13,
				k20,k21,k22,k23,
				k30,k31,k32,k33;
				
output [127:0] z;	

wire [7:0] a00,a01,a02,a03;//a:明文。数字表示行列
wire [7:0] a10,a11,a12,a13;
wire [7:0] a20,a21,a22,a23;
wire [7:0] a30,a31,a32,a33;

wire [7:0] k00,k01,k02,k03;//k:密钥。数字表示行列
wire [7:0] k10,k11,k12,k13;
wire [7:0] k20,k21,k22,k23;
wire [7:0] k30,k31,k32,k33;

reg [127:0] z;						

reg [7:0] ar00,ar01,ar02,ar03;//ar:存放明文a的寄存器(用于整个过程)
reg [7:0] ar10,ar11,ar12,ar13;
reg [7:0] ar20,ar21,ar22,ar23;
reg [7:0] ar30,ar31,ar32,ar33;

reg [7:0] aar00,aar01,aar02,aar03;//aar:存放明文a的寄存器(只用于第一轮的轮密钥加)
reg [7:0] aar10,aar11,aar12,aar13;
reg [7:0] aar20,aar21,aar22,aar23;
reg [7:0] aar30,aar31,aar32,aar33;

wire [7:0] awr00,awr01,awr02,awr03;//awr:用于字节替换的例化。为了例化ar,需要先将其传递给wire型数据,再对wire例化
wire [7:0] awr10,awr11,awr12,awr13;
wire [7:0] awr20,awr21,awr22,awr23;
wire [7:0] awr30,awr31,awr32,awr33;

wire [7:0] sa00,sa01,sa02,sa03;//sa:初始异或后,进行字节代换之后的明文(sbox_a)
wire [7:0] sa10,sa11,sa12,sa13;
wire [7:0] sa20,sa21,sa22,sa23;
wire [7:0] sa30,sa31,sa32,sa33;

reg [7:0] r00,r01,r02,r03;//r:用于行移位存放ar中的数据以便移位
reg [7:0] r10,r11,r12,r13;
reg [7:0] r20,r21,r22,r23;
reg [7:0] r30,r31,r32,r33;

wire [7:0] wk00,wk01,wk02,wk03,wk04,wk05,wk06,wk07,wk08,wk09,wk10,  //用于密钥扩展的例化(s盒输入)
           wk11,wk12,wk13,wk14,wk15,wk16,wk17,wk18,wk19,wk20,  //由于需要对reg进行例化,于是需要先将reg传递给wire,
           wk21,wk22,wk23,wk24,wk25,wk26,wk27,wk28,wk29,wk30,  //例化后再传回给reg
           wk31,wk32,wk33,wk34,wk35,wk36,wk37,wk38,wk39,wk40,wk41,wk42,wk43;

	  
wire [7:0] wrk00,wrk01,wrk02,wrk03,wrk04,wrk05,wrk06,wrk07,wrk08,wrk09,wrk10,//s盒的输出结果(密钥扩展)
           wrk11,wrk12,wrk13,wrk14,wrk15,wrk16,wrk17,wrk18,wrk19,wrk20,
           wrk21,wrk22,wrk23,wrk24,wrk25,wrk26,wrk27,wrk28,wrk29,wrk30,
           wrk31,wrk32,wrk33,wrk34,wrk35,wrk36,wrk37,wrk38,wrk39,wrk40,wrk41,wrk42,wrk43;


//这四行为密钥扩展的寄存器


reg [31:0] Rcon[9:0];

reg [31:0] w[43:0];//w:1字形式(4字节)保存的密钥。在每一轮中,
                   //每128位密钥保存为4个w。
reg [31:0] wr[43:0];	//wr:w的寄存器		
                     

//字节代换中用到的s盒替换

//百度说reg型变量不能直接例化,于是先将其传递给wire型变量,将wire例化后,后续再传回reg

assign awr00=ar00;assign awr01=ar01;assign awr02=ar02;assign awr03=ar03;
assign awr10=ar10;assign awr11=ar11;assign awr12=ar12;assign awr13=ar13;
assign awr20=ar20;assign awr21=ar21;assign awr22=ar22;assign awr23=ar23;
assign awr30=ar30;assign awr31=ar31;assign awr32=ar32;assign awr33=ar33;


AES_2_sbox s00(.ain(awr00),.aout(sa00)); AES_2_sbox s01(.ain(awr01),.aout(sa01));
AES_2_sbox s02(.ain(awr02),.aout(sa02)); AES_2_sbox s03(.ain(awr03),.aout(sa03));
AES_2_sbox s10(.ain(awr10),.aout(sa10)); AES_2_sbox s11(.ain(awr11),.aout(sa11));
AES_2_sbox s12(.ain(awr12),.aout(sa12)); AES_2_sbox s13(.ain(awr13),.aout(sa13));
AES_2_sbox s20(.ain(awr20),.aout(sa20)); AES_2_sbox s21(.ain(awr21),.aout(sa21));
AES_2_sbox s22(.ain(awr22),.aout(sa22)); AES_2_sbox s23(.ain(awr23),.aout(sa23));
AES_2_sbox s30(.ain(awr30),.aout(sa30)); AES_2_sbox s31(.ain(awr31),.aout(sa31));
AES_2_sbox s32(.ain(awr32),.aout(sa32)); AES_2_sbox s33(.ain(awr33),.aout(sa33));


//列混合中用到的乘法函数

function [7:0] two_times;
input [7:0] mixin_two;
begin
if (mixin_two[7]==0)
two_times={mixin_two[6:0],1'b0};
else
two_times={mixin_two[6:0],1'b0}^8'b00011011;
end
endfunction

function [7:0] three_times;
input [7:0] mixin_three;
begin
if (mixin_three[7]==0)
three_times={mixin_three[6:0],1'b0}^mixin_three;
else
three_times={mixin_three[6:0],1'b0}^8'b00011011^mixin_three;
end
endfunction							
					
					
//密钥扩展用到的例化,因为数组不能直接例化,所以需要将数组的reg传递给wire

assign wk00=w[3][7:0];        assign wk01=w[3][15:8];   
assign wk02=w[7][7:0];        assign wk03=w[7][15:8];   
assign wk04=w[11][7:0];       assign wk05=w[11][15:8];   
assign wk06=w[15][7:0];       assign wk07=w[15][15:8];   
assign wk08=w[19][7:0];       assign wk09=w[19][15:8];   
assign wk10=w[23][7:0];       assign wk11=w[23][15:8];   
assign wk12=w[27][7:0];       assign wk13=w[27][15:8];   
assign wk14=w[31][7:0];       assign wk15=w[31][15:8];   
assign wk16=w[35][7:0];       assign wk17=w[35][15:8];   
assign wk18=w[39][7:0];       assign wk19=w[39][15:8]; 
assign wk20=w[43][7:0];       assign wk21=w[43][15:8];   
  

assign wk22=w[3][23:16];      assign wk23=w[3][31:24];    
assign wk24=w[7][23:16];      assign wk25=w[7][31:24];    
assign wk26=w[11][23:16];     assign wk27=w[11][31:24];   
assign wk28=w[15][23:16];     assign wk29=w[15][31:24];   
assign wk30=w[19][23:16];     assign wk31=w[19][31:24];   
assign wk32=w[23][23:16];     assign wk33=w[23][31:24];   
assign wk34=w[27][23:16];     assign wk35=w[27][31:24];   
assign wk36=w[31][23:16];     assign wk37=w[31][31:24];   
assign wk38=w[35][23:16];     assign wk39=w[35][31:24];   
assign wk40=w[39][23:16];     assign wk41=w[39][31:24]; 
assign wk42=w[43][23:16];     assign wk43=w[43][31:24];   
   
  


AES_2_sbox  sk00(.ain (wk00),.aout (wrk00)); AES_2_sbox  sk01(.ain (wk01),.aout (wrk01));
AES_2_sbox  sk02(.ain (wk02),.aout (wrk02)); AES_2_sbox  sk03(.ain (wk03),.aout (wrk03));
AES_2_sbox  sk04(.ain (wk04),.aout (wrk04)); AES_2_sbox  sk05(.ain (wk05),.aout (wrk05));
AES_2_sbox  sk06(.ain (wk06),.aout (wrk06)); AES_2_sbox  sk07(.ain (wk07),.aout (wrk07));
AES_2_sbox  sk08(.ain (wk08),.aout (wrk08)); AES_2_sbox  sk09(.ain (wk09),.aout (wrk09));
AES_2_sbox  sk10(.ain (wk10),.aout (wrk10)); AES_2_sbox  sk11(.ain (wk11),.aout (wrk11));
AES_2_sbox  sk12(.ain (wk12),.aout (wrk12)); AES_2_sbox  sk13(.ain (wk13),.aout (wrk13));
AES_2_sbox  sk14(.ain (wk14),.aout (wrk14)); AES_2_sbox  sk15(.ain (wk15),.aout (wrk15));
AES_2_sbox  sk16(.ain (wk16),.aout (wrk16)); AES_2_sbox  sk17(.ain (wk17),.aout (wrk17));
AES_2_sbox  sk18(.ain (wk18),.aout (wrk18)); AES_2_sbox  sk19(.ain (wk19),.aout (wrk19));

AES_2_sbox  sk20(.ain (wk20),.aout (wrk20)); AES_2_sbox  sk21(.ain (wk21),.aout (wrk21));
AES_2_sbox  sk22(.ain (wk22),.aout (wrk22)); AES_2_sbox  sk23(.ain (wk23),.aout (wrk23));
AES_2_sbox  sk24(.ain (wk24),.aout (wrk24)); AES_2_sbox  sk25(.ain (wk25),.aout (wrk25));
AES_2_sbox  sk26(.ain (wk26),.aout (wrk26)); AES_2_sbox  sk27(.ain (wk27),.aout (wrk27));
AES_2_sbox  sk28(.ain (wk28),.aout (wrk28)); AES_2_sbox  sk29(.ain (wk29),.aout (wrk29));
AES_2_sbox  sk30(.ain (wk30),.aout (wrk30)); AES_2_sbox  sk31(.ain (wk31),.aout (wrk31));
AES_2_sbox  sk32(.ain (wk32),.aout (wrk32)); AES_2_sbox  sk33(.ain (wk33),.aout (wrk33));
AES_2_sbox  sk34(.ain (wk34),.aout (wrk34)); AES_2_sbox  sk35(.ain (wk35),.aout (wrk35));
AES_2_sbox  sk36(.ain (wk36),.aout (wrk36)); AES_2_sbox  sk37(.ain (wk37),.aout (wrk37));
AES_2_sbox  sk38(.ain (wk38),.aout (wrk38)); AES_2_sbox  sk39(.ain (wk39),.aout (wrk39));
AES_2_sbox  sk40(.ain (wk40),.aout (wrk40)); AES_2_sbox  sk41(.ain (wk41),.aout (wrk41));
AES_2_sbox  sk42(.ain (wk42),.aout (wrk42)); AES_2_sbox  sk43(.ain (wk43),.aout (wrk43));



integer  i;//i:用于加密轮数计数  注:若i用于循环计数(例如for,while),必须定义成integer,若是reg,会死循环
reg [3:0] j;//j:用于轮密钥加 轮数计数。由于我没用循环,而是用的if判断,然后case跳转来达到循环的效果,所以可用reg

reg [1:0] state_very;
reg [1:0] state_key_add;
reg [1:0] state_process;
reg [1:0] state_text_out;

reg [3:0] key_add;
reg [2:0] process;

reg [1:0] finish_state_very;
reg [1:0] finish_state_key_add;
reg [1:0] finish_state_process;
reg [1:0] finish_state_text_out;

always @(posedge clk or negedge rst) //初始准备 very first
begin
	if(rst==0)
		begin
		aar00<=0;aar01<=0;aar02<=0;aar03<=0;
		aar10<=0;aar11<=0;aar12<=0;aar13<=0;
		aar20<=0;aar21<=0;aar22<=0;aar23<=0;
		aar30<=0;aar31<=0;aar32<=0;aar33<=0;
		
		finish_state_very<=0;
		end
	else 
		begin			
			state_very<=1;
			if(state_very==1&finish_state_very==0)			
				begin
				
			//把明文存到寄存器中
			aar00<=a00;aar01<=a01;aar02<=a02;aar03<=a03;
			aar10<=a10;aar11<=a11;aar12<=a12;aar13<=a13;
			aar20<=a20;aar21<=a21;aar22<=a22;aar23<=a23;
			aar30<=a30;aar31<=a31;aar32<=a32;aar33<=a33;
	
			state_key_add<=1;
		   finish_state_very<=1;
				end
			
		end
end			


always @(posedge clk or negedge rst) //轮密钥加  key_round_add
begin
	if(rst==0)
		begin
		Rcon[0]<=0; 
		Rcon[1]<=0;
		Rcon[2]<=0;
		Rcon[3]<=0;
		Rcon[4]<=0;
		Rcon[5]<=0;
		Rcon[6]<=0;
		Rcon[7]<=0;
		Rcon[8]<=0;
		Rcon[9]<=0;
		
		w[1]<=0;w[2]<=0;w[3]<=0;w[4]<=0;w[5]<=0;w[6]<=0;w[7]<=0;w[8]<=0;w[9]<=0;w[10]<=0;
		w[11]<=0;w[12]<=0;w[13]<=0;w[14]<=0;w[15]<=0;w[16]<=0;w[17]<=0;w[18]<=0;w[19]<=0;w[20]<=0;
		w[21]<=0;w[22]<=0;w[23]<=0;w[24]<=0;w[25]<=0;w[26]<=0;w[27]<=0;w[28]<=0;w[29]<=0;w[30]<=0;
		w[31]<=0;w[32]<=0;w[33]<=0;w[34]<=0;w[35]<=0;w[36]<=0;w[37]<=0;w[38]<=0;w[39]<=0;w[40]<=0;
		w[41]<=0;w[42]<=0;w[43]<=0;
		
		wr[1]<=0;wr[2]<=0;wr[3]<=0;wr[4]<=0;wr[5]<=0;wr[6]<=0;wr[7]<=0;wr[8]<=0;wr[9]<=0;wr[10]<=0;
		wr[11]<=0;wr[12]<=0;wr[13]<=0;wr[14]<=0;wr[15]<=0;wr[16]<=0;wr[17]<=0;wr[18]<=0;wr[19]<=0;wr[20]<=0;
		wr[21]<=0;wr[22]<=0;wr[23]<=0;wr[24]<=0;wr[25]<=0;wr[26]<=0;wr[27]<=0;wr[28]<=0;wr[29]<=0;wr[30]<=0;
		wr[31]<=0;wr[32]<=0;wr[33]<=0;wr[34]<=0;wr[35]<=0;wr[36]<=0;wr[37]<=0;wr[38]<=0;wr[39]<=0;wr[40]<=0;
		wr[41]<=0;wr[42]<=0;wr[43]<=0;
		
		finish_state_key_add<=0;
		end
	else 
		begin
			if(state_key_add==1&finish_state_key_add==0)
				begin
				key_add<=0;				
					case(key_add)
0:
begin		
			i<=0;		
			
		   Rcon[0]<=32'h01000000;  
			Rcon[1]<=32'h02000000;
			Rcon[2]<=32'h04000000;
			Rcon[3]<=32'h08000000;
			Rcon[4]<=32'h10000000;
			Rcon[5]<=32'h20000000;
			Rcon[6]<=32'h40000000;
			Rcon[7]<=32'h80000000;
			Rcon[8]<=32'h1B000000;
			Rcon[9]<=32'h36000000;
								
			w[0]<={k00,k10,k20,k30};
			w[1]<={k01,k11,k21,k31};
			w[2]<={k02,k12,k22,k32};
			w[3]<={k03,k13,k23,k33};	
			
			key_add<=1;
end

1:       //将例化后的wire传回reg
begin

			wr[3][7:0]<=wrk00;    wr[3][15:8]<=wrk01;
			wr[7][7:0]<=wrk02;    wr[7][15:8]<=wrk03;
			wr[11][7:0]<=wrk04;   wr[11][15:8]<=wrk05;
			wr[15][7:0]<=wrk06;   wr[15][15:8]<=wrk07;
			wr[19][7:0]<=wrk08;   wr[19][15:8]<=wrk09;
			wr[23][7:0]<=wrk10;   wr[23][15:8]<=wrk11;
			wr[27][7:0]<=wrk12;   wr[27][15:8]<=wrk13;
			wr[31][7:0]<=wrk14;   wr[31][15:8]<=wrk15;
			wr[35][7:0]<=wrk16;   wr[35][15:8]<=wrk17;
			wr[39][7:0]<=wrk18;   wr[39][15:8]<=wrk19;
			wr[43][7:0]<=wrk20;   wr[43][15:8]<=wrk21;
			
			wr[3][23:16]<=wrk22;      wr[3][31:24]<=wrk23;
			wr[7][23:16]<=wrk24;      wr[7][31:24]<=wrk25;
			wr[11][23:16]<=wrk26;    wr[11][31:24]<=wrk27;
			wr[15][23:16]<=wrk28;    wr[15][31:24]<=wrk29;
			wr[19][23:16]<=wrk30;    wr[19][31:24]<=wrk31;
			wr[23][23:16]<=wrk32;    wr[23][31:24]<=wrk33;
			wr[27][23:16]<=wrk34;    wr[27][31:24]<=wrk35;
			wr[31][23:16]<=wrk36;    wr[31][31:24]<=wrk37;
			wr[35][23:16]<=wrk38;    wr[35][31:24]<=wrk39;
			wr[39][23:16]<=wrk40;    wr[39][31:24]<=wrk41;
			wr[43][23:16]<=wrk42;    wr[43][31:24]<=wrk43;
						
			key_add<=2;
end

2:
begin
		
			wr[4*i+3'd3]<={wr[4*i+3'd3][23:0],wr[4*i+3'd3][31:24]};//移位
																	 //移位和s盒代换的顺序可以交换
													 
			key_add<=3;														 
end
																	 
3:
begin					
					wr[4*i+3'd3]<=(wr[4*i+3'd3])^(Rcon[i]);//与轮常量异或

					key_add<=4;
end

4:             //由于非阻塞赋值是同步进行的,若把4-7放进同一步,会出现问题:
               //例如把w5=w1^w4也放进第4步,而w4此时的值是前一个时钟周期结束后w4的值
					//但w4直到第4步结束后才算出值,那么w5=w1^w4中w4就没有值。所以这几步要分开
begin					
					w[4*i+3'd4]<=(w[4*i])^(wr[4*i+3'd3]);
					
					key_add<=5;
end

5:					
begin
					w[4*i+3'd5]<=w[4*i+3'd1]^w[4*i+3'd4];					
					
					key_add<=6;
end

6:
begin
					w[4*i+3'd6]<=w[4*i+3'd2]^w[4*i+3'd5];
					
					key_add<=7;
end

7:
begin					
					w[4*i+3'd7]<=w[4*i+3'd3]^w[4*i+3'd6];
					
					key_add<=8;
end
					
8:
begin
					if(i<9)
						begin					
						key_add<=1;						
						i<=i+1;
						end
					else 
						begin
						state_process<=1;
						finish_state_key_add<=1;
						end
end
			
					endcase
					
				end
			
		end
end			





always @(posedge clk or negedge rst) //过程执行 process
begin
	if(rst==0)
		begin
		ar00<=0;ar01<=0;ar02<=0;ar03<=0;
		ar10<=0;ar11<=0;ar12<=0;ar13<=0;
		ar20<=0;ar21<=0;ar22<=0;ar23<=0;
		ar30<=0;ar31<=0;ar32<=0;ar33<=0;
		
		r00<=0;r01<=0;r02<=0;r03<=0;
		r10<=0;r11<=0;r12<=0;r13<=0;
		r20<=0;r21<=0;r22<=0;r23<=0;
		r30<=0;r31<=0;r32<=0;r33<=0;
		
		finish_state_process<=0;
		end
	else 
		begin
			if(state_process==1&finish_state_process==0)
				begin
				process<=0;
					case(process)	
0:		         // 0:初始异或			
begin
					j<=1;
					
					ar00<=aar00^k00;ar01<=aar01^k01;ar02<=aar02^k02;ar03<=aar03^k03;
					ar10<=aar10^k10;ar11<=aar11^k11;ar12<=aar12^k12;ar13<=aar13^k13;
					ar20<=aar20^k20;ar21<=aar21^k21;ar22<=aar22^k22;ar23<=aar23^k23;
					ar30<=aar30^k30;ar31<=aar31^k31;ar32<=aar32^k32;ar33<=aar33^k33;
										
					process<=1;
end

1:	            //1:字节代换
begin				
					ar00<=sa00;ar01<=sa01;ar02<=sa02;ar03<=sa03;
					ar10<=sa10;ar11<=sa11;ar12<=sa12;ar13<=sa13;
					ar20<=sa20;ar21<=sa21;ar22<=sa22;ar23<=sa23;
					ar30<=sa30;ar31<=sa31;ar32<=sa32;ar33<=sa33;	
										
					process<=2;
end

2:             //2-3:行移位
begin					
					r00<=ar00;r01<=ar01;r02<=ar02;r03<=ar03;
					r10<=ar10;r11<=ar11;r12<=ar12;r13<=ar13;
					r20<=ar20;r21<=ar21;r22<=ar22;r23<=ar23;
					r30<=ar30;r31<=ar31;r32<=ar32;r33<=ar33;
					
					process<=3;
end

3:
begin
					ar00<=r00;ar01<=r01;ar02<=r02;ar03<=r03;
					ar10<=r11;ar11<=r12;ar12<=r13;ar13<=r10;
					ar20<=r22;ar21<=r23;ar22<=r20;ar23<=r21;
					ar30<=r33;ar31<=r30;ar32<=r31;ar33<=r32;
					
					if(j==10) //最后一轮不用列混合
					process<=6;
					else
					process<=4;
end			

4:             //4-5:列混合
begin					
					r00<=ar00;r01<=ar01;r02<=ar02;r03<=ar03;
					r10<=ar10;r11<=ar11;r12<=ar12;r13<=ar13;
					r20<=ar20;r21<=ar21;r22<=ar22;r23<=ar23;
					r30<=ar30;r31<=ar31;r32<=ar32;r33<=ar33;
					
					process<=5;
end

5:
begin
					ar00<=two_times(r00)^three_times(r10)^r20^r30;
					ar01<=two_times(r01)^three_times(r11)^r21^r31;
					ar02<=two_times(r02)^three_times(r12)^r22^r32;
					ar03<=two_times(r03)^three_times(r13)^r23^r33;
					
					ar10<=r00^two_times(r10)^three_times(r20)^r30;
					ar11<=r01^two_times(r11)^three_times(r21)^r31;
					ar12<=r02^two_times(r12)^three_times(r22)^r32;
					ar13<=r03^two_times(r13)^three_times(r23)^r33;
					
					ar20<=r00^r10^two_times(r20)^three_times(r30);
					ar21<=r01^r11^two_times(r21)^three_times(r31);
					ar22<=r02^r12^two_times(r22)^three_times(r32);
					ar23<=r03^r13^two_times(r23)^three_times(r33);
					
					ar30<=three_times(r00)^r10^r20^two_times(r30);
					ar31<=three_times(r01)^r11^r21^two_times(r31);
					ar32<=three_times(r02)^r12^r22^two_times(r32);
					ar33<=three_times(r03)^r13^r23^two_times(r33);
					
					process<=6;
end		

6:             //轮密钥加
begin				
					
					{ar00,ar10,ar20,ar30}<={ar00,ar10,ar20,ar30}^w[4*j];
					{ar01,ar11,ar21,ar31}<={ar01,ar11,ar21,ar31}^w[4*j+3'd1];
					{ar02,ar12,ar22,ar32}<={ar02,ar12,ar22,ar32}^w[4*j+3'd2];
					{ar03,ar13,ar23,ar33}<={ar03,ar13,ar23,ar33}^w[4*j+3'd3];
					
				   j<=j+1;
				
					process<=7;	
end					
7:
begin					
					if(j<11)			
						process<=1;					
					else
						begin
						state_text_out<=1;
						finish_state_process<=1;
						end
end
						

					endcase
				end
		end				
end			



always @(posedge clk or negedge rst) //密文输出  text_out
begin
	if(rst==0)
		begin
		z<=0;
		finish_state_text_out<=0;
		end
	else 
		begin
			if(state_text_out==1&finish_state_text_out==0)
				begin			
				z<={ar00,ar10,ar20,ar30,ar01,ar11,ar21,ar31,ar02,ar12,ar22,ar32,ar03,ar13,ar23,ar33};
				finish_state_text_out<=1;
				end
			
		end
end			

endmodule

二、S盒module

module AES_2_sbox(ain,aout);
input	[7:0]	ain;
output [7:0]	aout;
wire [7:0]	ain;
reg [7:0]	aout;

always @(ain)
begin
	case(ain)		
	   8'h00: aout=8'h63;
	   8'h01: aout=8'h7c;
	   8'h02: aout=8'h77;
	   8'h03: aout=8'h7b;
	   8'h04: aout=8'hf2;
	   8'h05: aout=8'h6b;
	   8'h06: aout=8'h6f;
	   8'h07: aout=8'hc5;
	   8'h08: aout=8'h30;
	   8'h09: aout=8'h01;
	   8'h0a: aout=8'h67;
	   8'h0b: aout=8'h2b;
	   8'h0c: aout=8'hfe;
	   8'h0d: aout=8'hd7;
	   8'h0e: aout=8'hab;
	   8'h0f: aout=8'h76;
	   8'h10: aout=8'hca;
	   8'h11: aout=8'h82;
	   8'h12: aout=8'hc9;
	   8'h13: aout=8'h7d;
	   8'h14: aout=8'hfa;
	   8'h15: aout=8'h59;
	   8'h16: aout=8'h47;
	   8'h17: aout=8'hf0;
	   8'h18: aout=8'had;
	   8'h19: aout=8'hd4;
	   8'h1a: aout=8'ha2;
	   8'h1b: aout=8'haf;
	   8'h1c: aout=8'h9c;
	   8'h1d: aout=8'ha4;
	   8'h1e: aout=8'h72;
	   8'h1f: aout=8'hc0;
	   8'h20: aout=8'hb7;
	   8'h21: aout=8'hfd;
	   8'h22: aout=8'h93;
	   8'h23: aout=8'h26;
	   8'h24: aout=8'h36;
	   8'h25: aout=8'h3f;
	   8'h26: aout=8'hf7;
	   8'h27: aout=8'hcc;
	   8'h28: aout=8'h34;
	   8'h29: aout=8'ha5;
	   8'h2a: aout=8'he5;
	   8'h2b: aout=8'hf1;
	   8'h2c: aout=8'h71;
	   8'h2d: aout=8'hd8;
	   8'h2e: aout=8'h31;
	   8'h2f: aout=8'h15;
	   8'h30: aout=8'h04;
	   8'h31: aout=8'hc7;
	   8'h32: aout=8'h23;
	   8'h33: aout=8'hc3;
	   8'h34: aout=8'h18;
	   8'h35: aout=8'h96;
	   8'h36: aout=8'h05;
	   8'h37: aout=8'h9a;
	   8'h38: aout=8'h07;
	   8'h39: aout=8'h12;
	   8'h3a: aout=8'h80;
	   8'h3b: aout=8'he2;
	   8'h3c: aout=8'heb;
	   8'h3d: aout=8'h27;
	   8'h3e: aout=8'hb2;
	   8'h3f: aout=8'h75;
	   8'h40: aout=8'h09;
	   8'h41: aout=8'h83;
	   8'h42: aout=8'h2c;
	   8'h43: aout=8'h1a;
	   8'h44: aout=8'h1b;
	   8'h45: aout=8'h6e;
	   8'h46: aout=8'h5a;
	   8'h47: aout=8'ha0;
	   8'h48: aout=8'h52;
	   8'h49: aout=8'h3b;
	   8'h4a: aout=8'hd6;
	   8'h4b: aout=8'hb3;
	   8'h4c: aout=8'h29;
	   8'h4d: aout=8'he3;
	   8'h4e: aout=8'h2f;
	   8'h4f: aout=8'h84;
	   8'h50: aout=8'h53;
	   8'h51: aout=8'hd1;
	   8'h52: aout=8'h00;
	   8'h53: aout=8'hed;
	   8'h54: aout=8'h20;
	   8'h55: aout=8'hfc;
	   8'h56: aout=8'hb1;
	   8'h57: aout=8'h5b;
	   8'h58: aout=8'h6a;
	   8'h59: aout=8'hcb;
	   8'h5a: aout=8'hbe;
	   8'h5b: aout=8'h39;
	   8'h5c: aout=8'h4a;
	   8'h5d: aout=8'h4c;
	   8'h5e: aout=8'h58;
	   8'h5f: aout=8'hcf;
	   8'h60: aout=8'hd0;
	   8'h61: aout=8'hef;
	   8'h62: aout=8'haa;
	   8'h63: aout=8'hfb;
	   8'h64: aout=8'h43;
	   8'h65: aout=8'h4d;
	   8'h66: aout=8'h33;
	   8'h67: aout=8'h85;
	   8'h68: aout=8'h45;
	   8'h69: aout=8'hf9;
	   8'h6a: aout=8'h02;
	   8'h6b: aout=8'h7f;
	   8'h6c: aout=8'h50;
	   8'h6d: aout=8'h3c;
	   8'h6e: aout=8'h9f;
	   8'h6f: aout=8'ha8;
	   8'h70: aout=8'h51;
	   8'h71: aout=8'ha3;
	   8'h72: aout=8'h40;
	   8'h73: aout=8'h8f;
	   8'h74: aout=8'h92;
	   8'h75: aout=8'h9d;
	   8'h76: aout=8'h38;
	   8'h77: aout=8'hf5;
	   8'h78: aout=8'hbc;
	   8'h79: aout=8'hb6;
	   8'h7a: aout=8'hda;
	   8'h7b: aout=8'h21;
	   8'h7c: aout=8'h10;
	   8'h7d: aout=8'hff;
	   8'h7e: aout=8'hf3;
	   8'h7f: aout=8'hd2;
	   8'h80: aout=8'hcd;
	   8'h81: aout=8'h0c;
	   8'h82: aout=8'h13;
	   8'h83: aout=8'hec;
	   8'h84: aout=8'h5f;
	   8'h85: aout=8'h97;
	   8'h86: aout=8'h44;
	   8'h87: aout=8'h17;
	   8'h88: aout=8'hc4;
	   8'h89: aout=8'ha7;
	   8'h8a: aout=8'h7e;
	   8'h8b: aout=8'h3d;
	   8'h8c: aout=8'h64;
	   8'h8d: aout=8'h5d;
	   8'h8e: aout=8'h19;
	   8'h8f: aout=8'h73;
	   8'h90: aout=8'h60;
	   8'h91: aout=8'h81;
	   8'h92: aout=8'h4f;
	   8'h93: aout=8'hdc;
	   8'h94: aout=8'h22;
	   8'h95: aout=8'h2a;
	   8'h96: aout=8'h90;
	   8'h97: aout=8'h88;
	   8'h98: aout=8'h46;
	   8'h99: aout=8'hee;
	   8'h9a: aout=8'hb8;
	   8'h9b: aout=8'h14;
	   8'h9c: aout=8'hde;
	   8'h9d: aout=8'h5e;
	   8'h9e: aout=8'h0b;
	   8'h9f: aout=8'hdb;
	   8'ha0: aout=8'he0;
	   8'ha1: aout=8'h32;
	   8'ha2: aout=8'h3a;
	   8'ha3: aout=8'h0a;
	   8'ha4: aout=8'h49;
	   8'ha5: aout=8'h06;
	   8'ha6: aout=8'h24;
	   8'ha7: aout=8'h5c;
	   8'ha8: aout=8'hc2;
	   8'ha9: aout=8'hd3;
	   8'haa: aout=8'hac;
	   8'hab: aout=8'h62;
	   8'hac: aout=8'h91;
	   8'had: aout=8'h95;
	   8'hae: aout=8'he4;
	   8'haf: aout=8'h79;
	   8'hb0: aout=8'he7;
	   8'hb1: aout=8'hc8;
	   8'hb2: aout=8'h37;
	   8'hb3: aout=8'h6d;
	   8'hb4: aout=8'h8d;
	   8'hb5: aout=8'hd5;
	   8'hb6: aout=8'h4e;
	   8'hb7: aout=8'ha9;
	   8'hb8: aout=8'h6c;
	   8'hb9: aout=8'h56;
	   8'hba: aout=8'hf4;
	   8'hbb: aout=8'hea;
	   8'hbc: aout=8'h65;
	   8'hbd: aout=8'h7a;
	   8'hbe: aout=8'hae;
	   8'hbf: aout=8'h08;
	   8'hc0: aout=8'hba;
	   8'hc1: aout=8'h78;
	   8'hc2: aout=8'h25;
	   8'hc3: aout=8'h2e;
	   8'hc4: aout=8'h1c;
	   8'hc5: aout=8'ha6;
	   8'hc6: aout=8'hb4;
	   8'hc7: aout=8'hc6;
	   8'hc8: aout=8'he8;
	   8'hc9: aout=8'hdd;
	   8'hca: aout=8'h74;
	   8'hcb: aout=8'h1f;
	   8'hcc: aout=8'h4b;
	   8'hcd: aout=8'hbd;
	   8'hce: aout=8'h8b;
	   8'hcf: aout=8'h8a;
	   8'hd0: aout=8'h70;
	   8'hd1: aout=8'h3e;
	   8'hd2: aout=8'hb5;
	   8'hd3: aout=8'h66;
	   8'hd4: aout=8'h48;
	   8'hd5: aout=8'h03;
	   8'hd6: aout=8'hf6;
	   8'hd7: aout=8'h0e;
	   8'hd8: aout=8'h61;
	   8'hd9: aout=8'h35;
	   8'hda: aout=8'h57;
	   8'hdb: aout=8'hb9;
	   8'hdc: aout=8'h86;
	   8'hdd: aout=8'hc1;
	   8'hde: aout=8'h1d;
	   8'hdf: aout=8'h9e;
	   8'he0: aout=8'he1;
	   8'he1: aout=8'hf8;
	   8'he2: aout=8'h98;
	   8'he3: aout=8'h11;
	   8'he4: aout=8'h69;
	   8'he5: aout=8'hd9;
	   8'he6: aout=8'h8e;
	   8'he7: aout=8'h94;
	   8'he8: aout=8'h9b;
	   8'he9: aout=8'h1e;
	   8'hea: aout=8'h87;
	   8'heb: aout=8'he9;
	   8'hec: aout=8'hce;
	   8'hed: aout=8'h55;
	   8'hee: aout=8'h28;
	   8'hef: aout=8'hdf;
	   8'hf0: aout=8'h8c;
	   8'hf1: aout=8'ha1;
	   8'hf2: aout=8'h89;
	   8'hf3: aout=8'h0d;
	   8'hf4: aout=8'hbf;
	   8'hf5: aout=8'he6;
	   8'hf6: aout=8'h42;
	   8'hf7: aout=8'h68;
	   8'hf8: aout=8'h41;
	   8'hf9: aout=8'h99;
	   8'hfa: aout=8'h2d;
	   8'hfb: aout=8'h0f;
	   8'hfc: aout=8'hb0;
	   8'hfd: aout=8'h54;
	   8'hfe: aout=8'hbb;
	   8'hff: aout=8'h16;
		default:;
	endcase
end

endmodule

三、测试代码

module AES_2_tb;

reg rst,clk;

reg [7:0] a00,a01,a02,a03,
			 a10,a11,a12,a13,
			 a20,a21,a22,a23,
			 a30,a31,a32,a33;
			
reg [7:0] k00,k01,k02,k03,
			 k10,k11,k12,k13,
			 k20,k21,k22,k23,
			 k30,k31,k32,k33;
			 
			 
wire [127:0] z;


AES_2 aestb(.rst(rst),.clk(clk),

          .a00(a00),.a01(a01),.a02(a02),.a03(a03),
		    .a10(a10),.a11(a11),.a12(a12),.a13(a13),
			 .a20(a20),.a21(a21),.a22(a22),.a23(a23),
			 .a30(a30),.a31(a31),.a32(a32),.a33(a33),
				
				.k00(k00),.k01(k01),.k02(k02),.k03(k03),
				.k10(k10),.k11(k11),.k12(k12),.k13(k13),
				.k20(k20),.k21(k21),.k22(k22),.k23(k23),
				.k30(k30),.k31(k31),.k32(k32),.k33(k33),
				
				.z(z));
				
always #100 clk=~clk; //时钟周期设置为200ps

initial
begin
rst=0;
clk=0;

#100


rst=1;
clk=0;

a00=8'h23;a01=8'h63;a02=8'h49;a03=8'h66;
a10=8'h3e;a11=8'ha4;a12=8'ha7;a13=8'h2e;
a20=8'h1b;a21=8'hd2;a22=8'hd3;a23=8'hf5;
a30=8'h8c;a31=8'h47;a32=8'h5c;a33=8'h8d;
			
k00=8'h3c;k01=8'h57;k02=8'h90;k03=8'hac;
k10=8'ha1;k11=8'hf0;k12=8'h2e;k13=8'hc1;
k20=8'h0b;k21=8'h19;k22=8'h13;k23=8'h07;
k30=8'h21;k31=8'h16;k32=8'h80;k33=8'hbd;

//a=233e1b8c63a4d24749a7d35c662ef58d
//k=3ca10b2157f01916902e1380acc107bd

#31000 $finish;
end

endmodule

modelsim仿真

 结果正确

附上在线AES加密工具网站:AES在线解密 AES在线加密 Aes online hex 十六进制密钥 - The X 在线工具

设置如图所示。密钥记得输在“解密”按钮上面这个黄色框里面,不然输不下128位。

一些小tips

1. 虽然warning不影响编译,但是若得不到想要的波形结果,那么就该去看看这些warning。因为        warning不涉及语法错误,但可能影响功能完整性

2.modelsim中,仿真出波形后,单击右键,选择radix,可以设置数据进制

3.排查代码中的步骤错误,最直接的方法就是在modelsim中看相关的数据,一步一步找总能找到的

4.写注释是真的爽,不然等两天我自己都看不懂我写的代码了
 

 

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐