md5 算法标准:https://tools.ietf.org/html/rfc1321
MD5 算法有 5 个步骤:
1.将数据从头开始按 512 个 bit 划分成块。在最后一位数据后面添加一位 1 后,再继续添加一定数量的 0 使最后一块数据有448(512-64)位。
2.在剩下的64位里填入实际数据的长度(bit数)。
3.将512位的块按32位分为16份,使用a、b、c、d四个32位参数与这16份数据与都进行4轮函数变换(共64次)。最后得到变换后的a、b、c、d与原来的a、b、c、d分别相加得到新的a、b、c、d。
4.将新的a、b、c、d与下一块数据进行变换,直到最后一块数据。
5.将最终的a、b、c、d拼接为128位的结果输出。
工程源文件下载地址:https://download.csdn.net/download/Blaze_Xu/13713217
下面给出MD5最核心的第3步的源代码及仿真文件:
`timescale 1ns / 1ps
module md5_block(
input wire clk ,
input wire mes_en ,
input wire [511:0] mes_i ,
input wire [ 31:0] a_i ,
input wire [ 31:0] b_i ,
input wire [ 31:0] c_i ,
input wire [ 31:0] d_i ,
output reg [ 31:0] a_o ,
output reg [ 31:0] b_o ,
output reg [ 31:0] c_o ,
output reg [ 31:0] d_o ,
output reg abcd_en
);
reg [31:0] mes_part[15:0] ;
reg [31:0] a ;
reg [31:0] b ;
reg [31:0] c ;
reg [31:0] d ;
reg [31:0] A ;
reg [31:0] B ;
reg [31:0] C ;
reg [31:0] D ;
reg [ 5:0] steps ;
reg computing ;
reg compute_end ;
//---------------------mes_part_gen---------------------
always @(posedge clk)
begin
if(mes_en) begin
mes_part[ 0] <= mes_i[511:480];
mes_part[ 1] <= mes_i[479:448];
mes_part[ 2] <= mes_i[447:416];
mes_part[ 3] <= mes_i[415:384];
mes_part[ 4] <= mes_i[383:352];
mes_part[ 5] <= mes_i[351:320];
mes_part[ 6] <= mes_i[319:288];
mes_part[ 7] <= mes_i[287:256];
mes_part[ 8] <= mes_i[255:224];
mes_part[ 9] <= mes_i[223:192];
mes_part[10] <= mes_i[191:160];
mes_part[11] <= mes_i[159:128];
mes_part[12] <= mes_i[127: 96];
mes_part[13] <= mes_i[ 95: 64];
mes_part[14] <= mes_i[ 63: 32];
mes_part[15] <= mes_i[ 31: 0];
end
end
//-------------------- computing_gen -------------------------
always @(posedge clk)
begin
if(mes_en==1'b1) begin
computing <= 1'b1;
end else if(steps==6'd63) begin
computing <= 1'b0;
end else
computing <= computing;
end
always @(posedge clk)
begin
if(mes_en) begin
steps <= 6'b0;
a <= a_i ;
b <= b_i ;
c <= c_i ;
d <= d_i ;
end else if(computing==1'b1) begin
case(steps)
0 : begin a <= b + ( (a+((b&c)|((~b)&d))+mes_part[ 0]+32'hd76a_a478)<< 7 | (a+((b&c)|((~b)&d))+mes_part[ 0]+32'hd76a_a478)>>(32- 7) ); steps <= steps + 1; end
1 : begin d <= a + ( (d+((a&b)|((~a)&c))+mes_part[ 1]+32'he8c7_b756)<<12 | (d+((a&b)|((~a)&c))+mes_part[ 1]+32'he8c7_b756)>>(32-12) ); steps <= steps + 1; end
2 : begin c <= d + ( (c+((d&a)|((~d)&b))+mes_part[ 2]+32'h2420_70db)<<17 | (c+((d&a)|((~d)&b))+mes_part[ 2]+32'h2420_70db)>>(32-17) ); steps <= steps + 1; end
3 : begin b <= c + ( (b+((c&d)|((~c)&a))+mes_part[ 3]+32'hc1bd_ceee)<<22 | (b+((c&d)|((~c)&a))+mes_part[ 3]+32'hc1bd_ceee)>>(32-22) ); steps <= steps + 1; end
4 : begin a <= b + ( (a+((b&c)|((~b)&d))+mes_part[ 4]+32'hf57c_0faf)<< 7 | (a+((b&c)|((~b)&d))+mes_part[ 4]+32'hf57c_0faf)>>(32- 7) ); steps <= steps + 1; end
5 : begin d <= a + ( (d+((a&b)|((~a)&c))+mes_part[ 5]+32'h4787_c62a)<<12 | (d+((a&b)|((~a)&c))+mes_part[ 5]+32'h4787_c62a)>>(32-12) ); steps <= steps + 1; end
6 : begin c <= d + ( (c+((d&a)|((~d)&b))+mes_part[ 6]+32'ha830_4613)<<17 | (c+((d&a)|((~d)&b))+mes_part[ 6]+32'ha830_4613)>>(32-17) ); steps <= steps + 1; end
7 : begin b <= c + ( (b+((c&d)|((~c)&a))+mes_part[ 7]+32'hfd46_9501)<<22 | (b+((c&d)|((~c)&a))+mes_part[ 7]+32'hfd46_9501)>>(32-22) ); steps <= steps + 1; end
8 : begin a <= b + ( (a+((b&c)|((~b)&d))+mes_part[ 8]+32'h6980_98d8)<< 7 | (a+((b&c)|((~b)&d))+mes_part[ 8]+32'h6980_98d8)>>(32- 7) ); steps <= steps + 1; end
9 : begin d <= a + ( (d+((a&b)|((~a)&c))+mes_part[ 9]+32'h8b44_f7af)<<12 | (d+((a&b)|((~a)&c))+mes_part[ 9]+32'h8b44_f7af)>>(32-12) ); steps <= steps + 1; end
10: begin c <= d + ( (c+((d&a)|((~d)&b))+mes_part[10]+32'hffff_5bb1)<<17 | (c+((d&a)|((~d)&b))+mes_part[10]+32'hffff_5bb1)>>(32-17) ); steps <= steps + 1; end
11: begin b <= c + ( (b+((c&d)|((~c)&a))+mes_part[11]+32'h895c_d7be)<<22 | (b+((c&d)|((~c)&a))+mes_part[11]+32'h895c_d7be)>>(32-22) ); steps <= steps + 1; end
12: begin a <= b + ( (a+((b&c)|((~b)&d))+mes_part[12]+32'h6b90_1122)<< 7 | (a+((b&c)|((~b)&d))+mes_part[12]+32'h6b90_1122)>>(32- 7) ); steps <= steps + 1; end
13: begin d <= a + ( (d+((a&b)|((~a)&c))+mes_part[13]+32'hfd98_7193)<<12 | (d+((a&b)|((~a)&c))+mes_part[13]+32'hfd98_7193)>>(32-12) ); steps <= steps + 1; end
14: begin c <= d + ( (c+((d&a)|((~d)&b))+mes_part[14]+32'ha679_438e)<<17 | (c+((d&a)|((~d)&b))+mes_part[14]+32'ha679_438e)>>(32-17) ); steps <= steps + 1; end
15: begin b <= c + ( (b+((c&d)|((~c)&a))+mes_part[15]+32'h49b4_0821)<<22 | (b+((c&d)|((~c)&a))+mes_part[15]+32'h49b4_0821)>>(32-22) ); steps <= steps + 1; end
16: begin a <= b + ( (a+((b&d)|(c&~(d)))+mes_part[1 ]+32'hf61e_2562)<< 5 | (a+((b&d)|(c&~(d)))+mes_part[1 ]+32'hf61e_2562)>>(32- 5) ); steps <= steps + 1; end
17: begin d <= a + ( (d+((a&c)|(b&~(c)))+mes_part[6 ]+32'hc040_b340)<< 9 | (d+((a&c)|(b&~(c)))+mes_part[6 ]+32'hc040_b340)>>(32- 9) ); steps <= steps + 1; end
18: begin c <= d + ( (c+((d&b)|(a&~(b)))+mes_part[11]+32'h265e_5a51)<<14 | (c+((d&b)|(a&~(b)))+mes_part[11]+32'h265e_5a51)>>(32-14) ); steps <= steps + 1; end
19: begin b <= c + ( (b+((c&a)|(d&~(a)))+mes_part[0 ]+32'he9b6_c7aa)<<20 | (b+((c&a)|(d&~(a)))+mes_part[0 ]+32'he9b6_c7aa)>>(32-20) ); steps <= steps + 1; end
20: begin a <= b + ( (a+((b&d)|(c&~(d)))+mes_part[5 ]+32'hd62f_105d)<< 5 | (a+((b&d)|(c&~(d)))+mes_part[5 ]+32'hd62f_105d)>>(32- 5) ); steps <= steps + 1; end
21: begin d <= a + ( (d+((a&c)|(b&~(c)))+mes_part[10]+32'h0244_1453)<< 9 | (d+((a&c)|(b&~(c)))+mes_part[10]+32'h0244_1453)>>(32- 9) ); steps <= steps + 1; end
22: begin c <= d + ( (c+((d&b)|(a&~(b)))+mes_part[15]+32'hd8a1_e681)<<14 | (c+((d&b)|(a&~(b)))+mes_part[15]+32'hd8a1_e681)>>(32-14) ); steps <= steps + 1; end
23: begin b <= c + ( (b+((c&a)|(d&~(a)))+mes_part[4 ]+32'he7d3_fbc8)<<20 | (b+((c&a)|(d&~(a)))+mes_part[4 ]+32'he7d3_fbc8)>>(32-20) ); steps <= steps + 1; end
24: begin a <= b + ( (a+((b&d)|(c&~(d)))+mes_part[9 ]+32'h21e1_cde6)<< 5 | (a+((b&d)|(c&~(d)))+mes_part[9 ]+32'h21e1_cde6)>>(32- 5) ); steps <= steps + 1; end
25: begin d <= a + ( (d+((a&c)|(b&~(c)))+mes_part[14]+32'hc337_07d6)<< 9 | (d+((a&c)|(b&~(c)))+mes_part[14]+32'hc337_07d6)>>(32- 9) ); steps <= steps + 1; end
26: begin c <= d + ( (c+((d&b)|(a&~(b)))+mes_part[3 ]+32'hf4d5_0d87)<<14 | (c+((d&b)|(a&~(b)))+mes_part[3 ]+32'hf4d5_0d87)>>(32-14) ); steps <= steps + 1; end
27: begin b <= c + ( (b+((c&a)|(d&~(a)))+mes_part[8 ]+32'h455a_14ed)<<20 | (b+((c&a)|(d&~(a)))+mes_part[8 ]+32'h455a_14ed)>>(32-20) ); steps <= steps + 1; end
28: begin a <= b + ( (a+((b&d)|(c&~(d)))+mes_part[13]+32'ha9e3_e905)<< 5 | (a+((b&d)|(c&~(d)))+mes_part[13]+32'ha9e3_e905)>>(32- 5) ); steps <= steps + 1; end
29: begin d <= a + ( (d+((a&c)|(b&~(c)))+mes_part[2 ]+32'hfcef_a3f8)<< 9 | (d+((a&c)|(b&~(c)))+mes_part[2 ]+32'hfcef_a3f8)>>(32- 9) ); steps <= steps + 1; end
30: begin c <= d + ( (c+((d&b)|(a&~(b)))+mes_part[7 ]+32'h676f_02d9)<<14 | (c+((d&b)|(a&~(b)))+mes_part[7 ]+32'h676f_02d9)>>(32-14) ); steps <= steps + 1; end
31: begin b <= c + ( (b+((c&a)|(d&~(a)))+mes_part[12]+32'h8d2a_4c8a)<<20 | (b+((c&a)|(d&~(a)))+mes_part[12]+32'h8d2a_4c8a)>>(32-20) ); steps <= steps + 1; end
32: begin a <= b + ( (a+(b^c^d)+mes_part[5 ]+32'hfffa_3942)<< 4 | (a+(b^c^d)+mes_part[5 ]+32'hfffa_3942)>>(32- 4) ); steps <= steps + 1; end
33: begin d <= a + ( (d+(a^b^c)+mes_part[8 ]+32'h8771_f681)<<11 | (d+(a^b^c)+mes_part[8 ]+32'h8771_f681)>>(32-11) ); steps <= steps + 1; end
34: begin c <= d + ( (c+(d^a^b)+mes_part[11]+32'h6d9d_6122)<<16 | (c+(d^a^b)+mes_part[11]+32'h6d9d_6122)>>(32-16) ); steps <= steps + 1; end
35: begin b <= c + ( (b+(c^d^a)+mes_part[14]+32'hfde5_380c)<<23 | (b+(c^d^a)+mes_part[14]+32'hfde5_380c)>>(32-23) ); steps <= steps + 1; end
36: begin a <= b + ( (a+(b^c^d)+mes_part[1 ]+32'ha4be_ea44)<< 4 | (a+(b^c^d)+mes_part[1 ]+32'ha4be_ea44)>>(32- 4) ); steps <= steps + 1; end
37: begin d <= a + ( (d+(a^b^c)+mes_part[4 ]+32'h4bde_cfa9)<<11 | (d+(a^b^c)+mes_part[4 ]+32'h4bde_cfa9)>>(32-11) ); steps <= steps + 1; end
38: begin c <= d + ( (c+(d^a^b)+mes_part[7 ]+32'hf6bb_4b60)<<16 | (c+(d^a^b)+mes_part[7 ]+32'hf6bb_4b60)>>(32-16) ); steps <= steps + 1; end
39: begin b <= c + ( (b+(c^d^a)+mes_part[10]+32'hbebf_bc70)<<23 | (b+(c^d^a)+mes_part[10]+32'hbebf_bc70)>>(32-23) ); steps <= steps + 1; end
40: begin a <= b + ( (a+(b^c^d)+mes_part[13]+32'h289b_7ec6)<< 4 | (a+(b^c^d)+mes_part[13]+32'h289b_7ec6)>>(32- 4) ); steps <= steps + 1; end
41: begin d <= a + ( (d+(a^b^c)+mes_part[0 ]+32'heaa1_27fa)<<11 | (d+(a^b^c)+mes_part[0 ]+32'heaa1_27fa)>>(32-11) ); steps <= steps + 1; end
42: begin c <= d + ( (c+(d^a^b)+mes_part[3 ]+32'hd4ef_3085)<<16 | (c+(d^a^b)+mes_part[3 ]+32'hd4ef_3085)>>(32-16) ); steps <= steps + 1; end
43: begin b <= c + ( (b+(c^d^a)+mes_part[6 ]+32'h0488_1d05)<<23 | (b+(c^d^a)+mes_part[6 ]+32'h0488_1d05)>>(32-23) ); steps <= steps + 1; end
44: begin a <= b + ( (a+(b^c^d)+mes_part[9 ]+32'hd9d4_d039)<< 4 | (a+(b^c^d)+mes_part[9 ]+32'hd9d4_d039)>>(32- 4) ); steps <= steps + 1; end
45: begin d <= a + ( (d+(a^b^c)+mes_part[12]+32'he6db_99e5)<<11 | (d+(a^b^c)+mes_part[12]+32'he6db_99e5)>>(32-11) ); steps <= steps + 1; end
46: begin c <= d + ( (c+(d^a^b)+mes_part[15]+32'h1fa2_7cf8)<<16 | (c+(d^a^b)+mes_part[15]+32'h1fa2_7cf8)>>(32-16) ); steps <= steps + 1; end
47: begin b <= c + ( (b+(c^d^a)+mes_part[2 ]+32'hc4ac_5665)<<23 | (b+(c^d^a)+mes_part[2 ]+32'hc4ac_5665)>>(32-23) ); steps <= steps + 1; end
48: begin a <= b + ( (a+(c^(b|(~d)))+mes_part[0 ]+32'hf429_2244)<< 6 | (a+(c^(b|(~d)))+mes_part[0 ]+32'hf429_2244)>>(32- 6) ); steps <= steps + 1; end
49: begin d <= a + ( (d+(b^(a|(~c)))+mes_part[7 ]+32'h432a_ff97)<<10 | (d+(b^(a|(~c)))+mes_part[7 ]+32'h432a_ff97)>>(32-10) ); steps <= steps + 1; end
50: begin c <= d + ( (c+(a^(d|(~b)))+mes_part[14]+32'hab94_23a7)<<15 | (c+(a^(d|(~b)))+mes_part[14]+32'hab94_23a7)>>(32-15) ); steps <= steps + 1; end
51: begin b <= c + ( (b+(d^(c|(~a)))+mes_part[5 ]+32'hfc93_a039)<<21 | (b+(d^(c|(~a)))+mes_part[5 ]+32'hfc93_a039)>>(32-21) ); steps <= steps + 1; end
52: begin a <= b + ( (a+(c^(b|(~d)))+mes_part[12]+32'h655b_59c3)<< 6 | (a+(c^(b|(~d)))+mes_part[12]+32'h655b_59c3)>>(32- 6) ); steps <= steps + 1; end
53: begin d <= a + ( (d+(b^(a|(~c)))+mes_part[3 ]+32'h8f0c_cc92)<<10 | (d+(b^(a|(~c)))+mes_part[3 ]+32'h8f0c_cc92)>>(32-10) ); steps <= steps + 1; end
54: begin c <= d + ( (c+(a^(d|(~b)))+mes_part[10]+32'hffef_f47d)<<15 | (c+(a^(d|(~b)))+mes_part[10]+32'hffef_f47d)>>(32-15) ); steps <= steps + 1; end
55: begin b <= c + ( (b+(d^(c|(~a)))+mes_part[1 ]+32'h8584_5dd1)<<21 | (b+(d^(c|(~a)))+mes_part[1 ]+32'h8584_5dd1)>>(32-21) ); steps <= steps + 1; end
56: begin a <= b + ( (a+(c^(b|(~d)))+mes_part[8 ]+32'h6fa8_7e4f)<< 6 | (a+(c^(b|(~d)))+mes_part[8 ]+32'h6fa8_7e4f)>>(32- 6) ); steps <= steps + 1; end
57: begin d <= a + ( (d+(b^(a|(~c)))+mes_part[15]+32'hfe2c_e6e0)<<10 | (d+(b^(a|(~c)))+mes_part[15]+32'hfe2c_e6e0)>>(32-10) ); steps <= steps + 1; end
58: begin c <= d + ( (c+(a^(d|(~b)))+mes_part[6 ]+32'ha301_4314)<<15 | (c+(a^(d|(~b)))+mes_part[6 ]+32'ha301_4314)>>(32-15) ); steps <= steps + 1; end
59: begin b <= c + ( (b+(d^(c|(~a)))+mes_part[13]+32'h4e08_11a1)<<21 | (b+(d^(c|(~a)))+mes_part[13]+32'h4e08_11a1)>>(32-21) ); steps <= steps + 1; end
60: begin a <= b + ( (a+(c^(b|(~d)))+mes_part[4 ]+32'hf753_7e82)<< 6 | (a+(c^(b|(~d)))+mes_part[4 ]+32'hf753_7e82)>>(32- 6) ); steps <= steps + 1; end
61: begin d <= a + ( (d+(b^(a|(~c)))+mes_part[11]+32'hbd3a_f235)<<10 | (d+(b^(a|(~c)))+mes_part[11]+32'hbd3a_f235)>>(32-10) ); steps <= steps + 1; end
62: begin c <= d + ( (c+(a^(d|(~b)))+mes_part[2 ]+32'h2ad7_d2bb)<<15 | (c+(a^(d|(~b)))+mes_part[2 ]+32'h2ad7_d2bb)>>(32-15) ); steps <= steps + 1; end
63: begin b <= c + ( (b+(d^(c|(~a)))+mes_part[9 ]+32'heb86_d391)<<21 | (b+(d^(c|(~a)))+mes_part[9 ]+32'heb86_d391)>>(32-21) ); steps <= steps + 1; end
endcase
end else begin
a <= a;
b <= b;
c <= c;
d <= d;
end
end
//-------------------------- compute_end_gen ------------------------
always @(posedge clk)
begin
if(steps==63)
compute_end <= 1'b1;
else
compute_end <= 1'b0;
end
always @(posedge clk)
begin
if(mes_en) begin
A <= a_i ;
B <= b_i ;
C <= c_i ;
D <= d_i ;
end
end
//------------------a_o_gen,b_o_gen,c_o_gen,d_o_gen---------------
always @(posedge clk)
begin
if(compute_end) begin
a_o <= a + A;
b_o <= b + B;
c_o <= c + C;
d_o <= d + D;
end else begin
a_o <= a_o;
b_o <= b_o;
c_o <= c_o;
d_o <= d_o;
end
end
//--------------------------abcd_en_gen----------------------------
always @(posedge clk)
begin
if(compute_end)
abcd_en <= 1'b1;
else
abcd_en <= 1'b0;
end
endmodule
tb代码:
`timescale 1ns / 1ps
module tb_md5_block(
);
reg clk ;
reg mes_en ;
reg [511:0] mes_i ;
reg [ 31:0] a_i ;
reg [ 31:0] b_i ;
reg [ 31:0] c_i ;
reg [ 31:0] d_i ;
wire [ 31:0] a_o ;
wire [ 31:0] b_o ;
wire [ 31:0] c_o ;
wire [ 31:0] d_o ;
wire abcd_en ;
md5_block u_md5_block(
.clk ( clk ),
.mes_i ( mes_i ),
.mes_en ( mes_en ),
.a_i ( a_i ),
.b_i ( b_i ),
.c_i ( c_i ),
.d_i ( d_i ),
.a_o ( a_o ),
.b_o ( b_o ),
.c_o ( c_o ),
.d_o ( d_o ),
.abcd_en ( abcd_en )
);
parameter clk_period = 10;
//clk
initial begin
clk = 1;
forever
#(clk_period/2) clk = ~clk;
end
//a_i,b_i,c_i,d_i
initial begin
a_i = 'h67452301;
b_i = 'hefcdab89;
c_i = 'h98badcfe;
d_i = 'h10325476;
end
//mes_i
initial begin
//"12"
mes_i = 512'h00803231_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_0000_0010_0000_0000;
//----------------p0-------p1-------p2-------p3-------p4-------p5--------p6-------p7------p8--------p9------p10------p11------p12------p13-------p14------p15----
end
//mes_en
initial begin
mes_en = 0;
#(clk_period * 2)
mes_en = 1;
#clk_period
mes_en = 0;
end
endmodule
tb文件测试对字符串"12"的MD5加密。ASCII码分别为 0x31 0x32。
每步的结算结果可使用该工具验证:https://download.csdn.net/download/Blaze_Xu/13134582
在终端cd进路径后运行该工具传入字符串"12"的结果:
上面是算法验证,下面是能综合优化后的:
module md5(
input clk_i,
input rst_i,
input date_en_in,
input [ 7:0] date_in,
input date_soc_in,
input date_eoc_in,
output wire date_buf_fifo_full,
output reg [31:0] a_o,
output reg [31:0] b_o,
output reg [31:0] c_o,
output reg [31:0] d_o,
output reg abcd_en
);
reg rst_d1;
reg rst_d2;
wire rst;
reg buf_ready;
reg buf_ready_d1;
reg date_eoc_in_d1;
wire date_buf_fifo_we;
wire [ 7:0] date_buf_fifo_in;
reg date_buf_fifo_rd;
reg date_buf_fifo_rd_d1;
wire [ 7:0] date_buf_fifo_out;
wire date_buf_fifo_emp;
wire [12:0] date_buf_fifo_cnt;
wire date_buf_fifo_pfull;
reg date_buf_fifo_pfull_d1;
reg [10:0] date_len_cnt;
wire date_len_fifo_emp;
wire date_len_fifo_we;
wire [10:0] date_len_fifo_in;
reg date_len_fifo_rd;
reg date_len_fifo_rd_d1;
wire [10:0] date_len_fifo_dout;
reg [10:0] fr_len_out_cnt;
reg fr_read;
reg fr_read_d1;
reg fr_read_d2;
reg fr_read_d3;
reg fr_read_d4;
reg [ 7:0] md5_date;
reg md5_date_en;
reg md5_date_soc;
reg md5_date_eoc;
reg [ 1:0] mem_cnt; // record quantity of 512bits in the ram. 0, 1, 2
reg ready; // allow date entry.
reg [63:0] bit_len;
reg [63:0] bit_len_r;
wire push_en;
reg [ 1:0] push4_cnt; // record the number of date pushing the ram. 8*4=32
reg [ 5:0] push64_cnt; // record the number of date pushing the ram. 8*63=512
reg pad_en; // allow pad 1, 0 and the date length follow the date.
reg pad_1_en;
reg pad_0_en;
reg pad_len_en;
reg [31:0] merge_4_d;
reg [ 4:0] md5_date_ram_waddr;
reg md5_date_ram_we;
wire [31:0] md5_date_ram_din;
wire [ 4:0] md5_date_ram_raddr;
reg md5_date_ram_rd; // virtual
reg md5_date_ram_rd_d1; // virtual
wire [31:0] md5_date_ram_dout;
reg md5_date_ram_raddr_h;
reg [ 3:0] md5_date_ram_raddr_l;
reg [ 5:0] md5_para_rom_raddr;
wire [31:0] md5_para_rom_dout;
reg operate;
reg operate_d1;
reg operate_neg;
reg [ 8:0] step; // operate step. 0 to 319. 512bit/320clk_i.
reg [ 2:0] step_5_cnt;
reg [ 4:0] step_20_cnt;
wire [ 2:0] roundad[3:0];
reg [ 1:0] round;
reg [31:0] s1;
reg [31:0] s21;
reg [31:0] s22;
reg [31:0] s3;
reg [31:0] s4;
reg [31:0] a;
reg [31:0] b;
reg [31:0] c;
reg [31:0] cc;
reg [31:0] d;
reg [31:0] a_r;
reg [31:0] b_r;
reg [31:0] c_r;
reg [31:0] d_r;
//------------asynchronous reset----------------
always @(posedge clk_i or posedge rst_i)
begin
if(rst_i) begin
rst_d1 <= 1'b1;
rst_d2 <= 1'b1;
end else begin
rst_d1 <= 1'b0;
rst_d2 <= rst_d1;
end
end
assign rst = rst_d2;
//============================================== buffer ===========================================
//---------------- buf_ready -------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
buf_ready <= 1'b0;
else if(date_buf_fifo_pfull==1'b0)
buf_ready <= 1'b1;
else if(date_buf_fifo_pfull==1'b1 && date_eoc_in==1'b1)
buf_ready <= 1'b0;
else
buf_ready <= buf_ready;
end
//---------------- buf_ready_d -----------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
buf_ready_d1 <= 1'b0;
else
buf_ready_d1 <= buf_ready;
end
//----------------date_buf_fifo_we_gen----------
assign date_buf_fifo_we = buf_ready_d1 & date_en_in;
//----------------date_buf_fifo_in_gen----------
assign date_buf_fifo_in = date_in;
//----------------date_buf_fifo_full_gen--------
assign date_buf_fifo_full = date_buf_fifo_pfull;
//----------------date_len_cnt_gen--------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
date_len_cnt <= 11'd1;
else if(buf_ready==1'b1 && date_soc_in==1'b1)
date_len_cnt <= 11'd1;
else if(buf_ready==1'b1 && date_en_in==1'b1)
date_len_cnt <= date_len_cnt + 1'b1;
else
date_len_cnt <= date_len_cnt;
end
//----------------date_eoc_in_d1----------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
date_eoc_in_d1 <= 1'b0;
else
date_eoc_in_d1 <= date_eoc_in;
end
//----------------date_len_fifo_we_gen----------
assign date_len_fifo_we = buf_ready_d1 & date_eoc_in_d1;
//----------------date_len_fifo_in_gen----------
assign date_len_fifo_in = date_len_cnt;
//============================================== read buffer ======================================
//----------------date_len_fifo_rd_gen----------
always @(posedge clk_i or posedge rst)
begin
if(rst)
date_len_fifo_rd <= 1'b0;
else if(fr_read==1'b0 && date_len_fifo_rd==1'b0 && date_len_fifo_emp==1'b0 && md5_ready==1'b1)
date_len_fifo_rd <= 1'b1; // get frame length
else
date_len_fifo_rd <= 1'b0;
end
//----------------date_len_fifo_rd_d1-----------
always @(posedge clk_i or posedge rst)
begin
if(rst)
date_len_fifo_rd_d1 <= 1'b0;
else
date_len_fifo_rd_d1 <= date_len_fifo_rd;
end
//----------------fr_read_gen-------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
fr_read <= 1'b0;
else if(date_len_fifo_rd==1'b1) // operate start
fr_read <= 1'b1;
else if(abcd_en==1'b1) //operate end
fr_read <= 1'b0;
else
fr_read <= fr_read;
end
//----------------fr_read_d---------------------
always @(posedge clk_i or posedge rst)
begin
if(rst) begin
fr_read_d1 <= 1'b0;
fr_read_d2 <= 1'b0;
fr_read_d3 <= 1'b0;
fr_read_d4 <= 1'b0;
end else begin
fr_read_d1 <= fr_read;
fr_read_d2 <= fr_read_d1;
fr_read_d3 <= fr_read_d2;
fr_read_d4 <= fr_read_d3;
end
end
//----------------fr_out_en_gen-----------------
assign fr_out_en = fr_read & md5_ready & (fr_len_out_cnt!=11'd0);
//----------------fr_len_out_cnt----------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
fr_len_out_cnt <= 11'h0;//
else if(fr_read==1'b1 && date_len_fifo_rd_d1==1'b1)
fr_len_out_cnt <= date_len_fifo_dout;
else if(fr_read==1'b1 && fr_out_en==1'b1)
fr_len_out_cnt <= fr_len_out_cnt - 1'b1;
else
fr_len_out_cnt <= fr_len_out_cnt;
end
//----------------date_buf_fifo_rd_gen--------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
date_buf_fifo_rd <= 1'b0;
else if(fr_out_en==1'b1)
date_buf_fifo_rd <= 1'b1;
else
date_buf_fifo_rd <= 1'b0;
end
//----------------date_buf_fifo_rd_d1---------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
date_buf_fifo_rd_d1 <= 1'b0;
else
date_buf_fifo_rd_d1 <= date_buf_fifo_rd;
end
//----------------md5_date_en-------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
md5_date_en <= 1'b0;
else
md5_date_en <= date_buf_fifo_rd_d1;
end
//----------------md5_date----------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
md5_date <= 8'd0;
else
md5_date <= date_buf_fifo_out;
end
//----------------md5_date_soc_gen--------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
md5_date_soc <= 1'b0;
else if(fr_read_d3==1'b1 && fr_read_d4==1'b0)
md5_date_soc <= 1'b1;
else
md5_date_soc <= 1'b0;
end
//----------------md5_date_eoc_gen--------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
md5_date_eoc <= 1'b0;
else if(fr_read==1'b1 && date_buf_fifo_rd==1'b0 && date_buf_fifo_rd_d1==1'b1 && fr_len_out_cnt==11'd0)
md5_date_eoc <= 1'b1;
else
md5_date_eoc <= 1'b0;
end
date_b_fifo date_buf_fifo_inst (
.clk (clk_i ), // input wire clk_i
.srst (rst ), // input wire srst
.din (date_buf_fifo_in ), // input wire [7 : 0] din
.wr_en (date_buf_fifo_we ), // input wire wr_en
.rd_en (date_buf_fifo_rd ), // input wire rd_en
.dout (date_buf_fifo_out ), // output wire [7 : 0] dout
.empty (date_buf_fifo_emp ), // output wire empty
.full ( ), // output wire full
.prog_full (date_buf_fifo_pfull) // output wire prog_full
);
date_len_fifo date_len_fifo_inst (
.clk (clk_i ), // input wire clk_i
.srst (rst ), // input wire srst
.din (date_len_fifo_in ), // input wire [10 : 0] din
.wr_en (date_len_fifo_we ), // input wire wr_en
.rd_en (date_len_fifo_rd ), // input wire rd_en
.dout (date_len_fifo_dout ), // output wire [10 : 0] dout
.full (full ), // output wire full
.empty (date_len_fifo_emp ) // output wire empty
);
//============================================== push =============================================
//----------------bit_len_gen-------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
bit_len <= 64'd8;
else if(md5_date_eoc==1'b1)
bit_len <= 64'd8;
else if(md5_date_en==1'b1)
bit_len <= bit_len + 64'd8;
else
bit_len <= bit_len;
end
//----------------bit_len_r_gen-----------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
bit_len_r <= 64'd0;
else if(md5_date_eoc==1'b1)
bit_len_r <= bit_len;
else
bit_len_r <= bit_len_r;
end
//----------------push_en_gen-------------------
assign push_en = md5_date_en | (pad_en & ready); // push enter date and pad date
//----------------push4_cnt_gen-----------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
push4_cnt <= 2'd0;
else if(md5_date_soc==1'b1)
push4_cnt <= 2'd1;
else if(push_en==1'b1)
push4_cnt <= push4_cnt + 1'b1;
else
push4_cnt <= push4_cnt;
end
//----------------push64_cnt_gen----------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
push64_cnt <= 6'd0;
else if(md5_date_soc==1'b1)
push64_cnt <= 6'd1;
else if(push_en==1'b1)
push64_cnt <= push64_cnt + 1'b1;
else
push64_cnt <= push64_cnt;
end
//----------------mem_cnt_gen-------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
mem_cnt <= 2'd0;
else if(push_en==1'b1 && push64_cnt==6'd62) // pushed 512bits
mem_cnt <= mem_cnt + 1'b1;
else if(operate==1'b1 && step==9'd319) // operated 512bits
mem_cnt <= mem_cnt - 1'b1;
else
mem_cnt <= mem_cnt;
end
//----------------ready_gen---------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
ready <= 1'b0;
else if(mem_cnt!=2'd2)
ready <= 1'b1;
else
ready <= 1'b0;
end
//----------------md5_ready_gen-----------------
assign md5_ready = ready;
//============================================== save and pad ========================================
//----------------pad_en------------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
pad_en <= 1'b0;
else if(md5_date_eoc==1'b1)
pad_en <= 1'b1;
else if(push_en==1'b1 && push64_cnt==6'd63 && pad_len_en==1) // pad last bit
pad_en <= 1'b0;
else
pad_en <= pad_en;
end
//----------------pad_1_en_gen------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
pad_1_en <= 1'b0;
else if(md5_date_eoc==1'b1)
pad_1_en <= 1'b1;
else if(push_en==1'b1 && pad_1_en==1'b1) // pad the first bit of 512 unready.
pad_1_en <= 1'b0;
else
pad_1_en <= pad_1_en;
end
//----------------pad_0_en_gen------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
pad_0_en <= 1'b0;
else if(push_en==1'b1 && push64_cnt==6'd55) //448bit
pad_0_en <= 1'b0;
else if(push_en==1'b1 && pad_1_en==1'b1) // negedge of pad_1_en
pad_0_en <= 1'b1;
else
pad_0_en <= pad_0_en;
end
//----------------pad_len_en_gen----------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
pad_len_en <= 1'b0;
else if(push_en==1'b1 && push64_cnt==6'd55 && (pad_1_en==1'b1 || pad_0_en==1'b1))
pad_len_en <= 1'b1;
else if(push_en==1'b1 && push64_cnt==6'd63 && pad_len_en==1'b1) // 512bit
pad_len_en <= 1'b0;
else
pad_len_en <= pad_len_en;
end
//----------------merge_4_d_gen-----------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
merge_4_d <= 32'd0;
else if(md5_date_en==1'b1)
merge_4_d <= {md5_date,merge_4_d[31:8]}; // pad date
else if(pad_1_en==1'b1 && ready==1'b1)
merge_4_d <= {8'h80,merge_4_d[31:8]}; // pad 1
else if(pad_0_en==1'b1 && ready==1'b1)
merge_4_d <= {8'h00,merge_4_d[31:8]}; // pad 0
else if(pad_len_en==1'b1 && ready==1'b1) begin
if(push_en==1'b1 && push64_cnt<6'd60)
merge_4_d <= bit_len_r[31:0]; // pad length low 32 bit
else
merge_4_d <= bit_len_r[63:32]; // pad length high 32 bit
end else
merge_4_d <= merge_4_d;
end
//----------------md5_date_ram_we_gen-----------
always @(posedge clk_i or posedge rst)
begin
if(rst)
md5_date_ram_we <= 1'b0;
else if(push_en==1'b1 && push4_cnt==2'd3)
md5_date_ram_we <= 1'b1;
else
md5_date_ram_we <= 1'b0;
end
//----------------md5_date_ram_waddr_gen--------
always @(posedge clk_i or posedge rst)
begin
if(rst)
md5_date_ram_waddr <= 5'd0;
else if(md5_date_soc==1'b1)
md5_date_ram_waddr <= 5'd0;
else if(push_en==1'b1 && push4_cnt==2'd0)
md5_date_ram_waddr <= md5_date_ram_waddr + 1'b1;
else
md5_date_ram_waddr <= md5_date_ram_waddr;
end
//----------------md5_date_ram_din_gen----------
assign md5_date_ram_din = merge_4_d;
md5_date_ram md5_date_ram_inst (
.we (md5_date_ram_we ), // input wire we
.a (md5_date_ram_waddr ), // input wire [ 4 : 0] a
.d (md5_date_ram_din ), // input wire [31 : 0] d
.clk (clk_i ), // input wire clk_i
.dpra (md5_date_ram_raddr ), // input wire [ 4 : 0] dpra
.qdpo (md5_date_ram_dout ) // output wire [31 : 0] qdpo
);
//============================================== get date =========================================
//----------------oprate_gen--------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
operate <= 1'b0;
else if(mem_cnt!=2'd0) //关键控制信号operate
operate <= 1'b1;
else
operate <= 1'b0;
end
//----------------step_gen----------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
step <= 9'd0;
else if((operate==1'b1 && step==9'd319) || md5_date_soc==1'b1)
step <= 9'd0;
else if(operate==1'b1)
step <= step + 1'b1;
else
step <= step;
end
//----------------step_5_cnt_gen----------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
step_5_cnt <= 3'd0;
else if((operate==1'b1 && step_5_cnt==3'd4) || md5_date_soc==1'b1)
step_5_cnt <= 3'd0;
else if(operate==1'b1)
step_5_cnt <= step_5_cnt + 1'b1;
else
step_5_cnt <= step_5_cnt;
end
//----------------step_20_cnt_gen---------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
step_20_cnt <= 5'd0;
else if((operate==1'b1 && step_20_cnt==5'd19) || md5_date_soc==1'b1)
step_20_cnt <= 5'd0;
else if(operate==1'b1)
step_20_cnt <= step_20_cnt + 1'b1;
else
step_20_cnt <= step_20_cnt;
end
//----------------roundad-----------------------
assign roundad[0] = 3'd1;
assign roundad[1] = 3'd5;
assign roundad[2] = 3'd3;
assign roundad[3] = 3'd7;
//----------------round_gen---------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
round <= 2'd0;
else begin
case(step)
9'd0 : round <= 2'd0;
9'd79 : round <= 2'd1;
9'd159: round <= 2'd2;
9'd239: round <= 2'd3;
9'd319: round <= 2'd0;
default: round <= round;
endcase
end
end
//----------------md5_date_ram_raddr_h_gen------
always @(posedge clk_i or posedge rst)
begin
if(rst)
md5_date_ram_raddr_h <= 1'b0;
else if(md5_date_soc==1'b1)
md5_date_ram_raddr_h <= 1'b0;
else if(operate==1'b1 && step==9'd318)
md5_date_ram_raddr_h <= ~md5_date_ram_raddr_h;
else
md5_date_ram_raddr_h <= md5_date_ram_raddr_h;
end
//----------------md5_date_ram_rd_gen-----------
always @(posedge clk_i or posedge rst)
begin
if(rst)
md5_date_ram_rd <= 1'b0;
else if(operate==1'b1 && step_5_cnt==3'd2)
md5_date_ram_rd <= 1'b1;
else
md5_date_ram_rd <= 1'b0;
end
//----------------md5_date_ram_rd_d1------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
md5_date_ram_rd_d1 <= 1'b0;
else
md5_date_ram_rd_d1 <= md5_date_ram_rd;
end
//----------------md5_date_ram_raddr_l_gen------
always @(posedge clk_i or posedge rst)
begin
if(rst)
md5_date_ram_raddr_l <= 4'd0;
else if(md5_date_ram_rd==1'b1)begin
case(step)
9'd0 : md5_date_ram_raddr_l <= 4'd0;
9'd78 : md5_date_ram_raddr_l <= 4'd1;
9'd158 : md5_date_ram_raddr_l <= 4'd5;
9'd238 : md5_date_ram_raddr_l <= 4'd0;
default: md5_date_ram_raddr_l <= md5_date_ram_raddr_l + roundad[round];
endcase
end else
md5_date_ram_raddr_l <= md5_date_ram_raddr_l;
end
//----------------md5_date_ram_raddr_gen--------
assign md5_date_ram_raddr = {md5_date_ram_raddr_h,md5_date_ram_raddr_l};
//----------------md5_para_rom_raddr_gen--------
always @(posedge clk_i or posedge rst)
begin
if(rst)
md5_para_rom_raddr <= 6'd0;
else if(step==1'b0)
md5_para_rom_raddr <= 6'd0;
else if(operate==1'b1 && step_5_cnt==3'd3)
md5_para_rom_raddr <= md5_para_rom_raddr + 1'b1;
else
md5_para_rom_raddr <= md5_para_rom_raddr;
end
md5_para_rom md5_para_rom_inst (
.a (md5_para_rom_raddr ), // input wire [ 5 : 0] a
.clk (clk_i ), // input wire clk_i
.qspo (md5_para_rom_dout ) // output wire [31 : 0] qspo
);
//============================================== operate ==========================================
//----------------s1_gen------------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
s1 <= 32'h0;
else begin
case({operate,round,step_20_cnt})
8'b1_00_00000: s1 <= (b&c)|((~b)&d);
8'b1_00_00101: s1 <= (a&b)|((~a)&c);
8'b1_00_01010: s1 <= (d&a)|((~d)&b);
8'b1_00_01111: s1 <= (c&d)|((~c)&a);
8'b1_01_00000: s1 <= (b&d)|(c&(~d));
8'b1_01_00101: s1 <= (a&c)|(b&(~c));
8'b1_01_01010: s1 <= (d&b)|(a&(~b));
8'b1_01_01111: s1 <= (c&a)|(d&(~a));
8'b1_10_00000: s1 <= b^c^d;
8'b1_10_00101: s1 <= a^b^c;
8'b1_10_01010: s1 <= d^a^b;
8'b1_10_01111: s1 <= c^d^a;
8'b1_11_00000: s1 <= c^(b|(~d));
8'b1_11_00101: s1 <= b^(a|(~c));
8'b1_11_01010: s1 <= a^(d|(~b));
8'b1_11_01111: s1 <= d^(c|(~a));
default : s1 <= s1;
endcase
end
end
//----------------s21_gen-----------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
s21 <= 32'h0;
else begin
case({operate,step_20_cnt})
6'b1_00001: s21 <= a + s1;
6'b1_00110: s21 <= d + s1;
6'b1_01011: s21 <= c + s1;
6'b1_10000: s21 <= b + s1;
default : s21 <= s21;
endcase
end
end
//----------------s22_gen-----------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
s22 <= 32'h0;
else if(operate==1'b1 && step_5_cnt==3'd1)
s22 <= md5_date_ram_dout + md5_para_rom_dout;
else
s22 <= s22;
end
//----------------s3_gen------------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
s3 <= 32'h0;
else if(operate==1'b1 && step_5_cnt==3'd2)
s3 <= s21 + s22;
else
s3 <= s3;
end
//----------------s4_gen------------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
s4 <= 32'h0;
else begin
case({operate,round,step_20_cnt})
8'b1_00_00011: s4 <= {s3[24:0],s3[31:25]};
8'b1_00_01000: s4 <= {s3[19:0],s3[31:20]};
8'b1_00_01101: s4 <= {s3[14:0],s3[31:15]};
8'b1_00_10010: s4 <= {s3[ 9:0],s3[31:10]};
8'b1_01_00011: s4 <= {s3[26:0],s3[31:27]};
8'b1_01_01000: s4 <= {s3[22:0],s3[31:23]};
8'b1_01_01101: s4 <= {s3[17:0],s3[31:18]};
8'b1_01_10010: s4 <= {s3[11:0],s3[31:12]};
8'b1_10_00011: s4 <= {s3[27:0],s3[31:28]};
8'b1_10_01000: s4 <= {s3[20:0],s3[31:21]};
8'b1_10_01101: s4 <= {s3[15:0],s3[31:16]};
8'b1_10_10010: s4 <= {s3[ 8:0],s3[31: 9]};
8'b1_11_00011: s4 <= {s3[25:0],s3[31:26]};
8'b1_11_01000: s4 <= {s3[21:0],s3[31:22]};
8'b1_11_01101: s4 <= {s3[16:0],s3[31:17]};
8'b1_11_10010: s4 <= {s3[10:0],s3[31:11]};
default: s4 <= s4;
endcase
end
end
//----------------a_gen-------------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
a <= 32'h67452301;
else if(md5_date_soc==1'b1)
a <= 32'h67452301;
else if(operate==1'b1 && step_20_cnt==5'd4)
a <= b + s4;
else if(operate==1'b1 && step==9'd319)
a <= a + a_r;
else
a <= a;
end
//----------------d_gen-------------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
d <= 32'h10325476;
else if(md5_date_soc==1'b1)
d <= 32'h10325476;
else if(operate==1'b1 && step_20_cnt==5'd9)
d <= a + s4;
else if(operate==1'b1 && step==9'd319)
d <= d + d_r;
else
d <= d;
end
//----------------c_gen-------------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
c <= 32'h98badcfe;
else if(md5_date_soc==1'b1)
c <= 32'h98badcfe;
else if(operate==1'b1 && step_20_cnt==5'd14)
c <= d + s4;
else if(operate==1'b1 && step==9'd319)
c <= c + c_r;
else
c <= c;
end
//----------------b_gen-------------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
b <= 32'hefcdab89;
else if(md5_date_soc==1'b1)
b <= 32'hefcdab89;
else if(operate==1'b1 && step==9'd318)
cc <= c + b_r; // pre add
else if(operate==1'b1 && step==9'd319)
b <= cc + s4; // dissatisfy clk_i
else if(operate==1'b1 && step_20_cnt==5'd19)
b <= c + s4;
else
b <= b;
end
//----------------a_r_gen-----------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
a_r <= 32'h67452301;
else if(operate==1'b1 && step==9'd0)
a_r <= a;
else
a_r <= a_r;
end
//----------------b_r_gen-----------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
b_r <= 32'hefcdab89;
else if(operate==1'b1 && step==9'd0)
b_r <= b;
else
b_r <= b_r;
end
//----------------c_r_gen-----------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
c_r <= 32'h98badcfe;
else if(operate==1'b1 && step==9'd0)
c_r <= c;
else
c_r <= c_r;
end
//----------------d_r_gen-----------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
d_r <= 32'h10325476;
else if(operate==1'b1 && step==9'd0)
d_r <= d;
else
d_r <= d_r;
end
//============================================== out ==============================================
//----------------operate_neg-------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
operate_neg <= 1'b0;
else if(operate==1'b0 && operate_d1==1'b1)
operate_neg <= 1'b1;
else
operate_neg <= 1'b0;
end
//----------------a_o_gen-----------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
a_o <= 32'h67452301;
else if(operate_neg==1'b1)
a_o <= a;
else
a_o <= a_o;
end
//----------------b_o_gen-----------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
b_o <= 32'hefcdab89;
else if(operate_neg==1'b1)
b_o <= b;
else
b_o <= b_o;
end
//----------------c_o_gen-----------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
c_o <= 32'h98badcfe;
else if(operate_neg==1'b1)
c_o <= c;
else
c_o <= c_o;
end
//----------------d_o_gen-----------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
d_o <= 32'h10325476;
else if(operate_neg==1'b1)
d_o <= d;
else
d_o <= d_o;
end
//----------------operate_d1--------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
operate_d1 <= 1'b0;
else
operate_d1 <= operate;
end
//----------------abcd_en_gen-------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
abcd_en <= 1'b0;
else if(operate_neg==1'b1) // operate negedge
abcd_en <= 1'b1;
else
abcd_en <= 1'b0;
end
endmodule
仿真文件
`timescale 1ns / 1ps
module md5tb(
);
reg clk_i;
reg rst;
reg date_en_in;
reg date_soc_in;
reg date_eoc_in;
reg [ 7:0] date_in;
wire date_buf_fifo_full;
wire [31:0] a_o;
wire [31:0] b_o;
wire [31:0] c_o;
wire [31:0] d_o;
wire abcd_en;
reg req;
reg [15:0] date_cnt;
reg [ 7:0] date_txt [0:1499];
md5 md5_tb(
.clk_i (clk_i ),
.rst_i (rst ),
.date_en_in (date_en_in ),
.date_soc_in (date_soc_in ),
.date_eoc_in (date_eoc_in ),
.date_in (date_in ),
.date_buf_fifo_full (date_buf_fifo_full ),
.a_o (a_o ),
.b_o (b_o ),
.c_o (c_o ),
.d_o (d_o ),
.abcd_en (abcd_en )
);
parameter clk_i_PERIOD = 10;
parameter NUM = 60;
//-----------------clk_i-----------------------
initial begin
clk_i = 1;
forever begin
#(clk_i_PERIOD/2)
clk_i = ~clk_i;
end
end
//-----------------rst--------------------------
initial begin
rst = 0;
#clk_i_PERIOD
rst = 1;
#clk_i_PERIOD
rst = 0;
end
//-------------- length ------------------------
integer arr [0 : NUM-1];
integer n;
initial begin
n = 0;
forever @(posedge clk_i) begin
if(n<NUM) begin
arr[n] = (({$random}%3) + 1) * 96; //96 192 288
n = n + 1;
end
end
end
//----------------req_gen-----------------------
always @(posedge clk_i or posedge rst)
begin
if(rst)
req <= 1'b0;
else if(date_buf_fifo_full==1'b1 && date_eoc_in==1'b1)
req <= 1'b0;
else if(date_buf_fifo_full==1'b0)
req <= 1'b1;
else
req <= req;
end
//----------------date_cnt_gen------------------
integer j;
initial begin
date_cnt = 16'd0;
j = 0;
#(clk_i_PERIOD*11)
forever @(posedge clk_i)
begin
if(req==1'b1 && date_cnt==arr[j] && j<NUM-1) begin
j = j + 1;
date_cnt = 16'd0;
end else if(req==1'b1 && date_cnt<=arr[j])
date_cnt = date_cnt + 1'b1;
else
date_cnt = date_cnt;
end
end
//----------------date_in_gen-------------------
integer i;
initial begin
$readmemh("D:/Projects/source/tb_md5_data.txt",date_txt,0,1499);
i = 0;
date_in = 1'b0;
#(clk_i_PERIOD*10)
forever @(posedge clk_i)
begin
if(date_cnt==arr[j])begin
i = 0;
end else if(req==1'b1 && date_cnt<arr[j]) begin
date_in = date_txt[i];
i = i + 1;
end else begin
i = i;
date_in = date_in;
end
end
end
//----------------date_en_i_gen-----------------
initial begin
date_en_in = 1'b0;
#(clk_i_PERIOD*10)
forever @(posedge clk_i)
begin
if(req==1'b1 && date_cnt<arr[j])
date_en_in = 1'b1;
else
date_en_in = 1'b0;
end
end
//----------------date_soc_i_gen----------------
initial begin
date_soc_in = 1'b0;
#(clk_i_PERIOD*10)
forever @(posedge clk_i)
begin
if(req==1'b1 && date_cnt==16'd0)
date_soc_in = 1'b1;
else
date_soc_in = 1'b0;
end
end
//----------------date_eoc_i_gen----------------
initial begin
date_eoc_in = 1'b0;
forever @(posedge clk_i)
begin
if(req==1'b1 && date_en_in==1'b1 && date_cnt==arr[j]-1)
date_eoc_in = 1'b1;
else
date_eoc_in = 1'b0;
end
end
endmodule
仿真数据是用matlab生成的12345678的ASCII码的循环。
tb_md5_data.txt:
31 // ASCII of "1"
32
33
34
35
36
37
38
31
32
33
34
35
36
37
38
.
.
.
//一直循环2000行,这里测试的数据长度为1500bit以内。
参数rom的初始化文件md5_rom.coe
MEMORY_INITIALIZATION_RADIX=16;
MEMORY_INITIALIZATION_VECTOR=
d76aa478,
e8c7b756,
242070db,
c1bdceee,
f57c0faf,
4787c62a,
a8304613,
fd469501,
698098d8,
8b44f7af,
ffff5bb1,
895cd7be,
6b901122,
fd987193,
a679438e,
49b40821,
f61e2562,
c040b340,
265e5a51,
e9b6c7aa,
d62f105d,
02441453,
d8a1e681,
e7d3fbc8,
21e1cde6,
c33707d6,
f4d50d87,
455a14ed,
a9e3e905,
fcefa3f8,
676f02d9,
8d2a4c8a,
fffa3942,
8771f681,
6d9d6122,
fde5380c,
a4beea44,
4bdecfa9,
f6bb4b60,
bebfbc70,
289b7ec6,
eaa127fa,
d4ef3085,
04881d05,
d9d4d039,
e6db99e5,
1fa27cf8,
c4ac5665,
f4292244,
432aff97,
ab9423a7,
fc93a039,
655b59c3,
8f0ccc92,
ffeff47d,
85845dd1,
6fa87e4f,
fe2ce6e0,
a3014314,
4e0811a1,
f7537e82,
bd3af235,
2ad7d2bb,
eb86d391;
工程源文件下载地址:https://download.csdn.net/download/Blaze_Xu/13713217