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)
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)
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)