Throughout this project, a variety of interfaces, some standard and some bespoke, are used to communicate between cores.

“MII”

This is the Media-Independent Interface (MII) described by IEEE 802.3 clause 22. However, instead of RX and TX clocks, clock-enables are used instead. This is a better fit for the clocking resources found on iCE40 FPGAs. In the 125 MHz clock domain used by these cores, the clock enable is asserted every 5 clock cycles. The clock enable generated by pcs_rx may vary somewhat from this due to differences in the local and far end clocks. The mii_elastic_buffer module can be used to smooth out these variations over the course of a frame.

“100Base-X”

This is a bespoke interface used by modules in the receive data path below the PCS layer. It consists of three signals: clk, data, and data_valid. data and data_valid are both two bits wide. Data is transferred on the rising edge of clk. The following table shows the relation between data and data_valid:

data_valid data[1] data[0]

0

Invalid

Invalid

1

Valid

Invalid

2 or 3

Valid

Valid

In the case where both bits in data are valid, data[1] is the most recent bit. As a consequence, when data_valid is non-zero, data[1] always holds the new bit to process. Because three bits cannot be transferred at once, only data_valid[1] is necessary to determine if two bits are to be transferred. However, all cores which generate data_valid must not generate a value of 3 for data_valid.

AXI-Stream

This is AMBA 4 AXI4-Stream, minus several signals. Generally, ARESETn, TSTRB, TKEEP, TID, TDEST are omitted. Sometimes TUSER is omitted as well. Additionally, the A and T prefixes are not used. When the user signal is present, it generally indicates that the associated data is erronious.

Wishbone

This is Wishbone B4 in non-pipelined (“classic”) mode. This imposes a performance penalty on the bus, but wishbone is just used for management registers so I am not too concerned. Generally, RST, TGA, TGC, TGD, RTY, SEL, and LOCK signals are omitted. The _I and _O suffixes are not used. DAT is named data_read or data_write, depending on the direction of transfer. ADR is expanded to addr. All cores have 16-bit ports with 16-bit granularity.