diff --git a/liteeth/phy/rmii.py b/liteeth/phy/rmii.py index 29d9a5f..48d9c36 100644 --- a/liteeth/phy/rmii.py +++ b/liteeth/phy/rmii.py @@ -40,6 +40,7 @@ class LiteEthPHYRMIITX(LiteXModule): for i in range(2): self.specials += SDROutput(i=converter.source.data[i], o=pads.tx_data[i]) + # LiteEth PHY RMII RX ------------------------------------------------------------------------------ class LiteEthPHYRMIIRX(LiteXModule): @@ -62,6 +63,8 @@ class LiteEthPHYRMIIRX(LiteXModule): # Delay. # ------ + # Add a delay to align the data with the frame boundaries since the end-of-frame condition + # (2 consecutive `crs_dv` signals low) is detected with a few cycles delay. self.delay = delay = stream.Delay(layout=[("data", 8)], n=2) # Frame Delimitation. @@ -69,31 +72,30 @@ class LiteEthPHYRMIIRX(LiteXModule): crs_dv_d = Signal() crs_first = Signal() crs_last = Signal() + crs_run = Signal() self.sync += crs_dv_d.eq(crs_dv) self.comb += [ - crs_first.eq(crs_dv & (rx_data != 0b00)), # Start of frame on crs_dv at 1 and non-null data. - crs_last.eq(~crs_dv & ~crs_dv_d), # End of frame on 2 consecutives crs_dv at 0. + crs_first.eq(crs_dv & (rx_data != 0b00)), # Start of frame on crs_dv high and non-null data. + crs_last.eq(~crs_dv & ~crs_dv_d), # End of frame on 2 consecutive crs_dv low. + ] + self.sync += [ + If(crs_first, crs_run.eq(1)), + If(crs_last, crs_run.eq(0)), ] - self.fsm = fsm = FSM(reset_state="IDLE") - fsm.act("IDLE", - delay.source.ready.eq(1), - If(crs_first, - delay.sink.valid.eq(1), - delay.sink.data.eq(rx_data), - NextState("RECEIVE") - ) - ) - fsm.act("RECEIVE", - delay.sink.valid.eq(1), + # Datapath: Input -> Delay -> Converter -> Source. + # ------------------------------------------------ + self.comb += [ + delay.source.ready.eq(1), # Ready by default to flush pipeline. + delay.sink.valid.eq(crs_first | crs_run), delay.sink.data.eq(rx_data), - delay.source.connect(converter.sink), - If(crs_last, - converter.sink.last.eq(1), - NextState("IDLE") - ) - ) - self.comb += converter.source.connect(source) + If(crs_run, + converter.sink.last.eq(crs_last), + delay.source.connect(converter.sink, keep={"valid", "ready", "data"}) + ), + converter.source.connect(source), + ] + # LiteEth PHY RMII CRG -----------------------------------------------------------------------------