基于FPGA的百兆以太网ARP测试实验

Deceiver_Ker·2022-12-10 21:51·2131 次阅读

基于FPGA的百兆以太网ARP测试实验

由于各种原因,如旧式电脑的网卡不支持千兆网等,导致PHY在自协商时速率达不到1000Mbps。而目前主流的FPGA的以太网实验均基于千兆网络编写测试代码,因此根据千兆网络降速编写百兆网的测试实验样例是有必要的,后续可再进一步编写自适应网速切换百兆或千兆的测试例程。

本文将基于正点原子开拓者V2开发板进行适配百兆网络的FPGA中的ARP测试代码编写,主要由正点原子千兆网实验教程改编,千兆网与百兆网的区别并不是很大,因此,主要将记录不同的代码,百兆网下其余与千兆网相同的代码将不再赘述。

实验环境:

Quartus II 13.1 Altera FPGA EP4CE10F17C8N

若是Xilinx环境,则将相关的IP核在基于Xilinx进行更改重新生成,其余RTL级代码基本相同。

代码更改:

正点原子开拓者V2开发板的以太网接口为RGMII接口,数据位宽为4位,在千兆网络下,在时钟上下沿采样,在百兆与十兆网络下,为单个时钟沿采样。

相比GMII接口与MII接口,RGMII至少可以节省8根数据线,因此,现多数PHY侧芯片连接FPGA时多采用RGMII接口。

在RGMII下,百兆网通信时,主要有几根数据线需要注意。

ETH_RXC:接收数据参考时钟,100Mbps 速率下,时钟频率为 25MHz ETH_RXC 由 PHY 侧提供。

ETH_RXCTL(ETH_RX_DV):接收数据控制信号。

ETH_TXC:发送参考时钟,100Mbps 速率下,时钟频率为 25MHz, ETH_TXC 由 MAC 侧提供。

ETH_TXCTL(ETH_TXEN):发送数据控制信号。

rgmii接收模块

由于ARP模块中的arp_rx.v,即 arp接收模块下的输入数据gmii_rxd为为8位,因此arp接收模块的输入时钟应该为12.5Mhz,而为了保持arp接收模块与前一级的rgmii接收模块时钟一致,保证时钟尽量同步。rgmii接收模块的输入时钟也为12.5Mhz。rgmii接收模块百兆时序如下:

rgmii接收模块的输入如果为12.5Mhz,且根据百兆网协议单边沿采样传输数据,则网络速率将只为12.5MhzX4bit=50Mbps,因此为了保证100Mbps的速率,rgmii接收模块将以12.5Mhz的时钟,以双边沿采样的方式,采样RGMII接收数据,将速率提升至100Mbps,具体代码如下:

