From 7448170390ddf4b7c353ae10932377255581c25a Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 28 Dec 2020 11:29:00 +0100 Subject: [PATCH] liteth/phy/rmii: add support for ref_clk as input. In some hardware, ref_clk can be input for both the MAC and the PHY. In this case, setting refclk_cd to None will make the CRG use ref_clk as the RMII input reference clock: Pads: # RMII Ethernet ("eth_clocks", 0, Subsignal("ref_clk", Pins("D17")), IOStandard("LVCMOS33"), ), ("eth", 0, Subsignal("rst_n", Pins("F16")), Subsignal("rx_data", Pins("A20 B18")), Subsignal("crs_dv", Pins("C20")), Subsignal("tx_en", Pins("A19")), Subsignal("tx_data", Pins("C18 C19")), Subsignal("mdc", Pins("F14")), Subsignal("mdio", Pins("F13")), Subsignal("rx_er", Pins("B20")), Subsignal("int_n", Pins("D21")), IOStandard("LVCMOS33") ), PHY: self.submodules.ethphy = LiteEthPHYRMII( clock_pads = self.platform.request("eth_clocks"), pads = self.platform.request("eth"), refclk_cd = None) Thanks @mwick83 for reporting the use case and for the initial implementation. --- liteeth/phy/rmii.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/liteeth/phy/rmii.py b/liteeth/phy/rmii.py index e320c10..87ed31a 100644 --- a/liteeth/phy/rmii.py +++ b/liteeth/phy/rmii.py @@ -99,12 +99,22 @@ class LiteEthPHYRMIICRG(Module, AutoCSR): # # # # RX/TX clocks + self.clock_domains.cd_eth_rx = ClockDomain() self.clock_domains.cd_eth_tx = ClockDomain() - self.comb += self.cd_eth_rx.clk.eq(ClockSignal(refclk_cd)) - self.comb += self.cd_eth_tx.clk.eq(ClockSignal(refclk_cd)) - if clock_pads is not None: - self.specials += DDROutput(0, 1, clock_pads.ref_clk, ClockSignal("eth_tx")) + + # When no refclk_cd, use clock_pads.ref_clk as RMII reference clock. + if refclk_cd is None: + self.comb += self.cd_eth_rx.clk.eq(clock_pads.ref_clk) + self.comb += self.cd_eth_tx.clk.eq(clock_pads.ref_clk) + + # Else use refclk_cd as RMII reference clock (provided by user design). + else: + self.comb += self.cd_eth_rx.clk.eq(ClockSignal(refclk_cd)) + self.comb += self.cd_eth_tx.clk.eq(ClockSignal(refclk_cd)) + # Drive clock_pads if provided. + if clock_pads is not None: + self.specials += DDROutput(0, 1, clock_pads.ref_clk, ClockSignal("eth_tx")) # Reset self.reset = reset = Signal()