基于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
相关推荐
ALINX技术博客2 小时前
【期刊共读】如何应对 FPGA 短缺常态?
嵌入式硬件·fpga开发·fpga
CDN3603 小时前
APP和小程序在地铁里总断连?360CDN上HTTP/3(QUIC),把弱网失败率死死压在0.7%
网络·网络协议·http
吠品4 小时前
SQL Server 版本查询的几种实用方法
数据库·网络协议·ssl
156082072195 小时前
短波接收机灵敏度测试
fpga开发
Shadow(⊙o⊙)5 小时前
CMake实战Http+编译、链接选项的使用
网络·网络协议·http
Fxkj8885 小时前
传统企业布局新媒体:自行摸索与IP陪跑模式深度对比
人工智能·网络协议·tcp/ip·媒体
可乐鸡翅yeah_6 小时前
HTTPS 站点下 M3U8 混合内容问题深度排查,HLS 协议安全策略踩坑实录
数据库·网络协议·https·m3u8·m3u8在线
Riwuarua16 小时前
从近似0基础开始FPGA开发 -- part.6 逻辑设计与状态机
fpga开发
rockingdingo16 小时前
Codex Claude 智能体做3D/潮玩/IP设计——装上Craftsman Agent工匠智能体Skills 游泳男孩IP案例分享
网络协议·tcp/ip·3d
泡海椒17 小时前
告别手写 HTTP 模板!JQuick-Curl:直接把 curl 命令跑在 Java 中
java·网络协议·http