Skip to content

Commit 4b8d9b6

Browse files
committedAug 4, 2015
liteeth: add rgmii phy
1 parent c03ef52 commit 4b8d9b6

File tree

2 files changed

+164
-0
lines changed

2 files changed

+164
-0
lines changed
 

Diff for: ‎misoclib/com/liteeth/phy/__init__.py

+4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ def LiteEthPHY(clock_pads, pads, **kwargs):
1616
# This is a pure 1G PHY
1717
from misoclib.com.liteeth.phy.gmii import LiteEthPHYGMII
1818
return LiteEthPHYGMII(clock_pads, pads, **kwargs)
19+
elif hasattr(pads, "rx_ctl"):
20+
# This is a 10/100/1G RGMII PHY
21+
from misoclib.com.liteeth.phy.rgmii import LiteEthPHYRGMII
22+
return LiteEthPHYRGMII(clock_pads, pads, **kwargs)
1923
elif flen(pads.tx_data) == 4:
2024
# This is a MII PHY
2125
from misoclib.com.liteeth.phy.mii import LiteEthPHYMII

Diff for: ‎misoclib/com/liteeth/phy/rgmii.py

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

0 commit comments

Comments
 (0)