diff --git a/phy/rmii.md b/phy/rmii.md index 17842ac..5072d0a 100644 --- a/phy/rmii.md +++ b/phy/rmii.md @@ -2,6 +2,43 @@ This guide exists because information on how to structure MII/RMII data is hard to come by. It is also not helpful that asking an AI that is also provided datasheets with accurate information on the subject will return garbage information. Thus the need to document this so that X person can deterministically find this info. +## RMII Overview + +RMII (Reduced Media Independent Interface) reduces MII's 16 data/control pins down to 7-8 pins, simplifying PCB layout and reducing trace count between MAC and PHY. + +| Signal | Direction (PHY perspective) | Function | +|--------|----------------------------|----------| +| **TX_EN** | Input | Transmit enable - MAC asserts when presenting valid dibits | +| **TXD[1:0]** | Input | Transmit data - 2-bit dibit per clock cycle | +| **CRS_DV** | Output | Carrier Sense / Receive Data Valid (combined signal) | +| **RXD[1:0]** | Output | Receive data - 2-bit dibit per clock cycle | +| **RX_ER** | Output | Receive error indicator (optional on some PHYs) | +| **REF_CLK** | Input or Output | 50 MHz reference clock (direction depends on mode) | + +All RMII signals are synchronous to the 50 MHz REF_CLK rising edge. + + +## REF_CLK: Reference Clock + +All RMII signals are synchronous to a continuous 50 MHz reference clock. Two modes exist: + +### Clock Source Mode (PHY is clock source) +- PHY takes 25 MHz crystal/oscillator on XI/XO pins +- PHY PLL multiplies to 50 MHz internally +- PHY outputs 50 MHz on REF_CLK pin to MAC +- Example: KSZ8081RNA default, LAN8720A with nINTSEL pin low at reset + +### Clock Follower Mode (MAC is clock source) +- External 50 MHz oscillator feeds both PHY (XI pin) and MAC +- PHY REF_CLK pin left unconnected or used as input +- Example: DP83826 RMII follower mode + +**Clock Requirements** (typical): +- Frequency: 50 MHz ±50 ppm +- Duty cycle: 40-60% +- Jitter: <150 ps peak-to-peak + + ## Tx0/Tx1/TxEN and CLKREF/RETCLK interface ### Practical Tx example: To illustrate programatically we'll suppose we have a hardware which requires a byte for every clock. Each byte contains 3 bits to be sent out: Tx0,Tx1,TxEn bits. @@ -139,3 +176,83 @@ mov x, status side 0 // Get Tx not empty status. jmp !x, preamb_t side 1 .wrap_t ``` + + +## Rx0/Rx1/CRS_DV Interface + +The receive path uses RXD[1:0] for data and CRS_DV as a combined carrier sense and data valid signal. + +### Key points +1. CRS_DV combines two functions into one signal. Is **not synchronous in all RMII revisions.** + - **CRS (Carrier Sense)**: Asserted when receive medium is non-idle ("idle" defined in IEEE 802.3). CRS is asserted based on PHY operating mode. + - Loss of carrier results results in deassertion of CRS_DV synchronous to REF_CLK. See [DP83848 PHY datasheet](https://www.ti.com/lit/an/snla076a/snla076a.pdf) for more info. + - The data on RXD[1:0] is considered valid once CRS_DV is asserted but is asynchronous relative REF_CLK, so RXD[1:0] is 0b00 until proper receive signal decoding takes place. + - CRS_DV may be toggled on the second dibit of the next nibble after deassertion if it has additional bits to present to MAC (RMII revision 1.2 spec) + +2. **RXD[1:0]** transitions synchronously to REF_CLK. + - RXD[1:0] is 0b00 to indicate idle when CRS_DV is deasserted and remains 0b00 on CRS_DV assertion until proper receive decoding takes place. + - For every clock period in which CRS_DV is asserted, RXD[1:0] transfers two bits of recovered data + - For a normal reception upon detecting SSD(start of stream delimiter) after CRS_DV assertion the PHY will drive preamble 0b01 followed by the SFD (start of frame delimiter). MAC/STA should capture data after the SFD. +3. RX_ER is synchronous to REF_CLK and asserted for one or more REF_CLK periods to indicate that an error was detected somewhere in the frame being transferred to PHY while CRS_DV asserted. If CRS_DV not asserted RX_ER is ignored. Although frames should be discarded if RX_ER is set, if RX_ER unable to be checked the MAC checking the CRC should surface the error. Below are some common causes for RX_ER assertion: + - 4B/5B invalid code group (100BASE-TX) + - Bad SSD (Start of Stream Delimiter) + - Signal amplitude below squelch threshold + - PHY receive FIFO overflow + +4. Some PHYs provide **RX_DV** signal. RX_DV is asserted with first properly recovered data (preamble) or false carrier detection. It is deasserted following transfer of final di-bit of recovered data. A full duplex MAC may use this signal to avoid having to recover RX_DV from CRS_DV. + + +### Frame Reception Sequence +Example supposes 100M link mode: +``` +REF_CLK: _|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_ ... +CRS|CRS_DV: __|‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ ... (stays HIGH until end of frame) +DV: __________|‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ ... +RXD[1:0]: 00|00|00|00|01|01|01|01|01|01|01|01|01|01|11|DA|TA|... + └async─┘└───── Preamble ────┘└───SFD────┘└─ Frame data ─... +``` + +CRS_DV remains asserted throughout the entire frame (preamble, SFD, payload, CRC) and only de-asserts after the last dibit. + +**End of packet toggle pattern**: When the carrier ends before the PHY's elasticity buffer empties (common case), CRS_DV toggles at nibble rate to indicate CRS has dropped while DV remains: +- HIGH on second dibit of each nibble (data still valid) +- LOW on first dibit of each nibble (carrier lost) + +``` +End of frame with CRS ending before DV at 100M link mode: + +REF_CLK: _|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_ +CRS_DV: ‾‾‾‾‾‾‾‾‾‾|___|‾‾‾|___|‾‾‾|_______________ +CRS: ‾‾‾‾‾‾‾‾‾‾|______________________________ +DV: ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾|_______________ +RXD[1:0]: ...data...|D0 |D1 |D2 |D3 |00 |00 |00 |00 + └nibble┘└nibble┘ +``` + +**Idle indication**: RXD[1:0] = 00 when CRS_DV is low. + + +### Practical Rx Sequence +1. Monitor CRS_DV for assertion +2. Wait for SFD pattern: dibits ending in "11" (0xD5 byte) +3. Sample RXD[1:0] on each REF_CLK rising while DV asserted (CRS_DV may toggle for DV assert) +4. Check RX_ER was never asserted during frame. Some PHYs emit invalid/preset data on RX[1:0] after RX_ER asserted +5. Assemble dibits into bytes (LSB first, same as Tx) +6. Validate CRC32 on assembled frame + + +## 10M vs 100M link mode Speed Differences + +At 100 Mbps, RMII delivers one dibit per REF_CLK cycle (50 MHz × 2 bits = 100 Mbps). + +At 10 Mbps, each dibit is **repeated 10 times** across 10 REF_CLK cycles: + +``` +100M: one dibit per clock +REF_CLK: _|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_ +RXD[1:0]: |D0|D1|D2|D3|D4|D5|D6|D7| + +10M: each dibit held for 10 clocks +REF_CLK: _|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_ ... (×10 per dibit) +RXD[1:0]: |D0|D0|D0|D0|D0|D0|D0|D0|D0|D0|D1|D1|D1|... +```