10G_ethernet学习记录(3): IP层编写

0,IP层协议

版本:占 4 位,ipv4(0100),ipv6(0110);

首部长度:占 4 位;表示一共有多少个32bit(4字节),无可选字段时固定为5;

区分服务:占 8 位,用来获得更好的服务,在旧标准中叫做服务类型,但实际上一直未被使用过 1998 年这个字段改名为区分服务.只有在使用区分服务(DiffServ)时,这个字段才起作用.一般的情况下都不使用这个字段;设置为0;

总长度:占 16 位,指首部和数据之和的长度,单位为字节,因此数据报的最大长度为 65535字节总长度必须不超过最大传送单元 MTU(最大传输负载)。数据长度等于总长度-20(IP首部)

标识:占 16 位,它是一个计数器,用来产生数据报的标识;

标志(flag):占 3 位,第一位保留,第二位(1是不分片,0是分片),第三位是否有更多的分片;

片偏移:占 13 位,指较长的分组在分片后某片在原分组中的相对位置.片偏移以 8 个字节为偏移单位;

生存时间:占 8 位,记为 TTL (Time To Live) 数据报在网络中可通过的路由器数的最大值,TTL 字段是由发送端初始设置一个 8 bit 字段.推荐的初始值由分配数字 RFC 指定,当前值为 64.发送 ICMP 回显应答时经常把 TTL 设为最大值 255;

协议:占 8 位,指出此数据报携带的数据使用何种协议以便目的主机的 IP 层将数据部分上交给哪个处理过程, 1 表示为 ICMP 协议, 2 表示为 IGMP 协议, 6 表示为 TCP 协议, 17表示为 UDP 协议

首部检验和:占 16 位,只检验数据报的首部不检验数据部分,采用二进制反码求和,即将16 位数据相加后,再将进位与低 16 位相加,直到进位为 0,最后将 16 位取反;

源地址:自身IP地址;

目的地址:接收方IP地址;

1,编写工程

        ip层主要包含三个模块:ip_rx,ip_tx,ip_module


module _10g_ip_module
#(
    parameter                           P_SOURCE_IP = 32'hc0_01_01_01,
    parameter                           P_TARGET_IP = 32'hc0_01_01_01 
)
(
    input                               i_clk                      ,
    input                               i_rst                      ,

    //drp
    input              [  31:0]         i_dynamic_source_ip        ,
    input                               i_dynamic_source_valid     ,
    input              [  31:0]         i_dynamic_target_ip        ,
    input                               i_dynamic_target_valid     ,

    /**************   axi_mac   *********************/
    output             [  63:0]         m_axis_mac_data            ,
    output             [  79:0]         m_axis_mac_user            ,//len(16)+source_mac(48)+type(16)
    output             [   7:0]         m_axis_mac_keep            ,
    output                              m_axis_mac_last            ,
    output                              m_axis_mac_valid           ,

    input              [  63:0]         s_axis_mac_data            ,
    input              [  79:0]         s_axis_mac_user            ,//len(16)+source_mac(48)+type(16)
    input              [   7:0]         s_axis_mac_keep            ,
    input                               s_axis_mac_last            ,
    input                               s_axis_mac_valid           ,

    /**************   axi_out   *********************/
    //与UDP或者ICMP层的交互
    output             [  63:0]         m_axis_out_data            ,
    output             [  55:0]         m_axis_out_user            ,//16len + 8type + 16ip + 3mflag + 13offset
    output             [   7:0]         m_axis_out_keep            ,
    output                              m_axis_out_last            ,
    output                              m_axis_out_valid           ,

    input              [  63:0]         s_axis_out_data            ,
    input              [  55:0]         s_axis_out_user            ,//16len + 8type + 16ip + 3mflag + 13offset
    input              [   7:0]         s_axis_out_keep            ,
    input                               s_axis_out_last            ,
    input                               s_axis_out_valid            
);

