一、AES的Verilog流水线实现原理
AES(高级加密标准)是一种对称加密算法,广泛应用于信息安全领域。Verilog流水线实现能够显著提高AES加密的吞吐量,使其适合高速数据处理场景。该实现采用128位密钥(AES-128),通过将加密过程分解为多个流水线阶段,每个时钟周期可以处理不同的数据块。
流水线设计的关键在于将AES的10轮加密操作划分为独立的处理阶段。每个加密轮次由四个基本操作组成:字节替换(SubBytes)、行移位(ShiftRows)、列混淆(MixColumns)和轮密钥加(AddRoundKey)。在流水线实现中,这些操作被分配到不同的硬件模块,数据在各模块间流动时可以实现并行处理。
密钥扩展模块采用另一种流水线策略,它预先计算所有轮密钥并存储在寄存器中。这种设计虽然增加了初始延迟,但一旦密钥扩展完成,加密过程可以全速运行,无需等待轮密钥计算。主密钥通过load_mkey信号加载后,模块会在内部生成10个轮密钥。
整个系统采用同步设计,所有操作在时钟上升沿触发。busy信号指示系统状态,防止在密钥扩展或加密过程中加载新数据。这种设计在保证数据安全性的同时,实现了较高的时钟频率和吞吐量,适合FPGA或ASIC实现。
二、Verilog代码解析
1. aes_top模块
aes_top是系统的顶层模块,负责连接密钥扩展和加密模块,并提供统一的外部接口。它包含时钟、复位、主密钥加载、明文输入和密文输出等信号。busy信号由密钥扩展和加密模块的busy信号逻辑或得到,指示系统是否就绪。
该模块实例化了两个主要子模块:key_expand和encrypt。key_expand负责从主密钥生成所有轮密钥,encrypt则执行实际的AES加密操作。round_keys_flatten信号将11个128位轮密钥拼接成1408位宽总线,在模块间传递。
顶层设计采用了清晰的流水线控制策略。当load_mkey有效时加载主密钥,din_valid有效时开始加密过程。dout_valid信号指示输出密文有效,完成了从输入到输出的完整流水线控制。
module aes_top (
input clk,
input rst_n,
input [127:0] mkey,
input load_mkey,
input [127:0] plaintext,
input din_valid,
output [127:0] ciphertext,
output dout_valid,
output busy
);
wire [1407:0] round_keys_flatten;
wire encrypt_busy;
wire key_expand_busy;
assign busy = encrypt_busy | key_expand_busy;
encrypt u_en (
.clk(clk),
.rst_n(rst_n),
.din_valid(din_valid),
.plaintext(plaintext),
.ciphertext(ciphertext),
.dout_valid(dout_valid),
.busy(encrypt_busy),
.round_keys_flatten(round_keys_flatten)
);
key_expand u_ke (
.clk(clk),
.rst_n(rst_n),
.load_mkey(load_mkey),
.mkey(mkey),
.round_keys_flatten(round_keys_flatten),
.busy(key_expand_busy)
);
endmodule
2. key_expand模块
key_expand模块实现了AES的密钥扩展算法,将128位主密钥扩展为11个128位轮密钥。模块采用状态机控制,round_ctrl寄存器实现10步扩展过程。每次扩展使用rcon常量进行异或操作,并通过sbox进行非线性变换。
密钥扩展算法基于递推关系,每个新密钥字由前一个密钥字和4个周期前的密钥字计算得到。模块中w0-w3寄存器存储中间状态,rcon_new计算下一轮的轮常量。扩展完成后,所有轮密钥存储在round_keys数组中。
该设计优化了时序性能,通过并行计算四个密钥字(w0_new到w3_new)减少关键路径延迟。busy信号在密钥扩展期间保持有效,防止在扩展过程中加载新主密钥。
module key_expand (
input clk,
input rst_n,
input load_mkey,
input [127:0] mkey,
output [1407:0] round_keys_flatten,
output busy
);
reg [9:0] round_ctrl;
reg [7:0] rcon;
reg [31:0] w0, w1, w2, w3;
reg [127:0] round_keys[0:10];
wire [31:0] sbox_out;
wire [7:0] rcon_new = {rcon[6:0], 1'b0} ^ (rcon[7] ? 8'h1b : 8'h0);
wire [31:0] w0_new = w0 ^ {sbox_out[31:24] ^ rcon, sbox_out[23:0]};
wire [31:0] w1_new = w1 ^ w0_new;
wire [31:0] w2_new = w2 ^ w1_new;
wire [31:0] w3_new = w3 ^ w2_new;
wire start_key_expand = load_mkey & ~(|round_ctrl);
integer i;
assign round_keys_flatten = {
round_keys[0], round_keys[1], round_keys[2],
round_keys[3], round_keys[4], round_keys[5],
round_keys[6], round_keys[7], round_keys[8],
round_keys[9], round_keys[10]
};
assign busy = load_mkey | (|round_ctrl);
always @(posedge clk, negedge rst_n) begin
if (~rst_n) begin
rcon <= 8'h00;
{w0, w1, w2, w3} <= 128'h0;
end else begin
if (start_key_expand) begin
{w0, w1, w2, w3} <= mkey;
rcon <= 8'h01;
end else if (|round_ctrl) begin
{w0, w1, w2, w3} <= {w0_new, w1_new, w2_new, w3_new};
rcon <= rcon_new;
end
end
end
always @(posedge clk) begin
if (start_key_expand) begin
round_keys[0] <= mkey;
end else if (|round_ctrl) begin
round_keys[10] <= {w0_new, w1_new, w2_new, w3_new};
for (i = 10; i > 1; i = i - 1) begin
round_keys[i-1] <= round_keys[i];
end
end
end
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
round_ctrl <= 0;
end else begin
if (load_mkey) begin
round_ctrl <= 1;
end else if (busy) begin
round_ctrl <= {round_ctrl[8:0], 1'b0};
end
end
end
sbox sbox1 (.s_in (w3[31:24]), .s_out(sbox_out[7:0]));
sbox sbox2 (.s_in (w3[7:0]), .s_out(sbox_out[15:8]));
sbox sbox3 (.s_in (w3[15:8]), .s_out(sbox_out[23:16]));
sbox sbox4 (.s_in (w3[23:16]), .s_out(sbox_out[31:24]));
endmodule
3. encrypt模块
encrypt模块实现了AES加密的流水线结构。它包含11个状态寄存器(state[0]到state[10]),对应初始密钥加和10轮加密。模块使用round_ctrl移位寄存器控制流水线推进,每个时钟周期数据向下一级移动。
加密过程分为三个阶段:初始轮密钥加、9轮标准加密和最后一轮特殊加密。generate语句实例化了9个encrypt_round模块和1个encrypt_round_last模块,形成完整流水线。round_keys_flatten输入被解包为11个轮密钥。
dout_valid信号由round_ctrl的第10位产生,精确指示加密完成时刻。busy信号在加密过程中保持高电平,防止新数据过早进入流水线。这种设计实现了每个时钟周期处理一个新数据块的吞吐量。
module encrypt (
input clk,
input rst_n,
input din_valid,
input [127:0] plaintext,
output [127:0] ciphertext,
output dout_valid,
output busy,
input [1407:0] round_keys_flatten
);
reg [11:0] round_ctrl;
reg [127:0] state[0:10];
wire [127:0] round_out[0:9];
wire [127:0] round_keys[0:10];
integer i;
genvar j;
assign {
round_keys[0], round_keys[1], round_keys[2],
round_keys[3], round_keys[4], round_keys[5],
round_keys[6], round_keys[7], round_keys[8],
round_keys[9], round_keys[10]
} = round_keys_flatten;
assign ciphertext = state[10];
assign busy = din_valid | (|round_ctrl);
assign dout_valid = round_ctrl[10];
always @(posedge clk, negedge rst_n) begin
if (~rst_n) begin
for (i = 0; i < 11; i = i + 1) begin
state[i] <= 128'h0;
end
end else begin
if (din_valid) begin
state[0] <= plaintext ^ round_keys[0];
end
for (i = 1; i < 11; i = i + 1) begin
state[i] <= round_out[i-1];
end
end
end
always @(posedge clk, negedge rst_n) begin
if (~rst_n) begin
round_ctrl <= 12'd0;
end else begin
round_ctrl <= {round_ctrl[10:0], din_valid};
end
end
generate
for (j = 0; j < 9; j = j + 1) begin : enr_instances
encrypt_round u_er (
.din(state[j]),
.round_key(round_keys[j+1]),
.dout(round_out[j])
);
end
encrypt_round_last u_er_last (
.din(state[9]),
.round_key(round_keys[10]),
.dout(round_out[9])
);
endgenerate
endmodule
4. encrypt_round模块
encrypt_round实现标准AES加密轮次,包含SubBytes、ShiftRows、MixColumns和AddRoundKey四个步骤。模块使用generate语句实例化16个sbox,并行处理所有字节替换操作。
ShiftRows通过硬连线重新排列字节位置,不消耗逻辑资源。MixColumns使用函数实现,通过gm2和gm3函数计算伽罗瓦域乘法,然后组合成新的列。最后与轮密钥异或完成AddRoundKey操作。
该设计优化了组合逻辑路径,所有步骤在一个时钟周期内完成。模块化设计使得每轮加密可以独立工作,形成高效流水线。
module encrypt_round (
input [127:0] din,
input [127:0] round_key,
output [127:0] dout
);
wire [127:0] sbox_out, shift_out, mix_out;
genvar i;
generate
for (i = 0; i < 16; i = i + 1) begin : sbox_instances
sbox u_sbox (
.s_in (din[i*8+:8]),
.s_out(sbox_out[i*8+:8])
);
end
endgenerate
assign shift_out[7:0] = sbox_out[39:32];
assign shift_out[15:8] = sbox_out[79:72];
assign shift_out[23:16] = sbox_out[119:112];
assign shift_out[31:24] = sbox_out[31:24];
assign shift_out[39:32] = sbox_out[71:64];
assign shift_out[47:40] = sbox_out[111:104];
assign shift_out[55:48] = sbox_out[23:16];
assign shift_out[63:56] = sbox_out[63:56];
assign shift_out[71:64] = sbox_out[103:96];
assign shift_out[79:72] = sbox_out[15:8];
assign shift_out[87:80] = sbox_out[55:48];
assign shift_out[95:88] = sbox_out[95:88];
assign shift_out[103:96] = sbox_out[7:0];
assign shift_out[111:104] = sbox_out[47:40];
assign shift_out[119:112] = sbox_out[87:80];
assign shift_out[127:120] = sbox_out[127:120];
assign mix_out = mixcolumns(shift_out);
assign dout = mix_out ^ round_key;
function [7:0] gm2(input [7:0] op);
begin
gm2 = {op[6:0], 1'b0} ^ (8'h1b & {8{op[7]}});
end
endfunction
function [7:0] gm3(input [7:0] op);
begin
gm3 = gm2(op) ^ op;
end
endfunction
function [31:0] mixw(input [31:0] w);
reg [7:0] b0, b1, b2, b3;
reg [7:0] mb0, mb1, mb2, mb3;
begin
{b0, b1, b2, b3} = w;
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};
end
endfunction
function [127:0] mixcolumns(input [127:0] data);
reg [31:0] w0, w1, w2, w3;
begin
{w0, w1, w2, w3} = data;
mixcolumns = {mixw(w0), mixw(w1), mixw(w2), mixw(w3)};
end
endfunction
endmodule
module encrypt_round_last (
input [127:0] din,
input [127:0] round_key,
output [127:0] dout
);
wire [127:0] sbox_out, shift_out, mix_out;
genvar i;
generate
for (i = 0; i < 16; i = i + 1) begin : sbox_instances
sbox u_sbox (
.s_in (din[i*8+:8]),
.s_out(sbox_out[i*8+:8])
);
end
endgenerate
assign shift_out[7:0] = sbox_out[39:32];
assign shift_out[15:8] = sbox_out[79:72];
assign shift_out[23:16] = sbox_out[119:112];
assign shift_out[31:24] = sbox_out[31:24];
assign shift_out[39:32] = sbox_out[71:64];
assign shift_out[47:40] = sbox_out[111:104];
assign shift_out[55:48] = sbox_out[23:16];
assign shift_out[63:56] = sbox_out[63:56];
assign shift_out[71:64] = sbox_out[103:96];
assign shift_out[79:72] = sbox_out[15:8];
assign shift_out[87:80] = sbox_out[55:48];
assign shift_out[95:88] = sbox_out[95:88];
assign shift_out[103:96] = sbox_out[7:0];
assign shift_out[111:104] = sbox_out[47:40];
assign shift_out[119:112] = sbox_out[87:80];
assign shift_out[127:120] = sbox_out[127:120];
assign dout = shift_out ^ round_key;
endmodule
5. sbox模块
sbox模块实现AES的字节替换表,使用查找表方式实现非线性变换。模块包含256个8位预计算值,通过输入字节直接寻址获得输出。
module sbox(
input [7:0] s_in,
output [7:0] s_out
);
reg [7:0] sbox[0:255];
initial begin
sbox[000]=8'h63; sbox[001]=8'h7c; sbox[002]=8'h77; sbox[003]=8'h7b; sbox[004]=8'hf2; sbox[005]=8'h6b; sbox[006]=8'h6f; sbox[007]=8'hc5;
sbox[008]=8'h30; sbox[009]=8'h01; sbox[010]=8'h67; sbox[011]=8'h2b; sbox[012]=8'hfe; sbox[013]=8'hd7; sbox[014]=8'hab; sbox[015]=8'h76;
sbox[016]=8'hca; sbox[017]=8'h82; sbox[018]=8'hc9; sbox[019]=8'h7d; sbox[020]=8'hfa; sbox[021]=8'h59; sbox[022]=8'h47; sbox[023]=8'hf0;
sbox[024]=8'had; sbox[025]=8'hd4; sbox[026]=8'ha2; sbox[027]=8'haf; sbox[028]=8'h9c; sbox[029]=8'ha4; sbox[030]=8'h72; sbox[031]=8'hc0;
sbox[032]=8'hb7; sbox[033]=8'hfd; sbox[034]=8'h93; sbox[035]=8'h26; sbox[036]=8'h36; sbox[037]=8'h3f; sbox[038]=8'hf7; sbox[039]=8'hcc;
sbox[040]=8'h34; sbox[041]=8'ha5; sbox[042]=8'he5; sbox[043]=8'hf1; sbox[044]=8'h71; sbox[045]=8'hd8; sbox[046]=8'h31; sbox[047]=8'h15;
sbox[048]=8'h04; sbox[049]=8'hc7; sbox[050]=8'h23; sbox[051]=8'hc3; sbox[052]=8'h18; sbox[053]=8'h96; sbox[054]=8'h05; sbox[055]=8'h9a;
sbox[056]=8'h07; sbox[057]=8'h12; sbox[058]=8'h80; sbox[059]=8'he2; sbox[060]=8'heb; sbox[061]=8'h27; sbox[062]=8'hb2; sbox[063]=8'h75;
sbox[064]=8'h09; sbox[065]=8'h83; sbox[066]=8'h2c; sbox[067]=8'h1a; sbox[068]=8'h1b; sbox[069]=8'h6e; sbox[070]=8'h5a; sbox[071]=8'ha0;
sbox[072]=8'h52; sbox[073]=8'h3b; sbox[074]=8'hd6; sbox[075]=8'hb3; sbox[076]=8'h29; sbox[077]=8'he3; sbox[078]=8'h2f; sbox[079]=8'h84;
sbox[080]=8'h53; sbox[081]=8'hd1; sbox[082]=8'h00; sbox[083]=8'hed; sbox[084]=8'h20; sbox[085]=8'hfc; sbox[086]=8'hb1; sbox[087]=8'h5b;
sbox[088]=8'h6a; sbox[089]=8'hcb; sbox[090]=8'hbe; sbox[091]=8'h39; sbox[092]=8'h4a; sbox[093]=8'h4c; sbox[094]=8'h58; sbox[095]=8'hcf;
sbox[096]=8'hd0; sbox[097]=8'hef; sbox[098]=8'haa; sbox[099]=8'hfb; sbox[100]=8'h43; sbox[101]=8'h4d; sbox[102]=8'h33; sbox[103]=8'h85;
sbox[104]=8'h45; sbox[105]=8'hf9; sbox[106]=8'h02; sbox[107]=8'h7f; sbox[108]=8'h50; sbox[109]=8'h3c; sbox[110]=8'h9f; sbox[111]=8'ha8;
sbox[112]=8'h51; sbox[113]=8'ha3; sbox[114]=8'h40; sbox[115]=8'h8f; sbox[116]=8'h92; sbox[117]=8'h9d; sbox[118]=8'h38; sbox[119]=8'hf5;
sbox[120]=8'hbc; sbox[121]=8'hb6; sbox[122]=8'hda; sbox[123]=8'h21; sbox[124]=8'h10; sbox[125]=8'hff; sbox[126]=8'hf3; sbox[127]=8'hd2;
sbox[128]=8'hcd; sbox[129]=8'h0c; sbox[130]=8'h13; sbox[131]=8'hec; sbox[132]=8'h5f; sbox[133]=8'h97; sbox[134]=8'h44; sbox[135]=8'h17;
sbox[136]=8'hc4; sbox[137]=8'ha7; sbox[138]=8'h7e; sbox[139]=8'h3d; sbox[140]=8'h64; sbox[141]=8'h5d; sbox[142]=8'h19; sbox[143]=8'h73;
sbox[144]=8'h60; sbox[145]=8'h81; sbox[146]=8'h4f; sbox[147]=8'hdc; sbox[148]=8'h22; sbox[149]=8'h2a; sbox[150]=8'h90; sbox[151]=8'h88;
sbox[152]=8'h46; sbox[153]=8'hee; sbox[154]=8'hb8; sbox[155]=8'h14; sbox[156]=8'hde; sbox[157]=8'h5e; sbox[158]=8'h0b; sbox[159]=8'hdb;
sbox[160]=8'he0; sbox[161]=8'h32; sbox[162]=8'h3a; sbox[163]=8'h0a; sbox[164]=8'h49; sbox[165]=8'h06; sbox[166]=8'h24; sbox[167]=8'h5c;
sbox[168]=8'hc2; sbox[169]=8'hd3; sbox[170]=8'hac; sbox[171]=8'h62; sbox[172]=8'h91; sbox[173]=8'h95; sbox[174]=8'he4; sbox[175]=8'h79;
sbox[176]=8'he7; sbox[177]=8'hc8; sbox[178]=8'h37; sbox[179]=8'h6d; sbox[180]=8'h8d; sbox[181]=8'hd5; sbox[182]=8'h4e; sbox[183]=8'ha9;
sbox[184]=8'h6c; sbox[185]=8'h56; sbox[186]=8'hf4; sbox[187]=8'hea; sbox[188]=8'h65; sbox[189]=8'h7a; sbox[190]=8'hae; sbox[191]=8'h08;
sbox[192]=8'hba; sbox[193]=8'h78; sbox[194]=8'h25; sbox[195]=8'h2e; sbox[196]=8'h1c; sbox[197]=8'ha6; sbox[198]=8'hb4; sbox[199]=8'hc6;
sbox[200]=8'he8; sbox[201]=8'hdd; sbox[202]=8'h74; sbox[203]=8'h1f; sbox[204]=8'h4b; sbox[205]=8'hbd; sbox[206]=8'h8b; sbox[207]=8'h8a;
sbox[208]=8'h70; sbox[209]=8'h3e; sbox[210]=8'hb5; sbox[211]=8'h66; sbox[212]=8'h48; sbox[213]=8'h03; sbox[214]=8'hf6; sbox[215]=8'h0e;
sbox[216]=8'h61; sbox[217]=8'h35; sbox[218]=8'h57; sbox[219]=8'hb9; sbox[220]=8'h86; sbox[221]=8'hc1; sbox[222]=8'h1d; sbox[223]=8'h9e;
sbox[224]=8'he1; sbox[225]=8'hf8; sbox[226]=8'h98; sbox[227]=8'h11; sbox[228]=8'h69; sbox[229]=8'hd9; sbox[230]=8'h8e; sbox[231]=8'h94;
sbox[232]=8'h9b; sbox[233]=8'h1e; sbox[234]=8'h87; sbox[235]=8'he9; sbox[236]=8'hce; sbox[237]=8'h55; sbox[238]=8'h28; sbox[239]=8'hdf;
sbox[240]=8'h8c; sbox[241]=8'ha1; sbox[242]=8'h89; sbox[243]=8'h0d; sbox[244]=8'hbf; sbox[245]=8'he6; sbox[246]=8'h42; sbox[247]=8'h68;
sbox[248]=8'h41; sbox[249]=8'h99; sbox[250]=8'h2d; sbox[251]=8'h0f; sbox[252]=8'hb0; sbox[253]=8'h54; sbox[254]=8'hbb; sbox[255]=8'h16;
end
assign s_out=sbox[s_in];
endmodule
三、实验结果
使用iverilog进行快速功能验证,测试了10组明文/密文对,testbench和测试结果如下。所有测试用例均通过,实际输出与预期密文完全一致。测试平台自动比较结果并显示通过/失败信息,验证了设计的正确性。VCD波形文件被成功生成,便于后续分析。
`timescale 1ns/1ps
module aes_top_tb;
reg clk=0;
reg rst_n=0;
reg [127:0] mkey=0;
reg load_mkey=0;
reg [127:0] plaintext=0;
reg din_valid=0;
wire [127:0] ciphertext;
wire dout_valid;
wire busy;
aes_top uut (
.clk(clk),
.rst_n(rst_n),
.mkey(mkey),
.load_mkey(load_mkey),
.plaintext(plaintext),
.din_valid(din_valid),
.ciphertext(ciphertext),
.dout_valid(dout_valid),
.busy(busy)
);
always #5 clk = ~clk;
reg [127:0] test_plaintexts [0:9];
reg [127:0] expected_ciphertexts [0:9];
initial begin
test_plaintexts[0]=128'h00112233445566778899aabbccddeeff;
test_plaintexts[1]=128'h74c78ff3d66dbf57133ad70f3783632e;
test_plaintexts[2]=128'h274c7ca8660c45692ae89ad0ccb181ba;
test_plaintexts[3]=128'h6d996b1ee433d25ec82ae8e525853ef7;
test_plaintexts[4]=128'h53330c09f3b978bfb6f124ef34329292;
test_plaintexts[5]=128'h720f5ec1eafcb180549b5dd35aaa4311;
test_plaintexts[6]=128'hf7cfe13517d5a56ee8390ab607bb1025;
test_plaintexts[7]=128'h7074fa1315798698fee73b1beb30ab55;
test_plaintexts[8]=128'h5e6030ea185d0ea90e1a81a84b2f5651;
test_plaintexts[9]=128'h944375ea4102920901f920a09a86efa7;
expected_ciphertexts[0]=128'h69c4e0d86a7b0430d8cdb78070b4c55a;
expected_ciphertexts[1]=128'heb7db34352d001fe483bddb27e9349a1;
expected_ciphertexts[2]=128'h67d455bea9e118bd8425eaf27bc08933;
expected_ciphertexts[3]=128'h5fe2c1898df6a83b9b061c589357f587;
expected_ciphertexts[4]=128'h965c2dba77ff86a316199702c7c36728;
expected_ciphertexts[5]=128'h5edcf52367a8f289ff6fc2a41d2752a9;
expected_ciphertexts[6]=128'h22f0eaf54a178cf157514dcf83673862;
expected_ciphertexts[7]=128'h6a1ce927be8ea92bcf185f4370c29087;
expected_ciphertexts[8]=128'h2f1043780796ac3b4332e5e09460f327;
expected_ciphertexts[9]=128'h4a5a4421892df67cd9b8af80c0b8f3b6;
end
integer i = 0;
initial begin
#15 rst_n = 1;
mkey = 128'h000102030405060708090a0b0c0d0e0f;
load_mkey = 1;
@(negedge clk);
load_mkey = 0;
wait(busy == 0);
@(negedge clk);
#20 plaintext=test_plaintexts[0]; din_valid = 1;
#10 din_valid = 0;
#20 plaintext = test_plaintexts[1]; din_valid = 1;
#10 plaintext = test_plaintexts[2];
#10 plaintext = test_plaintexts[3];
#10 plaintext = test_plaintexts[4];
#10 din_valid = 0;
#30 plaintext = test_plaintexts[5]; din_valid = 1;
#10 plaintext = test_plaintexts[6];
#10 plaintext = test_plaintexts[7];
#10 plaintext = test_plaintexts[8];
#10 plaintext = test_plaintexts[9];
#10 din_valid = 0;
wait(busy == 0);
#100 $finish;
end
always @(posedge clk) begin
if (dout_valid) begin
if (ciphertext === expected_ciphertexts[i]) begin
$display("Test %0d: Passed, Expected %h, Actual %h", i, expected_ciphertexts[i], ciphertext);
end else begin
$display("Test %0d: Failed, Expected %h, Actual %h", i, expected_ciphertexts[i], ciphertext);
end
i = i + 1;
end
end
initial begin
$dumpfile("aes_top.vcd");
$dumpvars(0, aes_top_tb);
end
endmodule
在gtkwave和Modelsim中观察仿真波形,可以清晰看到流水线的工作过程。当din_valid有效时,明文进入流水线,经过11个周期后dout_valid变高,输出有效密文。busy信号准确反映了系统状态,密钥扩展和加密过程没有重叠时的控制信号行为符合预期。
用Vivado(XC7A35T-1CSG324C)进行综合,结果如下:
四、总结
AES算法是一种广泛使用的对称加密标准,其Verilog流水线实现通过将加密过程分解为多级处理,显著提高了数据吞吐量。该设计采用128位密钥,包含密钥扩展和加密两大模块,通过流水线结构实现每个时钟周期处理一个数据块。密钥扩展模块预先计算所有轮密钥,加密模块则分为初始轮加、9轮标准加密和最终轮加密,形成11级流水线。实验验证表明,该设计功能正确,所有测试用例均通过验证。每周期128位的吞吐量使其适合高速加密场景,而模块化设计便于在不同平台移植和优化,为安全通信提供了高效的硬件解决方案。