文章目录
- 前言:ICMP层报文解析
- 一、ICMP_TX模块
- 一、ICMP_RX模块
前言:ICMP层报文解析
各字段说明
类型:占一字节,标识ICMP报文的类型,目前已定义了14种,从类型值来看ICMP报文可以分为两大类。第一类是取值为1~127的差错报文,第2类是取值128以上的信息报文。
代码:占一字节,标识对应ICMP报文的代码。它与类型字段一起共同标识了ICMP报文的详细类型。
校验和:这是对包括ICMP报文数据部分在内的整个ICMP数据报的校验和,以检验报文在传输过程中是否出现了差错。其计算方法与在我们介绍IP报头中的校验和计算方法是一样的。
标识:占两字节,用于标识本ICMP进程,但仅适用于回显请求和应答ICMP报文,对于目标不可达ICMP报文和超时ICMP报文等,该字段的值为0。
对于该层协议,只实现了PING请求与应答,所以内容很简单。
一、ICMP_TX模块
设计代码为本人参考FPGA奇哥系列网课自行编写
module ICMP_TX(input i_clk ,input i_rst ,input i_trig_reply ,input [15:0] i_trig_seq ,// input i_active_req ,// input [15:0] i_active_seq ,/*----send port----*/output [7 :0] o_icmp_data ,output [15:0] o_icmp_len ,output o_icmp_last ,output o_icmp_valid
);
/******************************function***************************//******************************parameter**************************/
localparam P_ICMP_LEN = 15'd40;
localparam P_ICMP_REPLY_TYPE = 8'd0;
localparam P_ICMP_REQ_TYPE = 8'd8;
/******************************port*******************************//******************************machine****************************//******************************reg********************************/
reg ri_trig_reply ;
reg [15:0] ri_trig_seq ;
reg ri_active_req ;
reg [15:0] ri_active_seq ;
reg [7 :0] ro_icmp_data ;
reg ro_icmp_last ;
reg ro_icmp_valid ;
//组帧
reg [15:0] r_icmp_cnt ;
reg [31:0] r_checksum ;
reg [15:0] r_check_cnt ;
/******************************wire*******************************//******************************component**************************//******************************assign*****************************/
assign o_icmp_data = ro_icmp_data ;
assign o_icmp_len = P_ICMP_LEN ;
assign o_icmp_last = ro_icmp_last ;
assign o_icmp_valid = ro_icmp_valid ;
/******************************always*****************************/
always @(posedge i_clk or posedge i_rst) beginif(i_rst)beginri_trig_reply <= 'd0;ri_trig_seq <= 'd0; ri_active_req <= 'd0;ri_active_seq <= 'd0; endelse beginri_trig_reply <= i_trig_reply;ri_trig_seq <= i_trig_seq; // ri_active_req <= i_active_req;// ri_active_seq <= i_active_seq;end
end
//check sum
always @(posedge i_clk or posedge i_rst) beginif(i_rst)r_check_cnt <= 'd0;else if(r_icmp_cnt == P_ICMP_LEN - 1)r_check_cnt <= 'd0;else if(r_check_cnt == 3)r_check_cnt <= r_check_cnt + 'd1;else if(ri_trig_reply || r_check_cnt)r_check_cnt <= r_check_cnt + 'd1;elser_check_cnt <= r_check_cnt;
endalways @(posedge i_clk or posedge i_rst) beginif(i_rst)r_checksum <= 'd0;else if(ri_trig_reply || r_check_cnt == 0)r_checksum <= 16'h0001 + ri_trig_seq;else if(r_check_cnt == 1)r_checksum <= r_checksum[31:16] + r_checksum[15:0];else if(r_check_cnt == 2)r_checksum <= r_checksum[31:16] + r_checksum[15:0];else if(r_check_cnt == 3)r_checksum <= ~r_checksum;elser_checksum <= r_checksum;
endalways @(posedge i_clk or posedge i_rst) beginif(i_rst)r_icmp_cnt <= 'd0;else if(r_icmp_cnt == P_ICMP_LEN - 1)r_icmp_cnt <= 'd0;else if(r_check_cnt == 3 || r_icmp_cnt)r_icmp_cnt <= r_icmp_cnt + 'd1;elser_icmp_cnt <= r_icmp_cnt;
endalways @(posedge i_clk or posedge i_rst) beginif(i_rst)ro_icmp_data <= 'd0;else case (r_icmp_cnt)0 : ro_icmp_data <= P_ICMP_REPLY_TYPE;//类型 8:请求回显 0:回显应答1 : ro_icmp_data <= 'd0;//代码 0:回复应答2 : ro_icmp_data <= r_checksum[15:8];//校验和3 : ro_icmp_data <= r_checksum[7 :0];4 : ro_icmp_data <= 8'h00;//标识符 16'h00015 : ro_icmp_data <= 8'h01;6 : ro_icmp_data <= ri_trig_seq[15:8];//序号7 : ro_icmp_data <= ri_trig_seq[7 :0];default : ro_icmp_data <= 'd0;//数据endcase
endalways @(posedge i_clk or posedge i_rst) beginif(i_rst)ro_icmp_valid <= 'd0;else if(ro_icmp_last)ro_icmp_valid <= 'd0;else if(r_check_cnt == 3)ro_icmp_valid <= 'd1;elsero_icmp_valid <= ro_icmp_valid;
endalways @(posedge i_clk or posedge i_rst) beginif(i_rst)ro_icmp_last <= 'd0;else if(r_icmp_cnt == P_ICMP_LEN - 1)ro_icmp_last <= 'd1;elsero_icmp_last <= 'd0;
endendmodule
一、ICMP_RX模块
module ICMP_RX(input i_clk ,input i_rst ,/*----recv port----*/input [7 :0] i_icmp_data ,input [15:0] i_icmp_len ,input i_icmp_last ,input i_icmp_valid ,/*----send port----*/output o_trig_reply ,output [15:0] o_trig_seq
);
/******************************function***************************//******************************parameter**************************/
localparam P_ICMP_REPLY_TYPE = 8'd0;
localparam P_ICMP_REQ_TYPE = 8'd8;
/******************************port*******************************//******************************machine****************************//******************************reg********************************/
reg [7 :0] ri_icmp_data ;
reg [15:0] ri_icmp_len ;
reg ri_icmp_last ;
reg ri_icmp_valid ;
reg ro_trig_reply ;
reg [15:0] ro_trig_seq ;
//解析接收的ICMP报文
reg [15:0] r_recv_icmp_cnt ;
reg [7 :0] r_icmp_type ;
/******************************wire*******************************//******************************component**************************//******************************assign*****************************/
assign o_trig_reply = ro_trig_reply ;
assign o_trig_seq = ro_trig_seq ;
/******************************always*****************************/
always @(posedge i_clk or posedge i_rst) beginif(i_rst) beginri_icmp_data <= 'd0;ri_icmp_len <= 'd0;ri_icmp_last <= 'd0;ri_icmp_valid <= 'd0; endelse beginri_icmp_data <= i_icmp_data ;ri_icmp_len <= i_icmp_len ;ri_icmp_last <= i_icmp_last ;ri_icmp_valid <= i_icmp_valid; end
endalways @(posedge i_clk or posedge i_rst) beginif(i_rst)r_recv_icmp_cnt <= 'd0;else if(ri_icmp_valid)r_recv_icmp_cnt <= r_recv_icmp_cnt + 'd1;elser_recv_icmp_cnt <= 'd0;
endalways @(posedge i_clk or posedge i_rst) beginif(i_rst)r_icmp_type <= 'd0;else if(ri_icmp_valid && r_recv_icmp_cnt == 0)r_icmp_type <= ri_icmp_data;elser_icmp_type <= r_icmp_type;
endalways @(posedge i_clk or posedge i_rst) beginif(i_rst)ro_trig_reply <= 'd0;else if(r_recv_icmp_cnt == 7 && r_icmp_type == P_ICMP_REQ_TYPE)//计数器为7时才获取到了请求回应序号ro_trig_reply <= 'd1;elsero_trig_reply <= 'd0;
endalways @(posedge i_clk or posedge i_rst) beginif(i_rst)ro_trig_seq <= 'd0;else if(r_recv_icmp_cnt >= 6 && r_recv_icmp_cnt <= 7)ro_trig_seq <= {ro_trig_seq[7:0],ri_icmp_data};elsero_trig_seq <= 'd0;
endendmodule