liteeth/phy: add GMII/MII phy
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Sun, 12 Apr 2015 14:49:39 +0000 (16:49 +0200)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Sun, 12 Apr 2015 15:25:55 +0000 (17:25 +0200)
for now swicth is manual, we will need a clk counter to allow software or logic to automatically switch between GMII and MII

misoclib/com/liteeth/phy/__init__.py
misoclib/com/liteeth/phy/gmii_mii.py [new file with mode: 0644]

index 311afc8e1297af0c7ccb6df85e0ee34691d660a6..df9623aa993ca793e322b14840c562a995df56e7 100644 (file)
@@ -7,8 +7,14 @@ def LiteEthPHY(clock_pads, pads, **kwargs):
                from misoclib.com.liteeth.phy.sim import LiteEthPHYSim
                return LiteEthPHYSim(pads)
        elif hasattr(clock_pads, "gtx") and flen(pads.tx_data) == 8:
-               from misoclib.com.liteeth.phy.gmii import LiteEthPHYGMII
-               return LiteEthPHYGMII(clock_pads, pads, **kwargs)
+               if hasattr(clock_pads, "tx"):
+                       # This is a 10/100/1G PHY
+                       from misoclib.com.liteeth.phy.gmii_mii import LiteEthPHYGMIIMII
+                       return LiteEthPHYGMIIMII(clock_pads, pads, **kwargs)
+               else:
+                       # This is a pure 1G PHY
+                       from misoclib.com.liteeth.phy.gmii import LiteEthPHYGMII
+                       return LiteEthPHYGMII(clock_pads, pads, **kwargs)
        elif flen(pads.tx_data) == 4:
                from misoclib.com.liteeth.phy.mii import LiteEthPHYMII
                return LiteEthPHYMII(clock_pads, pads, **kwargs)
diff --git a/misoclib/com/liteeth/phy/gmii_mii.py b/misoclib/com/liteeth/phy/gmii_mii.py
new file mode 100644 (file)
index 0000000..5cf8669
--- /dev/null
@@ -0,0 +1,79 @@
+from migen.genlib.io import DDROutput
+from migen.flow.plumbing import Multiplexer, Demultiplexer
+
+from misoclib.com.liteeth.common import *
+from misoclib.com.liteeth.generic import *
+
+from misoclib.com.liteeth.phy.gmii import LiteEthPHYGMIIMIICRG
+from misoclib.com.liteeth.phy.mii import LiteEthPHYMIITX, LiteEthPHYMIIRX
+from misoclib.com.liteeth.phy.gmii import LiteEthPHYGMIITX, LiteEthPHYGMIIRX
+
+modes = {
+       "GMII"  : 0,
+       "MII"   : 1
+}
+
+class LiteEthPHYGMIIMIITX(Module):
+       def __init__(self, pads, mode):
+               self.sink = sink = Sink(eth_phy_description(8))
+               ###
+               tx_pads_layout = [("tx_er", 1), ("tx_en", 1), ("tx_data", 8)]
+
+               gmii_tx_pads = Record(tx_pads_layout)
+               gmii_tx = LiteEthPHYGMIITX(gmii_tx_pads)
+               self.submodules += gmii_tx
+
+               mii_tx_pads = Record(tx_pads_layout)
+               mii_tx = LiteEthPHYMIITX(mii_tx_pads)
+               self.submodules += mii_tx
+
+               demux = Demultiplexer(eth_phy_description(8), 2)
+               self.submodules += demux
+               self.comb += [
+                       demux.sel.eq(mode==modes["MII"]),
+                       Record.connect(sink, demux.sink),
+                       Record.connect(demux.source0, gmii_tx.sink),
+                       Record.connect(demux.source1, mii_tx.sink),
+               ]
+
+               if hasattr(pads, "tx_er"):
+                       self.comb += pads.tx_er.eq(0)
+               self.sync += [
+                       If(mode==modes["MII"],
+                               pads.tx_en.eq(mii_tx_pads.tx_en),
+                               pads.tx_data.eq(mii_tx_pads.tx_data),
+                       ).Else(
+                               pads.tx_en.eq(gmii_tx_pads.tx_en),
+                               pads.tx_data.eq(gmii_tx_pads.tx_data),
+                       )
+               ]
+
+class LiteEthPHYGMIIMIIRX(Module):
+       def __init__(self, pads, mode):
+               self.source = source = Source(eth_phy_description(8))
+               ###
+               gmii_rx = LiteEthPHYGMIIRX(pads)
+               self.submodules += gmii_rx
+
+               mii_rx = LiteEthPHYMIIRX(pads)
+               self.submodules += mii_rx
+
+               mux = Multiplexer(eth_phy_description(8), 2)
+               self.submodules += mux
+               self.comb += [
+                       mux.sel.eq(mode==modes["MII"]),
+                       Record.connect(gmii_rx.source, mux.sink0),
+                       Record.connect(mii_rx.source, mux.sink1),
+                       Record.connect(mux.source, source)
+               ]
+
+class LiteEthPHYGMIIMII(Module, AutoCSR):
+       def __init__(self, clock_pads, pads, with_hw_init_reset=True):
+               self.dw = 8
+               self._mode = CSRStorage()
+               mode = self._mode.storage
+               # Note: we can use GMII CRG since it also handles tx clock pad used for MII
+               self.submodules.crg = LiteEthPHYGMIICRG(clock_pads, pads, with_hw_init_reset)
+               self.submodules.tx = RenameClockDomains(LiteEthPHYGMIIMIITX(pads, mode), "eth_tx")
+               self.submodules.rx = RenameClockDomains(LiteEthPHYGMIIMIIRX(pads, mode), "eth_rx")
+               self.sink, self.source = self.tx.sink, self.rx.source