1f312aceb549d256b2f8514916cb5601e99ed9d1
[litex.git] / litex / soc / misoc / cores / liteeth_mini / phy / s6rgmii.py
1 # RGMII PHY for Spartan-6
2
3 from migen import *
4 from migen.genlib.io import DDROutput
5 from migen.genlib.misc import WaitTimer
6 from migen.genlib.fsm import FSM, NextState
7
8 from misoc.interconnect.stream import *
9 from misoc.interconnect.csr import *
10 from misoc.cores.liteeth_mini.common import *
11
12
13 class LiteEthPHYRGMIITX(Module):
14 def __init__(self, pads, pads_register=True):
15 self.sink = sink = Sink(eth_phy_description(8))
16
17 # # #
18
19 self.specials += Instance("ODDR2",
20 p_DDR_ALIGNMENT="C0", p_INIT=0, p_SRTYPE="ASYNC",
21 i_C0=ClockSignal("eth_tx"), i_C1=~ClockSignal("eth_tx"),
22 i_CE=1, i_S=0, i_R=0,
23 i_D0=sink.stb, i_D1=sink.stb, o_Q=pads.tx_ctl,
24 )
25 for i in range(4):
26 self.specials += Instance("ODDR2",
27 p_DDR_ALIGNMENT="C0", p_INIT=0, p_SRTYPE="ASYNC",
28 i_C0=ClockSignal("eth_tx"), i_C1=~ClockSignal("eth_tx"),
29 i_CE=1, i_S=0, i_R=0,
30 i_D0=sink.data[i], i_D1=sink.data[4+i], o_Q=pads.tx_data[i],
31 )
32 self.comb += sink.ack.eq(1)
33
34
35 class LiteEthPHYRGMIIRX(Module):
36 def __init__(self, pads):
37 self.source = source = Source(eth_phy_description(8))
38
39 # # #
40
41 rx_ctl = Signal()
42 rx_data = Signal(8)
43
44 self.specials += Instance("IDDR2",
45 p_DDR_ALIGNMENT="C0", p_INIT_Q0=0, p_INIT_Q1=0, p_SRTYPE="ASYNC",
46 i_C0=ClockSignal("eth_rx"), i_C1=~ClockSignal("eth_rx"),
47 i_CE=1, i_S=0, i_R=0,
48 i_D=pads.rx_ctl, o_Q1=rx_ctl,
49 )
50 for i in range(4):
51 self.specials += Instance("IDDR2",
52 p_DDR_ALIGNMENT="C0", p_INIT_Q0=0, p_INIT_Q1=0, p_SRTYPE="ASYNC",
53 i_C0=ClockSignal("eth_rx"), i_C1=~ClockSignal("eth_rx"),
54 i_CE=1, i_S=0, i_R=0,
55 i_D=pads.rx_data[i], o_Q0=rx_data[4+i], o_Q1=rx_data[i],
56 )
57
58
59 rx_ctl_d = Signal()
60 self.sync += rx_ctl_d.eq(rx_ctl)
61
62 sop = Signal()
63 eop = Signal()
64 self.comb += [
65 sop.eq(rx_ctl & ~rx_ctl_d),
66 eop.eq(~rx_ctl & rx_ctl_d)
67 ]
68 self.sync += [
69 source.stb.eq(rx_ctl),
70 source.sop.eq(sop),
71 source.data.eq(rx_data)
72 ]
73 self.comb += source.eop.eq(eop)
74
75
76 class LiteEthPHYRGMIICRG(Module, AutoCSR):
77 def __init__(self, clock_pads, pads, with_hw_init_reset):
78 self._reset = CSRStorage()
79
80 # # #
81
82 self.clock_domains.cd_eth_rx = ClockDomain()
83 self.clock_domains.cd_eth_tx = ClockDomain()
84
85
86 # RX
87 dcm_reset = Signal()
88 dcm_locked = Signal()
89
90 timer = WaitTimer(1024)
91 fsm = FSM(reset_state="DCM_RESET")
92 self.submodules += timer, fsm
93
94 fsm.act("DCM_RESET",
95 dcm_reset.eq(1),
96 timer.wait.eq(1),
97 If(timer.done,
98 timer.wait.eq(0),
99 NextState("DCM_WAIT")
100 )
101 )
102 fsm.act("DCM_WAIT",
103 timer.wait.eq(1),
104 If(timer.done,
105 NextState("DCM_CHECK_LOCK")
106 )
107 )
108 fsm.act("DCM_CHECK_LOCK",
109 If(~dcm_locked,
110 NextState("DCM_RESET")
111 )
112 )
113
114 clk90_rx = Signal()
115 clk0_rx = Signal()
116 clk0_rx_bufg = Signal()
117 self.specials += Instance("DCM",
118 i_CLKIN=clock_pads.rx,
119 i_CLKFB=clk0_rx_bufg,
120 o_CLK0=clk0_rx,
121 o_CLK90=clk90_rx,
122 o_LOCKED=dcm_locked,
123 i_PSEN=0,
124 i_PSCLK=0,
125 i_PSINCDEC=0,
126 i_RST=dcm_reset
127 )
128
129 self.specials += Instance("BUFG", i_I=clk0_rx, o_O=clk0_rx_bufg)
130 self.specials += Instance("BUFG", i_I=clk90_rx, o_O=self.cd_eth_rx.clk)
131
132 # TX
133 self.specials += DDROutput(1, 0, clock_pads.tx, ClockSignal("eth_tx"))
134 self.specials += Instance("BUFG", i_I=self.cd_eth_rx.clk, o_O=self.cd_eth_tx.clk)
135
136 # Reset
137 if with_hw_init_reset:
138 reset = Signal()
139 counter_done = Signal()
140 self.submodules.counter = counter = Counter(max=512)
141 self.comb += [
142 counter_done.eq(counter.value == 256),
143 counter.ce.eq(~counter_done),
144 reset.eq(~counter_done | self._reset.storage)
145 ]
146 else:
147 reset = self._reset.storage
148 self.comb += pads.rst_n.eq(~reset)
149 self.specials += [
150 AsyncResetSynchronizer(self.cd_eth_tx, reset),
151 AsyncResetSynchronizer(self.cd_eth_rx, reset),
152 ]
153
154
155 class LiteEthPHYRGMII(Module, AutoCSR):
156 def __init__(self, clock_pads, pads, with_hw_init_reset=True):
157 self.dw = 8
158 self.submodules.crg = LiteEthPHYRGMIICRG(clock_pads, pads, with_hw_init_reset)
159 self.submodules.tx = ClockDomainsRenamer("eth_tx")(LiteEthPHYRGMIITX(pads))
160 self.submodules.rx = ClockDomainsRenamer("eth_rx")(LiteEthPHYRGMIIRX(pads))
161 self.sink, self.source = self.tx.sink, self.rx.source