Skip to content

Commit

Permalink
phy/a7_1000basex: Add parameters to allow selecting TX/RX Clock Manag…
Browse files Browse the repository at this point in the history
…ment Modules (PLL or MMCM) and buffer types.

This is useful when using multiple instance in the design to optimize/select resources and allow build.
  • Loading branch information
enjoy-digital committed Mar 22, 2024
1 parent 1a5d935 commit 292551a
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 37 deletions.
20 changes: 14 additions & 6 deletions liteeth/gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,12 +324,20 @@ def __init__(self, platform, core_config):
qpll_channel.index = qpll_channel_index
# PHY.
ethphy = phy(
qpll_channel = qpll_channel,
data_pads = ethphy_pads,
sys_clk_freq = self.clk_freq,
with_csr = False,
rx_polarity = core_config.get("phy_rx_polarity", 0),
tx_polarity = core_config.get("phy_tx_polarity", 0),
# General.
data_pads = ethphy_pads,
sys_clk_freq = self.clk_freq,
with_csr = False,
# QPLL.
qpll_channel = qpll_channel,
# TX.
tx_cm_type = core_config.get("phy_tx_cm_type", "MMCM"),
tx_cm_buf_type = core_config.get("phy_tx_cm_buf_type", "BUFH"),
tx_polarity = core_config.get("phy_tx_polarity", 0),
# RX.
rx_cm_type = core_config.get("phy_rx_cm_type", "MMCM"),
rx_cm_buf_type = core_config.get("phy_rx_cm_buf_type", "BUFG"),
rx_polarity = core_config.get("phy_rx_polarity", 0),
)
# Other 7-Series/Ultrascale(+).
else:
Expand Down
72 changes: 41 additions & 31 deletions liteeth/phy/a7_1000basex.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

from litex.gen import *

from litex.soc.cores.clock import S7MMCM
from litex.soc.cores.clock import S7PLL, S7MMCM

from liteeth.common import *
from liteeth.phy.a7_gtp import *
Expand All @@ -25,7 +25,17 @@ class A7_1000BASEX(LiteXModule):
linerate = 1.25e9
rx_clk_freq = 125e6
tx_clk_freq = 125e6
def __init__(self, qpll_channel, data_pads, sys_clk_freq, with_csr=True, rx_polarity=0, tx_polarity=0):
def __init__(self, qpll_channel, data_pads, sys_clk_freq, with_csr=True,
# TX Parameters.
tx_cm_type = "PLL",
tx_cm_buf_type = "BUFH",
tx_polarity = 0,

# RX Parameters.
rx_cm_type = "PLL",
rx_cm_buf_type = "BUFG",
rx_polarity = 0,
):
self.pcs = pcs = PCS(lsb_first=True)