_10g_ip_tx
#(
    .P_SOURCE_IP                       (P_SOURCE_IP               ),
    .P_TARGET_IP                       (P_TARGET_IP               ) 
)
_10g_ip_tx_inst
(
    .i_clk                             (i_clk                     ),
    .i_rst                             (i_rst                     ),

    //drp
    .i_dynamic_source_ip               (i_dynamic_source_ip       ),
    .i_dynamic_source_valid            (i_dynamic_source_valid    ),
    .i_dynamic_target_ip               (i_dynamic_target_ip       ),
    .i_dynamic_target_valid            (i_dynamic_target_valid    ),

    .m_axis_mac_data                   (m_axis_mac_data           ),
    .m_axis_mac_user                   (m_axis_mac_user           ),//len(16)+source_mac(48)+type(16)
    .m_axis_mac_keep                   (m_axis_mac_keep           ),
    .m_axis_mac_last                   (m_axis_mac_last           ),
    .m_axis_mac_valid                  (m_axis_mac_valid          ),
    .m_axis_mac_ready                  (                          ),

    .s_axis_out_data                   (s_axis_out_data           ),
    .s_axis_out_user                   (s_axis_out_user           ),//16len + 8type + 16ip + 3mflag + 13offset
    .s_axis_out_keep                   (s_axis_out_keep           ),
    .s_axis_out_last                   (s_axis_out_last           ),
    .s_axis_out_valid                  (s_axis_out_valid          ) 
);

_10g_ip_rx
#(
    .P_SOURCE_IP                       (P_SOURCE_IP               ),
    .P_TARGET_IP                       (P_TARGET_IP               ) 
)
_10g_ip_rx_inst
(
    .i_clk                             (i_clk                     ),
    .i_rst                             (i_rst                     ),

    //drp
    .i_dynamic_source_ip               (i_dynamic_source_ip       ),
    .i_dynamic_source_valid            (i_dynamic_source_valid    ),
    .i_dynamic_target_ip               (i_dynamic_target_ip       ),
    .i_dynamic_target_valid            (i_dynamic_target_valid    ),

    .s_axis_mac_data                   (s_axis_mac_data           ),
    .s_axis_mac_user                   (s_axis_mac_user           ),//len(16)+source_mac(48)+type(16)
    .s_axis_mac_keep                   (s_axis_mac_keep           ),
    .s_axis_mac_last                   (s_axis_mac_last           ),
    .s_axis_mac_valid                  (s_axis_mac_valid          ),

    .m_axis_out_data                   (m_axis_out_data           ),
    .m_axis_out_user                   (m_axis_out_user           ),//16len + 8type + 16ip + 3mflag + 13offset
    .m_axis_out_keep                   (m_axis_out_keep           ),
    .m_axis_out_last                   (m_axis_out_last           ),
    .m_axis_out_valid                  (m_axis_out_valid          ) 
);

 1.1,ip_rx

        该模块主要负责接受MAC层输出的类型为0800的ip类型数据,进行数据报文的解析,主要功能如下:

module _10g_ip_rx
#(
    parameter                           P_SOURCE_IP = 32'hc0_01_01_01,
    parameter                           P_TARGET_IP = 32'hc0_01_01_01 
)
(
    input                               i_clk                      ,
    input                               i_rst                      ,

    //drp
    input              [  31:0]         i_dynamic_source_ip        ,
    input                               i_dynamic_source_valid     ,
    input              [  31:0]         i_dynamic_target_ip        ,
    input                               i_dynamic_target_valid     ,

    input              [  63:0]         s_axis_mac_data            ,
    input              [  79:0]         s_axis_mac_user            ,//len(16)+source_mac(48)+type(16)
    input              [   7:0]         s_axis_mac_keep            ,
    input                               s_axis_mac_last            ,
    input                               s_axis_mac_valid           ,

    output             [  63:0]         m_axis_out_data            ,
    output             [  55:0]         m_axis_out_user            ,//16len + 8type + 16ip + 3mflag + 13offset
    output             [   7:0]         m_axis_out_keep            ,
    output                              m_axis_out_last            ,
    output                              m_axis_out_valid            
);

        1,解析出报文的长度(1byte形式),这里长度需要进行统一,有的是按照64bit(8byte形式),长度存放在user中,后续统一。

        2,解析出协议protocal,为后续的ICMP,UDP仲裁使用。1 表示为 ICMP 协议, 2 表示为 IGMP 协议, 6 表示为 TCP 协议, 17表示为 UDP 协议

        3,解析出MFB,offset,为后续巨帧的开发做准备。

        4,因为在MAC做了CRC校验,这里就不再对ip的首部检验和做检查,而是仅仅检查IP头部中的目的IP与IP层中的source_ip是否一致,用于控制输出的valid信号。

        5,解析数据,传递给下一层,任然是老套的keep处理,尤其是尾端keep,但是因为经过MAC处理之后已经是字节对齐过了的,处理起来很方便。

    else if( !r_s_axis_mac_valid && r_s_axis_mac_valid_1d && !(r_last_keep == 8'b1000_0000 || r_last_keep == 8'b1100_0000 || r_last_keep == 8'b1110_0000 || r_last_keep == 8'b1111_0000 )   ) begin
        case (r_last_keep)
            8'b1000_0000 : r_m_axis_out_keep <= 8'b1111_1000;//提前一个周期             
            8'b1100_0000 : r_m_axis_out_keep <= 8'b1111_1100;//提前一个周期             
            8'b1110_0000 : r_m_axis_out_keep <= 8'b1111_1110;//提前一个周期             
            8'b1111_0000 : r_m_axis_out_keep <= 8'b1111_1111;//提前一个周期             
            8'b1111_1000 : r_m_axis_out_keep <= 8'b1000_0000;              
            8'b1111_1100 : r_m_axis_out_keep <= 8'b1100_0000;              
            8'b1111_1110 : r_m_axis_out_keep <= 8'b1110_0000;
            8'b1111_1111 : r_m_axis_out_keep <= 8'b1111_1111;
            default      : r_m_axis_out_keep <= 8'b1111_1111;
        endcase
    end    
    else if( !s_axis_mac_valid && r_s_axis_mac_valid && (r_last_keep == 8'b1000_0000 || r_last_keep == 8'b1100_0000 || r_last_keep == 8'b1110_0000 || r_last_keep == 8'b1111_0000 )   ) begin
        case (r_last_keep)
            8'b1000_0000 : r_m_axis_out_keep <= 8'b1111_1000;//提前一个周期             
            8'b1100_0000 : r_m_axis_out_keep <= 8'b1111_1100;//提前一个周期             
            8'b1110_0000 : r_m_axis_out_keep <= 8'b1111_1110;//提前一个周期             
            8'b1111_0000 : r_m_axis_out_keep <= 8'b1111_1111;//提前一个周期             
            8'b1111_1000 : r_m_axis_out_keep <= 8'b1000_0000;              
            8'b1111_1100 : r_m_axis_out_keep <= 8'b1100_0000;              
            8'b1111_1110 : r_m_axis_out_keep <= 8'b1110_0000;
            8'b1111_1111 : r_m_axis_out_keep <= 8'b1111_1111;
            default      : r_m_axis_out_keep <= 8'b1111_1111;
        endcase
    end

 仿真波形:

 可以看到ip报文头部的20个byte已经全部移除,数据提取完毕且完成字节对齐。

1.2,ip_tx

        将IMCP,UDP层发送的数据添加IP首部发送给MAC。


module _10g_ip_tx
#(
    parameter                           P_SOURCE_IP = 32'hc0_01_01_01,
    parameter                           P_TARGET_IP = 32'hc0_01_01_01 
)
(
    input                               i_clk                      ,
    input                               i_rst                      ,

    //drp
    input              [  31:0]         i_dynamic_source_ip        ,
    input                               i_dynamic_source_valid     ,
    input              [  31:0]         i_dynamic_target_ip        ,
    input                               i_dynamic_target_valid     ,

    output             [  63:0]         m_axis_mac_data            ,
    output             [  79:0]         m_axis_mac_user            ,//len(16)+source_mac(48)+type(16)
    output             [   7:0]         m_axis_mac_keep            ,
    output                              m_axis_mac_last            ,
    output                              m_axis_mac_valid           ,
    output                              m_axis_mac_ready           ,

    input              [  63:0]         s_axis_out_data            ,
    input              [  55:0]         s_axis_out_user            ,//16len + 8type + 16ip + 3mflag + 13offset
    input              [   7:0]         s_axis_out_keep            ,
    input                               s_axis_out_last            ,
    input                               s_axis_out_valid            
);

 主要功能:

  1,根据输入的user中的数据进行IP首部的组帧

