本文将演示 EBAZ4205的百兆网络功能
写在前面:
ZYNQ 网络功能可以有4种方式实现
- 一 PS端 MIO功能直接扩展以太网口
- 二 PS端通过EMIO的方式将以太网口映射到PL端口上
- 三 PL端口的硬件以太网功能 通过AXI的方式供PS端调用
- 四 PL端用逻辑跑以太网功能(不需要PS端参与)
我们这里 因为网口接到了 PS端上,所以理论上 可以实现二 三 四, 第二种和第三种方式 其实效果差不多,只是方式三更占用逻辑资源,而方式四是 FPGA直接控制网络,所以为了方便测试我们先用方式三EMIO的方式来进行测试
本文在 vivado2018.3版本上 演示, 其他版本请自行研究
工程创建
1)新建一个项目,芯片型号选择 XC7Z010CLG400-1(略掉部分过程,详细图文过程可以参考前面的几个帖子)
2) 创建一个BLOCK设计,并添加ZYNQ7 PROCESSING SYSTEM模块,软件自动生成了一个 zynq的block 如下图所示,接下来要做一些相应的设置,双击下图中的ZYNQ核
3)依次在弹窗里找到DDR Configuration→DDR Controller Configuration→DDR3,在Memory Part下拉菜单中根据自己板子上的DDR来选择相应的DDR3,本实验所用到型号:MT41K128M16JT 125,数据位宽选择16bit 最后点击“OK”,如下图所示。
因为工程暂时用不到 AXI功能,所以可以先禁用AXI功能
4) 这里把ENET0通过EMIO引出来 ,并且选中MDIO功能
5) 因为我们需要通过uart 来观察显示的现象,所以这里我们在mio的地方开启UART的功能(假设大家手上都是用本站的转接板进行调试,则这里UART的位置选择EMIO方式,如果没有转接板,则选择MIO方式(UART1对应管脚设置成 MIO24 MIO 25))
6) 因为网络部分EBAZ4205主板分两种类型 (分别对应不同的批次)
- 一种是网络部分自带了25M 无源晶振来为网络芯片提供时钟(对应下图的1)
- 一种是没有无源晶振,但是网络芯片时钟通过一个0欧电阻和ZYNQ的U18脚相连的(对应下图的2)
对应第一种情况,我们在ZYNQ芯片的输出端不需要提供额外的时钟,但是对应第二种情况,我们需要额外为网络芯片输出一个25M的时钟。 我们可以在PS端的PLL处添加这个时钟输出
将 FCLK_CLK0 由默认的50M 改成25M
7)按住CTRL键然后用鼠标分别点选 GMII_ETHERNET_0 , MDIO_ETHERNET_0 , UART_1, FCLK_CLK0 ,右键点Make External
之后点选OK 来保存ZYNQ的配置,之后 Block Design 如下图所示
因为ZYNQ的PS 是同时支持MII 和RMII的 而MII是8bit 传输 RMII是4Bit传输的, 网上大家的资料都是通过添加Concat来实现位宽的转换,我觉得没必要, 这里就不添加了, 后面将增加一个顶层模块来直接映射低4位的管脚
另外这里也不建议点选Run Block Automation 来自动布线 ,这反而会引起混乱
8)创建硬件描述,source→Design Source ,右键我们创建的BLOCK工程,点击create HDL wrapper如下图所示(这一步的作用相当于将图纸转换成对应的硬件描述语言的功能)
9) 这里添加一个顶层模块,并取名TOP_MODULE
在TOP_MODULE中添加如下代码 (这里默认当作UART 使用EMIO 方式连接到转接板的串口上)
`timescale 1ns / 1ps module TOP_MODULE( output FCLK_CLK, input GMII_ETHERNET_rx_clk, input GMII_ETHERNET_rx_dv, input [3:0]GMII_ETHERNET_rxd, input GMII_ETHERNET_tx_clk, output [0:0]GMII_ETHERNET_tx_en, output [3:0]GMII_ETHERNET_txd, output MDIO_ETHERNET_mdc, inout MDIO_ETHERNET_mdio_io, input UART_rxd, output UART_txd ); wire [7:0]GMII_ETHERNET_txd_wire; wire [7:0]GMII_ETHERNET_rxd_wire; assign GMII_ETHERNET_rxd=GMII_ETHERNET_rxd_wire[3:0]; assign GMII_ETHERNET_txd=GMII_ETHERNET_txd_wire[3:0]; ZYNQ_CORE_wrapper u_ZYNQ( .FCLK_CLK0_0(FCLK_CLK), .GMII_ETHERNET_0_0_col(), .GMII_ETHERNET_0_0_crs(), .GMII_ETHERNET_0_0_rx_clk(GMII_ETHERNET_rx_clk), .GMII_ETHERNET_0_0_rx_dv(GMII_ETHERNET_rx_dv), .GMII_ETHERNET_0_0_rx_er(), .GMII_ETHERNET_0_0_rxd(GMII_ETHERNET_rxd_wire), .GMII_ETHERNET_0_0_tx_clk(GMII_ETHERNET_tx_clk), .GMII_ETHERNET_0_0_tx_en(GMII_ETHERNET_tx_en), .GMII_ETHERNET_0_0_tx_er(), .GMII_ETHERNET_0_0_txd(GMII_ETHERNET_txd_wire), .MDIO_ETHERNET_0_0_mdc(MDIO_ETHERNET_mdc), .MDIO_ETHERNET_0_0_mdio_io(MDIO_ETHERNET_mdio_io), .UART_1_0_rxd(UART_rxd), .UART_1_0_txd(UART_txd) ); endmodule
其实这里的主要功能就是通过下面两句映射PS网络部分 rxd和txd 8位信号线中的低4位的管脚(RMII 只需要4位进行通讯)
assign GMII_ETHERNET_rxd=GMII_ETHERNET_rxd_wire[3:0];
assign GMII_ETHERNET_txd=GMII_ETHERNET_txd_wire[3:0];
10)编写好代码后 对代码进行编译
11)添加约束文件 对管脚 和 电平进行约束(这里默认当作UART 使用EMIO 方式连接到转接板的串口上)
set_property IOSTANDARD LVCMOS33 [get_ports FCLK_CLK] set_property IOSTANDARD LVCMOS33 [get_ports GMII_ETHERNET_rx_clk] set_property IOSTANDARD LVCMOS33 [get_ports GMII_ETHERNET_rx_dv] set_property IOSTANDARD LVCMOS33 [get_ports {GMII_ETHERNET_rxd[0]}] set_property IOSTANDARD LVCMOS33 [get_ports {GMII_ETHERNET_rxd[1]}] set_property IOSTANDARD LVCMOS33 [get_ports {GMII_ETHERNET_rxd[2]}] set_property IOSTANDARD LVCMOS33 [get_ports {GMII_ETHERNET_rxd[3]}] set_property IOSTANDARD LVCMOS33 [get_ports GMII_ETHERNET_tx_clk] set_property IOSTANDARD LVCMOS33 [get_ports {GMII_ETHERNET_tx_en[0]}] set_property IOSTANDARD LVCMOS33 [get_ports {GMII_ETHERNET_txd[0]}] set_property IOSTANDARD LVCMOS33 [get_ports {GMII_ETHERNET_txd[1]}] set_property IOSTANDARD LVCMOS33 [get_ports {GMII_ETHERNET_txd[2]}] set_property IOSTANDARD LVCMOS33 [get_ports {GMII_ETHERNET_txd[3]}] set_property IOSTANDARD LVCMOS33 [get_ports MDIO_ETHERNET_mdc] set_property IOSTANDARD LVCMOS33 [get_ports MDIO_ETHERNET_mdio_io] set_property IOSTANDARD LVCMOS33 [get_ports UART_rxd] set_property IOSTANDARD LVCMOS33 [get_ports UART_txd] set_property PACKAGE_PIN U18 [get_ports FCLK_CLK] set_property PACKAGE_PIN U14 [get_ports GMII_ETHERNET_rx_clk] set_property PACKAGE_PIN U15 [get_ports GMII_ETHERNET_tx_clk] set_property PACKAGE_PIN W19 [get_ports {GMII_ETHERNET_tx_en[0]}] set_property PACKAGE_PIN W18 [get_ports {GMII_ETHERNET_txd[0]}] set_property PACKAGE_PIN Y18 [get_ports {GMII_ETHERNET_txd[1]}] set_property PACKAGE_PIN V18 [get_ports {GMII_ETHERNET_txd[2]}] set_property PACKAGE_PIN Y19 [get_ports {GMII_ETHERNET_txd[3]}] set_property PACKAGE_PIN W16 [get_ports GMII_ETHERNET_rx_dv] set_property PACKAGE_PIN W15 [get_ports MDIO_ETHERNET_mdc] set_property PACKAGE_PIN Y14 [get_ports MDIO_ETHERNET_mdio_io] set_property PACKAGE_PIN Y16 [get_ports {GMII_ETHERNET_rxd[0]}] set_property PACKAGE_PIN V16 [get_ports {GMII_ETHERNET_rxd[1]}] set_property PACKAGE_PIN V17 [get_ports {GMII_ETHERNET_rxd[2]}] set_property PACKAGE_PIN Y17 [get_ports {GMII_ETHERNET_rxd[3]}] set_property PACKAGE_PIN H16 [get_ports UART_rxd] set_property PACKAGE_PIN H17 [get_ports UART_txd]
12. 修改之后 点击 Generate Bitstream 进行综合以及生成Bit 文件
等待布线综合完成
PS部分工程创建
1)File→Export→Export hardware…,在弹出的对话框中勾选“include bitstream”,点击“OK”确认,如下图所示。
2)File→Lauch SDK,在弹出的对话框中,保存默认,点击“OK”,如下图所示。
系统将自动打开SDK开发环境
3)在SDK环境下创建网络工程
输入一个工程名,然后点选下一步,选择 LwIP Echo Server选项,自动导入网络SDK自带的网络例程。
4) 创建好LWIP工程后,我们 需要手动修改其连接速度,默认是AUTO自动协商,实测自动协商的时候只会识别到10M 的网络, 这里我们手动在BSP中将设置修改成100Mbps
5)对网络进行调试
硬件部分将网络部分的RJ45接上网线,将扩展板通过TYPEC 连接电脑(在设备管理器中查看主板的串口在系统中的串口号),并且在SDK 的终端中添加这个串口,如下图所示(波特率115200) 也可以用第三方串口助手来调试
6)接下来右键点选工程,然后点Run As 进行配置,点选 Run Configurations
双击 最下方的System Debugger 选项,直到右边出现配置页面
勾选 Reset entire system 和Program FPGA 再下载,否则有可能不能正常访问网络(原因请看备注)
备注:如果先下载PL 后debug的方法操作 可能会出现无法自动获取路由器的IP(并且无法ping通的情况),并且路由器列表上没有检测到设备(猜测可能是因为PL单独下载后,PS还没下载的情况下,路由器和板子握手失败后,就停止了板子访问网络的权限,造成板子网络部能正常工作),所以这里要求要勾选reset entire system,和program fpga选项(让系统每次debug 都能重新配置整个fpga)
之后点选Apply 和 Run
通过串口观察到网络已经启动,并且速度为100M, 网络IP为192.168.1.110(板子需要连接到路由器才能分配到IP) 如果板子和PC直接通过网线直连 看本文最后的部分
用相同路由器网段的 WINDOWS电脑 ping 一下这个IP 可以ping 通,说明网络连接成功了
通过网络助手( 网络调试助手 v4.3.29下载)连接后,发送什么数据,就能通过网络接收到什么数据(设置的端口号是7,IP地址按照之前SDK 串口读到的板子IP地址设置)
板子和PC 通过网线直连的注意事项
直连状态会无法获得IP,那系统自动分配IP 192.168.1.10, 那本地主机也记得将对应的网络口设置成192.168.1.* 的网络段, 网关设置成192.168.1.1才可以ping通 (另外:之前别的千兆网络芯片用这个工程时,直连需要用交叉线,但是EBAZ4205的百兆测试下,实测不用交叉线也可以直连,大家自行尝试,如果不能ping通,请尝试用交叉网线)
另外因为我们之前强制设置了百兆模式,所以直连状态下,电脑端的网络也需要手动设置成百兆,否则会永远link down link up反复切换
以上是本次实验的内容,完整工程如下,SDK程序全部都是官网的例程,具体功能大家自行研究
下面是网络调试助手 网络调试助手 v4.3.29下载