How to use the AXI Ethernet Lite MAC IP from AMD (Previously Xilinx)

So you need/want to read/write data between an FPGA and an Ethernet connector, RJ45, via an Ethernet PHY, great, now how on earth do you get started with this? By sweating profusely after spending countless hours looking through the million pages long documents that appear after a google search of combinations containing the keywords Ethernet, IP or MAC? If this rings a bell then please don't worry, you're not alone! Well then, let's try to demystify this very cloudy space, no not the cloud computing variety, the real ones up in the sky ;)

So on the surface this topic looks like a case of mission impossible, however, with a little bit of terminology up our sleeve we can find something akin to what we're after. To start with we need to determine what we actually need from this magical IP, do we simply want to send data from the FPGA to a PHY chip and then through to an external Ethernet connector? Do we want to receive? Do we want both directions, i.e. bidirectional communication? Answering that question is a great start.

Let's assume we just want simple bidirectional communication, i.e. a transmit and receive channel connected between the FPGA and the PHY and RJ45 connector as shown below:

How to achieve "simple" bidirectional ethernet communication with an AMD FPGA

Let's begin by opening up Vivado's IP Catalog and searching for "ethernet"

Hmm 23 matches, okay... Let's look at a higher level in terms of the different folders to try and shed some light:

Okay that looks less intimidating. So what are we after? I'd take a punt at either "Communication & Networking" or "Embedded Processing" so let's see...

Let's see what's under "Ethernet":

Hmm that is still quite daunting. I don't know about you but to me I just see the words "ethernet" everywhere sprinked with jargon either side of it. We could try the 10G Ethernet MAC IP for example and from the description it would seem to do the job:

However, is this really necessary? Do we need to implement an Ethernet MAC just to communicate with an Ethernet PHY? The answer thankfully is no, we don't. If we go back a few layers you will see:

Introducing AXI EthernetLITE IP

Now this is the "diamond in the rough" so to speak as we are presented with this excellent summary of its capabilities:

Xilinx LogiCORE IP AXI Ethernet Lite MAC

So it is a MAC but a "lite" version of it which is significantly simpler to use and less hungry on precious FPGA resources, win-win.

Block Diagram of the AXI Ethernet Lite MAC

Shown above is a block diagram view of the IP internals, we can see both transmit, TX, and receive, RX, blocks as well as buffers, an AXI interface, an interrupt, clock and a MDIO Master Interface. The modules of particular interest for us to transmit/receive then is the Transmit, Receive, TX Buffer, RX Buffer, AXI Interface, the interrupt and the clock. The documentation nicely summarises each of these blocks below:

Block descriptions

Also please note the following unsupported features which may mean this IP is a deal breaker. The table below is also worth noting:

Maximum frequency vs family and speed grade with AXI interfaces

There are also resource estimates shown which are also important to note, such as the following for Artix-7 FPGA's:

Artix-7 FPGA Resource Estimation

AXI EthernetLite Signals

AXI EthernetLite Ports

Quick AXI Primer

AXI4 Write Channel Architecture - UG1037

Shown above is a nice diagram taken from the referenced user guide by AMD. As it very clearly shows we effectively have three channels which are:

  • Write address channel - Send address and control information from the master to slave
  • Write data channel - Send data from the master to the slave
  • Write response channel (B) - Receive write responses from the slave

Some Terminology:

  • m_axi                                               : AXI master
  • s_axi                                                 : AXI slave
  • s_axi_ar                                          : Address Read
  • s_axi_aw                                         : Address Write
  • s_axi_b                                            : Response
  • s_axi_w                                           : Data Write

S_AXI Signals:

  • s_axi_araddr[12:0]                     : Address Read of the first beat of the burst
  • s_axi_arready                               : Address Read Ready handshake signal
  • s_axi_arvalid                                 : Address Read Valid handshake signal
  • s_axi_awaddr[12:0]                    : Address Write of the first beat of the burst
  • s_axi_awready                             : Address Write Ready handshake signal
  • s_axi_awvalid                               : Address Write Valid handshake signal
  • s_axi_bready                               : Response Ready handshake signal
  • s_axi_bresp[1:0]                         : Write response, to specify the status of the burst
  • s_axi_bvalid                                  : Response valid handshake signal
  • s_axi_rdata[31:0]                       : Read Data
  • s_axi_rready                                 : Read Ready handshake signal
  • s_axi_rresp[1:0]                          : Read Response, to specify the status of the current RDATA signal
  • s_axi_rvalid                                   : Read Valid handshake signal
  • s_axi_wdata[31:0]                       : Write Data
  • s_axi_wready                                : Write Ready handshake signal
  • s_axi_wstrb[3:0]                          : Write byte strobe, to indicate which bytes of the WDATA signal are valid
  • s_axi_wvalid                                  : Write valid handshake signal
  • s_axi_aclk                                       : AXI clock
  • s_axi_aresetn                                : AXI active-low reset

MAC Interface Signals:

  • phy_tx_clk           : Ethernet transmit clock input from PHY
  • phy_rx_clk           : Ethernet receive clock input from PHY
  • phy_rx_data[3:0]             : Ethernet receive data input from Ethernet PHY
  • phy_tx_data[3:0]                          : Ethernet transmit data output to Ethernet PHY
  • phy_dv                                               : Ethernet receive data valid input from Ethernet PHY
  • phy_rx_er                                         : Ethernet receive error input from Ethernet PHY
  • phy_tx_en                                         : Ethernet transmit enable output to Ethernet PHY
  • phy_crs                                              : Ethernet carrier sense input from Ethernet PHY
  • phy_col                                              : Ethernet collision input from Ethernet PHY
  • phy_rst_n                                         : PHY reset, active-low
  • phy_mdc                                           : Ethernet to PHY MII Management clock
  • phy_mdio_i                                     : PHY MDIO data input from 3-state buffer
  • phy_mdio_o                                    : PHY MDIO data output to 3-state buffer
  • phy_mdio_t                                     : PHY MDIO data output enable to 3-state buffer

MAC Clock Domains

MAC Clock Domains

Shown above is the clock domain paths for the MAC showing both the TX and RX clock domain paths. Note that the phy_tx_clk signal drives the phy_tx_data signal and the phy_rx_clk signal is used to sample the phy_rx_data while phy_dv is 1 indicating valid data.

Transmit Interface and Flow

From the above MAC Clock Domains figure we can see that the transmit data is stored in dual port memory starting from address 0x0 which uses word aligned addressing (4 bytes) which means we start at address 0x0 and then 0x4 (as 0x00, 0x01, 0x02, 0x03 are occupied with data).

Transmit Dual Port Memory
Transmit Flow

Receive Interface

The receive data is also stored in dual port memory which starts at address 0x1000. It is important to note that 0x17FC bit[0] on the data bus is used as a status to indicate the presence of a receive packet that is ready for processing by software.

Receive Dual Port Memory
Receive Flow

We could now look at sample transactions but in the best use of time let's go straight to using the EthernetLite IP and learn from doing.

Software Sequences

Regarding the required software sequences for the transmit and receive this is all captured nicely within chapter 3 of the IP Product Guide.

Generating the IP Core

This is as simple as looking up the IP Core and enabling/disabling settings as required for your application, see below as an example:

This will then generate the following outputs: