基于FPGA的UDP协议栈设计第五章_ICMP层设计

文章目录

前言: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
相关推荐
XUEYUAN52125 天前
ASN 自治系统号风控:平台如何通过 IP 所属自治域批量识别代理流量
python·网络协议·http·网络安全·socks5
CHENKONG_CK5 天前
破解制鞋打磨痛点:RFID赋能去毛刺工序自动化升级
网络·单片机·嵌入式硬件·网络协议·tcp/ip
博览鸿蒙5 天前
FPGA开发使用的语言
fpga开发·fpga
z落落5 天前
C#UDP+串口服务端+UDP 客户端(含 CRC16 校验)
网络·网络协议·udp
明德扬5 天前
机器人多摄像头如何做FPGA多路视频聚合?
学习·fpga开发·fpga
曼巴UE55 天前
UE5 客户端 需要的网络同步概念总结(3 )-事件同步 RPC 以及三种调用方式
网络·c++·网络协议·学习·rpc·ue5
开开心心就好5 天前
安卓手写文字生成工具,多种纸张一直免费
网络·网络协议·tcp/ip·leetcode·智能手机·电脑·模拟退火算法
小贺儿开发6 天前
Unity 家居视频遥控(细节优化)
科技·unity·程序员·udp·视频·工具·通信
JoYER_cc6 天前
FPGA 调试实录:LED 闪烁程序从踩坑到仿真验证的完整经验总结
fpga开发
ktd0076 天前
复旦微开发环境搭建流程备忘录
fpga开发