FPGA实战(47):SM4加解密算法Verilog实现——全流水线架构设计详解(附完整代码)
继上一篇SM3算法博客之后,本文继续分享SM4分组密码算法的硬件实现。本设计采用全流水线架构,密钥扩展与数据加密并行执行,潜伏期193周期,适用于FPGA高吞吐量加解密场景。文末附全部Verilog源码及初始化文件,供读者参考。一、算法简介SM4是中国国家密码管理局发布的分组密码标准(GM/T 0002-2012),分组长度128比特,密钥长度128比特。加解密算法结构相同,均采用32轮非线性迭代,轮函数包含:异或操作S盒非线性替换(8×8)线性变换L(循环移位+异或)轮密钥异或加解密区别:加密时轮密钥顺序使用rk[0]~rk[31],解密时逆序使用rk[31]~rk[0]。二、整体架构本设计包含以下模块:模块文件功能描述S_Box.vS盒替换,查找表实现Key_Extending.v密钥扩展,生成32个轮密钥Round_Function.v单轮迭代函数SM4_Encrypt.v加密顶层,32级流水线SM4_Decrypt.v解密顶层,32级流水线rst_gen_module.v复位信号发生器XC7Z035_TOP.v顶层测试(加密→解密回环)r_CK_Init.txt系统常量CK(32个32位常量)r_s_Box_Init.txtS盒表数据(16×128位)架构特点:密钥扩展与加解密并行:密钥生成链与数据流水线深度耦合,无需等待全部轮密钥生成后再加密。全流水线处理:32轮迭代完全展开,每轮一个独立硬件级,每周期可处理一组新数据。AXI-stream握手:标准ready/valid接口,便于系统集成。三、核心模块详解3.1 S_Box模块S盒基于查找表,用r_s_Box[0:15]存储16行,每行128位(即16个字节)。输入8位数据分为高4位w_X(行索引)和低4位w_Y(列索引),输出对应字节。// 核心查找逻辑 assign w_X = i_data[7:4]; assign w_Y = i_data[3:0]; always@(posedge i_clk) begin case(w_Y) 0: ro_s_data = r_s_Box[w_X][127:120]; 1: ro_s_data = r_s_Box[w_X][119:112]; // ... 省略 15: ro_s_data = r_s_Box[w_X][7:0]; endcase end初始化文件r_s_Box_Init.txt按行存储16个十六进制数(每行128位)。3.2 Key_Extending模块密钥扩展将128位初始密钥MK = (MK₀, MK₁, MK₂, MK₃)扩展为32个轮密钥。关键参数:固定参数FK = {0xA3B1BAC6, 0x56AA3350, 0x677D9197, 0xB27022DC}系统常量CK[i]从文件读入运算流程:对i=0时:K_i = MK_i ⊕ FK_i,否则K_i = MK_i每轮计算:B = K₁⊕K₂⊕K₃⊕CK[i]S盒替换:S_out = S_Box(B)线性变换(密钥扩展专用):mid = ROTL19(S_out) ⊕ ROTL9(S_out) ⊕ S_out轮密钥:rk[i] = mid ⊕ K₀更新K₀,K₁,K₂,K₃为下一轮状态流水线设计:每个周期输出一个轮密钥,32个密钥扩展实例串行级联。3.3 Round_Function模块轮函数实现加密/解密单轮迭代。输入当前状态(X₀,X₁,X₂,X₃)和轮密钥rk,输出新状态(X₁,X₂,X₃,X₄)。运算流程:B = X₁⊕X₂⊕X₃⊕rkS_out = S_Box(B)线性变换(轮函数专用):mid = ROTL30(S_out)⊕ROTL22(S_out)⊕ROTL14(S_out)⊕ROTL8(S_out)⊕S_outX₄ = X₀⊕mid⚠️ 注意:轮函数与密钥扩展的线性变换循环移位参数不同。3.4 顶层加密/解密模块SM4_Encrypt和SM4_Decrypt结构对称,仅轮密钥顺序相反。流水线级联:32个Key_Extending实例首尾相连,形成密钥生成链。32个Round_Function实例级联,形成数据流水线。两链同步运行,r_Initial_valid信号控制数据流动。输出对齐:因为第28、29、30轮的结果比第31轮早若干周期输出,故使用延迟链(r_round_result28/29/30)将其对齐到同一周期,最终组合输出{X₃₁, X₃₀, X₂₉, X₂₈}(解密时同理)。四、核心创新点全流水线并行密钥扩展密钥生成与加密流水线同时启动,每周期产生一个新轮密钥并立即送入下一轮迭代,无需等待32个轮密钥全部就绪,极大提高吞吐率。资源优化的S盒实现采用16×128位寄存器阵列,通过行列二级索引,相比直接256×8查找表节省近一半存储资源,同时保持单周期查表速度。动态密钥更新支持外部可通过i_Initial_Key和i_Initial_valid随时更新主密钥,模块自动重置并重新开始密钥扩展,适用于密钥频繁轮换的场景。精确的流水线同步机制通过r_Initial_valid链和延迟对齐寄存器,确保32轮数据与对应轮密钥严格同步,输出数据无毛刺。加密→解密回环验证顶层测试模块将加密输出直接送入解密模块,验证加解密正确性,方便功能仿真和板级测试。五、接口说明顶层接口(以SM4_Encrypt为例):信号位宽方向描述i_clk1输入时钟i_rst1输入复位i_Initial_Key128输入初始密钥i_Initial_valid1输入密钥有效信号(高电平开始密钥扩展)i_axis_data128输入待加密数据i_axis_valid1输入数据有效信号o_axis_ready1输出准备接收新数据(流水线空闲)o_axim_data128输出加密结果o_axim_valid1输出结果有效信号时序要求:i_Initial_valid至少保持一个时钟周期,用于触发密钥扩展链的启动。o_axis_ready拉高后即可持续输入数据,流水线每周期处理一组数据。六、使用与测试初始化文件路径:需在Key_Extending.v和S_Box.v中修改$readmemh的绝对路径,指向r_CK_Init.txt和r_s_Box_Init.txt。板级测试:XC7Z035_TOP模块内置计数器生成递增测试向量,并将加密结果送入解密模块,最终比较输入输出是否一致。通过LED指示灯(o_led)可观察运行状态。仿真建议:编写简单testbench,先使能i_Initial_valid一个周期,等待约193周期后,流水线输出有效数据。可对比标准SM4软件计算结果验证正确性。七、完整代码附录以下为本设计全部源代码(按文件顺序列出)。请复制到本地工程中,并修改初始化文件路径。7.1 S_Box.v`timescale 1ns / 1ps module S_Box( input i_clk , input i_rst , input [7 :0] i_data , input i_valid , output [7 :0] o_s_data , output o_s_valid ); reg [7 :0] ro_s_data ; reg ro_s_valid ; reg [127:0] r_s_Box[0 :15] ; wire [3 :0] w_X ; wire [3 :0] w_Y ; assign o_s_data = ro_s_data ; assign o_s_valid= ro_s_valid ; assign w_X = i_data[7 :4] ; assign w_Y = i_data[3 :0] ; initial begin $readmemh("D:/08-CSDN/03-sm4/SM4/SM4/project_1/project_1.srcs/sources_1/new/r_s_Box_Init.txt",r_s_Box,0,15); end always@(posedge i_clk,posedge i_rst) begin if(i_rst) ro_s_valid = 'd0; else ro_s_valid = i_valid; end always@(posedge i_clk,posedge i_rst) begin if(i_rst) ro_s_data = 'd0; else case(w_Y) 0 :ro_s_data = r_s_Box[w_X][127:120]; 1 :ro_s_data = r_s_Box[w_X][119:112]; 2 :ro_s_dat

相关新闻

最新新闻

日新闻

周新闻

月新闻