input   [  55:0]  s_axis_out_user    ,//16len + 8type + 16ip + 3mflag + 13offset

  2,首部校验和的计算,接受我们可以不校验,但是发送需要自己组成,

             IP首部校验和计算方法:https://blog.youkuaiyun.com/weixin_44870077/article/details/118106364

        总结一下就是:

  1. 将头部20个字节的IP首部分为10个16bit大小的数据,且首部检验和为0,进行相加。存放进一个[31:0]result(大位宽防止加法溢出);
  2. 使用result[31:16]+result[15:0],进行相加(如果担心任然有溢出,再次操作);
  3. 对最后的到的result[15:0]进行取反,即为首部校验和;
//首部校验和
always @(posedge i_clk) begin
    if (i_rst) begin
        r_header_sum_check <= 'd0;
    end
    else if(r_in_cnt == 1) begin
        r_header_sum_check <= 16'h4500
                               +  (r_s_axis_out_user[55:40] + 16'd20)       //len
                               +  r_s_axis_out_user[31:16]                  //id
                               +  r_s_axis_out_user[15:0]                   //mflag + offset
                               +  {P_LIVE_TIME , r_s_axis_out_user[36:29]}  //live + protocol
                               +  16'd0                                      //header_sum
                               +  r_i_dynamic_source_ip[31:16] + r_i_dynamic_source_ip[15:0]
                               +  r_i_dynamic_target_ip[31:16] + r_i_dynamic_target_ip[15:0];
    end
    else if(r_in_cnt == 2) begin
        r_header_sum_check <= r_header_sum_check[31:16] + r_header_sum_check[15:0];
    end
    else if(r_in_cnt == 3) begin
        r_header_sum_check <= r_header_sum_check[31:16] + r_header_sum_check[15:0];
    end
    else begin
        r_header_sum_check <= r_header_sum_check;
    end
end

3,进行数据输出的控制

        主要还是keep,valid,last信号,发送给mac层 。

4,仿真波形:

2,上板 

等待总体工程完毕。。。

### AXI 10G以太网IP核或模块信息 AXI 10G以太网IP核是一种高度集成的硬件模块,专为高速网络通信设计。该IP核支持10千兆位每秒的数据传输速率,并通过AXI接口与处理器或其他外设连接。 #### 主要特性 - **协议兼容性**:完全符合IEEE 802.3ae标准,适用于各种高性能计算环境下的数据交换需求。 - **物理实现**:通常采用SerDes技术来完成电气信号到光信号之间的转换工作,确保长距离稳定传输性能[^1]。 #### 功能描述 为了满足不同应用场景的需求,AXI 10G以太网IP内集成了多种功能单元: - **MAC子处理**:负责执行介质访问控制算法,包括帧封装解封、地址过滤等功能; - **DMA引擎**:用于高效管理内存读写操作,减少CPU负担的同时提高吞吐量; - **统计计数器**:提供详细的流量监控手段,便于维护人员了解当前链路状态; 对于时钟分配方面,在某些复杂的设计中确实可能出现跨多个时钟域的情况。例如当外部接口接收到来自远端设备同步过来的参考时钟后,可能需要经过本地PLL/MMCM重新生成适合内部逻辑使用的频率点。这种情况下就需要特别注意时序收敛问题以及潜在的竞争冒险现象[^2]。 ```python # Python伪代码展示如何配置AXI 10G Ethernet IP Core参数 def configure_axi_10g_ethernet(): config = { &#39;mac_address&#39;: &#39;00:A0:C9:14:C8:29&#39;, &#39;ip_address&#39;: &#39;192.168.1.1&#39;, &#39;gateway&#39;: &#39;192.168.1.254&#39; } # 设置MAC地址和其他必要属性... set_mac(config[&#39;mac_address&#39;]) setup_networking(config) configure_axi_10g_ethernet() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值