Copy
/************************************************************************ * 项目名称 : $FPGA实验箱$ * 类 名 称 : $ARP测试实验$ * 版 本 号 : 1.0 * 作 者 : kxq * 邮 箱 : 2543697634@qq.com * 网 站 : https://www.cnblogs.com/kxqblog/ * 创建时间 : $2022/8/9$ * 项目描述 : RGMII接收模块 ************************************************************************/ module rgmii_rx( //以太网RGMII接口 input rgmii_rxc , //RGMII接收时钟 input sys_rst_n, input rgmii_rx_ctl, //RGMII接收数据控制信号 input [3:0] rgmii_rxd , //RGMII接收数据 //以太网GMII接口 output gmii_rx_clk , //GMII接收时钟 output gmii_rx_dv , //GMII接收数据有效信号 output [7:0] gmii_rxd //GMII接收数据 ); reg cnt; wire [1:0] gmii_rxdv_t; //两位GMII接收有效信号 //***************************************************** //** main code //***************************************************** assign gmii_rx_clk = rgmii_rxc; assign gmii_rx_dv = gmii_rxdv_t[0] & gmii_rxdv_t[1]; ddi_x4 ddi_x4_inst( .datain (rgmii_rxd ), .inclock (rgmii_rxc ), .dataout_h (gmii_rxd[7:4]), .dataout_l (gmii_rxd[3:0]) ); ddi_x1 ddi_x1_inst( .datain (rgmii_rx_ctl), .inclock (rgmii_rxc ), .dataout_h (gmii_rxdv_t[1]), .dataout_l (gmii_rxdv_t[0]) ); endmodule

这里的ddiIP核是Altera下的ALTDDIO_IN IP,实现双沿数据和单沿数据之间的转换,相关介绍可以参考网络上的一些教程与一些参考书籍。

这里的ddi_x4是在12.5Mhz下将输入的4bit rgmii_rxd转换为8bit gmii_rxd输入给arp接收模块。ddi_x1是将接收数据中的使能信号使能信号异或错误信号的结果输入给arp接收模块。

从之前的rgmii接收模块百兆时序图来看,时钟边沿与数据传输边沿对齐,这样将在采样时发生错误,因此,有必要对于输入时钟进行偏移,对于千兆网来说,可以通过硬件引脚上拉电阻的方式,硬件延时2ns来偏移1/4个周期。而对百兆网,千兆网硬件延时的时间较短,不适用于百兆网的rgmii接收模块,这里,在生成输入时钟的PLL的IP核中对于12.5Mhz进行偏移45度,如下图所示。

rgmii发送模块

相比较正点原子中的千兆速率下的rgmii发送模块,改动幅度较大。在百兆rgmii发送模块中,数据发送时钟ETH_TXC为25Mhz,且为上边沿采样方式。因此rgmii发送模块百兆时序如下:

从图中可以看出,数据发送时钟为25Mhz时,时钟采样发送数据将为25MhzX4bit=100Mbps,恰好为百兆的发送速率,具体代码如下,需要有一定的Verilog代码基础。

Copy
/************************************************************************ * 项目名称 : $FPGA实验箱$ * 类 名 称 : $ARP测试实验$ * 版 本 号 : 1.0 * 作 者 : kxq * 邮 箱 : 2543697634@qq.com * 网 站 : https://www.cnblogs.com/kxqblog/ * 创建时间 : $2022/8/9$ * 项目描述 : RGMII发送模块 ************************************************************************/ module rgmii_tx( //GMII发送端口 input gmii_tx_clk , //GMII发送时钟 input sys_rst_n, input gmii_tx_en , //GMII输出数据有效信号 input [7:0] gmii_txd , //GMII输出数据 //RGMII发送端口 output rgmii_txc , //RGMII发送数据时钟 output reg rgmii_tx_ctl, //RGMII输出数据有效信号 output reg [3:0] rgmii_txd //RGMII输出数据 ); reg cnt; //***************************************************** //** main code //***************************************************** always@(posedge gmii_tx_clk or negedge sys_rst_n)begin if(!sys_rst_n) cnt <= 1'b0; else cnt <= cnt + 1'b1; end always@(posedge gmii_tx_clk or negedge sys_rst_n)begin if(!sys_rst_n) rgmii_txd <= 4'd0; else if(cnt == 1'b1) rgmii_txd <= gmii_txd[3:0]; else rgmii_txd <= gmii_txd[7:4]; end always@(posedge gmii_tx_clk or negedge sys_rst_n)begin if(!sys_rst_n) rgmii_tx_ctl <= 1'b0; else if(cnt == 1'b1) rgmii_tx_ctl <= gmii_tx_en; else rgmii_tx_ctl <= gmii_tx_en; end assign rgmii_txc = gmii_tx_clk; endmodule

这里,GMII发送时钟与RGMII发送数据时钟速率设置保持一致。同样地,rgmii发送模块百兆时序中可以看出,时钟边沿与数据传输边沿对齐,这样将在采样时发生错误。因此需要在生成输入时钟的PLL的IP核中对于25Mhz进行偏移90度,如下图所示。

arp测试顶层模块

相比较于正点原子手册中的arp测试顶层模块,在本改进的百兆网模块下,主要是对rgmiigmii模块与时钟锁相环进行了更改,具体可以参考以下代码。

Copy
/************************************************************************ * 项目名称 : $FPGA实验箱$ * 类 名 称 : $ARP测试实验$ * 版 本 号 : 1.0 * 作 者 : kxq * 邮 箱 : 2543697634@qq.com * 网 站 : https://www.cnblogs.com/kxqblog/ * 创建时间 : $2022/8/9$ * 项目描述 : 顶层模块,实现ARP协议 ************************************************************************/ module eth_arp_top( input sys_rst_n , //系统复位信号,低电平有效 input touch_key , //KEY0按键开关 //以太网RGMII接口 input eth_rxc , //RGMII接收数据时钟 input eth_rx_ctl, //RGMII输入数据有效信号 input [3:0] eth_rxd , //RGMII输入数据 output eth_txc , //RGMII发送数据时钟 output eth_tx_ctl, //RGMII输出数据有效信号 output [3:0] eth_txd , //RGMII输出数据 output eth_rst_n , //以太网芯片复位信号,低电平有效 output sample_clk ); //parameter define //开发板MAC地址 00-11-22-33-44-55 parameter BOARD_MAC = 48'h00_11_22_33_44_55; //开发板IP地址 192.168.137.10 parameter BOARD_IP = {8'd192,8'd168,8'd137,8'd10}; //目的MAC地址 ff_ff_ff_ff_ff_ff parameter DES_MAC = 48'hff_ff_ff_ff_ff_ff; //目的IP地址 192.168.137.11 parameter DES_IP = {8'd192,8'd168,8'd137,8'd11}; //wire define wire eth_rxc_deg ; //eth_rxc时钟相位偏移 wire gmii_rx_clk ; //GMII接收时钟 wire gmii_rx_dv ; //GMII接收数据有效信号 wire [7:0] gmii_rxd ; //GMII接收数据 wire gmii_tx_clk ; //GMII发送时钟 wire gmii_tx_en ; //GMII发送数据使能信号 wire [7:0] gmii_txd ; //GMII发送数据 wire arp_gmii_tx_en; //ARP GMII输出数据有效信号 wire [7:0] arp_gmii_txd ; //ARP GMII输出数据 wire arp_rx_done ; //ARP接收完成信号 wire arp_rx_type ; //ARP接收类型 0:请求 1:应答 wire [47:0] src_mac ; //接收到目的MAC地址 wire [31:0] src_ip ; //接收到目的IP地址 wire arp_tx_en ; //ARP发送使能信号 wire arp_tx_type ; //ARP发送类型 0:请求 1:应答 wire [47:0] des_mac ; //发送的目标MAC地址 wire [31:0] des_ip ; //发送的目标IP地址 wire arp_tx_done ; //ARP发送完成信号 wire clk_25Mhz; //***************************************************** //** main code //***************************************************** assign des_mac = src_mac; assign des_ip = src_ip; assign eth_rst_n = sys_rst_n; //PLL pll my_pll( .inclk0 (eth_rxc), .c0 (eth_rxc_deg), .c1 (sample_clk), .c2 (clk_25Mhz), .locked () ); //GMII接口转RGMII接口 gmii_to_rgmii my_gmii_to_rgmii( .gmii_rx_clk (gmii_rx_clk ), .gmii_rx_dv (gmii_rx_dv ), .gmii_rxd (gmii_rxd ), .gmii_tx_clk (clk_25Mhz ), //gmii_tx_clk .gmii_tx_en (gmii_tx_en ), .gmii_txd (gmii_txd ), .rgmii_rxc (eth_rxc_deg ), .rgmii_rx_ctl (eth_rx_ctl ), .rgmii_rxd (eth_rxd ), .rgmii_txc (eth_txc ), .rgmii_tx_ctl (eth_tx_ctl ), .rgmii_txd (eth_txd ), .sys_rst_n (sys_rst_n) ); //ARP通信 arp #( .BOARD_MAC (BOARD_MAC), //参数例化 .BOARD_IP (BOARD_IP ), .DES_MAC (DES_MAC ), .DES_IP (DES_IP ) ) my_arp( .rst_n (sys_rst_n ), .gmii_rx_clk (gmii_rx_clk), .gmii_rx_dv (gmii_rx_dv ), .gmii_rxd (gmii_rxd ), .gmii_tx_clk (eth_rxc_deg), .gmii_tx_en (gmii_tx_en ), .gmii_txd (gmii_txd ), .arp_rx_done (arp_rx_done), .arp_rx_type (arp_rx_type), .src_mac (src_mac ), .src_ip (src_ip ), .arp_tx_en (arp_tx_en ), .arp_tx_type (arp_tx_type), .des_mac (des_mac ), .des_ip (des_ip ), .tx_done (tx_done ) ); //ARP控制 arp_ctrl my_arp_ctrl( .clk (gmii_rx_clk), .rst_n (sys_rst_n), .touch_key (~touch_key), .arp_rx_done (arp_rx_done), .arp_rx_type (arp_rx_type), .arp_tx_en (arp_tx_en), .arp_tx_type (arp_tx_type) ); endmodule

其中,PLL中的C1时钟100Mhz,是SignalTapII测试抓波时的采样时钟,可以不用。C0时钟eth_rxc_deg为之前所说的偏移后的12.5Mhz时钟。GMII接口转RGMII接口中对gmii_tx_clk进行了更改,同时再添加一路复位信号。ARP通信中对gmii_tx_clk进行了更改,上层的arp模块下的子发送模块的参考时钟同样要与GMII接口转RGMII接口中的发送时钟同步。

测试结果

最终经过测试,修改后的代码无论是在板子发送ARP消息给电脑,或是电脑给FPGA发送ping消息下,电脑均能正确解析,并动态加载板子的Mac地址。

板子发送消息给电脑并正确识别:

电脑ping板子,其中ARP消息被正确解析。

代码链接 :

https://pan.baidu.com/s/1kQ24aYFQdKwEA1BUmWDgzA?pwd=vgue

参考博客:

https://blog.csdn.net/weixin_55796564/article/details/122459134

https://www.likecs.com/show-204584212.html

https://www.jianshu.com/p/46b762fee7ad

http://t.zoukankan.com/571328401--p-12686528.html

https://blog.csdn.net/weixin_42464967/article/details/112781420

https://www.cnblogs.com/amxiang/p/16288835.html

以及小梅哥,野火等一些论坛中查找的资料,这里就不一一详细列举。

posted @   Deceiver_Ker  阅读(2131)  评论(7编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!
点击右上角即可分享
微信分享提示