import migen in litex/gen
[litex.git] / litex / soc / misoc / cores / liteeth_mini / phy / gmii.py
1 from migen import *
2 from migen.genlib.io import DDROutput
3 from migen.genlib.resetsync import AsyncResetSynchronizer
4
5 from misoc.cores.liteeth_mini.common import *
6
7
8 class LiteEthPHYGMIITX(Module):
9 def __init__(self, pads, pads_register=True):
10 self.sink = sink = Sink(eth_phy_description(8))
11
12 # # #
13
14 if hasattr(pads, "tx_er"):
15 self.sync += pads.tx_er.eq(0)
16 pads_eq = [
17 pads.tx_en.eq(sink.stb),
18 pads.tx_data.eq(sink.data)
19 ]
20 if pads_register:
21 self.sync += pads_eq
22 else:
23 self.comb += pads_eq
24 self.comb += sink.ack.eq(1)
25
26
27 class LiteEthPHYGMIIRX(Module):
28 def __init__(self, pads):
29 self.source = source = Source(eth_phy_description(8))
30
31 # # #
32
33 dv_d = Signal()
34 self.sync += dv_d.eq(pads.dv)
35
36 sop = Signal()
37 eop = Signal()
38 self.comb += [
39 sop.eq(pads.dv & ~dv_d),
40 eop.eq(~pads.dv & dv_d)
41 ]
42 self.sync += [
43 source.stb.eq(pads.dv),
44 source.sop.eq(sop),
45 source.data.eq(pads.rx_data)
46 ]
47 self.comb += source.eop.eq(eop)
48
49
50 class LiteEthPHYGMIICRG(Module, AutoCSR):
51 def __init__(self, clock_pads, pads, with_hw_init_reset, mii_mode=0):
52 self._reset = CSRStorage()
53
54 # # #
55
56 self.clock_domains.cd_eth_rx = ClockDomain()
57 self.clock_domains.cd_eth_tx = ClockDomain()
58
59 # RX : Let the synthesis tool insert the appropriate clock buffer
60 self.comb += self.cd_eth_rx.clk.eq(clock_pads.rx)
61
62 # TX : GMII: Drive clock_pads.gtx, clock_pads.tx unused
63 # MII: Use PHY clock_pads.tx as eth_tx_clk, do not drive clock_pads.gtx
64 self.specials += DDROutput(1, mii_mode, clock_pads.gtx, ClockSignal("eth_tx"))
65 # XXX Xilinx specific, replace BUFGMUX with a generic clock buffer?
66 self.specials += Instance("BUFGMUX",
67 i_I0=self.cd_eth_rx.clk,
68 i_I1=clock_pads.tx,
69 i_S=mii_mode,
70 o_O=self.cd_eth_tx.clk)
71
72 if with_hw_init_reset:
73 reset = Signal()
74 counter = Signal(max=512)
75 counter_done = Signal()
76 counter_ce = Signal()
77 self.sync += If(counter_ce, counter.eq(counter + 1))
78 self.comb += [
79 counter_done.eq(counter == 256),
80 counter_ce.eq(~counter_done),
81 reset.eq(~counter_done | self._reset.storage)
82 ]
83 else:
84 reset = self._reset.storage
85 self.comb += pads.rst_n.eq(~reset)
86 self.specials += [
87 AsyncResetSynchronizer(self.cd_eth_tx, reset),
88 AsyncResetSynchronizer(self.cd_eth_rx, reset),
89 ]
90
91
92 class LiteEthPHYGMII(Module, AutoCSR):
93 def __init__(self, clock_pads, pads, with_hw_init_reset=True):
94 self.dw = 8
95 self.submodules.crg = LiteEthPHYGMIICRG(clock_pads, pads, with_hw_init_reset)
96 self.submodules.tx = ClockDomainsRenamer("eth_tx")(LiteEthPHYGMIITX(pads))
97 self.submodules.rx = ClockDomainsRenamer("eth_rx")(LiteEthPHYGMIIRX(pads))
98 self.sink, self.source = self.tx.sink, self.rx.source