phy/ecp5rgmii.py: Add support for dynamic link speeds
This commit is contained in:
parent
64cceb24b1
commit
82d5f641e5
|
@ -8,6 +8,8 @@
|
||||||
# Copyright (c) 2023 LumiGuide Fietsdetectie B.V. <goemansrowan@gmail.com>
|
# Copyright (c) 2023 LumiGuide Fietsdetectie B.V. <goemansrowan@gmail.com>
|
||||||
# SPDX-License-Identifier: BSD-2-Clause
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
|
||||||
|
import math
|
||||||
|
|
||||||
from liteeth.common import *
|
from liteeth.common import *
|
||||||
from liteeth.mac import gap, preamble, crc, padding, last_be
|
from liteeth.mac import gap, preamble, crc, padding, last_be
|
||||||
from liteeth.phy.model import LiteEthPHYModel
|
from liteeth.phy.model import LiteEthPHYModel
|
||||||
|
@ -103,7 +105,14 @@ class LiteEthMACCore(Module, AutoCSR):
|
||||||
self.pipeline.append(tx_preamble)
|
self.pipeline.append(tx_preamble)
|
||||||
|
|
||||||
def add_gap(self):
|
def add_gap(self):
|
||||||
tx_gap = gap.LiteEthMACGap(phy_dw)
|
# Some phys, ECP5 for example, have a byte time enable to support
|
||||||
|
# dynamic link speeds.
|
||||||
|
# In the gap inserter we need to ensure this is enable holds for
|
||||||
|
# the gap counter. If not we would insert a gap that might be too
|
||||||
|
# short.
|
||||||
|
default_gap = Constant(math.ceil(eth_interpacket_gap/(phy_dw//8)))
|
||||||
|
gap_len = getattr(phy, "gap", default_gap)
|
||||||
|
tx_gap = gap.LiteEthMACGap(phy_dw, gap_len)
|
||||||
tx_gap = ClockDomainsRenamer("eth_tx")(tx_gap)
|
tx_gap = ClockDomainsRenamer("eth_tx")(tx_gap)
|
||||||
self.submodules += tx_gap
|
self.submodules += tx_gap
|
||||||
self.pipeline.append(tx_gap)
|
self.pipeline.append(tx_gap)
|
||||||
|
|
|
@ -4,35 +4,33 @@
|
||||||
# Copyright (c) 2015-2021 Florent Kermarrec <florent@enjoy-digital.fr>
|
# Copyright (c) 2015-2021 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||||
# Copyright (c) 2015-2017 Sebastien Bourdeauducq <sb@m-labs.hk>
|
# Copyright (c) 2015-2017 Sebastien Bourdeauducq <sb@m-labs.hk>
|
||||||
# Copyright (c) 2018 whitequark <whitequark@whitequark.org>
|
# Copyright (c) 2018 whitequark <whitequark@whitequark.org>
|
||||||
|
# Copyright (c) 2023 LumiGuide Fietsdetectie B.V. <goemansrowan@gmail.com>
|
||||||
# SPDX-License-Identifier: BSD-2-Clause
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
|
||||||
import math
|
|
||||||
|
|
||||||
from liteeth.common import *
|
from liteeth.common import *
|
||||||
|
|
||||||
# MAC Gap ------------------------------------------------------------------------------------------
|
# MAC Gap ------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
class LiteEthMACGap(Module):
|
class LiteEthMACGap(Module):
|
||||||
def __init__(self, dw):
|
def __init__(self, dw, gap=None):
|
||||||
self.sink = sink = stream.Endpoint(eth_phy_description(dw))
|
self.sink = sink = stream.Endpoint(eth_phy_description(dw))
|
||||||
self.source = source = stream.Endpoint(eth_phy_description(dw))
|
self.source = source = stream.Endpoint(eth_phy_description(dw))
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
counter_bits, _ = value_bits_sign(gap)
|
||||||
gap = math.ceil(eth_interpacket_gap/(dw//8))
|
counter = Signal(max=2**counter_bits, reset_less=True)
|
||||||
counter = Signal(max=gap, reset_less=True)
|
|
||||||
|
|
||||||
self.submodules.fsm = fsm = FSM(reset_state="COPY")
|
self.submodules.fsm = fsm = FSM(reset_state="COPY")
|
||||||
fsm.act("COPY",
|
fsm.act("COPY",
|
||||||
NextValue(counter, 0),
|
NextValue(counter, gap),
|
||||||
sink.connect(source),
|
sink.connect(source),
|
||||||
If(sink.valid & sink.last & sink.ready,
|
If(sink.valid & sink.last & sink.ready,
|
||||||
NextState("GAP")
|
NextState("GAP")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
fsm.act("GAP",
|
fsm.act("GAP",
|
||||||
NextValue(counter, counter + 1),
|
NextValue(counter, counter - 1),
|
||||||
If(counter == (gap-1),
|
If(counter == 1,
|
||||||
NextState("COPY")
|
NextState("COPY")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
from migen import *
|
from migen import *
|
||||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||||
|
from migen.genlib.cdc import MultiReg
|
||||||
|
|
||||||
from litex.gen import *
|
from litex.gen import *
|
||||||
|
|
||||||
|
@ -17,10 +18,44 @@ from litex.build.io import DDROutput, DDRInput
|
||||||
from liteeth.common import *
|
from liteeth.common import *
|
||||||
from liteeth.phy.common import *
|
from liteeth.phy.common import *
|
||||||
|
|
||||||
|
# LiteEth PHY RGMII LINK Status --------------------------------------------------------------------
|
||||||
|
|
||||||
|
class LiteEthOneHotLinkState(LiteXModule):
|
||||||
|
def __init__(self):
|
||||||
|
# Encode link status as one hot so we can easily use a DFF synchronizer
|
||||||
|
self.link_up = Signal(reset_less=True)
|
||||||
|
self.link_10M = Signal(reset_less=True)
|
||||||
|
self.link_100M = Signal(reset_less=True)
|
||||||
|
self.link_1G = Signal(reset_less=True)
|
||||||
|
|
||||||
|
def synchronize(self, to, cd):
|
||||||
|
return [
|
||||||
|
MultiReg(
|
||||||
|
self.link_up,
|
||||||
|
to.link_up,
|
||||||
|
cd
|
||||||
|
),
|
||||||
|
MultiReg(
|
||||||
|
self.link_1G,
|
||||||
|
to.link_1G,
|
||||||
|
cd
|
||||||
|
),
|
||||||
|
MultiReg(
|
||||||
|
self.link_100M,
|
||||||
|
to.link_100M,
|
||||||
|
cd
|
||||||
|
),
|
||||||
|
MultiReg(
|
||||||
|
self.link_10M,
|
||||||
|
to.link_10M,
|
||||||
|
cd
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
# LiteEth PHY RGMII TX -----------------------------------------------------------------------------
|
# LiteEth PHY RGMII TX -----------------------------------------------------------------------------
|
||||||
|
|
||||||
class LiteEthPHYRGMIITX(LiteXModule):
|
class LiteEthPHYRGMIITX(LiteXModule):
|
||||||
def __init__(self, pads):
|
def __init__(self, pads, linkstate=None, clk_en=None):
|
||||||
self.sink = sink = stream.Endpoint(eth_phy_description(8))
|
self.sink = sink = stream.Endpoint(eth_phy_description(8))
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
@ -28,11 +63,61 @@ class LiteEthPHYRGMIITX(LiteXModule):
|
||||||
tx_ctl_oddrx1f = Signal()
|
tx_ctl_oddrx1f = Signal()
|
||||||
tx_data_oddrx1f = Signal(4)
|
tx_data_oddrx1f = Signal(4)
|
||||||
|
|
||||||
|
valid = Signal()
|
||||||
|
data = Signal(8)
|
||||||
|
ready = Signal()
|
||||||
|
|
||||||
|
if linkstate is not None:
|
||||||
|
ready_next = Signal()
|
||||||
|
nibble_select = Signal()
|
||||||
|
|
||||||
|
# If link speed is not 1G we need to take care
|
||||||
|
# that the DDR lines only transfer 4-bit of data at a time
|
||||||
|
# This means we need to provide back pressure on non-1G link speeds
|
||||||
|
self.sync += If(clk_en,
|
||||||
|
ready_next.eq(~ready_next & sink.valid)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.sync += If(linkstate.link_1G,
|
||||||
|
data.eq(sink.data)
|
||||||
|
).Elif(clk_en & nibble_select,
|
||||||
|
data.eq(Cat(sink.data[4:8], sink.data[4:8]))
|
||||||
|
).Elif(clk_en,
|
||||||
|
data.eq(Cat(sink.data[0:4], sink.data[0:4]))
|
||||||
|
)
|
||||||
|
|
||||||
|
self.sync += If(clk_en,
|
||||||
|
valid.eq(sink.valid)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.sync += If(linkstate.link_1G,
|
||||||
|
ready.eq(1),
|
||||||
|
).Elif(clk_en,
|
||||||
|
ready.eq(ready_next)
|
||||||
|
).Else(
|
||||||
|
ready.eq(0)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.sync += If(linkstate.link_1G,
|
||||||
|
nibble_select.eq(0)
|
||||||
|
).Elif(clk_en & sink.valid,
|
||||||
|
nibble_select.eq(~nibble_select)
|
||||||
|
).Else(
|
||||||
|
nibble_select.eq(nibble_select)
|
||||||
|
)
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.comb += [
|
||||||
|
ready.eq(1),
|
||||||
|
valid.eq(sink.valid),
|
||||||
|
data.eq(sink.data)
|
||||||
|
]
|
||||||
|
|
||||||
self.specials += [
|
self.specials += [
|
||||||
DDROutput(
|
DDROutput(
|
||||||
clk = ClockSignal("eth_tx"),
|
clk = ClockSignal("eth_tx"),
|
||||||
i1 = sink.valid,
|
i1 = valid,
|
||||||
i2 = sink.valid,
|
i2 = valid,
|
||||||
o = tx_ctl_oddrx1f,
|
o = tx_ctl_oddrx1f,
|
||||||
),
|
),
|
||||||
Instance("DELAYG",
|
Instance("DELAYG",
|
||||||
|
@ -46,8 +131,8 @@ class LiteEthPHYRGMIITX(LiteXModule):
|
||||||
self.specials += [
|
self.specials += [
|
||||||
DDROutput(
|
DDROutput(
|
||||||
clk = ClockSignal("eth_tx"),
|
clk = ClockSignal("eth_tx"),
|
||||||
i1 = sink.data[i],
|
i1 = data[i],
|
||||||
i2 = sink.data[4+i],
|
i2 = data[4+i],
|
||||||
o = tx_data_oddrx1f[i],
|
o = tx_data_oddrx1f[i],
|
||||||
),
|
),
|
||||||
Instance("DELAYG",
|
Instance("DELAYG",
|
||||||
|
@ -57,12 +142,12 @@ class LiteEthPHYRGMIITX(LiteXModule):
|
||||||
o_Z = pads.tx_data[i],
|
o_Z = pads.tx_data[i],
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
self.comb += sink.ready.eq(1)
|
self.comb += sink.ready.eq(ready)
|
||||||
|
|
||||||
# LiteEth PHY RGMII RX -----------------------------------------------------------------------------
|
# LiteEth PHY RGMII RX -----------------------------------------------------------------------------
|
||||||
|
|
||||||
class LiteEthPHYRGMIIRX(LiteXModule):
|
class LiteEthPHYRGMIIRX(LiteXModule):
|
||||||
def __init__(self, pads, rx_delay=2e-9, with_inband_status=True):
|
def __init__(self, pads, rx_delay=2e-9, with_inband_status=True, linkstate=None):
|
||||||
self.source = source = stream.Endpoint(eth_phy_description(8))
|
self.source = source = stream.Endpoint(eth_phy_description(8))
|
||||||
|
|
||||||
if with_inband_status:
|
if with_inband_status:
|
||||||
|
@ -123,15 +208,46 @@ class LiteEthPHYRGMIIRX(LiteXModule):
|
||||||
o2 = rx_data[i+4],
|
o2 = rx_data[i+4],
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
self.sync += rx_data_reg.eq(rx_data)
|
|
||||||
|
|
||||||
rx_ctl_reg_d = Signal(2)
|
# 1G has DDR, 100m and 10m are SDR on Rising edge only
|
||||||
self.sync += rx_ctl_reg_d.eq(rx_ctl_reg)
|
valid_reg = Signal()
|
||||||
|
valid_last0 = Signal()
|
||||||
|
valid_last1 = Signal()
|
||||||
|
|
||||||
|
if linkstate is not None:
|
||||||
|
valid_sdr = Signal()
|
||||||
|
|
||||||
|
self.sync += If(linkstate.link_1G,
|
||||||
|
rx_data_reg.eq(rx_data),
|
||||||
|
).Else(
|
||||||
|
rx_data_reg.eq(Cat(rx_data_reg[4:8], rx_data[0:4])),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.sync += If(linkstate.link_1G,
|
||||||
|
valid_sdr.eq(0),
|
||||||
|
valid_reg.eq(rx_ctl[0])
|
||||||
|
).Elif(rx_ctl[0],
|
||||||
|
valid_sdr.eq(~valid_sdr),
|
||||||
|
valid_reg.eq(valid_sdr)
|
||||||
|
).Else(
|
||||||
|
valid_reg.eq(valid_sdr)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.sync += valid_last0.eq(rx_ctl[0])
|
||||||
|
else:
|
||||||
|
self.sync += [
|
||||||
|
rx_data_reg.eq(rx_data),
|
||||||
|
valid_reg.eq(rx_ctl[0])
|
||||||
|
]
|
||||||
|
|
||||||
|
self.comb += valid_last0.eq(valid_reg)
|
||||||
|
|
||||||
|
self.sync += valid_last1.eq(valid_last0)
|
||||||
|
|
||||||
last = Signal()
|
last = Signal()
|
||||||
self.comb += last.eq(~rx_ctl_reg[0] & rx_ctl_reg_d[0])
|
self.comb += last.eq(~valid_last0 & valid_last1)
|
||||||
self.sync += [
|
self.sync += [
|
||||||
source.valid.eq(rx_ctl_reg[0]),
|
source.valid.eq(valid_reg),
|
||||||
source.data.eq(rx_data_reg)
|
source.data.eq(rx_data_reg)
|
||||||
]
|
]
|
||||||
self.comb += source.last.eq(last)
|
self.comb += source.last.eq(last)
|
||||||
|
@ -142,13 +258,17 @@ class LiteEthPHYRGMIIRX(LiteXModule):
|
||||||
self.inband_status.fields.link_status.eq( rx_data[0]),
|
self.inband_status.fields.link_status.eq( rx_data[0]),
|
||||||
self.inband_status.fields.clock_speed.eq( rx_data[1:3]),
|
self.inband_status.fields.clock_speed.eq( rx_data[1:3]),
|
||||||
self.inband_status.fields.duplex_status.eq(rx_data[3]),
|
self.inband_status.fields.duplex_status.eq(rx_data[3]),
|
||||||
|
linkstate.link_up.eq(rx_data[0]),
|
||||||
|
linkstate.link_10M.eq(rx_data[1:3] == 0b00),
|
||||||
|
linkstate.link_100M.eq(rx_data[1:3] == 0b01),
|
||||||
|
linkstate.link_1G.eq(rx_data[1:3] == 0b10),
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
# LiteEth PHY RGMII CRG ----------------------------------------------------------------------------
|
# LiteEth PHY RGMII CRG ----------------------------------------------------------------------------
|
||||||
|
|
||||||
class LiteEthPHYRGMIICRG(LiteXModule):
|
class LiteEthPHYRGMIICRG(LiteXModule):
|
||||||
def __init__(self, clock_pads, pads, with_hw_init_reset, tx_delay=2e-9, tx_clk=None):
|
def __init__(self, clock_pads, pads, with_hw_init_reset, tx_delay=2e-9, tx_clk=None, linkstate_rx=None, linkstate_tx=None):
|
||||||
self._reset = CSRStorage()
|
self._reset = CSRStorage()
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
@ -167,12 +287,76 @@ class LiteEthPHYRGMIICRG(LiteXModule):
|
||||||
tx_delay_taps = int(tx_delay/25e-12) # 25ps per tap
|
tx_delay_taps = int(tx_delay/25e-12) # 25ps per tap
|
||||||
assert tx_delay_taps < 128
|
assert tx_delay_taps < 128
|
||||||
|
|
||||||
|
self.tx_clk_en = Signal(reset_less=True)
|
||||||
|
rising_edge = Signal()
|
||||||
|
falling_edge = Signal()
|
||||||
|
|
||||||
|
# Without loop-clocking we need to divide the 125Mhz clock
|
||||||
|
# into either 25Mhz or 2.5Mhz. Some Phys require the clock to
|
||||||
|
# be glitchless
|
||||||
|
if linkstate_rx is not None and tx_clk is not None:
|
||||||
|
with_switch = Signal()
|
||||||
|
counter_switch = Signal(5)
|
||||||
|
counter = Signal(6)
|
||||||
|
counter_rst = Signal(1)
|
||||||
|
|
||||||
|
self.comb += counter_rst.eq(counter == 0)
|
||||||
|
|
||||||
|
# clock divider for 100M and 10M
|
||||||
|
self.sync.eth_tx += If(counter_rst,
|
||||||
|
If(linkstate_tx.link_10M,
|
||||||
|
with_switch.eq(0),
|
||||||
|
counter_switch.eq(24),
|
||||||
|
counter.eq(49)
|
||||||
|
).Elif(linkstate_tx.link_100M,
|
||||||
|
with_switch.eq(1),
|
||||||
|
counter_switch.eq(2),
|
||||||
|
counter.eq(4)
|
||||||
|
).Else(
|
||||||
|
with_switch.eq(1),
|
||||||
|
counter_switch.eq(0),
|
||||||
|
counter.eq(0)
|
||||||
|
)
|
||||||
|
).Else(
|
||||||
|
counter.eq(counter - 1)
|
||||||
|
)
|
||||||
|
|
||||||
|
at_switch = Signal()
|
||||||
|
self.comb += at_switch.eq(counter == counter_switch)
|
||||||
|
|
||||||
|
self.sync.eth_tx += If(with_switch & at_switch,
|
||||||
|
rising_edge.eq(1),
|
||||||
|
falling_edge.eq(0),
|
||||||
|
).Elif(counter > counter_switch,
|
||||||
|
rising_edge.eq(1),
|
||||||
|
falling_edge.eq(1),
|
||||||
|
).Else(
|
||||||
|
rising_edge.eq(0),
|
||||||
|
falling_edge.eq(0)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.sync.eth_tx += self.tx_clk_en.eq(counter == 0)
|
||||||
|
|
||||||
|
# When loop clocking we don't need to divide the tx clock since it will
|
||||||
|
# allready be at the correct speed.
|
||||||
|
elif linkstate_rx is not None:
|
||||||
|
self.comb += [
|
||||||
|
self.tx_clk_en.eq(1),
|
||||||
|
rising_edge.eq(1),
|
||||||
|
falling_edge.eq(0)
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
self.comb += [
|
||||||
|
rising_edge.eq(1),
|
||||||
|
falling_edge.eq(0)
|
||||||
|
]
|
||||||
|
|
||||||
eth_tx_clk_o = Signal()
|
eth_tx_clk_o = Signal()
|
||||||
self.specials += [
|
self.specials += [
|
||||||
DDROutput(
|
DDROutput(
|
||||||
clk = ClockSignal("eth_tx"),
|
clk = ClockSignal("eth_tx"),
|
||||||
i1 = 1,
|
i1 = rising_edge,
|
||||||
i2 = 0,
|
i2 = falling_edge,
|
||||||
o = eth_tx_clk_o,
|
o = eth_tx_clk_o,
|
||||||
),
|
),
|
||||||
Instance("DELAYG",
|
Instance("DELAYG",
|
||||||
|
@ -207,11 +391,70 @@ class LiteEthPHYRGMII(LiteXModule):
|
||||||
rx_delay = 2e-9,
|
rx_delay = 2e-9,
|
||||||
with_inband_status = True,
|
with_inband_status = True,
|
||||||
tx_clk = None,
|
tx_clk = None,
|
||||||
|
linkstate = None
|
||||||
):
|
):
|
||||||
self.crg = LiteEthPHYRGMIICRG(clock_pads, pads, with_hw_init_reset, tx_delay, tx_clk)
|
|
||||||
self.tx = ClockDomainsRenamer("eth_tx")(LiteEthPHYRGMIITX(pads))
|
# We cannot have two sources of linkstate
|
||||||
self.rx = ClockDomainsRenamer("eth_rx")(LiteEthPHYRGMIIRX(pads, rx_delay, with_inband_status))
|
assert not (linkstate is not None and with_inband_status)
|
||||||
|
|
||||||
|
linkstate_rx = None
|
||||||
|
linkstate_tx = None
|
||||||
|
if linkstate or with_inband_status:
|
||||||
|
linkstate_rx = LiteEthOneHotLinkState()
|
||||||
|
|
||||||
|
# If we have a source of link state from sys we need to sync it to rx clk
|
||||||
|
if linkstate:
|
||||||
|
self.specials += linkstate.synchronize(linkstate_rx, "eth_rx")
|
||||||
|
|
||||||
|
|
||||||
|
self.rx = ClockDomainsRenamer("eth_rx")(LiteEthPHYRGMIIRX(
|
||||||
|
pads, rx_delay, with_inband_status,
|
||||||
|
linkstate=linkstate_rx
|
||||||
|
))
|
||||||
|
|
||||||
|
if linkstate_rx is not None:
|
||||||
|
linkstate_tx = linkstate_rx
|
||||||
|
# If we aren't loop clocking the tx is clock is different from the rx
|
||||||
|
# clock and we need to synchronize
|
||||||
|
if tx_clk is not None:
|
||||||
|
linkstate_src = linkstate if linkstate is not None else linkstate_rx
|
||||||
|
linkstate_tx = LiteEthOneHotLinkState()
|
||||||
|
self.specials += linkstate_src.synchronize(linkstate_tx, "eth_tx")
|
||||||
|
|
||||||
|
if linkstate is None:
|
||||||
|
linkstate = LiteEthOneHotLinkState()
|
||||||
|
self.specials += linkstate_rx.synchronize(linkstate, "sys")
|
||||||
|
|
||||||
|
self.crg = LiteEthPHYRGMIICRG(
|
||||||
|
clock_pads, pads, with_hw_init_reset, tx_delay, tx_clk,
|
||||||
|
linkstate_rx, linkstate_tx
|
||||||
|
)
|
||||||
|
|
||||||
|
self.tx = ClockDomainsRenamer("eth_tx")(LiteEthPHYRGMIITX(
|
||||||
|
pads, linkstate=linkstate_rx, clk_en = self.crg.tx_clk_en
|
||||||
|
))
|
||||||
self.sink, self.source = self.tx.sink, self.rx.source
|
self.sink, self.source = self.tx.sink, self.rx.source
|
||||||
|
|
||||||
|
# Create a custom gap length to paper over transmit clock and Phy
|
||||||
|
# internal clock periods beeing different
|
||||||
|
if linkstate is not None and tx_clk is not None:
|
||||||
|
self.gap = Signal(max=eth_interpacket_gap*100, reset_less = True)
|
||||||
|
|
||||||
|
self.sync += If(linkstate.link_1G,
|
||||||
|
self.gap.eq(eth_interpacket_gap)
|
||||||
|
).Elif(linkstate.link_100M,
|
||||||
|
self.gap.eq(eth_interpacket_gap*10)
|
||||||
|
).Else(
|
||||||
|
self.gap.eq(eth_interpacket_gap*100)
|
||||||
|
)
|
||||||
|
elif linkstate is not None:
|
||||||
|
self.gap = Signal(max=eth_interpacket_gap*2, reset_less = True)
|
||||||
|
|
||||||
|
self.sync += If(linkstate.link_1G,
|
||||||
|
self.gap.eq(eth_interpacket_gap)
|
||||||
|
).Else(
|
||||||
|
self.gap.eq(eth_interpacket_gap*2)
|
||||||
|
)
|
||||||
|
|
||||||
if hasattr(pads, "mdc"):
|
if hasattr(pads, "mdc"):
|
||||||
self.mdio = LiteEthPHYMDIO(pads)
|
self.mdio = LiteEthPHYMDIO(pads)
|
||||||
|
|
Loading…
Reference in New Issue