最近学习了AES加密算法的Verilog实现,在此记录一下学习心得,以及将代码分享给大家
算法原理:AES加密算法的详细介绍与实现_TimeShatter的博客-CSDN博客_aes加密
感谢这位大佬的文章,讲的非常详细,帮了我不少忙
之前在网上到处找代码,发现找的并不容易,注释也写的很少。在学习了其他大佬的代码后,我完成了自己的代码,在此分享给大家。
我只是一个Verilog的初学者,代码水平不高。代码只以正确实现功能为目的,并没有考虑到资源的占用、延时等等实际工程问题,还请批评指正。不过我写代码就很喜欢写注释,希望这能帮助和我一样刚入门的同学更容易看懂。
目录
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.写注释是真的爽,不然等两天我自己都看不懂我写的代码了