基于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
相关推荐
二狗mao6 小时前
Uniapp使用websocket进行ai回答的流式输出
websocket·网络协议·uni-app
1560820721912 小时前
基于7VX690T FPGA实现万兆TCP/IP资源和性能测试
网络协议·tcp/ip·fpga开发
踏浪无痕14 小时前
线上偶发 502 排查:用 Netty 成功复现 KeepAlive 时间窗口案例实战(附完整源码)
运维·网络协议
爱学习的小可爱卢14 小时前
Java UDP编程实战:UDP数据报套接字编程DatagramPacket、DatagramSocket 、InetSocketAddress
java·udp·udp数据报
北京耐用通信14 小时前
告别“牵一发而动全身”:耐达讯自动化Profibus PA分线器为石化流量计网络构筑安全屏障
人工智能·网络协议·安全·自动化·信息与通信
Sinowintop15 小时前
易连EDI-EasyLink无缝集成之消息队列Kafka
分布式·网络协议·kafka·集成·国产化·as2·国产edi
nuoxin11420 小时前
GSV1011-富利威-HDMI芯片选型
arm开发·驱动开发·fpga开发·ffmpeg·射频工程
ChipCamp20 小时前
FPGA开发入门----1. Mux的三种写法,RTL的认知大提升!
fpga开发·时序逻辑·组合逻辑
阿巴~阿巴~1 天前
自定义协议设计与实践:从协议必要性到JSON流式处理
服务器·网络·网络协议·json·操作系统·自定义协议
jinxinyuuuus1 天前
GTA 风格 AI 生成器:跨IP融合中的“视觉语义冲突”与风格适配损失
人工智能·网络协议