zed_ether Getting Started Guide
This is a reference platform to demonstrate use of the OpenCPI Ethernet interface. It is based around an Avnet Zedboard (Xilinx Zynq 7020) and an Avnet FMC Ethernet card to provide dual RGMII Ethernet interfaces connected to the FPGA fabric.
Note that since the FMC connector is used to provide Ethernet connectivity, it is integral to the platform and not available for other uses. Therefore this platform does not declare a slot for the FMC connector, and the platform worker and XDC file are written assuming that the Ethernet card is always present.
The Zynq PS and attached devices (e.g. on-board Ethernet interface) are not used in this platform. The bitstream will not boot without the FMC card attached as the 125MHz oscillator on the FMC card is used to derive all clocks.
The MAC address for the Ethernet interface is read from the EEPROM associated with Ethernet Port 1. If the second Ethernet interface is enabled, a bonded configuration is used so the same MAC address is used for both interfaces, and outbound packets are dispatched in a round-robin fashion. See Connect the host PC to the device for details on how to set up the host to work in this mode.
Revision History
Revision |
Description of Change |
Date |
|---|---|---|
v1.0 |
Initial Release |
2nd March 2022 |
v1.1 |
Change zed_ether to a built-in platform |
24th June 2022 |
Software Prerequisites
A Linux host PC with a Vivado 2019.2 installation (Lab Edition at a minimum to run applications, Design Edition or Webpack to build a bitstream) and an OpenCPI installation.
The Ethernet interfaces use raw sockets to communicate with the device, which
requires the CAP_NET_RAW capability. This can be accomplished either by running
as root, or (preferably) by setting this capability on the application executable.
For example, to work through the rest of this guide, run
$ sudo setcap CAP_NET_RAW+eip $(readlink -f $(which ocpihdl))
$ sudo setcap CAP_NET_RAW+eip $(readlink -f $(which ocpirun))
to enable raw sockets for ocpihdl and ocpirun. Note that to use an ACI
application rather than ocpirun, the capability needs to be set on the
application binary as part of the installation process. If you want to debug
an application, the gdb executable also needs the capability.
Hardware Prerequisites
Avnet Zedboard with VAUX select jumper J18 set to 2V5 (the default)
Avnet FMC Ethernet card, modified as described below.
Host PC with one or two 1Gb Ethernet interfaces
The Q1 transistor on the Ethernet card must be removed to resolve a PCB erratum which makes the stock PCB incompatible with the Zedboard (the transistor drives the Power Good LED but the required base current is too high for the Zedboard’s Power Good output to supply - if the fix is not applied, the Zedboard will not come out of reset).
Note that the date code information in the errata appears to be incorrect. We have an affected board with date code “2019” (according to the document the errata should not applied to this board).
Platform details
This platform provides one dataplane transport called ether, which can be
used to connect input and output ports in the container XML file.
The dgrdma_config_dev device worker (from opencpi/projects/core/components)
must be included in the container in order for the runtime to properly configure
the DG-RDMA component. The easiest way to do this is to specify the dgrdma_dev
platform configuration (rather than base) in the container XML file. An example
minimal container.xml is shown below.
<HdlContainer Platform="zed_ether" Config="dgrdma_dev">
<Connection External="in_1" Interconnect="ether"/>
<Connection External="out_1" Interconnect="ether"/>
</HdlContainer>
The switches and LEDs on the board are not made available to the application; instead they are used for debug outputs from the platform worker. SW[2:0] are used to select the LED display mode (SW[0] and LED[0] are nearest the FMC connector).
SW[2:0] |
LED function |
|
|---|---|---|
000 |
[0]: 1Hz heartbeat, [1]: MAC address successfully read, [2]: MAC address read error, [4:3] ETH1 MAC speed (00=10M, 01=100M, 10=1000M), [6:5] ETH2 MAC speed |
|
001 |
mac_addr[7:0] |
|
010 |
mac_addr[15:8] |
|
011 |
mac_addr[23:16] |
|
100 |
mac_addr[31:24] |
|
101 |
mac_addr[39:32] |
|
110 |
mac_addr[47:40] |
|
111 |
constant 0xaa |
Setup Guide
In order to set a host system up to run applications on this platform, the following steps need to be completed:
Build a test bitstream to be used for autodiscovery and configuration
Connect the host PC to the device
Set up the JTAG cable drivers
Write a system.xml file specifying the system configuration
Build a test bitstream to be used for autodiscovery and configuration
Install the platform by running:
$ ocpiadmin install platform zed_ether --minimal
To create and build a test project with a minimal assembly.
$ ocpidev create project zed_ether_test -K local.zed_ether_test -y ocpi.platform
$ cd zed_ether_test
$ touch hdl/assemblies/bias_loopback/zed_ether_container.xml
$ ocpidev create application -X loopback
Edit the assembly hdl/assemblies/bias_loopback/bias_loopback.xml.
<hdlassembly defaultcontainers="" containers="zed_ether_container">
<connection name="fpga_in" external="consumer">
<port instance="bias_vhdl" name="in"/>
</connection>
<instance worker="bias_vhdl"/>
<connection name="fpga_out" external="producer">
<port instance="bias_vhdl" name="out"/>
</connection>
</hdlassembly>
Edit the container hdl/assemblies/bias_loopback/zed_ether_container.xml.
<hdlcontainer platform="zed_ether" config="dgrdma_dev">
<connection External="fpga_in" interconnect="ether"/>
<connection External="fpga_out" interconnect="ether"/>
</hdlcontainer>
Edit the application applications/loopback.xml.
<application package="ocpi.core" finished="file_write">
<instance component="ocpi.core.dgrdma_config_proxy"/>
<instance component="ocpi.core.file_read" connect="bias">
<property name="fileName" value="in_file.bin" />
<property name="messagesInFile" value="false"/>
</instance>
<instance component="ocpi.core.bias" connect="file_write"/>
<instance component="ocpi.core.file_write">
<property name="fileName" value="out_file.bin"/>
</instance>
</application>
Build the assembly:
$ ocpidev build project --hdl-platform zed_ether --workers-as-needed
Connect the host PC to the device
Connect a USB cable from the host PC to the PROG port on the Zedboard (next to the power connector). Connect the FMC card to the FMC connector on the Zedboard, and apply power. The red LED on the Ethernet card should illuminate indicating that the correct VAUX voltage (2V5) has been selected; if the LED is green or orange, check the J18 jumper on the Zedboard.
If using a single Ethernet connection, connect it to port 1 on the Zedboard and note the name of the network interface.
If using two Ethernet interfaces, connect them both to the Zedboard and create a Linux bonded interface as follows:
If using two Ethernet interfaces, connect them both to the Zedboard and run the
following commands as root to create a Linux bonded interface (assuming the
two interfaces on the PC are named eth1 and eth2):
$ ip link add bond0 type bond
$ echo balance-rr > /sys/class/net/bond0/bonding/mode
$ echo 100 > /sys/class/net/bond0/bonding/miimon
$ ip link set eth1 down
$ ip link set eth2 down
$ ip link set eth1 master bond0
$ ip link set eth2 master bond0
$ ip link set bond0 up
This creates a bonded network interface called bond0 using the balance-rr
method (which uses a round-robin algorithm to dispatch outbound packets on the
two interfaces). The bonded interface name and MAC address should be used for all
OpenCPI configuration as described below (usually the MAC address of the first
physical interface added is used, eth1 in this case).
If you wish to use an interface MTU larger than the default of 1500 bytes, it must be configured on the network interface.
To verify that networking is properly configured, manually load the example OpenCPI bitstream into the device using Vivado Hardware Manager. Verify that the network interface is up and visible to OpenCPI:
$ ocpihdl ethers
1. lo: MAC address none, up, connected, loopback, IP address: 127.0.0.1
2. ens36: MAC address 00:0c:29:e2:30:24, up, connected
Then perform discovery:
$ export OCPI_ENABLE_HDL_NETWORK_DISCOVERY=1
$ ocpihdl search
OpenCPI HDL device found: 'Ether:ens36/80:1f:12:7c:d7:fa': bitstream date Thu Mar 3 08:08:11 2022, platform "zed_ether", part "xc7z020", UUID 1fbbe888-9b0c-11ec-a9eb-dbc5900fab1a
This requires raw socket access: either run as root or set the CAP_NET_RAW
capability on the ocpihdl executable as described in Software Prerequisites.
The OCPI_ENABLE_HDL_NETWORK_DISCOVERY environment variable must be set to
search for Ethernet devices as shown above.
If no devices were found, refer to Troubleshooting section.
Set up the JTAG cable drivers
Ensure that the cable drivers are installed - once Vivado is installed, a separate script needs to be run to install drivers on Linux:
$ cd /tools/Xilinx/Vivado_Lab/2019.2/data/xicom/cable_drivers/lin64/install_script/install_drivers
$ ./install_drivers.sh
for Lab Edition, or
$ cd /tools/Xilinx/Vivado/2019.2/data/xicom/cable_drivers/lin64/install_script/install_drivers
$ ./install_drivers.sh
for Design Edition. Then change to the platform directory, and run:
$ cd ($OCPI_CDK_DIR)/../projects/platform/hdl/platforms/zed_ether
$ ./jtagSupport_zed_ether cables temp
localhost:3121/xilinx_tcf/Digilent/210248B1880E=210248B1880E~
The text between the = and the ~ is the ESN (cable serial number),
210248B1880E in this example, which is used for writing the system.xml
file below. If this does not work, ensure that the cable drivers are installed
and that the USB cable is connected from the host PC to the PROG port on the
Zedboard.
Write a system.xml file specifying the system configuration
The configuration of an Ethernet-connected system is quite complex and cannot
be fully discovered at runtime by OpenCPI. However, the autodiscovery functionality
can be used to easily put together the system.xml file. Note that
Information you will need (note that properties are named from the FPGA’s perspective):
ID of the HDL device in the format
Ether:<ifname>/<fpga_mac_addr>(found usingocpihdl searchas described above)MAC address of the local interface (if using dual-Ethernet configuration, use the MAC address of the bonded interface) (found using
ifconfig)esn: JTAG cable serial number (discover using Vivado, see above)
Optional configurable parameters:
interface_mtu: MTU used by the FPGA. This is independent of the MTU used by the PC and should be set to the actual MTU of the Ethernet hardware for best performance [default: 1500 bytes]ack_wait: How long the FPGA waits before sending an ACK if there is no outgoing traffic [default: 187500 = 1.5ms @ 125MHz]max_acks_outstanding: Maximum number of ACKs accumulated in the FPGA if there is no outgoing traffic [default: 32 packets]coalesce_wait: How long the FPGA waits before sending a partially-empty frame (should be <= ack_wait). Set to zero to disable message coalescence [default: 125000 = 1ms @ 125MHz]dual_ethernet: set to 1 to enable second Ethernet interface, or 0 otherwise [default: 0]remote_dst_id: [default: 1]local_src_id: [default: 1]
Wait parameters are clock cycles at the OpenCPI application clock rate, which is 125MHz for this platform.
An example system.xml file is shown below. To run an application, set the
OCPI_SYSTEM_CONFIG environment variable to the path to this file as described
below, assuming that:
The FPGA is connected on the
bond0interface which has MAC address00:e0:4c:70:de:e2(the configuration property requires this as a 48-bit hex number in network byte order:0x00e04c70dee2)The FPGA’s MAC address is
80:1f:12:7c:79:04The link MTU is configured to 8kB
The cable ESN is
210248B1880EDual-Ethernet is enabled
All other parameters are left at their default values
<opencpi>
<container>
<rcc load='1'/>
<hdl load='1' discovery='static'>
<device name="Ether:bond0/80:1f:12:7c:79:04" device="xc7z020" platform="zed_ether" esn="210248B1880E" static="true">
<instance worker='dgrdma_config_dev'>
<property name="remote_mac_addr_d" value="0x00e04c70dee2"/>
<property name="interface_mtu_d" value="8192"/>
<property name="dual_ethernet_d" value="1"/>
</instance>
</device>
</hdl>
</container>
<transfer smbsize='128K'>
<pio load='1'/>
<datagram2-ether load='1'/>
</transfer>
</opencpi>
This selects the new datagram2 transfer driver. This is a rewrite of the
existing datagram transfer driver to improve performance. It does not
implement some features of DG-RDMA which are not used by the FPGA implementation
(e.g. ACK generation). For more details, refer to the design documentation for
the datagram2 driver at opencpi/runtime/xfer/drivers/datagram2/README.md.
To use the old driver instead, replace the line
<datagram2-ether load='1'/>
with
<datagram-datagram_ether load='1'/>
Loading a bitstream via ocpihdl load (optional)
Once you have a system.xml file which specifies the JTAG cable ESN, you can
use ocpihdl load to load a bitstream into the FPGA. This is not required to
run an applicaton (ocpirun or an ACI application will automatically load the
FPGA bitstream is required), but may be useful to test the JTAG connection and to
do other low-level programming via ocpihdl.
$ ocpihdl load -d Ether:bond0/80:1f:12:7c:79:04 /path/to/artifact.bitz
Running an Application
Ensure that you have a valid system.xml file. Ensure that the following environment
variables are set:
Name |
Value |
Remarks |
|---|---|---|
|
1 |
Required to find network devices |
|
name of local Ethernet interface |
Used by transfer driver |
|
MTU for packets sent by the PC |
Optional; if not present, the default (1498) will be used. This must not be set larger than the actual MTU configured in the Linux network interface. |
|
Path to |
Required by OpenCPI framework |
|
Colon-separated list of artifact paths |
Required by OpenCPI framework. dgrdma_config_proxy is in ocpi.core. |
Now you can run the bias_loopback application created earlier:
$ cd zed_ether_test/applications
$ dd if=/dev/urandom of=in_file.bin bs=65536 count=1
$ ocpirun -d -P bias=zed_ether loopback.xml
$ diff in_file.bin out_file.bin
This configures the FPGA as a loopback. It creates a file in_file.bin
containing 16kB of binary data and sends it to the FPGA, saving the result in
out_file.bin (which should be identical). You can send a larger block
of data, e.g.
$ dd if=/dev/urandom of=in_file.bin bs=65536 count=100
If OpenCPI reports that the HDL device is not found, ensure that:
The USB cable is connected and the correct cable ESN is configured in
system.xmlThe Ethernet interface(s) are connected to the FPGA and up
The correct Ethernet interface(s) and MAC address(es) are configured in
system.xml
The other applications in this directory can be used to make more detailed
performance measurements of the Ethernet link using the perftest HDL worker
(documentation TODO).
Troubleshooting
There are several things that need to be configured correctly for the Ethernet
interface to work. The recommended approach is to get the demo loopback
application working first, then use the same system.xml and environment to
run your real application (whether via ocpirun or as an ACI app).
Problem: Vivado fails to program the FPGA, even though the JTAG USB cable is connected
Determine whether the FPGA can be programmed without the FMC card attached. If so, apply the PCB modification described in Hardware prerequisites above.
When the FPGA is configured and the Zedboard switches are all set to ‘0’, LED[0] should flash at about 1Hz (as long as the FMC card is connected - as all clocks are derived from oscillators on the card).
Problem: ocpihdl/ocpirun fails to program the FPGA
Ensure that the cable ESN is set in
system.xmlKill any stale Vivado hardware server process (killall hw_server; killall cs_server) before programming
Problem: ocpihdl search does not find any devices
Check that the device is turned on, configured with an OpenCPI bitstream, and not in reset
If using single-Ethernet connection: check that Ethernet cable is connected to ‘Port 1’ on the FMC card
If using dual-Ethernet connection: check that both Ethernet cables are connected and the bonded interface is up
Ensure that the FMC Ethernet card is properly connected, and the VAUX jumper on the Zedboard is correctly set to 2V5 (the red LED on the FMC card should be on).
Ensure that you are running as root, or with the
CAP_NET_RAWcapability set on the executable (see Software Prerequisites above)Ensure that the
OCPI_ENABLE_HDL_NETWORK_DISCOVERYenvironment variable is set to 1
If the above steps do not solve the problem, further debugging steps include:
Set the
OCPI_LOG_LEVELenvironment variable to 10 before runningocpihdland look through the output for lines relating to the network interface in useCapture a Wireshark trace on the network interface. During
ocpihdl searchyou should see one outgoing DCP frame (Ethertype=0xf040) sent to the broadcast addressff:ff:ff:ff:ff:ff, and one incoming frame from the FPGA.Wireshark dissectors for DCP and DG-RDMA are in the main OpenCPI repo under
tools/wireshark-dissectors. Include these on your Wireshark plugin path to help debugging issues at the protocol level. This requires a build of Wireshark that supports Lua protocol dissectors. You can find the Lua plugin path by opening the Wireshark about box and looking in the ‘Folders’ tabIf the outgoing frame is not present, it is most likely a problem with the PC network configuration or the permissions on
ocpihdl.If the response is not present, it is most likely a problem with the Ethernet connection or the FPGA configuration
Problem: ocpirun fails opening raw socket
E.g.
$ ocpirun -d -P bias=zed_ether loopback.xml
OCPI( 2:176.0297): HDL driver, got error opening static device: opening raw socket (Operation not permitted [1])
Available containers are: 0: rcc0 [model: rcc os: linux platform: ubuntu18_04]
Run as root, or ensure that the CAP_NET_RAW capability is set on the ocpirun
executable (or application executable, if using an ACI app).
Problem: the test application starts, but no data is sent to or from the FPGA
Check that:
the
OCPI_ETHER_INTERFACEis correctly setthe
remote_mac_addr_dproperty is set to the MAC address of the PC insystem.xmlthe
interface_mtu_dproperty is set to a value supported by the PC’s network interface (if in doubt, get things working with the default 1500 bytes before increasing).if set, the
OCPI_MAX_ETHER_PAYLOAD_SIZEenvironment variable is set to a value less than or equal to the actual configured MTU of the PC network interface (if in doubt, get things working with the default 1500 bytes before increasing).
Problem: the demo application works, but my application doesn’t
Check that:
Your bitstream includes the
dgrdma_config_devdevice worker (by using thedgrdma_devconfiguration or directly instantiating it in the container XML)Your application XML includes the
ocpi.core.dgrdma_config_proxyworker