phy/a7_1000basex: Add parameters to allow selecting TX/RX Clock Managment Modules (PLL or MMCM) and buffer types.

This is useful when using multiple instance in the design to optimize/select resources and allow build.
This commit is contained in:
Florent Kermarrec 2024-03-22 12:28:24 +01:00
parent 1a5d93509b
commit 292551a0f1
2 changed files with 54 additions and 36 deletions

View File

@ -324,12 +324,20 @@ class PHYCore(SoCMini):
qpll_channel.index = qpll_channel_index qpll_channel.index = qpll_channel_index
# PHY. # PHY.
ethphy = phy( ethphy = phy(
qpll_channel = qpll_channel, # General.
data_pads = ethphy_pads, data_pads = ethphy_pads,
sys_clk_freq = self.clk_freq, sys_clk_freq = self.clk_freq,
with_csr = False, with_csr = False,
rx_polarity = core_config.get("phy_rx_polarity", 0), # 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), 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(+). # Other 7-Series/Ultrascale(+).
else: else:

View File

@ -12,7 +12,7 @@ from migen.genlib.cdc import PulseSynchronizer
from litex.gen import * 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.common import *
from liteeth.phy.a7_gtp import * from liteeth.phy.a7_gtp import *
@ -25,7 +25,17 @@ class A7_1000BASEX(LiteXModule):
linerate = 1.25e9 linerate = 1.25e9
rx_clk_freq = 125e6 rx_clk_freq = 125e6
tx_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.pcs = pcs = PCS(lsb_first=True)
self.sink = pcs.sink self.sink = pcs.sink
@ -47,16 +57,16 @@ class A7_1000BASEX(LiteXModule):
# # # # # #
# GTP transceiver # GTP transceiver.
tx_reset = Signal() tx_reset = Signal()
tx_mmcm_locked = Signal() tx_cm_locked = Signal()
tx_mmcm_reset = Signal(reset=1) tx_cm_reset = Signal(reset=1)
tx_data = Signal(20) tx_data = Signal(20)
tx_reset_done = Signal() tx_reset_done = Signal()
rx_reset = Signal() rx_reset = Signal()
rx_mmcm_locked = Signal() rx_cm_locked = Signal()
rx_mmcm_reset = Signal(reset=1) rx_cm_reset = Signal(reset=1)
rx_data = Signal(20) rx_data = Signal(20)
rx_reset_done = Signal() rx_reset_done = Signal()
rx_pma_reset_done = Signal() rx_pma_reset_done = Signal()
@ -415,7 +425,7 @@ class A7_1000BASEX(LiteXModule):
i_SETERRSTATUS = 0, i_SETERRSTATUS = 0,
# RX Initialization and Reset Ports # RX Initialization and Reset Ports
i_EYESCANRESET = 0, i_EYESCANRESET = 0,
i_RXUSERRDY = rx_mmcm_locked, i_RXUSERRDY = rx_cm_locked,
# RX Margin Analysis Ports # RX Margin Analysis Ports
o_EYESCANDATAERROR = Open(), o_EYESCANDATAERROR = Open(),
i_EYESCANMODE = 0, i_EYESCANMODE = 0,
@ -571,7 +581,7 @@ class A7_1000BASEX(LiteXModule):
i_CFGRESET = 0, i_CFGRESET = 0,
i_GTTXRESET = tx_reset, i_GTTXRESET = tx_reset,
o_PCSRSVDOUT = Open(), o_PCSRSVDOUT = Open(),
i_TXUSERRDY = tx_mmcm_locked, i_TXUSERRDY = tx_cm_locked,
# TX Phase Interpolator PPM Controller Ports # TX Phase Interpolator PPM Controller Ports
i_TXPIPPMEN = 0, i_TXPIPPMEN = 0,
i_TXPIPPMOVRDEN = 0, i_TXPIPPMOVRDEN = 0,
@ -702,21 +712,21 @@ class A7_1000BASEX(LiteXModule):
o_O = rxoutclk_rebuffer o_O = rxoutclk_rebuffer
) )
# TX MMCM. # TX CM.
self.tx_mmcm = tx_mmcm = S7MMCM() self.tx_cm = tx_cm = {"PLL": S7PLL, "MMCM": S7MMCM}[tx_cm_type]()
tx_mmcm.register_clkin(txoutclk_rebuffer, self.tx_clk_freq/2) tx_cm.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_cm.create_clkout(self.cd_eth_tx_half, self.tx_clk_freq/2, buf=tx_cm_buf_type, with_reset=False)
tx_mmcm.create_clkout(self.cd_eth_tx, self.tx_clk_freq, buf="bufh", with_reset=True) tx_cm.create_clkout(self.cd_eth_tx, self.tx_clk_freq, buf=tx_cm_buf_type, with_reset=True)
self.comb += tx_mmcm.reset.eq(tx_mmcm_reset) self.comb += tx_cm.reset.eq(tx_cm_reset)
self.comb += tx_mmcm_locked.eq(tx_mmcm.locked) self.comb += tx_cm_locked.eq(tx_cm.locked)
# RX MMCM. # RX CM.
self.rx_mmcm = rx_mmcm = S7MMCM() self.rx_cm = rx_cm = {"PLL": S7PLL, "MMCM": S7MMCM}[rx_cm_type]()
rx_mmcm.register_clkin(rxoutclk_rebuffer, self.rx_clk_freq/2) rx_cm.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_cm.create_clkout(self.cd_eth_rx_half, self.rx_clk_freq/2, buf=rx_cm_buf_type, with_reset=False)
rx_mmcm.create_clkout(self.cd_eth_rx, self.rx_clk_freq, buf="bufg", with_reset=True) rx_cm.create_clkout(self.cd_eth_rx, self.rx_clk_freq, buf=rx_cm_buf_type, with_reset=True)
self.comb += rx_mmcm.reset.eq(rx_mmcm_reset) self.comb += rx_cm.reset.eq(rx_cm_reset)
self.comb += rx_mmcm_locked.eq(rx_mmcm.locked) self.comb += rx_cm_locked.eq(rx_cm.locked)
# Transceiver init # Transceiver init
self.tx_init = tx_init = GTPTxInit(sys_clk_freq) self.tx_init = tx_init = GTPTxInit(sys_clk_freq)
@ -725,8 +735,8 @@ class A7_1000BASEX(LiteXModule):
tx_init.qpll_lock.eq(qpll_channel.lock), tx_init.qpll_lock.eq(qpll_channel.lock),
tx_reset.eq(tx_init.tx_reset | self.reset) tx_reset.eq(tx_init.tx_reset | self.reset)
] ]
self.sync += tx_mmcm_reset.eq(~qpll_channel.lock) self.sync += tx_cm_reset.eq(~qpll_channel.lock)
tx_mmcm_reset.attr.add("no_retiming") tx_cm_reset.attr.add("no_retiming")
self.rx_init = rx_init = GTPRxInit(sys_clk_freq) self.rx_init = rx_init = GTPRxInit(sys_clk_freq)
self.comb += [ self.comb += [
@ -761,9 +771,9 @@ class A7_1000BASEX(LiteXModule):
).Else( ).Else(
cdr_locked.eq(1) 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 # Gearbox and PCS connection
self.gearbox = gearbox = PCSGearbox() self.gearbox = gearbox = PCSGearbox()