文章目录
前言:ICMP层报文解析
各字段说明
类型 :占一字节,标识ICMP报文的类型,目前已定义了14种,从类型值来看ICMP报文可以分为两大类。第一类是取值为1~127的差错报文,第2类是取值128以上的信息报文。
代码 :占一字节,标识对应ICMP报文的代码。它与类型字段一起共同标识了ICMP报文的详细类型。
校验和 :这是对包括ICMP报文数据部分在内的整个ICMP数据报的校验和,以检验报文在传输过程中是否出现了差错。其计算方法与在我们介绍IP报头中的校验和计算方法是一样的。
标识 :占两字节,用于标识本ICMP进程,但仅适用于回显请求和应答ICMP报文,对于目标不可达ICMP报文和超时ICMP报文等,该字段的值为0。
对于该层协议,只实现了PING请求与应答,所以内容很简单。
一、ICMP_TX模块
设计代码为本人参考FPGA奇哥系列网课自行编写
c
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) begin
if(i_rst)begin
ri_trig_reply <= 'd0;
ri_trig_seq <= 'd0;
ri_active_req <= 'd0;
ri_active_seq <= 'd0;
end
else begin
ri_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) begin
if(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;
else
r_check_cnt <= r_check_cnt;
end
always @(posedge i_clk or posedge i_rst) begin
if(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;
else
r_checksum <= r_checksum;
end
always @(posedge i_clk or posedge i_rst) begin
if(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;
else
r_icmp_cnt <= r_icmp_cnt;
end
always @(posedge i_clk or posedge i_rst) begin
if(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'h0001
5 : 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
end
always @(posedge i_clk or posedge i_rst) begin
if(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;
else
ro_icmp_valid <= ro_icmp_valid;
end
always @(posedge i_clk or posedge i_rst) begin
if(i_rst)
ro_icmp_last <= 'd0;
else if(r_icmp_cnt == P_ICMP_LEN - 1)
ro_icmp_last <= 'd1;
else
ro_icmp_last <= 'd0;
end
endmodule
一、ICMP_RX模块
c
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) begin
if(i_rst) begin
ri_icmp_data <= 'd0;
ri_icmp_len <= 'd0;
ri_icmp_last <= 'd0;
ri_icmp_valid <= 'd0;
end
else begin
ri_icmp_data <= i_icmp_data ;
ri_icmp_len <= i_icmp_len ;
ri_icmp_last <= i_icmp_last ;
ri_icmp_valid <= i_icmp_valid;
end
end
always @(posedge i_clk or posedge i_rst) begin
if(i_rst)
r_recv_icmp_cnt <= 'd0;
else if(ri_icmp_valid)
r_recv_icmp_cnt <= r_recv_icmp_cnt + 'd1;
else
r_recv_icmp_cnt <= 'd0;
end
always @(posedge i_clk or posedge i_rst) begin
if(i_rst)
r_icmp_type <= 'd0;
else if(ri_icmp_valid && r_recv_icmp_cnt == 0)
r_icmp_type <= ri_icmp_data;
else
r_icmp_type <= r_icmp_type;
end
always @(posedge i_clk or posedge i_rst) begin
if(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;
else
ro_trig_reply <= 'd0;
end
always @(posedge i_clk or posedge i_rst) begin
if(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};
else
ro_trig_seq <= 'd0;
end
endmodule