FPGA Verilog md5算法实现源代码及仿真文件分享。

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

  • 5
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值