CHECK SUM校验和CRC校验相比简单之处就是每相加的16个BIT的字可以不论先后顺序。在UDP的CHECK SUM计算实现中,这地点就允许我们想算出来UDP报文内容的SUM,之后再加上UDP头部的各个16位字算出来最红CHECK SUM.
无论IP还是UDP的字节个数都是偶数,也就是有整数个16位字。但是UDP的报文可以是奇数个字节,我们这里在算到最后一个报文的时候要做一下处理,之后得到结果才能去和UDP头部的其他16位字相加求和。
module cal_byte_sum (
input clk,rst, clr,feed ,do_cal,
input [7:0] din ,
output reg [15:0] chk_sum ,
output reg result_valid
);
reg f = 0 ;
wire local_rst = clr | rst ;
reg [31:0] sum ;
reg [7:0] u8 ;
//always @ (posedge clk) if (local_rst) f<=0;else if (feed)f<=~f;//f <= f^feed;
always @ (posedge clk)
if (local_rst) {sum,u8,f}<=0; else
case ({feed ,do_cal})
2'b10:begin f<=~f; if (f==0) u8<=din[7:0] ; else sum<=sum+{u8,din};end
2'b01:begin f<=0 ; if (f==1) sum<=sum+{u8,8'b0} ; end
2'b11:begin f<=0 ; if (f==0) sum<=sum+{din[7:0], 8'b0}; else sum<=sum+{u8,din}; end
endcase // stage 1
reg [16:0] sumr;always @(posedge clk) sumr<= sum[15:0] + sum[31:16] ; //stage2
reg [15:0] sumrr;always @(posedge clk) sumrr<= sumr[15:0] + sumr[16] ;// stage3
always @ (posedge clk ) chk_sum <= ~sumrr; //stage 4
reg [3:0]r ;always @(posedge clk) r[3:0]<= {r[2:0],do_cal} ;
always @ (posedge clk ) if(local_rst) result_valid<=0;else if (r[2])result_valid<=1;
endmodule
其实我们直到对待最后一个奇数的字节就是将之作为高8位,而第八位补齐0,加到sum里面。
这里我们看到do_cal这个信号,在报文的最后一个字节到来的时候无论当前字节是奇数还是偶数,我们都要拉高do_cal先做16位字对其一个小结。
reg sum_gen_clr , sum_gen_feed , sum_do_cal ;
reg [7:0] sum_din ;
always @(posedge clk)case (st)
100: begin sum_gen_clr <=~s_tx_start ; sum_gen_feed<=s_tx_start ; sum_do_cal<=0;sum_din <= s_tx_dat; end
200: begin {sum_gen_clr , sum_gen_feed }<= 2'b01 ;sum_do_cal <= wr_addr == wr_addr_end ; sum_din<= s_tx_dat; end
300: begin {sum_gen_clr , sum_gen_feed , sum_do_cal}<= 3'b010 ;sum_din <= src_port_reg[15:8]; end
301: begin {sum_gen_clr , sum_gen_feed , sum_do_cal}<= 3'b010 ;sum_din <= src_port_reg[7:0]; end
302: begin {sum_gen_clr , sum_gen_feed , sum_do_cal}<= 3'b010 ;sum_din <= dst_port_reg[15:8]; end
303: begin {sum_gen_clr , sum_gen_feed , sum_do_cal}<= 3'b010 ;sum_din <= dst_port_reg[7:0]; end
304: begin {sum_gen_clr , sum_gen_feed , sum_do_cal}<= 3'b010 ;sum_din <= s_tx_len_p8_r[15:8]; end //ok
305: begin {sum_gen_clr , sum_gen_feed , sum_do_cal}<= 3'b010 ;sum_din <= s_tx_len_p8_r[7:0]; end //ok S
306: begin {sum_gen_clr , sum_gen_feed , sum_do_cal}<= 3'b000 ;sum_din <= 0 ; end
307: begin {sum_gen_clr , sum_gen_feed , sum_do_cal}<= 3'b000 ;sum_din <= 0 ; end
308:
case (chksum_state)
0:begin sum_din <= m_src_ip[31:24]; {sum_gen_clr , sum_gen_feed , sum_do_cal}<= 3'b010 ;end
1:begin sum_din <= m_src_ip[23:16]; end
2:begin sum_din <= m_src_ip[15:8]; end
3:begin sum_din<= m_src_ip[7:0]; end
4:begin sum_din<= m_dst_ip[31:24]; end
5:begin sum_din<= m_dst_ip[23:16]; end
6:begin sum_din<= m_dst_ip[15:8]; end
7:begin sum_din<= m_dst_ip[7:0]; end
9:begin sum_din<= 8'h11; end
8:begin sum_din<= 8'h00; end
10 :sum_din <= s_tx_len_p8_r[15:8];
11 :sum_din <= s_tx_len_p8_r[7:0];
12 :{sum_gen_clr , sum_gen_feed , sum_do_cal}<= 3'b001 ;
13 :{sum_gen_clr , sum_gen_feed , sum_do_cal}<= 3'b000 ;
endcase
endcase
其中
200: begin {sum_gen_clr , sum_gen_feed }<= 2'b01 ;sum_do_cal <= wr_addr == wr_addr_end ; sum_din<= s_tx_dat; end
我们看到在最后一个字节带来的同时设置do_Cal=0,由于此时当前数据也要写入进行运算,所以gen_feed也是数值为1 .
----
12 :{sum_gen_clr , sum_gen_feed , sum_do_cal}<= 3'b001 ;
这是求结果,但是当前无数据输入的状态。在这个应用中实际上到这里已经输入了偶数个自己的udp头部,因此没有可以不设置do_cal=1.
{{aAx8MiOIVToIU8xIoVTiiWiHWXXWWiOviHIWTmIxvxvwVTU8IiWIviMo8OVVvWoT8oUwWOviVIOxviIOUViXxUw8mxMmxOmIomiHO8MxTmvUUmTHWxHvOwooIVooHXTxZz}}