Practice
Dock RMII Receiver
At Kingfisher Dock, Pump 3 watches its network port through the two-bit RMII pins between the PHY chip and the FPGA.
The PHY delivers valid frames, but the monitor packs each group of two bits from the wrong starting point. Every field shifts out of place.
On a salt-streaked service laptop, the log fills with packet types that do not exist.
Your task: build the RMII receiver for the dock. Hunt for the real start-of-frame delimiter, 0xD5, before packing payload bytes.
Interface
| Port | Direction | Type | Description |
|---|---|---|---|
ref_clk | in | 1 bit | 50 MHz RMII reference clock and the only DUT clock |
rst | in | 1 bit | Synchronous reset (active high) |
crs_dv | in | 1 bit | High while the PHY delivers a frame |
rx_er | in | 1 bit | PHY damage flag for the current dibit |
rxd | in | 2-bit vector | One receive dibit per clock |
data | out | 8-bit vector | Latest payload byte, held |
valid | out | 1 bit | Payload byte ready (one-clock pulse) |
frame_start | out | 1 bit | First payload byte ready (one-clock pulse) |
frame_done | out | 1 bit | Recognized frame ended (one-clock pulse) |
bad | out | 1 bit | Frame damage detected (one-clock pulse) |
Behavior
- The receiver supports only 100 Mb/s RMII
- While
crs_dvis high, one dibit is sampled on each risingref_clkedge - The PHY changes its outputs after falling
ref_clkedges - The receiver samples
crs_dv,rx_er, andrxdonly on rising edges - In this bench,
crs_dvstays high for the whole frame - Each byte contains four dibits, with the least significant dibit arriving first
- The first dibit fills bits 1 through 0, and the last dibit fills bits 7 through 6
- A wire frame contains seven
0x55preamble bytes, one0xD5SFD byte, then payload bytes - Preamble and SFD bytes are never emitted on
data - While
crs_dvis high, the receiver hunts through the dibit stream for the SFD pattern - Payload byte packing begins only after the SFD
- A burst that ends without an SFD produces no output pulses
- After such a burst, the next burst re-arms and hunts from a clean state
dataupdates andvalidpulses one clock after a payload byte's fourth dibit is sampledframe_startpulses withvalidfor the first payload byte onlydataholds its latest value betweenvalidpulses- One clock after
crs_dvis sampled low,frame_donepulses - If the recognized frame ends mid-byte, the partial byte is discarded
- For a mid-byte ending,
badpulses together withframe_done - The first sampled high
rx_erafter the SFD makesbadpulse on the next clock. During the preamble hunt the flag is ignored - Further high
rx_ersamples in that frame do not create another receive-error pulse - A receive error does not stop byte delivery, and the frame still ends normally
rsthigh at a rising edge clears all outputs, state, partial data, and recorded errors- After reset, the receiver is idle and hunting for an SFD
What the bench checks
- The testbench drives PHY pins after falling edges and checks every output cycle by cycle against a reference model
- It sends dibit patterns that expose shifted, reversed, or misaligned packing, four dibits per byte with the least significant dibit first
- It checks that preamble and SFD bytes never appear on
data - It ends a burst without an SFD and checks that no output pulses at all, then that the next burst is received cleanly
- It cuts a frame mid-byte and checks that
badjoinsframe_doneand the partial byte is discarded - It samples
rx_erhigh twice in one frame and checks a single delayedbadpulse while bytes keep flowing - It replays SFD-shaped noise while the carrier is down and checks that the receiver ignores it
- It resets mid-frame and checks that all state clears with no
frame_donepulse
Constraints
everything is synchronous to ref_clk, the 50 MHz RMII reference clock. Inputs are sampled on rising edges, and all outputs are registered.
this covers 100 Mb/s RMII with simplified carrier behavior. FCS bytes emerge as ordinary payload, with no CRC checking. Other PHY pins and speeds are out of scope.
Do not add ports.
Click Run to execute your code. Output will appear here.