Electronic – Ethernet Phy Rx developed in a FPGA to send data to an ethernet Mac

ethernetfpgamiirgmiirmii

I'm trying to send data from a FPGA to the Ethernet Mac port of a SoC which has the stmmac Synopsys IP.

enter image description here

I'm using the MII protocol at 25MHz for 100Mb/s (4-bit per clock cycle).

I'm sending the following fake ethernet frame:

FF FF FF FF FF FF       Destination Mac (broadcast)
58 00 E3 5B E8 41       Source Mac
00 2E                   Type with size (46=0x2E)
01 02 03 ... 44 45 46   Packet
CF C7 1F CC             FCS

The whole frame is valid and checked at http://packetor.com. The FCS is correct.

FF FF FF FF FF FF 58 00 E3 5B E8 41 00 2E 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 CF C7 1F CC

My FPGA code looks like this:

reg [20:0] count;
reg ctl;
reg [3:0] d;

wire clk;
wire clk90;
pll pll_inst(
    .CLKI   (oscInternal),
    .CLKOP  (clk), //25MHz
    .CLKOS  (clk90) //25MHz shifted phase 90 degrees
);

//Packet is 8+6+6+2+46+4=72 bytes long, so 576 bits.
wire [575:0]val = 576'h55555555555555D5FFFFFFFFFFFF5800E35BE841002E01020304050607080910111213141516171819202122232425262728293031323334353637383940414243444546CFC71FCC;

always @(posedge clk) begin
    if (count < 72 * 2) begin
        ctl <= 1;
        if (count[0] == 0)
            d <= val >> (576 - 8 - 4 * count);
        else
            d <= val >> (576 - 4 * count);
    end else begin
        d <= 0;
        ctl <= 0;
    end
    count <= count + 1;
end

assign rxd0 = d[1];
assign rxd1 = d[0];
assign rxd2 = d[2];
assign rxd3 = d[3];
assign rxctl = ctl;
assign rxclk = clk90;

I send 4-bit by 4-bit, first the lower 4 bits then the higher 4 bits of each byte. This is done at each clock cycle.

The rxclock is shifted of 90 degrees so that data is valid when the 25MHz rx clock is rising up.

I have checked on a digital analyzer and it looks good, similar to the traffic sent by a Realtek PHY.

In the kernel DTS, I have:

phy-mode = "mii";
fixed-link {
    speed = <100>;
    full-duplex;
};

When I boot, the kernel is correctly setup with the stmmac Mac. The kernel driver is here:

https://elixir.bootlin.com/linux/v4.4.230/source/drivers/net/ethernet/stmicro/stmmac

In dmesg, I see eth0 up and configured at 100Mb/s. ifconfig eth0 up is good.

I can send traffic via a Realtek PHY in a similar setup and it's received by the kernel.

But I don't see anything when I'm sending through my FPGA. Is there anything I'm missing or doing wrong?

Best Answer

First, what interface are you using? You said MII, but MII uses tx_en/tx_er or rx_dv/rx_er instead of tx_ctl/rx_ctl. Unless you're actually using RGMII, which muxes those two into one signal on opposite clock edges, with er inverted to reduce the number of transitions.

Second, this could be a problem:

assign rxd0 = d[1];
assign rxd1 = d[0];
assign rxd2 = d[2];
assign rxd3 = d[3];

But presumably the MAC should still count dropped packets. Although perhaps not if the switched bits screw up detection of the start of the frame.

Also, assuming you're using RGMII, that interface can use the data signals to transfer status information between frames. See the RGMII spec. The MAC may be looking at this status information, so you should could try generating that. Looks like you might want to set the data at idle to 4'b1011, to indicate full duplex link, 25 MHz clock, link up.