Exemple #1
0
    def __init__(self,
                 pads,
                 gen,
                 clk_freq,
                 data_width=16,
                 tx_buffer_enable=False,
                 rx_buffer_enable=False):
        assert data_width in [16, 32]
        # Common signals
        self.data_width = data_width

        # Control
        self.ready = Signal()  # o

        self.tx_idle = Signal()  # i
        self.tx_polarity = Signal()  # i

        self.tx_cominit_stb = Signal()  # i
        self.tx_cominit_ack = Signal()  # o
        self.tx_comwake_stb = Signal()  # i
        self.tx_comwake_ack = Signal()  # o

        self.rx_idle = Signal()  # o
        self.rx_cdrhold = Signal()  # i
        self.rx_polarity = Signal()  # i

        self.rx_cominit_stb = Signal()  # o
        self.rx_comwake_stb = Signal()  # o

        self.rxdisperr = Signal(data_width // 8)  # o
        self.rxnotintable = Signal(data_width // 8)  # o

        # Datapath
        self.sink = stream.Endpoint(phy_description(data_width))
        self.source = stream.Endpoint(phy_description(data_width))

        # K7 specific signals
        # Channel - Ref Clock Ports
        self.gtrefclk0 = Signal()

        # Channel PLL
        self.cplllock = Signal()

        # Receive Ports - 8b10b Decoder
        self.rxcharisk = Signal(data_width // 8)

        # Receive Ports - RX Data Path interface
        self.rxdata = Signal(data_width)
        self.rxoutclk = Signal()
        self.rxusrclk = Signal()
        self.rxusrclk2 = Signal()

        # Receive Ports - RX Ports for SATA
        self.rxcominitdet = Signal()
        self.rxcomwakedet = Signal()

        # Transmit Ports - 8b10b Encoder Control Ports
        self.txcharisk = Signal(data_width // 8)

        # Transmit Ports - TX Data Path interface
        self.txdata = Signal(data_width)
        self.txoutclk = Signal()
        self.txusrclk = Signal()
        self.txusrclk2 = Signal()

        # Transmit Ports - TX Ports for PCI Express
        self.txelecidle = Signal(reset=1)

        # Transmit Ports - TX Ports for SATA
        self.txcomfinish = Signal()
        self.txcominit = Signal()
        self.txcomwake = Signal()

        # Power-down signals
        self.cpllpd = Signal()
        self.rxpd = Signal()
        self.txpd = Signal()

        # Config at startup
        div_config = {
            "gen1": 4,
            "gen2": 2,
            "gen3": 1,
        }
        rxout_div = div_config[gen]
        txout_div = div_config[gen]

        cdr_config = {
            "gen1": 0x0380008bff40100008,
            "gen2": 0x0388008bff40200008,
            "gen3": 0x0380008bff10200010,
        }
        rxcdr_cfg = cdr_config[gen]

        # TX Init ----------------------------------------------------------------------------------
        self.submodules.tx_init = tx_init = GTXTXInit(
            clk_freq, buffer_enable=tx_buffer_enable)
        self.comb += tx_init.plllock.eq(self.cplllock)

        # RX Init ----------------------------------------------------------------------------------
        self.submodules.rx_init = rx_init = GTXRXInit(
            clk_freq, buffer_enable=rx_buffer_enable)
        self.comb += rx_init.plllock.eq(self.cplllock)

        # Ready ------------------------------------------------------------------------------------
        self.comb += self.ready.eq(tx_init.done & rx_init.done)

        # Specific / Generic signals encoding/decoding ---------------------------------------------
        self.comb += [
            self.txelecidle.eq(self.tx_idle | self.txpd),
            self.tx_cominit_ack.eq(self.tx_cominit_stb & self.txcomfinish),
            self.tx_comwake_ack.eq(self.tx_comwake_stb & self.txcomfinish),
            self.rx_cominit_stb.eq(self.rxcominitdet),
            self.rx_comwake_stb.eq(self.rxcomwakedet),
        ]
        self.submodules += _RisingEdge(self.tx_cominit_stb, self.txcominit)
        self.submodules += _RisingEdge(self.tx_comwake_stb, self.txcomwake)

        self.sync.sata_rx += [
            self.source.valid.eq(1),
            self.source.charisk.eq(self.rxcharisk),
            self.source.data.eq(self.rxdata)
        ]

        self.sync.sata_tx += [
            self.txcharisk.eq(self.sink.charisk),
            self.txdata.eq(self.sink.data),
            self.sink.ready.eq(1),
        ]

        # Internals and clock domain crossing ------------------------------------------------------
        # sys_clk --> sata_tx clk
        txpd = Signal()
        txelecidle = Signal(reset=1)
        txcominit = Signal()
        txcomwake = Signal()
        self.specials += [
            MultiReg(self.txpd, txpd, "sata_tx"),
            MultiReg(self.txelecidle, txelecidle, "sata_tx"),
        ]
        self.submodules += [
            _PulseSynchronizer(self.txcominit, "sys", txcominit, "sata_tx"),
            _PulseSynchronizer(self.txcomwake, "sys", txcomwake, "sata_tx"),
        ]

        # sata_tx clk --> sys clk
        txcomfinish = Signal()
        self.submodules += _PulseSynchronizer(txcomfinish, "sata_tx",
                                              self.txcomfinish, "sys")

        # sata_rx clk --> sys clk
        rxcominitdet = Signal()
        rxcomwakedet = Signal()
        rxratedone = Signal()
        rxdisperr = Signal(data_width // 8)
        rxnotintable = Signal(data_width // 8)
        self.specials += [
            MultiReg(rxcominitdet, self.rxcominitdet, "sys"),
            MultiReg(rxcomwakedet, self.rxcomwakedet, "sys"),
            MultiReg(rxdisperr, self.rxdisperr, "sys"),
            MultiReg(rxnotintable, self.rxnotintable, "sys")
        ]

        # QPLL input clock -------------------------------------------------------------------------
        self.qpllclk = Signal()
        self.qpllrefclk = Signal()

        # OOB clock (75MHz) ------------------------------------------------------------------------
        oobclk = Signal()
        self.specials += Instance("FDPE",
                                  p_INIT=1,
                                  i_CE=1,
                                  i_PRE=0,
                                  i_C=self.gtrefclk0,
                                  i_D=~oobclk,
                                  o_Q=oobclk)

        # GTXE2_CHANNEL Instance -------------------------------------------------------------------
        class Open(Signal):
            pass

        gtx_params = dict(
            # Simulation-Only Attributes
            p_SIM_RECEIVER_DETECT_PASS="******",
            p_SIM_TX_EIDLE_DRIVE_LEVEL="X",
            p_SIM_RESET_SPEEDUP="FALSE",
            p_SIM_CPLLREFCLK_SEL="FALSE",
            p_SIM_VERSION="4.0",

            # RX Byte and Word Alignment Attributes
            p_ALIGN_COMMA_DOUBLE="FALSE",
            p_ALIGN_COMMA_ENABLE=0b1111111111,
            p_ALIGN_COMMA_WORD=2 if data_width == 16 else 4,
            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" if rx_buffer_enable else "PCS",
            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 if data_width == 16 else 20,
            p_CLK_COR_MIN_LAT=7 if data_width == 16 else 16,
            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 if data_width == 16 else 40,

            # PMA Attributes
            p_OUTREFCLK_SEL_INV=0b11,
            p_PMA_RSV=0x00018480,
            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=6,
            p_TX_CLK25_DIV=6,
            p_UCODEER_CLR=0b0,

            # PCI Express Attributes
            p_PCS_PCIE_EN="FALSE",

            # PCS Attributes
            p_PCS_RSVD_ATTR=0x108 if gen == "gen1" else 0x100,

            # RX Buffer Attributes
            p_RXBUF_ADDR_MODE="FAST",
            p_RXBUF_EIDLE_HI_CNT=0b1000,
            p_RXBUF_EIDLE_LO_CNT=0b0000,
            p_RXBUF_EN="TRUE" if rx_buffer_enable else "FALSE",
            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" if rx_buffer_enable else "RXUSR",
            p_RX_DDI_SEL=0b000000,
            p_RX_DEFER_RESET_BUF_EN="TRUE",

            # CDR Attributes
            p_RXCDR_CFG=rxcdr_cfg,
            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" if tx_buffer_enable else "FALSE",
            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" if tx_buffer_enable else "TXUSR",

            # FPGA TX Interface Attributes
            p_TX_DATA_WIDTH=20 if data_width == 16 else 40,

            # 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=4,
            p_CPLL_FBDIV_45=5,
            p_CPLL_INIT_CFG=0x00001E,
            p_CPLL_LOCK_CFG=0x01E8,
            p_CPLL_REFCLK_DIV=1,
            p_RXOUT_DIV=rxout_div,
            p_TXOUT_DIV=txout_div,
            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=0b1,
            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=data_width == 32,

            # FPGA TX Interface Attribute
            p_TX_INT_DATAWIDTH=data_width == 32,

            # TX Configurable Driver Attributes
            p_TX_QPI_STATUS_EN=0b0,

            # RX Equalizer Attributes
            p_RX_DFE_KL_CFG2=0x3310180c,
            p_RX_DFE_XYD_CFG=0b0000000000000,

            # TX Configurable Driver Attributes
            p_TX_PREDRIVER_MODE=0b0)
        gtx_params.update(
            # CPLL Ports
            o_CPLLFBCLKLOST=Open(),
            o_CPLLLOCK=self.cplllock,
            i_CPLLLOCKDETCLK=0,
            i_CPLLLOCKEN=1,
            i_CPLLPD=self.cpllpd,
            o_CPLLREFCLKLOST=Open(),
            i_CPLLREFCLKSEL=0b001,
            i_CPLLRESET=tx_init.pllreset,
            i_GTRSVD=0b0000000000000000,
            i_PCSRSVDIN=0b0000000000000000,
            i_PCSRSVDIN2=0b00000,
            i_PMARSVDIN=0b00000,
            i_PMARSVDIN2=0b00000,
            i_TSTIN=0b11111111111111111111,
            o_TSTOUT=Open(),

            # Channel
            i_CLKRSVD=oobclk,

            # Channel - Clocking Ports
            i_GTGREFCLK=0,
            i_GTNORTHREFCLK0=0,
            i_GTNORTHREFCLK1=0,
            i_GTREFCLK0=self.gtrefclk0,
            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=self.qpllclk,
            i_QPLLREFCLK=self.qpllrefclk,
            i_RXSYSCLKSEL=0b00,
            i_TXSYSCLKSEL=0b00,

            # Digital Monitor Ports
            o_DMONITOROUT=Open(),

            # FPGA TX Interface Datapath Configuration
            i_TX8B10BEN=1,

            # Loopback Ports
            i_LOOPBACK=0,

            # PCI Express Ports
            o_PHYSTATUS=Open(),
            i_RXRATE=0b000,
            o_RXVALID=Open(),

            # Power-Down Ports
            i_RXPD=Replicate(self.rxpd, 2),
            i_TXPD=Replicate(txpd, 2),

            # RX 8B/10B Decoder Ports
            i_SETERRSTATUS=0,

            # RX Initialization and Reset Ports
            i_EYESCANRESET=0,
            i_RXUSERRDY=rx_init.Xxuserrdy,

            # RX Margin Analysis Ports
            o_EYESCANDATAERROR=Open(),
            i_EYESCANMODE=0,
            i_EYESCANTRIGGER=0,

            # Receive Ports - CDR Ports
            i_RXCDRFREQRESET=0,
            i_RXCDRHOLD=self.rx_cdrhold,
            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=1,

            # Receive Ports - FPGA RX Interface Ports
            i_RXUSRCLK=self.rxusrclk,
            i_RXUSRCLK2=self.rxusrclk2,

            # Receive Ports - FPGA RX interface Ports
            o_RXDATA=self.rxdata,

            # 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
            o_RXDISPERR=rxdisperr,
            o_RXNOTINTABLE=rxnotintable,

            # Receive Ports - RX AFE
            i_GTXRXP=pads.rx_p,
            i_GTXRXN=pads.rx_n,

            # Receive Ports - RX Buffer Bypass Ports
            i_RXBUFRESET=0,
            o_RXBUFSTATUS=Open(),
            i_RXDDIEN=0 if rx_buffer_enable else 1,
            i_RXDLYBYPASS=1 if rx_buffer_enable else 0,
            i_RXDLYEN=0,
            i_RXDLYOVRDEN=0,
            i_RXDLYSRESET=rx_init.Xxdlysreset,
            o_RXDLYSRESETDONE=rx_init.Xxdlysresetdone,
            i_RXPHALIGN=0,
            o_RXPHALIGNDONE=rx_init.Xxphaligndone,
            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=0,
            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_init.gtXxreset,
            i_RXOOBRESET=0,
            i_RXPCSRESET=0,
            i_RXPMARESET=0,

            # Receive Ports - RX Margin Analysis ports
            i_RXLPMEN=1,

            # Receive Ports - RX OOB Signaling ports
            o_RXCOMSASDET=Open(),
            o_RXCOMWAKEDET=rxcomwakedet,

            # Receive Ports - RX OOB Signaling ports
            o_RXCOMINITDET=rxcominitdet,

            # Receive Ports - RX OOB signalling Ports
            o_RXELECIDLE=Open(),
            i_RXELECIDLEMODE=0b00,

            # Receive Ports - RX Polarity Control Ports
            i_RXPOLARITY=self.rx_polarity,

            # Receive Ports - RX gearbox ports
            i_RXSLIDE=0,

            # Receive Ports - RX8B/10B Decoder Ports
            o_RXCHARISCOMMA=Open(),
            o_RXCHARISK=self.rxcharisk,

            # Receive Ports - Rx Channel Bonding Ports
            i_RXCHBONDI=0b00000,

            # Receive Ports -RX Initialization and Reset Ports
            o_RXRESETDONE=rx_init.Xxresetdone,

            # 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_init.gtXxreset,
            o_PCSRSVDOUT=Open(),
            i_TXUSERRDY=tx_init.Xxuserrdy,

            # Transceiver Reset Mode Operation
            i_GTRESETSEL=0,
            i_RESETOVRD=0,

            # Transmit Ports - 8b10b Encoder Control Ports
            i_TXCHARDISPMODE=0,
            i_TXCHARDISPVAL=0,

            # Transmit Ports - FPGA TX Interface Ports
            i_TXUSRCLK=self.txusrclk,
            i_TXUSRCLK2=self.txusrclk2,

            # Transmit Ports - PCI Express Ports
            i_TXELECIDLE=txelecidle,
            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=0,
            i_TXDLYEN=0,
            i_TXDLYHOLD=0,
            i_TXDLYOVRDEN=0,
            i_TXDLYSRESET=tx_init.Xxdlysreset,
            o_TXDLYSRESETDONE=tx_init.Xxdlysresetdone,
            i_TXDLYUPDOWN=0,
            i_TXPHALIGN=0,
            o_TXPHALIGNDONE=tx_init.Xxphaligndone,
            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=self.txdata,

            # Transmit Ports - TX Driver and OOB signaling
            o_GTXTXP=pads.tx_p,
            o_GTXTXN=pads.tx_n,

            # Transmit Ports - TX Fabric Clock Output Control Ports
            o_TXOUTCLK=self.txoutclk,
            o_TXOUTCLKFABRIC=Open(),
            o_TXOUTCLKPCS=Open(),
            i_TXOUTCLKSEL=0b010
            if tx_buffer_enable else 0b011 if gen == "gen2" else 0b100,
            o_TXRATEDONE=Open(),

            # Transmit Ports - TX Gearbox Ports
            i_TXCHARISK=self.txcharisk,
            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_init.Xxresetdone,

            # Transmit Ports - TX OOB signaling Ports
            o_TXCOMFINISH=txcomfinish,
            i_TXCOMINIT=txcominit,
            i_TXCOMSAS=0,
            i_TXCOMWAKE=txcomwake,
            i_TXPDELECIDLEMODE=0,

            # Transmit Ports - TX Polarity Control Ports
            i_TXPOLARITY=self.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("GTXE2_CHANNEL", **gtx_params)
Exemple #2
0
    def __init__(self,
                 pads,
                 gen,
                 clk_freq,
                 data_width=16,
                 tx_buffer_enable=False,
                 rx_buffer_enable=False):
        assert data_width in [16, 32]
        # Common signals
        self.data_width = data_width

        # Control
        self.ready = Signal()  # o

        self.tx_idle = Signal()  # i
        self.tx_polarity = Signal()  # i

        self.tx_cominit_stb = Signal()  # i
        self.tx_cominit_ack = Signal()  # o
        self.tx_comwake_stb = Signal()  # i
        self.tx_comwake_ack = Signal()  # o

        self.rx_idle = Signal()  # o
        self.rx_cdrhold = Signal()  # i
        self.rx_polarity = Signal()  # i

        self.rx_cominit_stb = Signal()  # o
        self.rx_comwake_stb = Signal()  # o

        # Datapath
        self.sink = stream.Endpoint(phy_description(data_width))
        self.source = stream.Endpoint(phy_description(data_width))

        # PLL
        self.refclk = Signal()
        self.cplllock = Signal()
        self.cpllpd = Signal()
        self.cpllreset = Signal()

        # Receive Ports - 8b10b Decoder
        self.rxctrl0 = Signal(data_width // 8)
        self.rxctrl1 = Signal(data_width // 8)
        self.rxctrl2 = Signal(data_width // 8)
        self.rxctrl3 = Signal(data_width // 8)

        self.rxcharisk = Signal(data_width // 8)
        self.rxdisperr = Signal(data_width // 8)  # o
        self.rxnotintable = Signal(data_width // 8)  # o
        rxdisperr = Signal(data_width // 8)

        self.comb += [
            self.rxcharisk.eq(self.rxctrl0),
            rxdisperr.eq(self.rxctrl1)
        ]

        # Receive Ports - RX Data Path interface
        self.rxdata = Signal(data_width)
        self.rxoutclk = Signal()
        self.rxusrclk = Signal()
        self.rxusrclk2 = Signal()

        # Receive Ports - RX Ports for SATA
        self.rxcominitdet = Signal()
        self.rxcomwakedet = Signal()

        # Transmit Ports - 8b10b Encoder Control Ports
        self.txcharisk = Signal(data_width // 8)

        # Transmit Ports - TX Data Path interface
        self.txdata = Signal(data_width)
        self.txoutclk = Signal()
        self.txusrclk = Signal()
        self.txusrclk2 = Signal()

        # Transmit Ports - TX Ports for PCI Express
        self.txelecidle = Signal(reset=1)

        # Transmit Ports - TX Ports for SATA
        self.txcomfinish = Signal()
        self.txcominit = Signal()
        self.txcomwake = Signal()

        # Power-down signals
        self.rxpd = Signal()
        self.txpd = Signal()

        # Config at startup
        div_config = {
            "gen1": 4,
            "gen2": 2,
            "gen3": 1,
        }
        rxout_div = div_config[gen]
        txout_div = div_config[gen]

        progdiv = {
            "gen1": 40.0,
            "gen2": 20.0,
            "gen3": 10.0,
        }
        tx_progdiv_cfg = progdiv[gen]
        rx_progdiv_cfg = progdiv[gen]

        # TX Init ----------------------------------------------------------------------------------
        self.submodules.tx_init = tx_init = GTYTXInit(
            clk_freq, buffer_enable=tx_buffer_enable)
        self.comb += tx_init.plllock.eq(self.cplllock)
        self.comb += self.cpllreset.eq(tx_init.pllreset)

        # RX Init ----------------------------------------------------------------------------------
        self.submodules.rx_init = rx_init = GTYRXInit(
            clk_freq, buffer_enable=rx_buffer_enable)
        self.comb += rx_init.plllock.eq(self.cplllock)

        # Ready ------------------------------------------------------------------------------------
        self.comb += self.ready.eq(tx_init.done & rx_init.done)

        # Specific / Generic signals encoding/decoding ---------------------------------------------
        self.comb += [
            self.txelecidle.eq(self.tx_idle | self.txpd),
            self.tx_cominit_ack.eq(self.tx_cominit_stb & self.txcomfinish),
            self.tx_comwake_ack.eq(self.tx_comwake_stb & self.txcomfinish),
            self.rx_cominit_stb.eq(self.rxcominitdet),
            self.rx_comwake_stb.eq(self.rxcomwakedet),
        ]
        self.submodules += _RisingEdge(self.tx_cominit_stb, self.txcominit)
        self.submodules += _RisingEdge(self.tx_comwake_stb, self.txcomwake)

        self.sync.sata_rx += [
            self.source.valid.eq(1),
            self.source.charisk.eq(self.rxcharisk),
            self.source.data.eq(self.rxdata)
        ]

        self.sync.sata_tx += [
            self.txcharisk.eq(self.sink.charisk),
            self.txdata.eq(self.sink.data),
            self.sink.ready.eq(1),
        ]

        # Internals and clock domain crossing ------------------------------------------------------
        # sys_clk --> sata_tx clk
        txpd = Signal()
        txelecidle = Signal(reset=1)
        txcominit = Signal()
        txcomwake = Signal()
        self.specials += [
            MultiReg(self.txpd, txpd, "sata_tx"),
            MultiReg(self.txelecidle, txelecidle, "sata_tx"),
        ]
        self.submodules += [
            _PulseSynchronizer(self.txcominit, "sys", txcominit, "sata_tx"),
            _PulseSynchronizer(self.txcomwake, "sys", txcomwake, "sata_tx"),
        ]

        # sata_tx clk --> sys clk
        txcomfinish = Signal()
        self.submodules += _PulseSynchronizer(txcomfinish, "sata_tx",
                                              self.txcomfinish, "sys")

        # sata_rx clk --> sys clk
        rxcominitdet = Signal()
        rxcomwakedet = Signal()
        rxratedone = Signal()
        rxdisperr = Signal(data_width // 8)
        rxnotintable = Signal(data_width // 8)
        self.specials += [
            MultiReg(rxcominitdet, self.rxcominitdet, "sys"),
            MultiReg(rxcomwakedet, self.rxcomwakedet, "sys"),
            MultiReg(rxdisperr, self.rxdisperr, "sys"),
            MultiReg(rxnotintable, self.rxnotintable, "sys")
        ]

        # DRP mux ----------------------------------------------------------------------------------
        self.drp = DRPInterface()
        self.submodules.drp_mux = drp_mux = DRPMux()
        drp_mux.add_interface(self.drp)

        # GTYE4_CHANNEL instance -------------------------------------------------------------------
        class Open(Signal):
            pass

        rxphaligndone = Signal()
        self.gty_params = dict(
            p_ACJTAG_DEBUG_MODE=0b0,
            p_ACJTAG_MODE=0b0,
            p_ACJTAG_RESET=0b0,
            p_ADAPT_CFG0=0b0000000000000000,
            p_ADAPT_CFG1=0b1111100000011100,
            p_ADAPT_CFG2=0b0000000000000000,
            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_A_RXOSCALRESET=0b0,
            p_A_RXPROGDIVRESET=0b0,
            p_A_RXTERMINATION=0b1,
            p_A_TXDIFFCTRL=0b01100,
            p_A_TXPROGDIVRESET=0b0,
            p_CBCC_DATA_SOURCE_SEL="DECODED",
            p_CDR_SWAP_MODE_EN=0b0,
            p_CFOK_PWRSVE_EN=0b1,
            p_CHAN_BOND_KEEP_ALIGN="FALSE",
            p_CHAN_BOND_MAX_SKEW=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_CHAN_BOND_SEQ_LEN=1,
            p_CH_HSPMUX=0b0010000000100000,
            p_CKCAL1_CFG_0=0b1100000011000000,
            p_CKCAL1_CFG_1=0b0001000011000000,
            p_CKCAL1_CFG_2=0b0010000000001000,
            p_CKCAL1_CFG_3=0b0000000000000000,
            p_CKCAL2_CFG_0=0b1100000011000000,
            p_CKCAL2_CFG_1=0b1000000011000000,
            p_CKCAL2_CFG_2=0b0001000000000000,
            p_CKCAL2_CFG_3=0b0000000000000000,
            p_CKCAL2_CFG_4=0b0000000000000000,
            p_CLK_CORRECT_USE="FALSE",
            p_CLK_COR_KEEP_IDLE="FALSE",
            p_CLK_COR_MAX_LAT=20 if not rx_buffer_enable else {
                16: 6,
                32: 12
            }[data_width],
            p_CLK_COR_MIN_LAT=18 if not rx_buffer_enable else {
                16: 4,
                32: 8
            }[data_width],
            p_CLK_COR_PRECEDENCE="TRUE",
            p_CLK_COR_REPEAT_WAIT=0,
            p_CLK_COR_SEQ_1_1=0b0100000000,
            p_CLK_COR_SEQ_1_2=0b0100000000,
            p_CLK_COR_SEQ_1_3=0b0100000000,
            p_CLK_COR_SEQ_1_4=0b0100000000,
            p_CLK_COR_SEQ_1_ENABLE=0b1111,
            p_CLK_COR_SEQ_2_1=0b0100000000,
            p_CLK_COR_SEQ_2_2=0b0100000000,
            p_CLK_COR_SEQ_2_3=0b0100000000,
            p_CLK_COR_SEQ_2_4=0b0100000000,
            p_CLK_COR_SEQ_2_ENABLE=0b1111,
            p_CLK_COR_SEQ_2_USE="FALSE",
            p_CLK_COR_SEQ_LEN=1,
            p_CPLL_CFG0=0b0000000111111010,
            p_CPLL_CFG1=0b0000000000101011,
            p_CPLL_CFG2=0b0000000000000010,
            p_CPLL_CFG3=0b0000000000000000,
            p_CPLL_FBDIV=5,
            p_CPLL_FBDIV_45=4,
            p_CPLL_INIT_CFG0=0b0000001010110010,
            p_CPLL_LOCK_CFG=0b0000000111101000,
            p_CPLL_REFCLK_DIV=1,
            p_CTLE3_OCAP_EXT_CTRL=0b000,
            p_CTLE3_OCAP_EXT_EN=0b0,
            p_DDI_CTRL=0b00,
            p_DDI_REALIGN_WAIT=15,
            p_DEC_MCOMMA_DETECT="TRUE",
            p_DEC_PCOMMA_DETECT="TRUE",
            p_DEC_VALID_COMMA_ONLY="TRUE",
            p_DELAY_ELEC=0b0,
            p_DMONITOR_CFG0=0b0000000000,
            p_DMONITOR_CFG1=0b00000000,
            p_ES_CLK_PHASE_SEL=0b0,
            p_ES_CONTROL=0b000000,
            p_ES_ERRDET_EN="FALSE",
            p_ES_EYE_SCAN_EN="FALSE",
            p_ES_HORZ_OFFSET=0b000000000000,
            p_ES_PRESCALE=0b00000,
            p_ES_QUALIFIER0=0b0000000000000000,
            p_ES_QUALIFIER1=0b0000000000000000,
            p_ES_QUALIFIER2=0b0000000000000000,
            p_ES_QUALIFIER3=0b0000000000000000,
            p_ES_QUALIFIER4=0b0000000000000000,
            p_ES_QUALIFIER5=0b0000000000000000,
            p_ES_QUALIFIER6=0b0000000000000000,
            p_ES_QUALIFIER7=0b0000000000000000,
            p_ES_QUALIFIER8=0b0000000000000000,
            p_ES_QUALIFIER9=0b0000000000000000,
            p_ES_QUAL_MASK0=0b0000000000000000,
            p_ES_QUAL_MASK1=0b0000000000000000,
            p_ES_QUAL_MASK2=0b0000000000000000,
            p_ES_QUAL_MASK3=0b0000000000000000,
            p_ES_QUAL_MASK4=0b0000000000000000,
            p_ES_QUAL_MASK5=0b0000000000000000,
            p_ES_QUAL_MASK6=0b0000000000000000,
            p_ES_QUAL_MASK7=0b0000000000000000,
            p_ES_QUAL_MASK8=0b0000000000000000,
            p_ES_QUAL_MASK9=0b0000000000000000,
            p_ES_SDATA_MASK0=0b0000000000000000,
            p_ES_SDATA_MASK1=0b0000000000000000,
            p_ES_SDATA_MASK2=0b0000000000000000,
            p_ES_SDATA_MASK3=0b0000000000000000,
            p_ES_SDATA_MASK4=0b0000000000000000,
            p_ES_SDATA_MASK5=0b0000000000000000,
            p_ES_SDATA_MASK6=0b0000000000000000,
            p_ES_SDATA_MASK7=0b0000000000000000,
            p_ES_SDATA_MASK8=0b0000000000000000,
            p_ES_SDATA_MASK9=0b0000000000000000,
            p_EYESCAN_VP_RANGE=0,
            p_EYE_SCAN_SWAP_EN=0b0,
            p_FTS_DESKEW_SEQ_ENABLE=0b1111,
            p_FTS_LANE_DESKEW_CFG=0b1111,
            p_FTS_LANE_DESKEW_EN="FALSE",
            p_GEARBOX_MODE=0b00000,
            p_ISCAN_CK_PH_SEL2=0b0,
            p_LOCAL_MASTER=0b1,
            p_LPBK_BIAS_CTRL=4,
            p_LPBK_EN_RCAL_B=0b0,
            p_LPBK_EXT_RCAL=0b1000,
            p_LPBK_IND_CTRL0=5,
            p_LPBK_IND_CTRL1=5,
            p_LPBK_IND_CTRL2=5,
            p_LPBK_RG_CTRL=2,
            p_OOBDIVCTL=0b01,
            p_OOB_PWRUP=0b1,
            p_PCI3_AUTO_REALIGN="OVR_1K_BLK",
            p_PCI3_PIPE_RX_ELECIDLE=0b0,
            p_PCI3_RX_ASYNC_EBUF_BYPASS=0b00,
            p_PCI3_RX_ELECIDLE_EI2_ENABLE=0b0,
            p_PCI3_RX_ELECIDLE_H2L_COUNT=0b000000,
            p_PCI3_RX_ELECIDLE_H2L_DISABLE=0b000,
            p_PCI3_RX_ELECIDLE_HI_COUNT=0b000000,
            p_PCI3_RX_ELECIDLE_LP4_DISABLE=0b0,
            p_PCI3_RX_FIFO_DISABLE=0b0,
            p_PCIE3_CLK_COR_EMPTY_THRSH=0b00000,
            p_PCIE3_CLK_COR_FULL_THRSH=0b010000,
            p_PCIE3_CLK_COR_MAX_LAT=0b00100,
            p_PCIE3_CLK_COR_MIN_LAT=0b00000,
            p_PCIE3_CLK_COR_THRSH_TIMER=0b001000,
            p_PCIE_64B_DYN_CLKSW_DIS="FALSE",
            p_PCIE_BUFG_DIV_CTRL=0b0001000000000000,
            p_PCIE_GEN4_64BIT_INT_EN="FALSE",
            p_PCIE_PLL_SEL_MODE_GEN12=0b00,
            p_PCIE_PLL_SEL_MODE_GEN3=0b11,
            p_PCIE_PLL_SEL_MODE_GEN4=0b10,
            p_PCIE_RXPCS_CFG_GEN3=0b0000101010100101,
            p_PCIE_RXPMA_CFG=0b0010100000001010,
            p_PCIE_TXPCS_CFG_GEN3=0b0010110010100100,
            p_PCIE_TXPMA_CFG=0b0010100000001010,
            p_PCS_PCIE_EN="FALSE",
            p_PCS_RSVD0=0b0000000000000000,
            p_PD_TRANS_TIME_FROM_P2=0b000000111100,
            p_PD_TRANS_TIME_NONE_P2=0b00011001,
            p_PD_TRANS_TIME_TO_P2=0b01100100,
            p_PREIQ_FREQ_BST=0,
            p_RATE_SW_USE_DRP=0b1,
            p_RCLK_SIPO_DLY_ENB=0b0,
            p_RCLK_SIPO_INV_EN=0b0,
            p_RTX_BUF_CML_CTRL=0b011,
            p_RTX_BUF_TERM_CTRL=0b00,
            p_RXBUFRESET_TIME=0b00011,
            p_RXBUF_ADDR_MODE="FAST",
            p_RXBUF_EIDLE_HI_CNT=0b1000,
            p_RXBUF_EIDLE_LO_CNT=0b0000,
            p_RXBUF_EN="TRUE" if rx_buffer_enable else "FALSE",
            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_RXBUF_THRESH_OVFLW=0 if not rx_buffer_enable else {
                16: 61,
                32: 57
            }[data_width],
            p_RXBUF_THRESH_OVRD="TRUE" if rx_buffer_enable else "FALSE",
            p_RXBUF_THRESH_UNDFLW=4 if not rx_buffer_enable else {
                16: 1,
                32: 3
            }[data_width],
        )

        self.gty_params.update(
            p_RXCDRFREQRESET_TIME=0b00001,
            p_RXCDRPHRESET_TIME=0b00001,
            p_RXCDR_CFG0=0b0000000000000011,
            p_RXCDR_CFG0_GEN3=0b0000000000000011,
            p_RXCDR_CFG1=0b0000000000000000,
            p_RXCDR_CFG1_GEN3=0b0000000000000000,
            p_RXCDR_CFG2=0b0000001001000010 if gen == "gen1" else
            0b0000001001010011 if gen == "gen2" else 0b0000001001100011,
            p_RXCDR_CFG2_GEN2=0b1001000010 if gen == "gen1" else
            0b1001010011 if gen == "gen2" else 0b1001100011,
            p_RXCDR_CFG2_GEN3=0b0000001001000010 if gen == "gen1" else
            0b0000001001010011 if gen == "gen2" else 0b0000001001100011,
            p_RXCDR_CFG2_GEN4=0b0000000101100100,
            p_RXCDR_CFG3=0b0000000000011010,
            p_RXCDR_CFG3_GEN2=0b011010,
            p_RXCDR_CFG3_GEN3=0b0000000000011010,
            p_RXCDR_CFG3_GEN4=0b0000000000011010,
            p_RXCDR_CFG4=0b0101110011110110,
            p_RXCDR_CFG4_GEN3=0b0101110011110110,
            p_RXCDR_CFG5=0b1011010001101011,
            p_RXCDR_CFG5_GEN3=0b0001010001101011,
            p_RXCDR_FR_RESET_ON_EIDLE=0b0,
            p_RXCDR_HOLD_DURING_EIDLE=0b0,
            p_RXCDR_LOCK_CFG0=0b0010001000000001,
            p_RXCDR_LOCK_CFG1=0b1001111111111111,
            p_RXCDR_LOCK_CFG2=0b000000000000000,
            p_RXCDR_LOCK_CFG3=0b0000000000000000,
            p_RXCDR_LOCK_CFG4=0b0000000000000000,
            p_RXCDR_PH_RESET_ON_EIDLE=0b0,
            p_RXCFOK_CFG0=0b0000000000000000,
            p_RXCFOK_CFG1=0b1000000000010101,
            p_RXCFOK_CFG2=0b0000001010101110,
            p_RXCKCAL1_IQ_LOOP_RST_CFG=0b0000000000000000,
            p_RXCKCAL1_I_LOOP_RST_CFG=0b0000000000000000,
            p_RXCKCAL1_Q_LOOP_RST_CFG=0b0000000000000000,
            p_RXCKCAL2_DX_LOOP_RST_CFG=0b0000000000000000,
            p_RXCKCAL2_D_LOOP_RST_CFG=0b0000000000000000,
            p_RXCKCAL2_S_LOOP_RST_CFG=0b0000000000000000,
            p_RXCKCAL2_X_LOOP_RST_CFG=0b0000000000000000,
            p_RXDFELPMRESET_TIME=0b0001111,
            p_RXDFELPM_KL_CFG0=0b000000000000000,
            p_RXDFELPM_KL_CFG1=0b1010000010000010,
            p_RXDFELPM_KL_CFG2=0b0000000100000000,
            p_RXDFE_CFG0=0b0000101000000000,
            p_RXDFE_CFG1=0b0000000000000000,
            p_RXDFE_GC_CFG0=0b0000000000000000,
            p_RXDFE_GC_CFG1=0b1000000000000000,
            p_RXDFE_GC_CFG2=0b1111111111100000,
            p_RXDFE_H2_CFG0=0b0000000000000000,
            p_RXDFE_H2_CFG1=0b0000000000000010,
            p_RXDFE_H3_CFG0=0b0000000000000000,
            p_RXDFE_H3_CFG1=0b1000000000000010,
            p_RXDFE_H4_CFG0=0b0000000000000000,
            p_RXDFE_H4_CFG1=0b1000000000000010,
            p_RXDFE_H5_CFG0=0b0000000000000000,
            p_RXDFE_H5_CFG1=0b1000000000000010,
            p_RXDFE_H6_CFG0=0b0000000000000000,
            p_RXDFE_H6_CFG1=0b1000000000000010,
            p_RXDFE_H7_CFG0=0b0000000000000000,
            p_RXDFE_H7_CFG1=0b1000000000000010,
            p_RXDFE_H8_CFG0=0b0000000000000000,
            p_RXDFE_H8_CFG1=0b1000000000000010,
            p_RXDFE_H9_CFG0=0b0000000000000000,
            p_RXDFE_H9_CFG1=0b1000000000000010,
            p_RXDFE_HA_CFG0=0b0000000000000000,
            p_RXDFE_HA_CFG1=0b1000000000000010,
            p_RXDFE_HB_CFG0=0b0000000000000000,
            p_RXDFE_HB_CFG1=0b1000000000000010,
            p_RXDFE_HC_CFG0=0b0000000000000000,
            p_RXDFE_HC_CFG1=0b1000000000000010,
            p_RXDFE_HD_CFG0=0b0000000000000000,
            p_RXDFE_HD_CFG1=0b1000000000000010,
            p_RXDFE_HE_CFG0=0b0000000000000000,
            p_RXDFE_HE_CFG1=0b1000000000000010,
            p_RXDFE_HF_CFG0=0b0000000000000000,
            p_RXDFE_HF_CFG1=0b1000000000000010,
            p_RXDFE_KH_CFG0=0b1000000000000000,
            p_RXDFE_KH_CFG1=0b1111111000000000,
            p_RXDFE_KH_CFG2=0b0000001000000000,
            p_RXDFE_KH_CFG3=0b0100000100000001,
            p_RXDFE_OS_CFG0=0b0010000000000000,
            p_RXDFE_OS_CFG1=0b1000000000000000,
            p_RXDFE_UT_CFG0=0b0000000000000000,
            p_RXDFE_UT_CFG1=0b0000000000000011,
            p_RXDFE_UT_CFG2=0b0000000000000000,
            p_RXDFE_VP_CFG0=0b0000000000000000,
            p_RXDFE_VP_CFG1=0b0000000000110011,
            p_RXDLY_CFG=0b0000000000010000,
            p_RXDLY_LCFG=0b0000000000110000,
            p_RXELECIDLE_CFG="SIGCFG_4",
            p_RXGBOX_FIFO_INIT_RD_ADDR=4,
            p_RXGEARBOX_EN="FALSE",
            p_RXISCANRESET_TIME=0b00001,
            p_RXLPM_CFG=0b0000000000000000,
            p_RXLPM_GC_CFG=0b1111100000000000,
            p_RXLPM_KH_CFG0=0b0000000000000000,
            p_RXLPM_KH_CFG1=0b1010000000000010,
            p_RXLPM_OS_CFG0=0b0000000000000000,
            p_RXLPM_OS_CFG1=0b1000000000000010,
            p_RXOOB_CFG=0b000000110,
            p_RXOOB_CLK_CFG="PMA",
            p_RXOSCALRESET_TIME=0b00011,
            p_RXOUT_DIV=rxout_div,
            p_RXPCSRESET_TIME=0b00011,
            p_RXPHBEACON_CFG=0b0000000000000000,
            p_RXPHDLY_CFG=0b0010000001110000,
            p_RXPHSAMP_CFG=0b0010000100000000,
            p_RXPHSLIP_CFG=0b1001100100110011,
            p_RXPH_MONITOR_SEL=0b00000,
            p_RXPI_CFG0=0b0000001100000001,
            p_RXPI_CFG1=0b0000000011111100,
            p_RXPMACLK_SEL="DATA",
            p_RXPMARESET_TIME=0b00011,
            p_RXPRBS_ERR_LOOPBACK=0b0,
            p_RXPRBS_LINKACQ_CNT=15,
            p_RXREFCLKDIV2_SEL=0b0,
            p_RXSLIDE_AUTO_WAIT=7,
            p_RXSLIDE_MODE="PCS",
            p_RXSYNC_MULTILANE=0b0,
            p_RXSYNC_OVRD=0b0,
            p_RXSYNC_SKIP_DA=0b0,
            p_RX_AFE_CM_EN=0b0,
            p_RX_BIAS_CFG0=0b0001001010110000,
            p_RX_BUFFER_CFG=0b000000,
            p_RX_CAPFF_SARC_ENB=0b0,
            p_RX_CLK25_DIV=6,
            p_RX_CLKMUX_EN=0b1,
            p_RX_CLK_SLIP_OVRD=0b00000,
            p_RX_CM_BUF_CFG=0b1010,
            p_RX_CM_BUF_PD=0b0,
            p_RX_CM_SEL=3,
            p_RX_CM_TRIM=10,
            p_RX_CTLE_PWR_SAVING=0b0,
            p_RX_CTLE_RES_CTRL=0b0000,
            p_RX_DATA_WIDTH=20 if data_width == 16 else 40,
            p_RX_DDI_SEL=0b000000,
            p_RX_DEFER_RESET_BUF_EN="TRUE",
            p_RX_DEGEN_CTRL=0b100,
            p_RX_DFELPM_CFG0=10,
            p_RX_DFELPM_CFG1=0b1,
            p_RX_DFELPM_KLKH_AGC_STUP_EN=0b1,
            p_RX_DFE_AGC_CFG1=2,
            p_RX_DFE_KL_LPM_KH_CFG0=3,
            p_RX_DFE_KL_LPM_KH_CFG1=2,
            p_RX_DFE_KL_LPM_KL_CFG0=0b11,
            p_RX_DFE_KL_LPM_KL_CFG1=2,
            p_RX_DFE_LPM_HOLD_DURING_EIDLE=0b0,
            p_RX_DISPERR_SEQ_MATCH="TRUE",
            p_RX_DIVRESET_TIME=0b00001,
            p_RX_EN_CTLE_RCAL_B=0b0,
            p_RX_EN_SUM_RCAL_B=0,
            p_RX_EYESCAN_VS_CODE=0b0000000,
            p_RX_EYESCAN_VS_NEG_DIR=0b0,
            p_RX_EYESCAN_VS_RANGE=0b10,
            p_RX_EYESCAN_VS_UT_SIGN=0b0,
            p_RX_FABINT_USRCLK_FLOP=0b0,
            p_RX_I2V_FILTER_EN=0b1,
            p_RX_INT_DATAWIDTH=0 if data_width == 16 else 1,
            p_RX_PMA_POWER_SAVE=0b0,
            p_RX_PMA_RSV0=0b0000000000101111,
            p_RX_PROGDIV_CFG=rx_progdiv_cfg,
            p_RX_PROGDIV_RATE=0b0000000000000001,
            p_RX_RESLOAD_CTRL=0b0000,
            p_RX_RESLOAD_OVRD=0b0,
            p_RX_SAMPLE_PERIOD=0b111,
            p_RX_SIG_VALID_DLY=11,
            p_RX_SUM_DEGEN_AVTT_OVERITE=0,
            p_RX_SUM_DFETAPREP_EN=0b0,
            p_RX_SUM_IREF_TUNE=0b0000,
            p_RX_SUM_PWR_SAVING=0,
            p_RX_SUM_RES_CTRL=0b0000,
            p_RX_SUM_VCMTUNE=0b0011,
            p_RX_SUM_VCM_BIAS_TUNE_EN=0b1,
            p_RX_SUM_VCM_OVWR=0b0,
            p_RX_SUM_VREF_TUNE=0b100,
            p_RX_TUNE_AFE_OS=0b10,
            p_RX_VREG_CTRL=0b010,
            p_RX_VREG_PDB=0b1,
            p_RX_WIDEMODE_CDR=0b00,
            p_RX_WIDEMODE_CDR_GEN3=0b00,
            p_RX_WIDEMODE_CDR_GEN4=0b01,
            p_RX_XCLK_SEL="RXDES" if rx_buffer_enable else "RXUSR",
            p_RX_XMODE_SEL=0b1,
            p_SAMPLE_CLK_PHASE=0b0,
            p_SAS_12G_MODE=0b0,
            p_SATA_BURST_SEQ_LEN=0b0110,
            p_SATA_BURST_VAL=0b100,
            p_SATA_CPLL_CFG="VCO_3000MHZ",
            p_SATA_EIDLE_VAL=0b100,
            p_SHOW_REALIGN_COMMA="FALSE",
            p_SIM_DEVICE="ULTRASCALE_PLUS",
            p_SIM_MODE="FAST",
            p_SIM_RECEIVER_DETECT_PASS="******",
            p_SIM_RESET_SPEEDUP="TRUE",
            p_SIM_TX_EIDLE_DRIVE_LEVEL="Z",
            p_SRSTMODE=0b0,
            p_TAPDLY_SET_TX=0b00,
            p_TERM_RCAL_CFG=0b100001000000010,
            p_TERM_RCAL_OVRD=0b001,
            p_TRANS_TIME_RATE=0b00001110,
            p_TST_RSV0=0b00000000,
            p_TST_RSV1=0b00000000,
        )

        self.gty_params.update(
            p_TXBUF_EN="TRUE" if tx_buffer_enable else "FALSE",
            p_TXBUF_RESET_ON_RATE_CHANGE="TRUE",
            p_TXDLY_CFG=0b1000000000010000,
            p_TXDLY_LCFG=0b0000000000110000,
            p_TXDRV_FREQBAND=0,
            p_TXFE_CFG0=0b0000001111000010,
            p_TXFE_CFG1=0b0110110000000000,
            p_TXFE_CFG2=0b0110110000000000,
            p_TXFE_CFG3=0b0110110000000000,
            p_TXFIFO_ADDR_CFG="LOW",
            p_TXGBOX_FIFO_INIT_RD_ADDR=4,
            p_TXGEARBOX_EN="FALSE",
            p_TXOUT_DIV=txout_div,
            p_TXPCSRESET_TIME=0b00011,
            p_TXPHDLY_CFG0=0b0110000001110000,
            p_TXPHDLY_CFG1=0b0000000000001010
            if gen == "gen3" else 0b0000000000001111,
            p_TXPH_CFG=0b0000011100100011
            if gen == "gen1" else 0b0000001100100011,
            p_TXPH_CFG2=0b0000000000000000,
            p_TXPH_MONITOR_SEL=0b00000,
            p_TXPI_CFG0=0b0000001100000000,
            p_TXPI_CFG1=0b0111010101010101,
            p_TXPI_GRAY_SEL=0b0,
            p_TXPI_INVSTROBE_SEL=0b0,
            p_TXPI_PPM=0b0,
            p_TXPI_PPM_CFG=0b00000000,
            p_TXPI_SYNFREQ_PPM=0b001,
            p_TXPMARESET_TIME=0b00011,
            p_TXREFCLKDIV2_SEL=0b0,
            p_TXSWBST_BST=1,
            p_TXSWBST_EN=0,
            p_TXSWBST_MAG=4,
            p_TXSYNC_MULTILANE=0b0,
            p_TXSYNC_OVRD=0b0,
            p_TXSYNC_SKIP_DA=0b0,
            p_TX_CLK25_DIV=6,
            p_TX_CLKMUX_EN=0b1,
            p_TX_DATA_WIDTH=20 if data_width == 16 else 40,
            p_TX_DCC_LOOP_RST_CFG=0b0000000000000100,
            p_TX_DEEMPH0=0b000000,
            p_TX_DEEMPH1=0b000000,
            p_TX_DEEMPH2=0b000000,
            p_TX_DEEMPH3=0b000000,
            p_TX_DIVRESET_TIME=0b00001,
            p_TX_DRIVE_MODE="DIRECT",
            p_TX_EIDLE_ASSERT_DELAY=0b100,
            p_TX_EIDLE_DEASSERT_DELAY=0b011,
            p_TX_FABINT_USRCLK_FLOP=0b0,
            p_TX_FIFO_BYP_EN=0 if tx_buffer_enable else 1,
            p_TX_IDLE_DATA_ZERO=0b0,
            p_TX_INT_DATAWIDTH=0 if data_width == 16 else 1,
            p_TX_LOOPBACK_DRIVE_HIZ="FALSE",
            p_TX_MAINCURSOR_SEL=0b0,
            p_TX_MARGIN_FULL_0=0b1011000,
            p_TX_MARGIN_FULL_1=0b1010111,
            p_TX_MARGIN_FULL_2=0b1010101,
            p_TX_MARGIN_FULL_3=0b1010011,
            p_TX_MARGIN_FULL_4=0b1010001,
            p_TX_MARGIN_LOW_0=0b1001100,
            p_TX_MARGIN_LOW_1=0b1001011,
            p_TX_MARGIN_LOW_2=0b1001000,
            p_TX_MARGIN_LOW_3=0b1000010,
            p_TX_MARGIN_LOW_4=0b1000000,
            p_TX_PHICAL_CFG0=0b0000000000100000,
            p_TX_PHICAL_CFG1=0b0000000001000000,
            p_TX_PI_BIASSET=0,
            p_TX_PMADATA_OPT=0b0,
            p_TX_PMA_POWER_SAVE=0b0,
            p_TX_PMA_RSV0=0b0000000000000000,
            p_TX_PMA_RSV1=0b0000000000000000,
            p_TX_PROGCLK_SEL="PREPI",
            p_TX_PROGDIV_CFG=tx_progdiv_cfg,
            p_TX_PROGDIV_RATE=0b0000000000000001,
            p_TX_RXDETECT_CFG=0b00000000110010,
            p_TX_RXDETECT_REF=5,
            p_TX_SAMPLE_PERIOD=0b111,
            p_TX_SW_MEAS=0b00,
            p_TX_VREG_CTRL=0b011,
            p_TX_VREG_PDB=0b1,
            p_TX_VREG_VREFSEL=0b10,
            p_TX_XCLK_SEL="TXOUT" if tx_buffer_enable else "TXUSR",
            p_USB_BOTH_BURST_IDLE=0b0,
            p_USB_BURSTMAX_U3WAKE=0b1111111,
            p_USB_BURSTMIN_U3WAKE=0b1100011,
            p_USB_CLK_COR_EQ_EN=0b0,
            p_USB_EXT_CNTL=0b1,
            p_USB_IDLEMAX_POLLING=0b1010111011,
            p_USB_IDLEMIN_POLLING=0b0100101011,
            p_USB_LFPSPING_BURST=0b000000101,
            p_USB_LFPSPOLLING_BURST=0b000110001,
            p_USB_LFPSPOLLING_IDLE_MS=0b000000100,
            p_USB_LFPSU1EXIT_BURST=0b000011101,
            p_USB_LFPSU2LPEXIT_BURST_MS=0b001100011,
            p_USB_LFPSU3WAKE_BURST_MS=0b111110011,
            p_USB_LFPS_TPERIOD=0b0011,
            p_USB_LFPS_TPERIOD_ACCURATE=0b1,
            p_USB_MODE=0b0,
            p_USB_PCIE_ERR_REP_DIS=0b0,
            p_USB_PING_SATA_MAX_INIT=21,
            p_USB_PING_SATA_MIN_INIT=12,
            p_USB_POLL_SATA_MAX_BURST=8,
            p_USB_POLL_SATA_MIN_BURST=4,
            p_USB_RAW_ELEC=0b0,
            p_USB_RXIDLE_P0_CTRL=0b1,
            p_USB_TXIDLE_TUNE_ENABLE=0b1,
            p_USB_U1_SATA_MAX_WAKE=7,
            p_USB_U1_SATA_MIN_WAKE=4,
            p_USB_U2_SAS_MAX_COM=64,
            p_USB_U2_SAS_MIN_COM=36,
            p_USE_PCS_CLK_PHASE_SEL=0b0,
            p_Y_ALL_MODE=0b0)
        self.gty_params.update(
            #
            i_PCSRSVDIN=0x00,
            i_GTRSVD=0x0000,
            i_TSTIN=0,  #2**20-1,

            # Reset modes
            i_GTTXRESETSEL=0,
            i_GTRXRESETSEL=0,
            i_RESETOVRD=0,

            # DRP
            i_DRPADDR=drp_mux.addr,
            i_DRPCLK=drp_mux.clk,
            i_DRPDI=drp_mux.di,
            o_DRPDO=drp_mux.do,
            i_DRPEN=drp_mux.en,
            o_DRPRDY=drp_mux.rdy,
            i_DRPWE=drp_mux.we,

            # CPLL
            i_CPLLRESET=0,
            i_CPLLPD=self.cpllreset,
            o_CPLLLOCK=self.cplllock,
            i_CPLLLOCKEN=1,
            i_CPLLREFCLKSEL=0b111,
            i_GTGREFCLK=self.refclk,

            # QPLL
            i_QPLL0CLK=0,
            i_QPLL0REFCLK=0,
            i_QPLL1CLK=0,
            i_QPLL1REFCLK=0,
            i_QPLL0FREQLOCK=0,
            i_QPLL1FREQLOCK=0,

            # TX clock
            o_TXOUTCLK=self.txoutclk,
            i_TXSYSCLKSEL=0b00,
            i_TXPLLCLKSEL=0b00,
            i_TXOUTCLKSEL=0b010 if tx_buffer_enable else 0b101,

            # TX Startup/Reset
            i_GTTXRESET=tx_init.gtXxreset,
            o_TXRESETDONE=tx_init.Xxresetdone,
            i_TXDLYSRESET=tx_init.Xxdlysreset,
            o_TXDLYSRESETDONE=tx_init.Xxdlysresetdone,
            o_TXPHALIGNDONE=tx_init.Xxphaligndone,
            i_TXUSERRDY=tx_init.Xxuserrdy,
            i_TXSYNCMODE=1,
            i_TXDLYBYPASS=1 if tx_buffer_enable else 0,
            i_TXPHDLYPD=1 if tx_buffer_enable else 0,

            # Transmit Ports - TX 8B/10B Encoder Ports
            i_TX8B10BBYPASS=0,

            # TX data
            i_TXCTRL0=0,
            i_TXCTRL1=0,
            i_TXCTRL2=self.txcharisk,
            i_TXDATA=self.txdata,
            i_TXUSRCLK=self.txusrclk,
            i_TXUSRCLK2=self.txusrclk2,

            # Power-Down Ports
            i_RXPD=Replicate(self.rxpd, 2),
            i_TXPD=Replicate(txpd, 2),

            # TX electrical
            i_TXDIFFCTRL=0b1100,
            i_TXINHIBIT=0,

            # Transmit Ports - PCI Express Ports
            i_TXPDELECIDLEMODE=0,
            i_TXELECIDLE=txelecidle,
            i_TXMARGIN=0b000,
            i_TXRATE=0b000,
            i_TXSWING=0,

            # Internal Loopback
            i_LOOPBACK=0b000,

            # RX Startup/Reset
            i_GTRXRESET=rx_init.gtXxreset,
            o_RXRESETDONE=rx_init.Xxresetdone,
            i_RXDLYSRESET=rx_init.Xxdlysreset,
            o_RXDLYSRESETDONE=rx_init.Xxdlysresetdone,
            i_RXPMARESET=0,
            o_RXPHALIGNDONE=rxphaligndone,
            i_RXSYNCALLIN=rxphaligndone,
            i_RXUSERRDY=rx_init.Xxuserrdy,
            i_RXSYNCIN=0,
            i_RXSYNCMODE=1,
            o_RXSYNCDONE=rx_init.Xxsyncdone,
            i_RXDLYBYPASS=1 if rx_buffer_enable else 0,
            i_RXPHDLYPD=1 if rx_buffer_enable else 0,

            # RX AFE
            i_RXDFEXYDEN=1,
            i_RXLPMEN=1,

            # RX clock
            i_RXRATE=0,
            i_RXSYSCLKSEL=0b00,
            i_RXOUTCLKSEL=0b010,
            i_RXPLLCLKSEL=0b00,
            o_RXOUTCLK=self.rxoutclk,
            i_RXUSRCLK=self.rxusrclk,
            i_RXUSRCLK2=self.rxusrclk2,

            # FPGA RX Interface Datapath Configuration
            i_RX8B10BEN=1,

            # Receive Ports - CDR Ports
            i_RXCDRFREQRESET=0,
            i_RXCDRHOLD=self.rx_cdrhold,
            o_RXCDRLOCK=Open(),
            i_RXCDROVRDEN=0,
            i_RXCDRRESET=0,
            i_RXOSCALRESET=0,
            o_RXOSINTDONE=Open(),
            o_RXOSINTSTARTED=Open(),
            o_RXOSINTSTROBEDONE=Open(),
            o_RXOSINTSTROBESTARTED=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,
            i_RXSLIDE=0,
            o_GTPOWERGOOD=Open(),

            # Receive Ports - RX OOB Signaling ports
            o_RXCOMSASDET=Open(),
            o_RXCOMWAKEDET=rxcomwakedet,
            o_RXCOMINITDET=rxcominitdet,

            # Receive Ports - RX OOB signalling Ports
            o_RXELECIDLE=Open(),
            i_RXELECIDLEMODE=0b00,

            # Transmit Ports - TX OOB signaling Ports
            o_TXCOMFINISH=txcomfinish,
            i_TXCOMINIT=txcominit,
            i_TXCOMSAS=0,
            i_TXCOMWAKE=txcomwake,

            # FPGA TX Interface Datapath Configuration
            i_TX8B10BEN=1,

            # RX data
            o_RXCTRL0=self.rxctrl0,
            o_RXCTRL1=self.rxctrl1,
            o_RXCTRL2=self.rxctrl2,
            o_RXCTRL3=self.rxctrl3,
            o_RXDATA=self.rxdata,

            # Polarity
            i_TXPOLARITY=self.tx_polarity,
            i_RXPOLARITY=self.rx_polarity,

            # Pads
            i_GTYRXP=pads.rx_p,
            i_GTYRXN=pads.rx_n,
            o_GTYTXP=pads.tx_p,
            o_GTYTXN=pads.tx_n)

        self.specials += Instance("GTYE4_CHANNEL", **self.gty_params)
Exemple #3
0
    def __init__(self, pads, gen, clk_freq, data_width=16):
        assert data_width in [16, 32]
        # Common signals
        self.data_width = data_width

        # Control
        self.ready = Signal()  # o

        self.tx_idle = Signal()  # i

        self.tx_cominit_stb = Signal()  # i
        self.tx_cominit_ack = Signal()  # o
        self.tx_comwake_stb = Signal()  # i
        self.tx_comwake_ack = Signal()  # o

        self.rx_idle = Signal()  # o
        self.rx_cdrhold = Signal()  # i

        self.rx_cominit_stb = Signal()  # o
        self.rx_comwake_stb = Signal()  # o

        self.rxdisperr = Signal(data_width // 8)  # o
        self.rxnotintable = Signal(data_width // 8)  # o

        # Datapath
        self.sink = stream.Endpoint(phy_description(data_width))
        self.source = stream.Endpoint(phy_description(data_width))

        # K7 specific signals
        # Channel - Ref Clock Ports
        self.gtrefclk0 = Signal()

        # Quadl PLL
        self.qplllock = Signal()

        # Receive Ports - 8b10b Decoder
        self.rxcharisk = Signal(data_width // 8)

        # Receive Ports - RX Data Path interface
        self.rxdata = Signal(data_width)
        self.rxoutclk = Signal()
        self.rxusrclk = Signal()
        self.rxusrclk2 = Signal()

        # Receive Ports - RX Ports for SATA
        self.rxcominitdet = Signal()
        self.rxcomwakedet = Signal()

        # Transmit Ports - 8b10b Encoder Control Ports
        self.txcharisk = Signal(data_width // 8)

        # Transmit Ports - TX Data Path interface
        self.txdata = Signal(data_width)
        self.txoutclk = Signal()
        self.txusrclk = Signal()
        self.txusrclk2 = Signal()

        # Transmit Ports - TX Ports for PCI Express
        self.txelecidle = Signal(reset=1)

        # Transmit Ports - TX Ports for SATA
        self.txcomfinish = Signal()
        self.txcominit = Signal()
        self.txcomwake = Signal()

        # Power-down signals
        self.cpllpd = Signal()
        self.rxpd = Signal()
        self.txpd = Signal()

        # Config at startup
        div_config = {
            "gen1": 4,
            "gen2": 2,
            "gen3": 1,
        }
        rxout_div = div_config[gen]
        txout_div = div_config[gen]

        cdr_config = {
            "gen1": 0x0000047fe106024481010,
            "gen2": 0x0000047fe206024481010,
            "gen3": 0x0000087fe206024441010,
        }
        rxcdr_cfg = cdr_config[gen]

        # TX Init ----------------------------------------------------------------------------------
        self.submodules.tx_init = tx_init = GTPTXInit(clk_freq,
                                                      buffer_enable=False)
        self.comb += tx_init.plllock.eq(self.qplllock)

        # RX Init ----------------------------------------------------------------------------------
        self.submodules.rx_init = rx_init = GTPRXInit(clk_freq,
                                                      buffer_enable=False)
        self.comb += rx_init.plllock.eq(self.qplllock)

        # Ready ------------------------------------------------------------------------------------
        self.comb += self.ready.eq(tx_init.done & rx_init.done)

        # Specific / Generic signals encoding/decoding ---------------------------------------------
        self.comb += [
            self.txelecidle.eq(self.tx_idle | self.txpd),
            self.tx_cominit_ack.eq(self.tx_cominit_stb & self.txcomfinish),
            self.tx_comwake_ack.eq(self.tx_comwake_stb & self.txcomfinish),
            self.rx_cominit_stb.eq(self.rxcominitdet),
            self.rx_comwake_stb.eq(self.rxcomwakedet),
        ]
        self.submodules += _RisingEdge(self.tx_cominit_stb, self.txcominit)
        self.submodules += _RisingEdge(self.tx_comwake_stb, self.txcomwake)

        self.sync.sata_rx += [
            self.source.valid.eq(1),
            self.source.charisk.eq(self.rxcharisk),
            self.source.data.eq(self.rxdata)
        ]

        self.sync.sata_tx += [
            self.txcharisk.eq(self.sink.charisk),
            self.txdata.eq(self.sink.data),
            self.sink.ready.eq(1),
        ]

        # Internals and clock domain crossing ------------------------------------------------------
        # sys_clk --> sata_tx clk
        txpd = Signal()
        txelecidle = Signal(reset=1)
        txcominit = Signal()
        txcomwake = Signal()
        self.specials += [
            MultiReg(self.txpd, txpd, "sata_tx"),
            MultiReg(self.txelecidle, txelecidle, "sata_tx"),
        ]
        self.submodules += [
            _PulseSynchronizer(self.txcominit, "sys", txcominit, "sata_tx"),
            _PulseSynchronizer(self.txcomwake, "sys", txcomwake, "sata_tx"),
        ]

        # sata_tx clk --> sys clk
        txcomfinish = Signal()
        self.submodules += _PulseSynchronizer(txcomfinish, "sata_tx",
                                              self.txcomfinish, "sys")

        # sata_rx clk --> sys clk
        rxcominitdet = Signal()
        rxcomwakedet = Signal()
        rxratedone = Signal()
        rxdisperr = Signal(data_width // 8)
        rxnotintable = Signal(data_width // 8)
        self.specials += [
            MultiReg(rxcominitdet, self.rxcominitdet, "sys"),
            MultiReg(rxcomwakedet, self.rxcomwakedet, "sys"),
            MultiReg(rxdisperr, self.rxdisperr, "sys"),
            MultiReg(rxnotintable, self.rxnotintable, "sys")
        ]

        # QPLL ------------------------------------------------------------------------------------
        linerate_config = {"gen1": 1.5e9, "gen2": 3.0e9, "gen3": 6.0e9}
        self.submodules.qpll = GTPQuadPLL(self.gtrefclk0, 150e6,
                                          linerate_config[gen])
        self.comb += self.qplllock.eq(self.qpll.lock)

        # OOB clock (75MHz) ------------------------------------------------------------------------
        oobclk = Signal()
        self.specials += Instance("FDPE",
                                  p_INIT=1,
                                  i_CE=1,
                                  i_PRE=0,
                                  i_C=self.gtrefclk0,
                                  i_D=~oobclk,
                                  o_Q=oobclk)

        # GTPE2_CHANNEL Instance -------------------------------------------------------------------
        class Open(Signal):
            pass

        tx_buffer_enable = False
        rx_buffer_enable = False
        rxphaligndone = Signal()
        gtp_params = dict(
            # Simulation-Only Attributes
            p_SIM_RECEIVER_DETECT_PASS="******",
            p_SIM_TX_EIDLE_DRIVE_LEVEL="X",
            p_SIM_RESET_SPEEDUP="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 if data_width == 16 else 4,
            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" if rx_buffer_enable else "PCS",
            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 if data_width == 16 else 20,
            p_CLK_COR_MIN_LAT=7 if data_width == 16 else 16,
            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 if data_width == 16 else 40,

            # PMA Attributes
            p_OUTREFCLK_SEL_INV=0b11,
            p_PMA_RSV=0x00000333,
            p_PMA_RSV2=0x00002040,
            p_PMA_RSV3=0b00,
            p_PMA_RSV4=0b0000,
            p_RX_BIAS_CFG=0b0000111100110011,
            p_DMONITOR_CFG=0x000A00,
            p_RX_CM_SEL=0b11,
            p_RX_CM_TRIM=0b1010,
            p_RX_DEBUG_CFG=0b00000000000000,
            p_RX_OS_CFG=0b0000010000000,
            p_TERM_RCAL_CFG=0b100001000010000,
            p_TERM_RCAL_OVRD=0b000,
            p_TST_RSV=0x00000000,
            p_RX_CLK25_DIV=6,
            p_TX_CLK25_DIV=6,
            p_UCODEER_CLR=0b0,

            # PCI Express Attributes
            p_PCS_PCIE_EN="FALSE",

            # PCS Attributes
            p_PCS_RSVD_ATTR=0x100,

            # RX Buffer Attributes
            p_RXBUF_ADDR_MODE="FAST",
            p_RXBUF_EIDLE_HI_CNT=0b1000,
            p_RXBUF_EIDLE_LO_CNT=0b0000,
            p_RXBUF_EN="TRUE" if rx_buffer_enable else "FALSE",
            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=0xC00002,
            p_RXPHDLY_CFG=0x084020,
            p_RXPH_MONITOR_SEL=0b00000,
            p_RX_XCLK_SEL="RXREC" if rx_buffer_enable else "RXUSR",
            p_RX_DDI_SEL=0b000000,
            p_RX_DEFER_RESET_BUF_EN="TRUE",

            # CDR Attributes
            p_RXCDR_CFG=rxcdr_cfg,
            p_RXCDR_FR_RESET_ON_EIDLE=0b0,
            p_RXCDR_HOLD_DURING_EIDLE=0b0,
            p_RXCDR_PH_RESET_ON_EIDLE=0b0,
            p_RXCDR_LOCK_CFG=0b001001,

            # 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=0b111,
            p_SATA_EIDLE_VAL=0b111,
            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" if tx_buffer_enable else "FALSE",
            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" if tx_buffer_enable else "TXUSR",

            # FPGA TX Interface Attributes
            p_TX_DATA_WIDTH=20 if data_width == 16 else 40,

            # 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,

            # JTAG Attributes
            p_ACJTAG_DEBUG_MODE=0b0,
            p_ACJTAG_MODE=0b0,
            p_ACJTAG_RESET=0b0,

            # CDR Attributes
            p_CFOK_CFG=0x49000040E80,
            p_CFOK_CFG2=0b0100000,
            p_CFOK_CFG3=0b0100000,
            p_CFOK_CFG4=0b0,
            p_CFOK_CFG5=0x0,
            p_CFOK_CFG6=0b0000,
            p_RXOSCALRESET_TIME=0b00011,
            p_RXOSCALRESET_TIMEOUT=0b00000,

            # PMA Attributes
            p_CLK_COMMON_SWING=0b0,
            p_RX_CLKMUX_EN=0b1,
            p_TX_CLKMUX_EN=0b1,
            p_ES_CLK_PHASE_SEL=0b0,
            p_USE_PCS_CLK_PHASE_SEL=0b0,
            p_PMA_RSV6=0b0,
            p_PMA_RSV7=0b0,

            # TX Configuration Driver Attributes
            p_TX_PREDRIVER_MODE=0b0,
            p_PMA_RSV5=0b0,
            p_SATA_PLL_CFG="VCO_3000MHZ",

            # RX Fabric Clock Output Control Attributes
            p_RXOUT_DIV=rxout_div,

            # TX Fabric Clock Output Control Attributes
            p_TXOUT_DIV=txout_div,

            # RX Phase Interpolator Attributes
            p_RXPI_CFG0=0b000,
            p_RXPI_CFG1=0b1,
            p_RXPI_CFG2=0b1,

            # RX Equalizer Attributes
            p_ADAPT_CFG0=0x00000,
            p_RXLPMRESET_TIME=0b0001111,
            p_RXLPM_BIAS_STARTUP_DISABLE=0b0,
            p_RXLPM_CFG=0b0110,
            p_RXLPM_CFG1=0b0,
            p_RXLPM_CM_CFG=0b0,
            p_RXLPM_GC_CFG=0b111100010,
            p_RXLPM_GC_CFG2=0b001,
            p_RXLPM_HF_CFG=0b00001111110000,
            p_RXLPM_HF_CFG2=0b01010,
            p_RXLPM_HF_CFG3=0b0000,
            p_RXLPM_HOLD_DURING_EIDLE=0b0,
            p_RXLPM_INCM_CFG=0b1,
            p_RXLPM_IPCM_CFG=0b0,
            p_RXLPM_LF_CFG=0b000000001111110000,
            p_RXLPM_LF_CFG2=0b01010,
            p_RXLPM_OSINT_CFG=0b100,

            # TX Phase Interpolator PPM Controller Attributes
            p_TXPI_CFG0=0b00,
            p_TXPI_CFG1=0b00,
            p_TXPI_CFG2=0b00,
            p_TXPI_CFG3=0b0,
            p_TXPI_CFG4=0b0,
            p_TXPI_CFG5=0b000,
            p_TXPI_GREY_SEL=0b0,
            p_TXPI_INVSTROBE_SEL=0b0,
            p_TXPI_PPMCLK_SEL="TXUSRCLK2",
            p_TXPI_PPM_CFG=0x00,
            p_TXPI_SYNFREQ_PPM=0b001,

            # LOOPBACK Attributes
            p_LOOPBACK_CFG=0b0,
            p_PMA_LOOPBACK_CFG=0b0,

            # RX OOB Signalling Attributes
            p_RXOOB_CLK_CFG="FABRIC",

            # TX OOB Signalling Attributes
            p_TXOOB_CFG=0b0,

            # RX Buffer Attributes
            p_RXSYNC_MULTILANE=0b0,
            p_RXSYNC_OVRD=0b0,
            p_RXSYNC_SKIP_DA=0b0,

            # TX Buffer Attributes
            p_TXSYNC_MULTILANE=0b0,
            p_TXSYNC_OVRD=0b1,
            p_TXSYNC_SKIP_DA=0b0)
        gtp_params.update(
            # CPLL Ports
            i_GTRSVD=0b0000000000000000,
            i_PCSRSVDIN=0b0000000000000000,
            i_TSTIN=0b11111111111111111111,

            # 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
            i_RXSYSCLKSEL=0b00,
            i_TXSYSCLKSEL=0b00,

            # FPGA TX Interface Datapath Configuration
            i_TX8B10BEN=1,

            # GTPE2_CHANNEL Clocking Ports
            i_PLL0CLK=self.qpll.clk,
            i_PLL0REFCLK=self.qpll.refclk,
            i_PLL1CLK=0,
            i_PLL1REFCLK=0,

            # Loopback Ports
            i_LOOPBACK=0,

            # PCI Express Ports
            o_PHYSTATUS=Open(),
            i_RXRATE=0,
            o_RXVALID=Open(),

            # PMA Reserved Ports
            i_PMARSVDIN3=0b0,
            i_PMARSVDIN4=0b0,

            # Power-Down Ports
            i_RXPD=Cat(rx_init.gtrxpd, rx_init.gtrxpd),
            i_TXPD=0b00,

            # RX 8B/10B Decoder Ports
            i_SETERRSTATUS=0,

            # RX Initialization and Reset Ports
            i_EYESCANRESET=0,
            i_RXUSERRDY=rx_init.rxuserrdy,

            # RX Margin Analysis Ports
            o_EYESCANDATAERROR=Open(),
            i_EYESCANMODE=0,
            i_EYESCANTRIGGER=0,

            # Receive Ports
            i_CLKRSVD0=0,
            i_CLKRSVD1=0,
            i_DMONFIFORESET=0,
            i_DMONITORCLK=0,
            o_RXPMARESETDONE=rx_init.rxpmaresetdone,
            i_SIGVALIDCLK=oobclk,

            # Receive Ports - CDR Ports
            i_RXCDRFREQRESET=0,
            i_RXCDRHOLD=self.rx_cdrhold,
            o_RXCDRLOCK=Open(),
            i_RXCDROVRDEN=0,
            i_RXCDRRESET=0,
            i_RXCDRRESETRSV=0,
            i_RXOSCALRESET=0,
            i_RXOSINTCFG=0b0010,
            o_RXOSINTDONE=Open(),
            i_RXOSINTHOLD=0,
            i_RXOSINTOVRDEN=0,
            i_RXOSINTPD=0,
            o_RXOSINTSTARTED=Open(),
            i_RXOSINTSTROBE=0,
            o_RXOSINTSTROBESTARTED=Open(),
            i_RXOSINTTESTOVRDEN=0,

            # Receive Ports - Clock Correction Ports
            o_RXCLKCORCNT=Open(),

            # Receive Ports - FPGA RX Interface Datapath Configuration
            i_RX8B10BEN=1,

            # Receive Ports - FPGA RX Interface Ports
            i_RXUSRCLK=self.rxusrclk,
            i_RXUSRCLK2=self.rxusrclk2,

            # Receive Ports - FPGA RX interface Ports
            o_RXDATA=self.rxdata,
            # Receive Ports - Pattern Checker Ports
            o_RXPRBSERR=Open(),
            i_RXPRBSSEL=0b000,

            # Receive Ports - Pattern Checker ports
            i_RXPRBSCNTRESET=0,

            # Receive Ports - RX 8B/10B Decoder Ports
            o_RXCHARISCOMMA=Open(),
            o_RXCHARISK=self.rxcharisk,
            o_RXDISPERR=rxdisperr,
            o_RXNOTINTABLE=rxnotintable,

            # Receive Ports - RX AFE Ports
            i_GTPRXN=pads.rxn,
            i_GTPRXP=pads.rxp,
            i_PMARSVDIN2=0b0,
            o_PMARSVDOUT0=Open(),
            o_PMARSVDOUT1=Open(),

            # Receive Ports - RX Buffer Bypass Ports
            i_RXBUFRESET=0,
            o_RXBUFSTATUS=Open(),
            i_RXDDIEN=0 if rx_buffer_enable else 1,
            i_RXDLYBYPASS=1 if rx_buffer_enable else 0,
            i_RXDLYEN=0,
            i_RXDLYOVRDEN=0,
            i_RXDLYSRESET=rx_init.rxdlysreset,
            o_RXDLYSRESETDONE=rx_init.rxdlysresetdone,
            i_RXPHALIGN=0,
            o_RXPHALIGNDONE=rxphaligndone,
            i_RXPHALIGNEN=0,
            i_RXPHDLYPD=0,
            i_RXPHDLYRESET=0,
            o_RXPHMONITOR=Open(),
            i_RXPHOVRDEN=0,
            o_RXPHSLIPMONITOR=Open(),
            o_RXSTATUS=Open(),
            i_RXSYNCALLIN=rxphaligndone,
            o_RXSYNCDONE=rx_init.rxsyncdone,
            i_RXSYNCIN=0,
            i_RXSYNCMODE=0 if rx_buffer_enable else 1,
            o_RXSYNCOUT=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,
            i_RXSLIDE=0,

            # Receive Ports - RX Channel Bonding Ports
            o_RXCHANBONDSEQ=Open(),
            i_RXCHBONDEN=0,
            i_RXCHBONDI=0b0000,
            i_RXCHBONDLEVEL=0,
            i_RXCHBONDMASTER=0,
            o_RXCHBONDO=Open(),
            i_RXCHBONDSLAVE=0,

            # Receive Ports - RX Channel Bonding Ports
            o_RXCHANISALIGNED=Open(),
            o_RXCHANREALIGN=Open(),

            # Receive Ports - RX Decision Feedback Equalizer
            o_DMONITOROUT=Open(),
            i_RXADAPTSELTEST=0,
            i_RXDFEXYDEN=0,
            i_RXOSINTEN=0b1,
            i_RXOSINTID0=0,
            i_RXOSINTNTRLEN=0,
            o_RXOSINTSTROBEDONE=Open(),

            # Receive Ports - RX Driver,OOB signalling,Coupling and Eq.,CDR
            i_RXLPMLFOVRDEN=0,
            i_RXLPMOSINTNTRLEN=0,

            # Receive Ports - RX Equalizer Ports
            i_RXLPMHFHOLD=0,
            i_RXLPMHFOVRDEN=0,
            i_RXLPMLFHOLD=0,
            i_RXOSHOLD=0,
            i_RXOSOVRDEN=0,

            # Receive Ports - RX Fabric ClocK Output Control Ports
            o_RXRATEDONE=Open(),

            # Receive Ports - RX Fabric Clock Output Control Ports
            i_RXRATEMODE=0b0,

            # 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(),
            i_RXGEARBOXSLIP=0,

            # Receive Ports - RX Initialization and Reset Ports
            i_GTRXRESET=rx_init.gtrxreset,
            i_RXLPMRESET=0,
            i_RXOOBRESET=0,
            i_RXPCSRESET=0,
            i_RXPMARESET=0,

            # Receive Ports - RX OOB Signaling ports
            o_RXCOMSASDET=Open(),
            o_RXCOMWAKEDET=rxcomwakedet,

            # Receive Ports - RX OOB Signaling ports
            o_RXCOMINITDET=rxcominitdet,

            # Receive Ports - RX OOB signalling Ports
            o_RXELECIDLE=Open(),
            i_RXELECIDLEMODE=0b00,

            # Receive Ports - RX Polarity Control Ports
            i_RXPOLARITY=0,

            # Receive Ports -RX Initialization and Reset Ports
            o_RXRESETDONE=rx_init.rxresetdone,

            # TX Buffer Bypass Ports
            i_TXPHDLYTSTCLK=0,

            # TX Configurable Driver Ports
            i_TXPOSTCURSOR=0b00000,
            i_TXPOSTCURSORINV=0,
            i_TXPRECURSOR=0b00000,
            i_TXPRECURSORINV=0,

            # TX Fabric Clock Output Control Ports
            i_TXRATEMODE=0,

            # TX Initialization and Reset Ports
            i_CFGRESET=0,
            i_GTTXRESET=tx_init.gttxreset,
            o_PCSRSVDOUT=Open(),
            i_TXUSERRDY=tx_init.txuserrdy,

            # TX Phase Interpolator PPM Controller Ports
            i_TXPIPPMEN=0,
            i_TXPIPPMOVRDEN=0,
            i_TXPIPPMPD=0,
            i_TXPIPPMSEL=1,
            i_TXPIPPMSTEPSIZE=0,

            # Transceiver Reset Mode Operation
            i_GTRESETSEL=0,
            i_RESETOVRD=0,

            # Transmit Ports
            o_TXPMARESETDONE=Open(),

            # Transmit Ports - Configurable Driver Ports
            i_PMARSVDIN0=0b0,
            i_PMARSVDIN1=0b0,

            # Transmit Ports - FPGA TX Interface Ports
            i_TXDATA=self.txdata,
            i_TXUSRCLK=self.txusrclk,
            i_TXUSRCLK2=self.txusrclk2,

            # Transmit Ports - PCI Express Ports
            i_TXELECIDLE=txelecidle,
            i_TXMARGIN=0b000,
            i_TXRATE=0b000,
            i_TXSWING=0,

            # Transmit Ports - Pattern Generator Ports
            i_TXPRBSFORCEERR=0,

            # Transmit Ports - TX 8B/10B Encoder Ports
            i_TX8B10BBYPASS=0,
            i_TXCHARDISPMODE=0,
            i_TXCHARDISPVAL=0,
            i_TXCHARISK=self.txcharisk,

            # Transmit Ports - TX Buffer Bypass Ports
            i_TXDLYBYPASS=1 if tx_buffer_enable else 0,
            i_TXDLYEN=tx_init.txdlyen,
            i_TXDLYHOLD=0,
            i_TXDLYOVRDEN=0,
            i_TXDLYSRESET=tx_init.txdlysreset,
            o_TXDLYSRESETDONE=tx_init.txdlysresetdone,
            i_TXDLYUPDOWN=0,
            i_TXPHALIGN=tx_init.txphalign,
            o_TXPHALIGNDONE=tx_init.txphaligndone,
            i_TXPHALIGNEN=0 if tx_buffer_enable else 1,
            i_TXPHDLYPD=0,
            i_TXPHDLYRESET=0,
            i_TXPHINIT=tx_init.txphinit,
            o_TXPHINITDONE=tx_init.txphinitdone,
            i_TXPHOVRDEN=0,

            # Transmit Ports - TX Buffer Ports
            o_TXBUFSTATUS=Open(),

            # Transmit Ports - TX Buffer and Phase Alignment Ports
            i_TXSYNCALLIN=0,
            o_TXSYNCDONE=Open(),
            i_TXSYNCIN=0,
            i_TXSYNCMODE=0,
            o_TXSYNCOUT=Open(),

            # Transmit Ports - TX Configurable Driver Ports
            o_GTPTXN=pads.txn,
            o_GTPTXP=pads.txp,
            i_TXBUFDIFFCTRL=0b100,
            i_TXDEEMPH=0,
            i_TXDIFFCTRL=0b1000,
            i_TXDIFFPD=0,
            i_TXINHIBIT=0,
            i_TXMAINCURSOR=0b0000000,
            i_TXPISOPD=0,

            # Transmit Ports - TX Fabric Clock Output Control Ports
            o_TXOUTCLK=self.txoutclk,
            o_TXOUTCLKFABRIC=Open(),
            o_TXOUTCLKPCS=Open(),
            i_TXOUTCLKSEL=0b010 if tx_buffer_enable else 0b011,
            o_TXRATEDONE=Open(),

            # Transmit Ports - TX Gearbox Ports
            o_TXGEARBOXREADY=Open(),
            i_TXHEADER=0,
            i_TXSEQUENCE=0,
            i_TXSTARTSEQ=0,

            # Transmit Ports - TX Initialization and Reset Ports
            i_TXPCSRESET=0,
            i_TXPMARESET=0,
            o_TXRESETDONE=tx_init.txresetdone,

            # Transmit Ports - TX OOB signaling Ports
            o_TXCOMFINISH=txcomfinish,
            i_TXCOMINIT=txcominit,
            i_TXCOMSAS=0,
            i_TXCOMWAKE=txcomwake,
            i_TXPDELECIDLEMODE=0,

            # Transmit Ports - TX Polarity Control Ports
            i_TXPOLARITY=0,

            # Transmit Ports - TX Receiver Detection Ports
            i_TXDETECTRX=0,

            # Transmit Ports - pattern Generator Ports
            i_TXPRBSSEL=0b000,
        )
        self.specials += Instance("GTPE2_CHANNEL", **gtp_params)