self.sink = pcs.sink
Expand All @@ -47,16 +57,16 @@ def __init__(self, qpll_channel, data_pads, sys_clk_freq, with_csr=True, rx_pola

# # #

# GTP transceiver
tx_reset = Signal()
tx_mmcm_locked = Signal()
tx_mmcm_reset = Signal(reset=1)
tx_data = Signal(20)
tx_reset_done = Signal()
# GTP transceiver.
tx_reset = Signal()
tx_cm_locked = Signal()
tx_cm_reset = Signal(reset=1)
tx_data = Signal(20)
tx_reset_done = Signal()

rx_reset = Signal()
rx_mmcm_locked = Signal()
rx_mmcm_reset = Signal(reset=1)
rx_cm_locked = Signal()
rx_cm_reset = Signal(reset=1)
rx_data = Signal(20)
rx_reset_done = Signal()
rx_pma_reset_done = Signal()
Expand Down Expand Up @@ -415,7 +425,7 @@ def __init__(self, qpll_channel, data_pads, sys_clk_freq, with_csr=True, rx_pola
i_SETERRSTATUS = 0,
# RX Initialization and Reset Ports
i_EYESCANRESET = 0,
i_RXUSERRDY = rx_mmcm_locked,
i_RXUSERRDY = rx_cm_locked,
# RX Margin Analysis Ports
o_EYESCANDATAERROR = Open(),
i_EYESCANMODE = 0,
Expand Down Expand Up @@ -571,7 +581,7 @@ def __init__(self, qpll_channel, data_pads, sys_clk_freq, with_csr=True, rx_pola
i_CFGRESET = 0,
i_GTTXRESET = tx_reset,
o_PCSRSVDOUT = Open(),
i_TXUSERRDY = tx_mmcm_locked,
i_TXUSERRDY = tx_cm_locked,
# TX Phase Interpolator PPM Controller Ports
i_TXPIPPMEN = 0,
i_TXPIPPMOVRDEN = 0,
Expand Down Expand Up @@ -702,21 +712,21 @@ def __init__(self, qpll_channel, data_pads, sys_clk_freq, with_csr=True, rx_pola
o_O = rxoutclk_rebuffer
)

# TX MMCM.
self.tx_mmcm = tx_mmcm = S7MMCM()
tx_mmcm.register_clkin(txoutclk_rebuffer, self.tx_clk_freq/2)
tx_mmcm.create_clkout(self.cd_eth_tx_half, self.tx_clk_freq/2, buf="bufh", with_reset=False)
tx_mmcm.create_clkout(self.cd_eth_tx, self.tx_clk_freq, buf="bufh", with_reset=True)
self.comb += tx_mmcm.reset.eq(tx_mmcm_reset)
self.comb += tx_mmcm_locked.eq(tx_mmcm.locked)

# RX MMCM.
self.rx_mmcm = rx_mmcm = S7MMCM()
rx_mmcm.register_clkin(rxoutclk_rebuffer, self.rx_clk_freq/2)
rx_mmcm.create_clkout(self.cd_eth_rx_half, self.rx_clk_freq/2, buf="bufg", with_reset=False)
rx_mmcm.create_clkout(self.cd_eth_rx, self.rx_clk_freq, buf="bufg", with_reset=True)
self.comb += rx_mmcm.reset.eq(rx_mmcm_reset)
self.comb += rx_mmcm_locked.eq(rx_mmcm.locked)
# TX CM.
self.tx_cm = tx_cm = {"PLL": S7PLL, "MMCM": S7MMCM}[tx_cm_type]()
tx_cm.register_clkin(txoutclk_rebuffer, self.tx_clk_freq/2)
tx_cm.create_clkout(self.cd_eth_tx_half, self.tx_clk_freq/2, buf=tx_cm_buf_type, with_reset=False)
tx_cm.create_clkout(self.cd_eth_tx, self.tx_clk_freq, buf=tx_cm_buf_type, with_reset=True)
self.comb += tx_cm.reset.eq(tx_cm_reset)
self.comb += tx_cm_locked.eq(tx_cm.locked)

# RX CM.
self.rx_cm = rx_cm = {"PLL": S7PLL, "MMCM": S7MMCM}[rx_cm_type]()
rx_cm.register_clkin(rxoutclk_rebuffer, self.rx_clk_freq/2)
rx_cm.create_clkout(self.cd_eth_rx_half, self.rx_clk_freq/2, buf=rx_cm_buf_type, with_reset=False)
rx_cm.create_clkout(self.cd_eth_rx, self.rx_clk_freq, buf=rx_cm_buf_type, with_reset=True)
self.comb += rx_cm.reset.eq(rx_cm_reset)
self.comb += rx_cm_locked.eq(rx_cm.locked)

# Transceiver init
self.tx_init = tx_init = GTPTxInit(sys_clk_freq)
Expand All @@ -725,8 +735,8 @@ def __init__(self, qpll_channel, data_pads, sys_clk_freq, with_csr=True, rx_pola
tx_init.qpll_lock.eq(qpll_channel.lock),
tx_reset.eq(tx_init.tx_reset | self.reset)
]
self.sync += tx_mmcm_reset.eq(~qpll_channel.lock)
tx_mmcm_reset.attr.add("no_retiming")
self.sync += tx_cm_reset.eq(~qpll_channel.lock)
tx_cm_reset.attr.add("no_retiming")

self.rx_init = rx_init = GTPRxInit(sys_clk_freq)
self.comb += [
Expand Down Expand Up @@ -761,9 +771,9 @@ def __init__(self, qpll_channel, data_pads, sys_clk_freq, with_csr=True, rx_pola
).Else(
cdr_locked.eq(1)
),
rx_mmcm_reset.eq(~cdr_locked)
rx_cm_reset.eq(~cdr_locked)
]
rx_mmcm_reset.attr.add("no_retiming")
rx_cm_reset.attr.add("no_retiming")

# Gearbox and PCS connection
self.gearbox = gearbox = PCSGearbox()
Expand Down

0 comments on commit 292551a

Please sign in to comment.