AES加密解密硬件实现详解-完整代码(6):my_bit8_mixcolum.v
本章节为my_bit8_mixcolum.v代码解析完整代码见文章最后在上一篇文章中我们深入分析了bit1_mixcolum——一个仅处理4个输入字节、输出2个字节的轻量级线性变换单元。这种“比特片”设计展示了如何在有限域上仅用异或和移位实现高效运算。然而在实际的AES或类AES算法中我们需要处理32位字甚至128位状态块。如何将基础单元扩展为实用的模块本文介绍的bit8_mixcolum正是答案通过模块化复用和循环输入重排将四个bit1_mixcolum并行组合一次性完成32位数据的双路列混合。1. 模块功能概览端口名方向位宽描述ininput32输入数据按大端字节序包含四个字节 (a,b,c,d)outxoutput32第一个输出字由四组独立变换的结果拼接而成outyoutput32第二个输出字对应另一种线性组合的结果核心功能将输入的32位视为4个独立的字节通过四个并行的bit1_mixcolum实例每个实例的输入顺序经过循环移位产生两个32位输出。这两个输出分别对应同一输入列混合后的两组不同线性关系。2. 内部结构与工作原理2.1 字节拆分首先将32位输入按大端序拆分为四个字节a in[31:24]最高字节b in[23:16]c in[15:8]d in[7:0]最低字节这种拆分方式与AES官方文档及大多数处理器内存布局一致。2.2 并行实例化的连接方式模块内部例化了四个bit1_mixcolum子模块分别记为u1、u2、u3、u4。每个子模块的输入顺序不是固定的(a,b,c,d)而是按照循环右移或左移方式重排实例in1in2in3in4输出Out1输出Out2u1abcdx1y1u2bcdax2y2u3cdabx3y3u4dabcx4y4这种旋转方式的直观理解如果把输入四个字节看作一个循环队列那么每个子模块依次从队列的不同起点开始取四个连续元素。当所有子模块的Out1按顺序(x1,x2,x3,x4)拼接时得到的结果相当于对四组不同旋转的输入应用同一个变换F1。同理(y1,y2,y3,y4)拼接得到F2变换的结果。2.3 输出拼接最终输出为outx {x1, x2, x3, x4} outy {y1, y2, y3, y4}保持大端字节序与输入格式一致。3. 数学形式化描述设bit1_mixcolum定义的变换为F1(a,b,c,d) b ⊕ c ⊕ d ⊕ xtime(a ⊕ b) F2(a,b,c,d) xtime(xtime( (a⊕c) ⊕ xtime(a⊕b) ⊕ xtime(c⊕d) )) ⊕ F1(a,b,c,d)则bit8_mixcolum的输出为outx { F1(a,b,c,d), F1(b,c,d,a), F1(c,d,a,b), F1(d,a,b,c) } outy { F2(a,b,c,d), F2(b,c,d,a), F2(c,d,a,b), F2(d,a,b,c) }可以看出整个模块实际上对输入向量的四个循环移位版本分别应用相同的非线性‑线性组合然后将结果向量化输出。这是一种典型的**SIMD单指令多数据**风格的硬件设计。4. 创新点分析创新维度具体描述模块化分层设计直接复用bit1_mixcolum作为构建块避免了在更高层次上重新设计有限域乘法逻辑。这种“乐高式”搭建使得代码简洁、易于验证和维护。循环输入重排技巧通过简单的接线旋转无需额外逻辑实现了对输入字节所有循环排列的覆盖。这比硬编码四个不同的变换函数要优雅得多且面积几乎为零。双输出通道并行同时产生outx和outy两个32位结果满足了后续数据处理例如AES的列混合需要两行同时计算的需求提升了吞吐率。纯组合逻辑无流水线冲突整个模块没有任何寄存器所有子模块并行计算输出延迟等于单个bit1_mixcolum的传播延迟约4级xtime加若干异或门。非常适合整合到高性能流水线中。字节序友好明确采用大端字节序与AES标准、网络字节序以及多数RISC指令集的内存视图一致减少了集成的字节交换开销。可扩展性强以此模块为基础可以很容易地扩展到完整的128位列混合只需例化4个bit8_mixcolum分别处理四列即可一次完成整个状态矩阵的变换。5. 比喻想象你有一个4人小组每个人都要完成两道计算题F1和F2但每个人拿到的题目顺序不同第1人按顺序使用(a,b,c,d)作为输入第2人把题目向前滚动一位使用(b,c,d,a)第3人再滚动一位使用(c,d,a,b)第4人再滚动一位使用(d,a,b,c)四个人同时独立计算最后把所有人算出的F1结果按编号收起来就是outxF2结果收起来就是outy。这个比喻说明了并行四人同时和循环移位每人看到的顺序不同两个核心思想。6. 应用场景与扩展AES-128/256的列混合层将128位状态划分为4个32位列每个列送入一个bit8_mixcolum即可在单个时钟周期内完成整个MixColumns操作。自定义加密算法的混淆层如果读者需要设计轻量级分组密码可以调整bit1_mixcolum内部的xtime系数然后同样用这种“旋转并行”结构实现任意4字节的线性变换。FPGA中作为组合逻辑加速器由于无寄存器可放在逻辑路径中而不增加流水线深度适合对延迟敏感的协议处理。ASIC中的标准单元库模块面积小、扇出规整易于布局布线。7. 总结bit8_mixcolum是一个教科书级的模块化并行设计范例。它没有创造新的运算而是通过巧妙的例化方式和输入重排将基础单元的能力放大了四倍。读者可以从中学习到如何从底层模块构建上层功能如何利用循环移位覆盖所有需要的组合如何保持接口简洁而功能完整理解了这个模块也就掌握了构建更大规模密码硬件的基本思路。下一篇我们将继续向上组合展示完整的128位列混合模块敬请期待。my_bit8_mixcolum.v完整代码timescale 1ns / 10ps module bit8_mixcolum ( input [31:0] in, output [31:0] outx, output [31:0] outy ); // 内部线网w_ 前缀 wire [7:0] w_a, w_b, w_c, w_d; // 输入字节拆分 wire [7:0] w_x1, w_x2, w_x3, w_x4; // 子模块 outx 输出 wire [7:0] w_y1, w_y2, w_y3, w_y4; // 子模块 outy 输出 // 输入字节拆分 assign w_a in[31:24]; assign w_b in[23:16]; assign w_c in[15:8]; assign w_d in[7:0]; // 四个 bit1_mixcolum 实例化 bit1_mixcolum u1 ( .in1 (w_a), .in2 (w_b), .in3 (w_c), .in4 (w_d), .Out1 (w_x1), .Out2 (w_y1) ); bit1_mixcolum u2 ( .in1 (w_b), .in2 (w_c), .in3 (w_d), .in4 (w_a), .Out1 (w_x2), .Out2 (w_y2) ); bit1_mixcolum u3 ( .in1 (w_c), .in2 (w_d), .in3 (w_a), .in4 (w_b), .Out1 (w_x3), .Out2 (w_y3) ); bit1_mixcolum u4 ( .in1 (w_d), .in2 (w_a), .in3 (w_b), .in4 (w_c), .Out1 (w_x4), .Out2 (w_y4) ); // 输出拼接 assign outx {w_x1, w_x2, w_x3, w_x4}; assign outy {w_y1, w_y2, w_y3, w_y4}; endmoduletb_my_bit8_mixcolum.v完整代码timescale 1ns/10ps module tb_bit8_mixcolum; // // 信号声明全部放在模块头部符合 Verilog 2001 要求 // reg [31:0] in; wire [31:0] outx, outy; reg [31:0] expected_outx; reg [31:0] expected_outy; reg [7:0] a, b, c, d; // 输入字节拆分辅助 integer test_id; reg all_pass; // // 实例化待测模块 // bit8_mixcolum uut ( .in (in), .outx (outx), .outy (outy) ); // // 参考模型函数GF(2^8) 运算不可约多项式 x^8x^4x^3x1 // // xtime(x) x * {02} in GF(2^8) function [7:0] xtime; input [7:0] x; reg [7:0] tmp; begin tmp {x[6:0], 1b0}; if (x[7]) tmp tmp ^ 8h1b; xtime tmp; end endfunction // F1 函数对应 bit1_mixcolum 的 Out1 function [7:0] F1; input [7:0] a, b, c, d; reg [7:0] t1; begin t1 a ^ b; F1 b ^ c ^ d ^ xtime(t1); end endfunction // F2 函数对应 bit1_mixcolum 的 Out2 function [7:0] F2; input [7:0] a, b, c, d; reg [7:0] t1, t2, t3, t4, t5, t6; begin t1 a ^ b; t2 a ^ c; t3 c ^ d; t4 xtime(t1); t5 xtime(t3); t6 t2 ^ t4 ^ t5; F2 xtime(xtime(t6)) ^ F1(a, b, c, d); end endfunction // 期望 outx 的计算 function [31:0] exp_outx; input [7:0] a, b, c, d; begin exp_outx { F1(a,b,c,d), F1(b,c,d,a), F1(c,d,a,b), F1(d,a,b,c) }; end endfunction // 期望 outy 的计算 function [31:0] exp_outy; input [7:0] a, b, c, d; begin exp_outy { F2(a,b,c,d), F2(b,c,d,a), F2(c,d,a,b), F2(d,a,b,c) }; end endfunction // // 测试主流程 // initial begin $display(); $display(Starting auto-checking testbench for bit8_mixcolum); $display(\n); all_pass 1b1; test_id 0; // -------------------------------------------------------- // Test 1: 全零输入 // -------------------------------------------------------- test_id test_id 1; in 32h00000000; a 8h00; b 8h00; c 8h00; d 8h00; expected_outx exp_outx(a, b, c, d); expected_outy exp_outy(a, b, c, d); #10; run_check(test_id, in, outx, outy, expected_outx, expected_outy); // -------------------------------------------------------- // Test 2: 全 0x01 // -------------------------------------------------------- test_id test_id 1; in 32h01010101; a 8h01; b 8h01; c 8h01; d 8h01; expected_outx exp_outx(a, b, c, d); expected_outy exp_outy(a, b, c, d); #10; run_check(test_id, in, outx, outy, expected_outx, expected_outy); // -------------------------------------------------------- // Test 3: 全 0xFF // -------------------------------------------------------- test_id test_id 1; in 32hFFFFFFFF; a 8hFF; b 8hFF; c 8hFF; d 8hFF; expected_outx exp_outx(a, b, c, d); expected_outy exp_outy(a, b, c, d); #10; run_check(test_id, in, outx, outy, expected_outx, expected_outy); // -------------------------------------------------------- // Test 4: 递增模式 0x01020304 // -------------------------------------------------------- test_id test_id 1; in 32h01020304; a 8h01; b 8h02; c 8h03; d 8h04; expected_outx exp_outx(a, b, c, d); expected_outy exp_outy(a, b, c, d); #10; run_check(test_id, in, outx, outy, expected_outx, expected_outy); // -------------------------------------------------------- // Test 5: 随机模式 1 // -------------------------------------------------------- test_id test_id 1; in 32h12345678; a 8h12; b 8h34; c 8h56; d 8h78; expected_outx exp_outx(a, b, c, d); expected_outy exp_outy(a, b, c, d); #10; run_check(test_id, in, outx, outy, expected_outx, expected_outy); // -------------------------------------------------------- // Test 6: 随机模式 2 (边界含 0x80) // -------------------------------------------------------- test_id test_id 1; in 32h80A5C3F0; a 8h80; b 8hA5; c 8hC3; d 8hF0; expected_outx exp_outx(a, b, c, d); expected_outy exp_outy(a, b, c, d); #10; run_check(test_id, in, outx, outy, expected_outx, expected_outy); // -------------------------------------------------------- // Test 7: 交替 0x55 / 0xAA // -------------------------------------------------------- test_id test_id 1; in 32h55AA55AA; a 8h55; b 8hAA; c 8h55; d 8hAA; expected_outx exp_outx(a, b, c, d); expected_outy exp_outy(a, b, c, d); #10; run_check(test_id, in, outx, outy, expected_outx, expected_outy); // -------------------------------------------------------- // 最终报告 // -------------------------------------------------------- $display(\n); if (all_pass) $display(RESULT: ALL TESTS PASSED); else $display(RESULT: SOME TESTS FAILED (see above)); $display(); $finish; end // // 比较任务自动判断 PASS/FAIL // task run_check; input integer id; input [31:0] i, ox, oy, exx, exy; reg okx, oky; begin okx (ox exx); oky (oy exy); $display(Test %0d: in %h, id, i); $display( outx %h (%s) expected %h, ox, okx ? OK : FAIL, exx); $display( outy %h (%s) expected %h, oy, oky ? OK : FAIL, exy); if (okx oky) begin $display( PASS\n); end else begin $display( FAIL\n); all_pass 1b0; end end endtask endmoduleAES加密解密硬件实现详解从算法到Verilog设计AES加密解密硬件实现详解-完整代码1my_sbox_tops.vAES加密解密硬件实现详解-完整代码2my_subbytes.vAES加密解密硬件实现详解-完整代码3my_keysecret.vAES加密解密硬件实现详解-完整代码4my_mixcolum.vAES加密解密硬件实现详解-完整代码5my_bit1_mixcolum.vAES加密解密硬件实现详解-完整代码6my_bit8_mixcolum.vAES加密解密硬件实现详解-完整代码7my_aes_top.v如果您对模块的数学推导或硬件实现有疑问欢迎留言讨论