万兆网、10G ethernet subsystem IP核

随着FPGA在数据中心加速和Smart NIC在SDN和NFV领域的广泛应用,基于以太网接口的FPGA开发板越来越受到关注。而更高速率的以太网接口技术则是应用的关键,本文将详细介绍基于FPGA的10G以太网接口的原理及调试技术。

10G以太网接口简介

1、10G以太网结构

10G以太网接口分为10G PHY和10G MAC两部分。如下图所示。

详解FPGA的10G以太网接口调试

本设计中使用了Xilinx公司提供的10GEthernet PCS/PMA IP核充当连接10GMAC的PHY芯片,然后将该IP核约束到光模块上构建完整的物理层。需要说明的是本设计主要是完成以太网二层逻辑设计,不涉及PHY层的逻辑设计,如:bit同步、字节同步、字同步、64b/66b编解码等。

 

10G EthernetPCS/PMA的整体结构如图5.2所示,其核心是基于RocketIO GTH/GTX来实现的。从图中可知,该模块分为PCS层和PMA层,对于每一个串行高速收发器,其分为两个子层:PCS(物理编码子层)和 PMA(物理媒体连接子层)。PCS 层主要进行数据编解码以及多通道的处理;PMA 层主要进行串并、并串转换,预加重、去加重,串行数据的发送、数据时钟的提取。可以使用ibert IP核对接口进行回环测试,确定该接口是否可以正常使用。

对于发送数据,PCS层主要功能是对数据进行64B/66B编码、扰码、发送变速等功能。同时在测试模式下还提供了一个测试激励源,用于对链路进行检测。PMA层的主要功能是提供并串转换、对串行信号进行驱动并发送等功能。对于接收数据,PMA层的主要功能是将接收到的高速差分信号进行串并转换、bit同步、时钟恢复等功能,PCS层对于从PMA层接收到的数据进行块同步、解扰码、64B/66B解码、弹性缓存等。同时在测试模式下还提供测试激励检测功能,用于检测链路工作状态。

详解FPGA的10G以太网接口调试

在接口调试过程中,可能用到PMA层的近端环回和远端环回功能。PMA近端回环,用于测试IP核内部自回环;PMA远端回环,用于将接收到的远端10G PHY发送的的数据在PMA层直接回环发送给远端10G PHY,而不经过本地的PCS层。

example的tb中提供了DEMO和BIST模式,

DEMO

是近端环回,

  • 可以用于演示示例程序,
  • 提供四种数据测试,分别以下四种
  • 接受的数据通过axi-stream总线环回。数据自生成模式无效。

BIST模式

远端回环。

  • 将数据生成器打开,
  • 串行接受回路和发送回路连接,形成数据回环。
  • 数据可以从fifo中读出并做校验

三、时钟

 对于QPLL输出的两路时钟qplloutclk和qplloutrefclk,主要是用于IP核内GTH收发器使用的高性能时钟,其中qplloutclk直接用于驱动GTH内发送端的串行信号,其频率为5.15625GHz。qplloutrefclk用于驱动GTH内部部分逻辑模块,频率为156.25MHz。

(a) txoutclk是由10G Ethernet PCS/PMA IP产生的一个322.26MHz的时钟,该时钟经过BUFG后分为两路,其中txusrclk用于驱动IP核内GTH的32bits总线数据,txusrclk2用于驱动IP核内PCS层部分模块。

(b)200MHz的晶振产生差分时钟输入到FPGA内的PLL(Phase LockingLoop)模块,PLL模块以200MHz差分钟为驱动时钟生成192MHz用户钟(sys_clk)发送给10G MAC核用户侧。

 

 

  • 6
    点赞
  • 76
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是一个简单的基于UDP协议的10G以太网数据包发送代码示例,使用的是C语言和Linux平台: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/udp.h> #include <netinet/ip.h> #include <arpa/inet.h> #include <unistd.h> #define SRC_IP "192.168.1.100" #define DEST_IP "192.168.1.1" #define SRC_PORT 8888 #define DEST_PORT 9999 #define PACKET_SIZE 9000 int main(int argc, char *argv[]) { int sock; struct sockaddr_in src_addr, dest_addr; char buffer[PACKET_SIZE]; struct iphdr *ip_header = (struct iphdr *) buffer; struct udphdr *udp_header = (struct udphdr *) (buffer + sizeof(struct iphdr)); // 创建UDP套接字 if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { perror("socket creation failed"); exit(EXIT_FAILURE); } // 设置源地址和目的地址 memset(&src_addr, 0, sizeof(src_addr)); src_addr.sin_family = AF_INET; src_addr.sin_addr.s_addr = inet_addr(SRC_IP); src_addr.sin_port = htons(SRC_PORT); memset(&dest_addr, 0, sizeof(dest_addr)); dest_addr.sin_family = AF_INET; dest_addr.sin_addr.s_addr = inet_addr(DEST_IP); dest_addr.sin_port = htons(DEST_PORT); // 构造IP头部 ip_header->ihl = 5; ip_header->version = 4; ip_header->tos = 0; ip_header->tot_len = sizeof(struct iphdr) + sizeof(struct udphdr); ip_header->id = htons(54321); ip_header->frag_off = htons(16384); ip_header->ttl = 64; ip_header->protocol = IPPROTO_UDP; ip_header->check = 0; ip_header->saddr = inet_addr(SRC_IP); ip_header->daddr = inet_addr(DEST_IP); // 构造UDP头部 udp_header->source = htons(SRC_PORT); udp_header->dest = htons(DEST_PORT); udp_header->len = htons(sizeof(struct udphdr)); udp_header->check = 0; // 发送数据包 if (sendto(sock, buffer, PACKET_SIZE, 0, (struct sockaddr *) &dest_addr, sizeof(dest_addr)) < 0) { perror("sendto failed"); exit(EXIT_FAILURE); } // 关闭套接字 close(sock); return 0; } ``` 需要注意的是,这个示例只是一个基本的UDP数据包发送代码,实际环境中还需要考虑诸如错误处理、数据包大小控制、数据包分片等问题。另外,还需要根据具体的硬件和网络环境进行配置和调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

朝阳群众&热心市民

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值