parent
b573e1267c
commit
ac70566ab4
|
@ -0,0 +1,798 @@
|
||||||
|
#
|
||||||
|
# This file is part of LiteEth.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2018 Sebastien Bourdeauducq <sb@m-labs.hk>
|
||||||
|
# Copyright (c) 2019-2024 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||||
|
# Copyright (c) 2024 Gustavo Bastos <gustavocerq7gmail.com>
|
||||||
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
|
||||||
|
from migen import *
|
||||||
|
from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||||
|
from migen.genlib.cdc import PulseSynchronizer
|
||||||
|
|
||||||
|
from litex.soc.cores.clock import S7MMCM
|
||||||
|
|
||||||
|
from litex.gen import *
|
||||||
|
|
||||||
|
from liteiclink.serdes.gth_7series import GTHChannelPLL, GTHTXInit, GTHRXInit
|
||||||
|
|
||||||
|
from liteeth.common import *
|
||||||
|
from liteeth.phy.pcs_1000basex import *
|
||||||
|
|
||||||
|
# V7_1000BASEX PHY ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class V7_1000BASEX(LiteXModule):
|
||||||
|
# Configured for 200MHz or 156.25MHz transceiver reference clock
|
||||||
|
dw = 8
|
||||||
|
linerate = 1.25e9
|
||||||
|
rx_clk_freq = 125e6
|
||||||
|
tx_clk_freq = 125e6
|
||||||
|
def __init__(self, refclk_or_clk_pads, data_pads, sys_clk_freq, refclk_freq=200e6, with_csr=True, rx_polarity=0, tx_polarity=0):
|
||||||
|
assert refclk_freq in [200e6, 156.25e6]
|
||||||
|
self.pcs = pcs = PCS(lsb_first=True)
|
||||||
|
|
||||||
|
self.sink = pcs.sink
|
||||||
|
self.source = pcs.source
|
||||||
|
self.link_up = pcs.link_up
|
||||||
|
|
||||||
|
self.cd_eth_tx = ClockDomain()
|
||||||
|
self.cd_eth_rx = ClockDomain()
|
||||||
|
self.cd_eth_tx_half = ClockDomain(reset_less=True)
|
||||||
|
self.cd_eth_rx_half = ClockDomain(reset_less=True)
|
||||||
|
|
||||||
|
# for specifying clock constraints. 125MHz clocks.
|
||||||
|
self.txoutclk = Signal()
|
||||||
|
self.rxoutclk = Signal()
|
||||||
|
|
||||||
|
self.reset = Signal()
|
||||||
|
if with_csr:
|
||||||
|
self.add_csr()
|
||||||
|
|
||||||
|
# # #
|
||||||
|
|
||||||
|
if isinstance(refclk_or_clk_pads, Signal):
|
||||||
|
refclk = refclk_or_clk_pads
|
||||||
|
else:
|
||||||
|
refclk = Signal()
|
||||||
|
self.specials += Instance("IBUFDS_GTE2",
|
||||||
|
i_I = refclk_or_clk_pads.p,
|
||||||
|
i_IB = refclk_or_clk_pads.n,
|
||||||
|
i_CEB = 0,
|
||||||
|
o_O = refclk,
|
||||||
|
)
|
||||||
|
|
||||||
|
pll_locked = Signal()
|
||||||
|
|
||||||
|
tx_reset = Signal()
|
||||||
|
tx_data = Signal(20)
|
||||||
|
tx_reset_done = Signal()
|
||||||
|
|
||||||
|
rx_reset = Signal()
|
||||||
|
rx_data = Signal(20)
|
||||||
|
rx_reset_done = Signal()
|
||||||
|
|
||||||
|
# GTH transceiver
|
||||||
|
tx_mmcm_locked = Signal()
|
||||||
|
tx_mmcm_reset = Signal(reset=1)
|
||||||
|
|
||||||
|
rx_mmcm_locked = Signal()
|
||||||
|
rx_mmcm_reset = Signal(reset=1)
|
||||||
|
|
||||||
|
pll = GTHChannelPLL(refclk, 200e6, self.linerate)
|
||||||
|
self.submodules.pll = pll
|
||||||
|
print(pll)
|
||||||
|
|
||||||
|
gth_params = dict(
|
||||||
|
# Simulation-Only Attributes
|
||||||
|
p_SIM_RECEIVER_DETECT_PASS = "TRUE",
|
||||||
|
p_SIM_TX_EIDLE_DRIVE_LEVEL = "X",
|
||||||
|
p_SIM_RESET_SPEEDUP = "FALSE",
|
||||||
|
p_SIM_CPLLREFCLK_SEL = "FALSE",
|
||||||
|
p_SIM_VERSION = "2.0",
|
||||||
|
|
||||||
|
# RX Byte and Word Alignment Attributes
|
||||||
|
p_ALIGN_COMMA_DOUBLE = "FALSE",
|
||||||
|
p_ALIGN_COMMA_ENABLE = 0b1111111111,
|
||||||
|
p_ALIGN_COMMA_WORD = 2,
|
||||||
|
p_ALIGN_MCOMMA_DET = "TRUE",
|
||||||
|
p_ALIGN_MCOMMA_VALUE = 0b1010000011,
|
||||||
|
p_ALIGN_PCOMMA_DET = "TRUE",
|
||||||
|
p_ALIGN_PCOMMA_VALUE = 0b0101111100,
|
||||||
|
p_SHOW_REALIGN_COMMA = "TRUE",
|
||||||
|
p_RXSLIDE_AUTO_WAIT = 7,
|
||||||
|
p_RXSLIDE_MODE = "OFF",
|
||||||
|
p_RX_SIG_VALID_DLY = 10,
|
||||||
|
|
||||||
|
# RX 8B/10B Decoder Attributes
|
||||||
|
p_RX_DISPERR_SEQ_MATCH = "TRUE",
|
||||||
|
p_DEC_MCOMMA_DETECT = "TRUE",
|
||||||
|
p_DEC_PCOMMA_DETECT = "TRUE",
|
||||||
|
p_DEC_VALID_COMMA_ONLY = "TRUE",
|
||||||
|
|
||||||
|
# RX Clock Correction Attributes
|
||||||
|
p_CBCC_DATA_SOURCE_SEL = "DECODED",
|
||||||
|
p_CLK_COR_SEQ_2_USE = "FALSE",
|
||||||
|
p_CLK_COR_KEEP_IDLE = "FALSE",
|
||||||
|
p_CLK_COR_MAX_LAT = 9,
|
||||||
|
p_CLK_COR_MIN_LAT = 7,
|
||||||
|
p_CLK_COR_PRECEDENCE = "TRUE",
|
||||||
|
p_CLK_COR_REPEAT_WAIT = 0,
|
||||||
|
p_CLK_COR_SEQ_LEN = 1,
|
||||||
|
p_CLK_COR_SEQ_1_ENABLE = 0b1111,
|
||||||
|
p_CLK_COR_SEQ_1_1 = 0b0100000000,
|
||||||
|
p_CLK_COR_SEQ_1_2 = 0b0000000000,
|
||||||
|
p_CLK_COR_SEQ_1_3 = 0b0000000000,
|
||||||
|
p_CLK_COR_SEQ_1_4 = 0b0000000000,
|
||||||
|
p_CLK_CORRECT_USE = "FALSE",
|
||||||
|
p_CLK_COR_SEQ_2_ENABLE = 0b1111,
|
||||||
|
p_CLK_COR_SEQ_2_1 = 0b0100000000,
|
||||||
|
p_CLK_COR_SEQ_2_2 = 0b0000000000,
|
||||||
|
p_CLK_COR_SEQ_2_3 = 0b0000000000,
|
||||||
|
p_CLK_COR_SEQ_2_4 = 0b0000000000,
|
||||||
|
|
||||||
|
# RX Channel Bonding Attributes
|
||||||
|
p_CHAN_BOND_KEEP_ALIGN = "FALSE",
|
||||||
|
p_CHAN_BOND_MAX_SKEW = 1,
|
||||||
|
p_CHAN_BOND_SEQ_LEN = 1,
|
||||||
|
p_CHAN_BOND_SEQ_1_1 = 0b0000000000,
|
||||||
|
p_CHAN_BOND_SEQ_1_2 = 0b0000000000,
|
||||||
|
p_CHAN_BOND_SEQ_1_3 = 0b0000000000,
|
||||||
|
p_CHAN_BOND_SEQ_1_4 = 0b0000000000,
|
||||||
|
p_CHAN_BOND_SEQ_1_ENABLE = 0b1111,
|
||||||
|
p_CHAN_BOND_SEQ_2_1 = 0b0000000000,
|
||||||
|
p_CHAN_BOND_SEQ_2_2 = 0b0000000000,
|
||||||
|
p_CHAN_BOND_SEQ_2_3 = 0b0000000000,
|
||||||
|
p_CHAN_BOND_SEQ_2_4 = 0b0000000000,
|
||||||
|
p_CHAN_BOND_SEQ_2_ENABLE = 0b1111,
|
||||||
|
p_CHAN_BOND_SEQ_2_USE = "FALSE",
|
||||||
|
p_FTS_DESKEW_SEQ_ENABLE = 0b1111,
|
||||||
|
p_FTS_LANE_DESKEW_CFG = 0b1111,
|
||||||
|
p_FTS_LANE_DESKEW_EN = "FALSE",
|
||||||
|
|
||||||
|
# RX Margin Analysis Attributes
|
||||||
|
p_ES_CONTROL = 0b000000,
|
||||||
|
p_ES_ERRDET_EN = "FALSE",
|
||||||
|
p_ES_EYE_SCAN_EN = "TRUE",
|
||||||
|
p_ES_HORZ_OFFSET = 0x000,
|
||||||
|
p_ES_PMA_CFG = 0b0000000000,
|
||||||
|
p_ES_PRESCALE = 0b00000,
|
||||||
|
p_ES_QUALIFIER = 0x00000000000000000000,
|
||||||
|
p_ES_QUAL_MASK = 0x00000000000000000000,
|
||||||
|
p_ES_SDATA_MASK = 0x00000000000000000000,
|
||||||
|
p_ES_VERT_OFFSET = 0b000000000,
|
||||||
|
|
||||||
|
# FPGA RX Interface Attributes
|
||||||
|
p_RX_DATA_WIDTH = 20,
|
||||||
|
|
||||||
|
# PMA Attributes
|
||||||
|
p_OUTREFCLK_SEL_INV = 0b11,
|
||||||
|
p_PMA_RSV = 0x001e7080,
|
||||||
|
p_PMA_RSV2 = 0x2050,
|
||||||
|
p_PMA_RSV3 = 0b00,
|
||||||
|
p_PMA_RSV4 = 0x00000000,
|
||||||
|
p_RX_BIAS_CFG = 0b000000000100,
|
||||||
|
p_DMONITOR_CFG = 0x000A00,
|
||||||
|
p_RX_CM_SEL = 0b11,
|
||||||
|
p_RX_CM_TRIM = 0b010,
|
||||||
|
p_RX_DEBUG_CFG = 0b000000000000,
|
||||||
|
p_RX_OS_CFG = 0b0000010000000,
|
||||||
|
p_TERM_RCAL_CFG = 0b10000,
|
||||||
|
p_TERM_RCAL_OVRD = 0b0,
|
||||||
|
p_TST_RSV = 0x00000000,
|
||||||
|
p_RX_CLK25_DIV = 5,
|
||||||
|
p_TX_CLK25_DIV = 5,
|
||||||
|
p_UCODEER_CLR = 0b0,
|
||||||
|
|
||||||
|
# PCI Express Attributes
|
||||||
|
p_PCS_PCIE_EN = "FALSE",
|
||||||
|
|
||||||
|
# PCS Attributes
|
||||||
|
p_PCS_RSVD_ATTR = 0x000000000000,
|
||||||
|
|
||||||
|
# RX Buffer Attributes
|
||||||
|
p_RXBUF_ADDR_MODE = "FAST",
|
||||||
|
p_RXBUF_EIDLE_HI_CNT = 0b1000,
|
||||||
|
p_RXBUF_EIDLE_LO_CNT = 0b0000,
|
||||||
|
p_RXBUF_EN = "TRUE",
|
||||||
|
p_RX_BUFFER_CFG = 0b000000,
|
||||||
|
p_RXBUF_RESET_ON_CB_CHANGE = "TRUE",
|
||||||
|
p_RXBUF_RESET_ON_COMMAALIGN = "FALSE",
|
||||||
|
p_RXBUF_RESET_ON_EIDLE = "FALSE",
|
||||||
|
p_RXBUF_RESET_ON_RATE_CHANGE = "TRUE",
|
||||||
|
p_RXBUFRESET_TIME = 0b00001,
|
||||||
|
p_RXBUF_THRESH_OVFLW = 61,
|
||||||
|
p_RXBUF_THRESH_OVRD = "FALSE",
|
||||||
|
p_RXBUF_THRESH_UNDFLW = 4,
|
||||||
|
p_RXDLY_CFG = 0x001F,
|
||||||
|
p_RXDLY_LCFG = 0x030,
|
||||||
|
p_RXDLY_TAP_CFG = 0x0000,
|
||||||
|
p_RXPH_CFG = 0x000000,
|
||||||
|
p_RXPHDLY_CFG = 0x084020,
|
||||||
|
p_RXPH_MONITOR_SEL = 0b00000,
|
||||||
|
p_RX_XCLK_SEL = "RXREC",
|
||||||
|
p_RX_DDI_SEL = 0b000000,
|
||||||
|
p_RX_DEFER_RESET_BUF_EN = "TRUE",
|
||||||
|
|
||||||
|
# CDR Attributes
|
||||||
|
p_RXCDR_CFG = 0x03000023ff10100020, # FIXME: Add 2.5Gbps config.
|
||||||
|
p_RXCDR_FR_RESET_ON_EIDLE = 0b0,
|
||||||
|
p_RXCDR_HOLD_DURING_EIDLE = 0b0,
|
||||||
|
p_RXCDR_PH_RESET_ON_EIDLE = 0b0,
|
||||||
|
p_RXCDR_LOCK_CFG = 0b010101,
|
||||||
|
|
||||||
|
# RX Initialization and Reset Attributes
|
||||||
|
p_RXCDRFREQRESET_TIME = 0b00001,
|
||||||
|
p_RXCDRPHRESET_TIME = 0b00001,
|
||||||
|
p_RXISCANRESET_TIME = 0b00001,
|
||||||
|
p_RXPCSRESET_TIME = 0b00001,
|
||||||
|
p_RXPMARESET_TIME = 0b00011,
|
||||||
|
|
||||||
|
# RX OOB Signaling Attributes
|
||||||
|
p_RXOOB_CFG = 0b0000110,
|
||||||
|
|
||||||
|
# RX Gearbox Attributes
|
||||||
|
p_RXGEARBOX_EN = "FALSE",
|
||||||
|
p_GEARBOX_MODE = 0b000,
|
||||||
|
|
||||||
|
# PRBS Detection Attribute
|
||||||
|
p_RXPRBS_ERR_LOOPBACK = 0b0,
|
||||||
|
|
||||||
|
# Power-Down Attributes
|
||||||
|
p_PD_TRANS_TIME_FROM_P2 = 0x03c,
|
||||||
|
p_PD_TRANS_TIME_NONE_P2 = 0x3c,
|
||||||
|
p_PD_TRANS_TIME_TO_P2 = 0x64,
|
||||||
|
|
||||||
|
# RX OOB Signaling Attributes
|
||||||
|
p_SAS_MAX_COM = 64,
|
||||||
|
p_SAS_MIN_COM = 36,
|
||||||
|
p_SATA_BURST_SEQ_LEN = 0b0101,
|
||||||
|
p_SATA_BURST_VAL = 0b100,
|
||||||
|
p_SATA_EIDLE_VAL = 0b100,
|
||||||
|
p_SATA_MAX_BURST = 8,
|
||||||
|
p_SATA_MAX_INIT = 21,
|
||||||
|
p_SATA_MAX_WAKE = 7,
|
||||||
|
p_SATA_MIN_BURST = 4,
|
||||||
|
p_SATA_MIN_INIT = 12,
|
||||||
|
p_SATA_MIN_WAKE = 4,
|
||||||
|
|
||||||
|
# RX Fabric Clock Output Control Attributes
|
||||||
|
p_TRANS_TIME_RATE = 0x0E,
|
||||||
|
|
||||||
|
# TX Buffer Attributes
|
||||||
|
p_TXBUF_EN = "TRUE",
|
||||||
|
p_TXBUF_RESET_ON_RATE_CHANGE = "TRUE",
|
||||||
|
p_TXDLY_CFG = 0x001F,
|
||||||
|
p_TXDLY_LCFG = 0x030,
|
||||||
|
p_TXDLY_TAP_CFG = 0x0000,
|
||||||
|
p_TXPH_CFG = 0x0780,
|
||||||
|
p_TXPHDLY_CFG = 0x084020,
|
||||||
|
p_TXPH_MONITOR_SEL = 0b00000,
|
||||||
|
p_TX_XCLK_SEL = "TXOUT",
|
||||||
|
|
||||||
|
# FPGA TX Interface Attributes
|
||||||
|
p_TX_DATA_WIDTH = 20,
|
||||||
|
|
||||||
|
# TX Configurable Driver Attributes
|
||||||
|
p_TX_DEEMPH0 = 0b00000,
|
||||||
|
p_TX_DEEMPH1 = 0b00000,
|
||||||
|
p_TX_EIDLE_ASSERT_DELAY = 0b110,
|
||||||
|
p_TX_EIDLE_DEASSERT_DELAY = 0b100,
|
||||||
|
p_TX_LOOPBACK_DRIVE_HIZ = "FALSE",
|
||||||
|
p_TX_MAINCURSOR_SEL = 0b0,
|
||||||
|
p_TX_DRIVE_MODE = "DIRECT",
|
||||||
|
p_TX_MARGIN_FULL_0 = 0b1001110,
|
||||||
|
p_TX_MARGIN_FULL_1 = 0b1001001,
|
||||||
|
p_TX_MARGIN_FULL_2 = 0b1000101,
|
||||||
|
p_TX_MARGIN_FULL_3 = 0b1000010,
|
||||||
|
p_TX_MARGIN_FULL_4 = 0b1000000,
|
||||||
|
p_TX_MARGIN_LOW_0 = 0b1000110,
|
||||||
|
p_TX_MARGIN_LOW_1 = 0b1000100,
|
||||||
|
p_TX_MARGIN_LOW_2 = 0b1000010,
|
||||||
|
p_TX_MARGIN_LOW_3 = 0b1000000,
|
||||||
|
p_TX_MARGIN_LOW_4 = 0b1000000,
|
||||||
|
|
||||||
|
# TX Gearbox Attributes
|
||||||
|
p_TXGEARBOX_EN = "FALSE",
|
||||||
|
|
||||||
|
# TX Initialization and Reset Attributes
|
||||||
|
p_TXPCSRESET_TIME = 0b00001,
|
||||||
|
p_TXPMARESET_TIME = 0b00001,
|
||||||
|
|
||||||
|
# TX Receiver Detection Attributes
|
||||||
|
p_TX_RXDETECT_CFG = 0x1832,
|
||||||
|
p_TX_RXDETECT_REF = 0b100,
|
||||||
|
|
||||||
|
# CPLL Attributes
|
||||||
|
p_CPLL_CFG = 0xBC07DC,
|
||||||
|
p_CPLL_FBDIV = pll.config["n2"],
|
||||||
|
p_CPLL_FBDIV_45 = pll.config["n1"],
|
||||||
|
p_CPLL_INIT_CFG = 0x00001E,
|
||||||
|
p_CPLL_LOCK_CFG = 0x01E8,
|
||||||
|
p_CPLL_REFCLK_DIV = pll.config["m"],
|
||||||
|
p_RXOUT_DIV = pll.config["d"],
|
||||||
|
p_TXOUT_DIV = pll.config["d"],
|
||||||
|
p_SATA_CPLL_CFG = "VCO_3000MHZ",
|
||||||
|
|
||||||
|
# RX Initialization and Reset Attributes
|
||||||
|
p_RXDFELPMRESET_TIME = 0b0001111,
|
||||||
|
|
||||||
|
# RX Equalizer Attributes
|
||||||
|
p_RXLPM_HF_CFG = 0b00000011110000,
|
||||||
|
p_RXLPM_LF_CFG = 0b00000011110000,
|
||||||
|
p_RX_DFE_GAIN_CFG = 0x020FEA,
|
||||||
|
p_RX_DFE_H2_CFG = 0b000000000000,
|
||||||
|
p_RX_DFE_H3_CFG = 0b000001000000,
|
||||||
|
p_RX_DFE_H4_CFG = 0b00011110000,
|
||||||
|
p_RX_DFE_H5_CFG = 0b00011100000,
|
||||||
|
p_RX_DFE_KL_CFG = 0b0000011111110,
|
||||||
|
p_RX_DFE_LPM_CFG = 0x0954,
|
||||||
|
p_RX_DFE_LPM_HOLD_DURING_EIDLE = 0b0,
|
||||||
|
p_RX_DFE_UT_CFG = 0b10001111000000000,
|
||||||
|
p_RX_DFE_VP_CFG = 0b00011111100000011,
|
||||||
|
|
||||||
|
# Power-Down Attributes
|
||||||
|
p_RX_CLKMUX_PD = 0b1,
|
||||||
|
p_TX_CLKMUX_PD = 0b1,
|
||||||
|
|
||||||
|
# FPGA RX Interface Attribute
|
||||||
|
p_RX_INT_DATAWIDTH = 0,
|
||||||
|
|
||||||
|
# FPGA TX Interface Attribute
|
||||||
|
p_TX_INT_DATAWIDTH = 0,
|
||||||
|
|
||||||
|
# TX Configurable Driver Attributes
|
||||||
|
p_TX_QPI_STATUS_EN = 0b0,
|
||||||
|
|
||||||
|
)
|
||||||
|
gth_params.update(
|
||||||
|
# CPLL Ports
|
||||||
|
o_CPLLFBCLKLOST = Open(),
|
||||||
|
o_CPLLLOCK = pll.lock,
|
||||||
|
i_CPLLLOCKDETCLK = ClockSignal(),
|
||||||
|
i_CPLLLOCKEN = 1,
|
||||||
|
i_CPLLPD = 0,
|
||||||
|
o_CPLLREFCLKLOST = Open(),
|
||||||
|
i_CPLLREFCLKSEL = 0b001,
|
||||||
|
i_CPLLRESET = pll.reset,
|
||||||
|
i_GTRSVD = 0b0000000000000000,
|
||||||
|
i_PCSRSVDIN = 0b0000000000000000,
|
||||||
|
i_PCSRSVDIN2 = 0b00000,
|
||||||
|
i_PMARSVDIN = 0b00000,
|
||||||
|
|
||||||
|
# Channel - Clocking Ports
|
||||||
|
i_GTGREFCLK = 0,
|
||||||
|
i_GTNORTHREFCLK0 = 0,
|
||||||
|
i_GTNORTHREFCLK1 = 0,
|
||||||
|
i_GTREFCLK0 = pll.refclk,
|
||||||
|
i_GTREFCLK1 = 0,
|
||||||
|
i_GTSOUTHREFCLK0 = 0,
|
||||||
|
i_GTSOUTHREFCLK1 = 0,
|
||||||
|
|
||||||
|
# Channel - DRP Ports
|
||||||
|
i_DRPADDR = 0,
|
||||||
|
i_DRPCLK = 0,
|
||||||
|
i_DRPDI = 0,
|
||||||
|
o_DRPDO = Open(),
|
||||||
|
i_DRPEN = 0,
|
||||||
|
o_DRPRDY = Open(),
|
||||||
|
i_DRPWE = 0,
|
||||||
|
|
||||||
|
# Clocking Ports
|
||||||
|
o_GTREFCLKMONITOR = Open(),
|
||||||
|
i_QPLLCLK = 0,
|
||||||
|
i_QPLLREFCLK = 1,
|
||||||
|
i_RXSYSCLKSEL = 0b00,
|
||||||
|
i_TXSYSCLKSEL = 0b00,
|
||||||
|
|
||||||
|
# Digital Monitor Ports
|
||||||
|
o_DMONITOROUT = Open(),
|
||||||
|
|
||||||
|
# FPGA TX Interface Datapath Configuration
|
||||||
|
i_TX8B10BEN = 0,
|
||||||
|
|
||||||
|
# Loopback Ports
|
||||||
|
i_LOOPBACK = 0b000,
|
||||||
|
|
||||||
|
# PCI Express Ports
|
||||||
|
o_PHYSTATUS = Open(),
|
||||||
|
i_RXRATE = 0b000,
|
||||||
|
o_RXVALID = Open(),
|
||||||
|
|
||||||
|
# Power-Down Ports
|
||||||
|
i_RXPD = 0b00,
|
||||||
|
i_TXPD = 0b00,
|
||||||
|
|
||||||
|
# RX 8B/10B Decoder Ports
|
||||||
|
i_SETERRSTATUS = 0,
|
||||||
|
|
||||||
|
# RX Initialization and Reset Ports
|
||||||
|
i_EYESCANRESET = 0,
|
||||||
|
i_RXUSERRDY = rx_mmcm_locked,
|
||||||
|
|
||||||
|
# RX Margin Analysis Ports
|
||||||
|
o_EYESCANDATAERROR = Open(),
|
||||||
|
i_EYESCANMODE = 0,
|
||||||
|
i_EYESCANTRIGGER = 0,
|
||||||
|
|
||||||
|
# Receive Ports - CDR Ports
|
||||||
|
i_RXCDRFREQRESET = 0,
|
||||||
|
i_RXCDRHOLD = 0,
|
||||||
|
o_RXCDRLOCK = Open(),
|
||||||
|
i_RXCDROVRDEN = 0,
|
||||||
|
i_RXCDRRESET = 0,
|
||||||
|
i_RXCDRRESETRSV = 0,
|
||||||
|
|
||||||
|
# Receive Ports - Clock Correction Ports
|
||||||
|
o_RXCLKCORCNT = Open(),
|
||||||
|
|
||||||
|
# Receive Ports - FPGA RX Interface Datapath Configuration
|
||||||
|
i_RX8B10BEN = 0,
|
||||||
|
|
||||||
|
# Receive Ports - FPGA RX Interface Ports
|
||||||
|
i_RXUSRCLK = ClockSignal("eth_rx_half"),
|
||||||
|
i_RXUSRCLK2 = ClockSignal("eth_rx_half"),
|
||||||
|
|
||||||
|
# Receive Ports - FPGA RX interface Ports
|
||||||
|
o_RXDATA = Cat(*[rx_data[10*i:10*i+8] for i in range(2)]),
|
||||||
|
|
||||||
|
# Receive Ports - Pattern Checker Ports
|
||||||
|
o_RXPRBSERR = Open(),
|
||||||
|
i_RXPRBSSEL = 0b000,
|
||||||
|
|
||||||
|
# Receive Ports - Pattern Checker ports
|
||||||
|
i_RXPRBSCNTRESET = 0,
|
||||||
|
|
||||||
|
# Receive Ports - RX Equalizer Ports
|
||||||
|
i_RXDFEXYDEN = 1,
|
||||||
|
#i_RXDFEXYDHOLD = 0,
|
||||||
|
#i_RXDFEXYDOVRDEN = 0,
|
||||||
|
|
||||||
|
# Receive Ports - RX 8B/10B Decoder Ports
|
||||||
|
i_RXDISPERR = Cat(*[rx_data[10*i+9] for i in range(2)]),
|
||||||
|
o_RXNOTINTABLE = Open(),
|
||||||
|
|
||||||
|
# Receive Ports - RX AFE
|
||||||
|
i_GTHRXP = data_pads.rxp,
|
||||||
|
# Receive Ports - RX AFE Ports
|
||||||
|
i_GTHRXN = data_pads.rxn,
|
||||||
|
|
||||||
|
# Receive Ports - RX Buffer Bypass Ports
|
||||||
|
i_RXBUFRESET = 0,
|
||||||
|
o_RXBUFSTATUS = Open(),
|
||||||
|
i_RXDDIEN = 0,
|
||||||
|
i_RXDLYBYPASS = 1,
|
||||||
|
i_RXDLYEN = 0,
|
||||||
|
i_RXDLYOVRDEN = 0,
|
||||||
|
i_RXDLYSRESET = 0,
|
||||||
|
o_RXDLYSRESETDONE = Open(),
|
||||||
|
i_RXPHALIGN = 0,
|
||||||
|
o_RXPHALIGNDONE = Open(),
|
||||||
|
i_RXPHALIGNEN = 0,
|
||||||
|
i_RXPHDLYPD = 0,
|
||||||
|
i_RXPHDLYRESET = 0,
|
||||||
|
o_RXPHMONITOR = Open(),
|
||||||
|
i_RXPHOVRDEN = 0,
|
||||||
|
o_RXPHSLIPMONITOR = Open(),
|
||||||
|
o_RXSTATUS = Open(),
|
||||||
|
|
||||||
|
# Receive Ports - RX Byte and Word Alignment Ports
|
||||||
|
o_RXBYTEISALIGNED = Open(),
|
||||||
|
o_RXBYTEREALIGN = Open(),
|
||||||
|
o_RXCOMMADET = Open(),
|
||||||
|
i_RXCOMMADETEN = 1,
|
||||||
|
i_RXMCOMMAALIGNEN = 1,
|
||||||
|
i_RXPCOMMAALIGNEN = 1,
|
||||||
|
|
||||||
|
# Receive Ports - RX Channel Bonding Ports
|
||||||
|
o_RXCHANBONDSEQ = Open(),
|
||||||
|
i_RXCHBONDEN = 0,
|
||||||
|
i_RXCHBONDLEVEL = 0b000,
|
||||||
|
i_RXCHBONDMASTER = 0,
|
||||||
|
o_RXCHBONDO = Open(),
|
||||||
|
i_RXCHBONDSLAVE = 0,
|
||||||
|
|
||||||
|
# Receive Ports - RX Channel Bonding Ports
|
||||||
|
o_RXCHANISALIGNED = Open(),
|
||||||
|
o_RXCHANREALIGN = Open(),
|
||||||
|
|
||||||
|
# Receive Ports - RX Equailizer Ports
|
||||||
|
i_RXLPMHFHOLD = 0,
|
||||||
|
i_RXLPMHFOVRDEN = 0,
|
||||||
|
i_RXLPMLFHOLD = 0,
|
||||||
|
|
||||||
|
# Receive Ports - RX Equalizer Ports
|
||||||
|
i_RXDFEAGCHOLD = 0,
|
||||||
|
i_RXDFEAGCOVRDEN = 0,
|
||||||
|
i_RXDFECM1EN = 0,
|
||||||
|
i_RXDFELFHOLD = 0,
|
||||||
|
i_RXDFELFOVRDEN = 1,
|
||||||
|
i_RXDFELPMRESET = 0,
|
||||||
|
i_RXDFETAP2HOLD = 0,
|
||||||
|
i_RXDFETAP2OVRDEN = 0,
|
||||||
|
i_RXDFETAP3HOLD = 0,
|
||||||
|
i_RXDFETAP3OVRDEN = 0,
|
||||||
|
i_RXDFETAP4HOLD = 0,
|
||||||
|
i_RXDFETAP4OVRDEN = 0,
|
||||||
|
i_RXDFETAP5HOLD = 0,
|
||||||
|
i_RXDFETAP5OVRDEN = 0,
|
||||||
|
i_RXDFEUTHOLD = 0,
|
||||||
|
i_RXDFEUTOVRDEN = 0,
|
||||||
|
i_RXDFEVPHOLD = 0,
|
||||||
|
i_RXDFEVPOVRDEN = 0,
|
||||||
|
i_RXDFEVSEN = 0,
|
||||||
|
i_RXLPMLFKLOVRDEN = 0,
|
||||||
|
o_RXMONITOROUT = Open(),
|
||||||
|
i_RXMONITORSEL = 0,
|
||||||
|
i_RXOSHOLD = 0,
|
||||||
|
i_RXOSOVRDEN = 0,
|
||||||
|
|
||||||
|
# Receive Ports - RX Fabric ClocK Output Control Ports
|
||||||
|
o_RXRATEDONE = Open(),
|
||||||
|
|
||||||
|
# Receive Ports - RX Fabric Output Control Ports
|
||||||
|
o_RXOUTCLK = self.rxoutclk,
|
||||||
|
o_RXOUTCLKFABRIC = Open(),
|
||||||
|
o_RXOUTCLKPCS = Open(),
|
||||||
|
i_RXOUTCLKSEL = 0b010,
|
||||||
|
|
||||||
|
# Receive Ports - RX Gearbox Ports
|
||||||
|
o_RXDATAVALID = Open(),
|
||||||
|
o_RXHEADER = Open(),
|
||||||
|
o_RXHEADERVALID = Open(),
|
||||||
|
o_RXSTARTOFSEQ = Open(),
|
||||||
|
|
||||||
|
# Receive Ports - RX Gearbox Ports
|
||||||
|
i_RXGEARBOXSLIP = 0,
|
||||||
|
|
||||||
|
# Receive Ports - RX Initialization and Reset Ports
|
||||||
|
i_GTRXRESET = rx_reset,
|
||||||
|
i_RXOOBRESET = 0,
|
||||||
|
i_RXPCSRESET = 0,
|
||||||
|
i_RXPMARESET = 0,
|
||||||
|
|
||||||
|
# Receive Ports - RX Margin Analysis ports
|
||||||
|
i_RXLPMEN = 0,
|
||||||
|
|
||||||
|
# Receive Ports - RX OOB Signaling ports
|
||||||
|
o_RXCOMSASDET = Open(),
|
||||||
|
o_RXCOMWAKEDET = Open(),
|
||||||
|
|
||||||
|
# Receive Ports - RX OOB Signaling ports
|
||||||
|
o_RXCOMINITDET = Open(),
|
||||||
|
|
||||||
|
# Receive Ports - RX OOB signalling Ports
|
||||||
|
o_RXELECIDLE = Open(),
|
||||||
|
i_RXELECIDLEMODE = 0b11,
|
||||||
|
|
||||||
|
# Receive Ports - RX Polarity Control Ports
|
||||||
|
i_RXPOLARITY = rx_polarity,
|
||||||
|
|
||||||
|
# Receive Ports - RX gearbox ports
|
||||||
|
i_RXSLIDE = 0,
|
||||||
|
|
||||||
|
# Receive Ports - RX8B/10B Decoder Ports
|
||||||
|
o_RXCHARISCOMMA = Open(),
|
||||||
|
o_RXCHARISK = Cat(*[rx_data[10*i+8] for i in range(2)]),
|
||||||
|
|
||||||
|
# Receive Ports - Rx Channel Bonding Ports
|
||||||
|
i_RXCHBONDI = 0b00000,
|
||||||
|
|
||||||
|
# Receive Ports -RX Initialization and Reset Ports
|
||||||
|
o_RXRESETDONE = rx_reset_done,
|
||||||
|
|
||||||
|
# Rx AFE Ports
|
||||||
|
i_RXQPIEN = 0,
|
||||||
|
o_RXQPISENN = Open(),
|
||||||
|
o_RXQPISENP = Open(),
|
||||||
|
|
||||||
|
# TX Buffer Bypass Ports
|
||||||
|
i_TXPHDLYTSTCLK = 0,
|
||||||
|
|
||||||
|
# TX Configurable Driver Ports
|
||||||
|
i_TXPOSTCURSOR = 0b00000,
|
||||||
|
i_TXPOSTCURSORINV = 0,
|
||||||
|
i_TXPRECURSOR = 0b00000,
|
||||||
|
i_TXPRECURSORINV = 0,
|
||||||
|
i_TXQPIBIASEN = 0,
|
||||||
|
i_TXQPISTRONGPDOWN = 0,
|
||||||
|
i_TXQPIWEAKPUP = 0,
|
||||||
|
|
||||||
|
# TX Initialization and Reset Ports
|
||||||
|
i_CFGRESET = 0,
|
||||||
|
i_GTTXRESET = tx_reset,
|
||||||
|
o_PCSRSVDOUT = Open(),
|
||||||
|
i_TXUSERRDY = tx_mmcm_locked,
|
||||||
|
|
||||||
|
# Transceiver Reset Mode Operation
|
||||||
|
i_GTRESETSEL = 0,
|
||||||
|
i_RESETOVRD = 0,
|
||||||
|
|
||||||
|
# Transmit Ports - 8b10b Encoder Control Ports
|
||||||
|
i_TXCHARDISPMODE = Cat(*[tx_data[10*i+9] for i in range(2)]),
|
||||||
|
i_TXCHARDISPVAL = Cat(*[tx_data[10*i+8] for i in range(2)]),
|
||||||
|
|
||||||
|
# Transmit Ports - FPGA TX Interface Ports
|
||||||
|
i_TXUSRCLK = ClockSignal("eth_tx_half"),
|
||||||
|
i_TXUSRCLK2 = ClockSignal("eth_tx_half"),
|
||||||
|
|
||||||
|
# Transmit Ports - PCI Express Ports
|
||||||
|
i_TXELECIDLE = 0,
|
||||||
|
i_TXMARGIN = 0b000,
|
||||||
|
i_TXRATE = 0b000,
|
||||||
|
i_TXSWING = 0,
|
||||||
|
|
||||||
|
# Transmit Ports - Pattern Generator Ports
|
||||||
|
i_TXPRBSFORCEERR = 0,
|
||||||
|
|
||||||
|
# Transmit Ports - TX Buffer Bypass Ports
|
||||||
|
i_TXDLYBYPASS = 1,
|
||||||
|
i_TXDLYEN = 0,
|
||||||
|
i_TXDLYHOLD = 0,
|
||||||
|
i_TXDLYOVRDEN = 0,
|
||||||
|
i_TXDLYSRESET = 0,
|
||||||
|
o_TXDLYSRESETDONE = Open(),
|
||||||
|
i_TXDLYUPDOWN = 0,
|
||||||
|
i_TXPHALIGN = 0,
|
||||||
|
o_TXPHALIGNDONE = Open(),
|
||||||
|
i_TXPHALIGNEN = 0,
|
||||||
|
i_TXPHDLYPD = 0,
|
||||||
|
i_TXPHDLYRESET = 0,
|
||||||
|
i_TXPHINIT = 0,
|
||||||
|
o_TXPHINITDONE = Open(),
|
||||||
|
i_TXPHOVRDEN = 0,
|
||||||
|
|
||||||
|
# Transmit Ports - TX Buffer Ports
|
||||||
|
o_TXBUFSTATUS = Open(),
|
||||||
|
|
||||||
|
# Transmit Ports - TX Configurable Driver Ports
|
||||||
|
i_TXBUFDIFFCTRL = 0b100,
|
||||||
|
i_TXDEEMPH = 0,
|
||||||
|
i_TXDIFFCTRL = 0b1000,
|
||||||
|
i_TXDIFFPD = 0,
|
||||||
|
i_TXINHIBIT = 0,
|
||||||
|
i_TXMAINCURSOR = 0b0000000,
|
||||||
|
i_TXPISOPD = 0,
|
||||||
|
|
||||||
|
# Transmit Ports - TX Data Path interface
|
||||||
|
i_TXDATA = Cat(*[tx_data[10*i:10*i+8] for i in range(2)]),
|
||||||
|
|
||||||
|
# Transmit Ports - TX Driver and OOB signaling
|
||||||
|
o_GTHTXN = data_pads.txn,
|
||||||
|
o_GTHTXP = data_pads.txp,
|
||||||
|
|
||||||
|
# Transmit Ports - TX Fabric Clock Output Control Ports
|
||||||
|
o_TXOUTCLK = self.txoutclk,
|
||||||
|
o_TXOUTCLKFABRIC = Open(),
|
||||||
|
o_TXOUTCLKPCS = Open(),
|
||||||
|
i_TXOUTCLKSEL = 0b010,
|
||||||
|
o_TXRATEDONE = Open(),
|
||||||
|
|
||||||
|
# Transmit Ports - TX Gearbox Ports
|
||||||
|
i_TXCHARISK = 0b00000000,
|
||||||
|
o_TXGEARBOXREADY = Open(),
|
||||||
|
i_TXHEADER = 0b000,
|
||||||
|
i_TXSEQUENCE = 0b0000000,
|
||||||
|
i_TXSTARTSEQ = 0,
|
||||||
|
|
||||||
|
# Transmit Ports - TX Initialization and Reset Ports
|
||||||
|
i_TXPCSRESET = 0,
|
||||||
|
i_TXPMARESET = 0,
|
||||||
|
o_TXRESETDONE = tx_reset_done,
|
||||||
|
|
||||||
|
# Transmit Ports - TX OOB signaling Ports
|
||||||
|
o_TXCOMFINISH = Open(),
|
||||||
|
i_TXCOMINIT = 0,
|
||||||
|
i_TXCOMSAS = 0,
|
||||||
|
i_TXCOMWAKE = 0,
|
||||||
|
i_TXPDELECIDLEMODE = 0,
|
||||||
|
|
||||||
|
# Transmit Ports - TX Polarity Control Ports
|
||||||
|
i_TXPOLARITY = tx_polarity,
|
||||||
|
|
||||||
|
# Transmit Ports - TX Receiver Detection Ports
|
||||||
|
i_TXDETECTRX = 0,
|
||||||
|
|
||||||
|
# Transmit Ports - TX8b/10b Encoder Ports
|
||||||
|
i_TX8B10BBYPASS = 0b00000000,
|
||||||
|
|
||||||
|
# Transmit Ports - pattern Generator Ports
|
||||||
|
i_TXPRBSSEL = 0b000,
|
||||||
|
|
||||||
|
# Tx Configurable Driver Ports
|
||||||
|
o_TXQPISENN = Open(),
|
||||||
|
o_TXQPISENP = Open(),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.specials += Instance("GTHE2_CHANNEL", **gth_params)
|
||||||
|
|
||||||
|
# Get 125MHz clocks back - the GTH is outputting 62.5MHz.
|
||||||
|
txoutclk_rebuffer = Signal()
|
||||||
|
self.specials += Instance("BUFH",
|
||||||
|
i_I = self.txoutclk,
|
||||||
|
o_O = txoutclk_rebuffer
|
||||||
|
)
|
||||||
|
rxoutclk_rebuffer = Signal()
|
||||||
|
self.specials += Instance("BUFG",
|
||||||
|
i_I = self.rxoutclk,
|
||||||
|
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)
|
||||||
|
|
||||||
|
# Transceiver init
|
||||||
|
self.tx_init = tx_init = ResetInserter()(GTHTXInit(sys_clk_freq, buffer_enable=True))
|
||||||
|
self.comb += [
|
||||||
|
tx_init.reset.eq(self.reset),
|
||||||
|
pll.reset.eq(tx_init.pllreset),
|
||||||
|
tx_init.plllock.eq(pll.lock),
|
||||||
|
tx_reset.eq(tx_init.gtXxreset),
|
||||||
|
tx_init.Xxresetdone.eq(tx_reset_done),
|
||||||
|
]
|
||||||
|
self.sync += tx_mmcm_reset.eq(~pll.lock)
|
||||||
|
tx_mmcm_reset.attr.add("no_retiming")
|
||||||
|
|
||||||
|
self.rx_init = rx_init = ResetInserter()(GTHRXInit(sys_clk_freq, buffer_enable=True))
|
||||||
|
self.comb += [
|
||||||
|
rx_init.reset.eq(~tx_init.done | self.reset),
|
||||||
|
rx_init.plllock.eq(pll.lock),
|
||||||
|
rx_reset.eq(rx_init.gtXxreset),
|
||||||
|
rx_init.Xxresetdone.eq(rx_reset_done),
|
||||||
|
]
|
||||||
|
ps_restart = PulseSynchronizer("eth_tx", "sys")
|
||||||
|
self.submodules += ps_restart
|
||||||
|
self.comb += [
|
||||||
|
ps_restart.i.eq(pcs.restart),
|
||||||
|
rx_init.restart.eq(ps_restart.o)
|
||||||
|
]
|
||||||
|
|
||||||
|
# Assume CDR lock time is 50,000 UI as per DS183 and similar to what the Xilinx wizards does.
|
||||||
|
cdr_lock_time = round(sys_clk_freq*50e3/1.25e9)
|
||||||
|
cdr_lock_counter = Signal(max=cdr_lock_time+1)
|
||||||
|
cdr_locked = Signal()
|
||||||
|
self.sync += [
|
||||||
|
If(rx_reset,
|
||||||
|
cdr_locked.eq(0),
|
||||||
|
cdr_lock_counter.eq(0)
|
||||||
|
).Elif(cdr_lock_counter != cdr_lock_time,
|
||||||
|
cdr_lock_counter.eq(cdr_lock_counter + 1)
|
||||||
|
).Else(
|
||||||
|
cdr_locked.eq(1)
|
||||||
|
),
|
||||||
|
rx_mmcm_reset.eq(~cdr_locked)
|
||||||
|
]
|
||||||
|
rx_mmcm_reset.attr.add("no_retiming")
|
||||||
|
|
||||||
|
# Gearbox and PCS connection
|
||||||
|
self.gearbox = gearbox = PCSGearbox()
|
||||||
|
self.comb += [
|
||||||
|
tx_data.eq(gearbox.tx_data_half),
|
||||||
|
gearbox.rx_data_half.eq(rx_data),
|
||||||
|
|
||||||
|
gearbox.tx_data.eq(pcs.tbi_tx),
|
||||||
|
pcs.tbi_rx.eq(gearbox.rx_data)
|
||||||
|
]
|
||||||
|
|
||||||
|
def add_csr(self):
|
||||||
|
self._reset = CSRStorage()
|
||||||
|
self.comb += self.reset.eq(self._reset.storage)
|
||||||
|
|
||||||
|
# V7_2500BASEX PHY ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class V7_2500BASEX(V7_1000BASEX):
|
||||||
|
linerate = 3.125e9
|
||||||
|
rx_clk_freq = 312.5e6
|
||||||
|
tx_clk_freq = 312.5e6
|
Loading…
Reference in New Issue