JESD204C link establishment and debugging for ADRV9026

  • Typical initialization sequence that is used for bringing up ADRV9026 is listed below (listed in file adi_adrv9025_daughter_board.c)
    • preMcsInit_v2
    • preMcsInit_NonBroadcast
    • MCS
    • postMcsInit

In the above sequence, please make sure that MCS passes. The MCS phase would require SYSREF’s to be sent from the clock chip or BBIC. The user can use the API function MultichipSyncStatusGet to retrieve the status. For a good case, this value should be set to 0x17.

  • ADRV9026 supports lane rates of up to 25Gbps in JESD204C mode. The JESD link establishment is done after the postMcsInit phase of device initialization. The 204C deframer link bring up procedure in general follows the following steps:
    • FPGA framer sysref enable
    • FPGA framer reset
    • Send Sysref
    • FPGA framer sysref disable – After this step, it is assumed that the FPGA framer starts sending scrambled data with a deterministic LEMC phase (Required for Deserializer bring up)
    • Reset ADRV9026 Deframer using the following commands –
      • adi_adrv9025_DfrmLinkStateSet(ADI_DISABLE)
      • Wait 50 ms
      • adi_adrv9025_DfrmLinkStateSet(ADI_ENABLE)
    • Run the Serdes init cal (ADI_ADRV9025_SERDES_INIT) using initCalsRun and initCalsWait function.
    • Enable Sysref to deframer (using command – adi_adrv9025_DeframerSysrefCtrlSet(ADI_ENABLE))
    • Send Sysref
    • Disable Sysref to deframer (using command – adi_adrv9025_DeframerSysrefCtrlSet(ADI_DISABLE))
      • Enable the JESD204C tracking calibrations only if the JESD204C link is up and running.  This maintains the link parameters on a 60 second schedule.

The user can refer to adi_board_adrv9025_JesdTxBringup and adi_board_adrv9025_JesdBringup for detailed JESD bring up procedure for the Tx (deframer link). The overall detailed sequence including the MCS is in the file adi_adrv9025_daughter_board.c. The user can refer to the ‘LINK INITIALIZATION AND DEBUGGING’ section of the user guide for additional details on link bring up and debugging options for 204C links.

 

  • The following tests can be run to check if the deframer links are up or not –
    • Assuming the user follows the above steps, the user can use the DeframerStatusGet function so as to check if the sysref is received or not. This is important to establish the LEMC phase for the 204C link. After a successful link bring up, the user should readback DeframerStatusGet as 0x12, where bit 1 shows that SYSREF was successfully received. If the readback value is 0x10, it means that the SYSREF is not received and links would not come up. In this case, the user should make sure of following the correct deframer link bring up sequence as listed above.
    • In order to get the status of the link, the user can use the API function DfrmLinkConditionGet. If this function returns a value of 1, it suggests the link is up and running – a value of 0 denotes that the link is down.
    • The user can additionally readback the registers 0x6B2B, 0x6B2C, 0x6B2D, 0x6B2E to check the 204C link status per lane. For a good case, a value of 0x6 is returned for the active lanes. The user can refer to the section ‘CHECKING JESD204C LINK STATUS’ to understand the meaning of the other values returned from these registers.
    • Checking for signal integrity issues –

The user can check for any signal integrity issues after confirming that the init sequence looks fine. A PRBS test or an eye monitor test can be used for this. The user can refer to the section ‘FIRST TIME SYSTEM BRING UP—CHECKING LINK INTEGRITY’ in the ADRV9026 user guide. This section includes a reference test script for setting up the part for PRBS test as well as a SPO test to check the eye width inside the chip. Additional details are provided below –

  • For the PRBS test, the user can set up the ADRV9026 to receive a pre-determined PRBS pattern and then use DfrmPrbsErrCountGet API function to retrieve the error status and lane errors. For a good case, the error status should be 0 and lane errors should be 0 as well. The error status is a 3 bit word, where Bit 0 = Lane inverted, bit 1 = invalid data flag, bit 2 = sample/lane error flag. If the user is getting bit 2 set that means we have signal integrity issues. The user needs to make sure that bit 0 (lane inverted flag) is not set which would suggest that we have a lane polarity mismatch. This is controlled from the JESD deframer structure in the json file (data structure desCfg (desInvertLanePolarity)). A sample PRBS script is shown below –

 

##################################SAMPLE PYTHON PRBS SCRIPT########################################################

    DfrmPrbsCfg=Types.adi_adrv9010_DfrmPrbsCfg_t()

    DfrmPrbsCfg.deframerSel=Types.adi_adrv9010_DeframerSel_e.ADI_ADRV9010_DEFRAMER_0

    DfrmPrbsCfg.polyOrder=Types.adi_adrv9010_DeframerPrbsOrder_e.ADI_ADRV9010_PRBS31

    DfrmPrbsCfg.checkerLocation=Types.adi_adrv9010_DeframerPrbsCheckLoc_e.ADI_ADRV9010_PRBSCHECK_LANEDATA

    adrv9010.DataInterface.DfrmPrbsCheckerStateSet(DfrmPrbsCfg)

               

    DfrmPrbsErrCounters = Types.adi_adrv9025_DfrmPrbsErrCounters_t()

    DfrmPrbsErrCounters.sampleSource = Types.adi_adrv9010_DeframerPrbsCheckLoc_e.ADI_ADRV9010_PRBSCHECK_LANEDATA

 

    time.sleep(0.001)

 

    #Setup FPGA and DUT PRBS Generator/Checker for PRBS7

    print "Transmit PRBS 7 from FPGA"

    prbs_sel = 5 # prbs 31 and 1 for PRBS 7#

    arg = 1

    while arg < len(sys.argv):

        if sys.argv[arg] == "-pn":

            if sys.srgv[arg+1] == "7":

                prbs_sel = 1

            elif sys.argv[arg+1] == "9":

                prbs_sel = 2

            elif sys.argv[arg+1] == "15":

                prbs_sel = 3

            elif sys.argv[arg+1] == "23":

                prbs_sel = 4

            elif sys.argv[arg+1] == "31":

                prbs_sel = 5

            else:

                print "PRBS polynomial must be 7, 9, 15, 23, or 31"

                exit(1)

            arg = arg + 2

        elif sys.argv[arg] == "-h" or sys.argv[arg] == "help":

            print "Usage: -pn <polynomial>"

            print " -pn <polynomial>     :  polynomial = 7 (default), 9, 15, 23, 31"

            print " -h, help             :  this help message"

            exit(0)

 

 

    # Turn on PRBS

    print "Starting PRBS"

 

    for x in range(8):

        writefpga((0x43400100 + x*0x100),0x00000004)

        writefpga((0x43400148 + x*0x100),0x20800080)

        writefpga((0x43400140 + x*0x100),0x0003007C)

        writefpga((0x43400110 + x*0x100),0x02015233)

        writefpga((0x43400120 + x*0x100),prbs_sel * 0x01000000)

        writefpga((0x43400100 + x*0x100),0x00000000)

        val = 0

        #I do not know if this is needed

        #while (val & 0x1) == 0:

            #val = readfpga(0x43400104 + x*0x100)

 

 

    #link.platform.board.Fpga.Prbs.PrbsSerializerEnable(0x0F,0x1)

 

    print

    adrv9010.DataInterface.DfrmPrbsCountReset()

 

    print "Error Counters Cleared"

    print "--------------PRBS Error Count Readout (after error cntr clear)"

    adrv9010.DataInterface.DfrmPrbsErrCountGet(DfrmPrbsErrCounters)

    print 'SERDIN_A PRBS Err Cnt: ',DfrmPrbsErrCounters.laneErrors[0]

    print 'SERDIN_B PRBS Err Cnt: ',DfrmPrbsErrCounters.laneErrors[1]

    print 'SERDIN_C PRBS Err Cnt: ',DfrmPrbsErrCounters.laneErrors[2]

    print 'SERDIN_D PRBS Err Cnt: ',DfrmPrbsErrCounters.laneErrors[3]

 

    print 'SERDIN_A PRBS Err Cnt: ',DfrmPrbsErrCounters.errorStatus[0]

    print 'SERDIN_B PRBS Err Cnt: ',DfrmPrbsErrCounters.errorStatus[1]

    print 'SERDIN_C PRBS Err Cnt: ',DfrmPrbsErrCounters.errorStatus[2]

    print 'SERDIN_D PRBS Err Cnt: ',DfrmPrbsErrCounters.errorStatus[3]

    time.sleep(1)

 

    # Inject prbs error if desired:

    injectError = 1

    if injectError:

        for x in range(8):

            temp = readfpga(0x43400120 + x*0x100)

            writefpga((0x43400120 + x*0x100), temp | 0x10000000)

 

    print "--------------PRBS Error Count Readout (error injected)"

    link.platform.board.Adrv9010Device.DataInterface.DfrmPrbsErrCountGet(DfrmPrbsErrCounters)

    print 'SERDIN_A PRBS Err Cnt: ',DfrmPrbsErrCounters.laneErrors[0]

    print 'SERDIN_B PRBS Err Cnt: ',DfrmPrbsErrCounters.laneErrors[1]

    print 'SERDIN_C PRBS Err Cnt: ',DfrmPrbsErrCounters.laneErrors[2]

    print 'SERDIN_D PRBS Err Cnt: ',DfrmPrbsErrCounters.laneErrors[3]

    print 'SERDIN_A PRBS Err Cnt: ',DfrmPrbsErrCounters.errorStatus[0]

    print 'SERDIN_B PRBS Err Cnt: ',DfrmPrbsErrCounters.errorStatus[1]

    print 'SERDIN_C PRBS Err Cnt: ',DfrmPrbsErrCounters.errorStatus[2]

    print 'SERDIN_D PRBS Err Cnt: ',DfrmPrbsErrCounters.errorStatus[3]

                             ###################################END OF SCRIPT#########################################################

  • The SPO test is a method of determining the opening size by sweeping the sampling position and searching for ‘dead space’ where no transitions are occurring therefore the sampling point is in the eye. It offsets the clocks to move the sampling edge left or right on the waveform and the resulting ‘dead’ steps total at least 4 steps left and right from center, over all operating conditions the link is considered ‘good’. The SPO test requires PRBS transmission in the FPGA and setup of the PRBS pattern checker in the TRX.

If the user is not able to overcome signal integrity issues, ADI recommends changing the highBoost parameter in the profile. A value of 0 is recommended for low insertion loss (<11dB) lanes whereas a value of 1 is recommended for high insertion loss lanes (>11dB).

As aforementioned, for 25Gbps, ADI recommends to have the insertion loss over the SERDES lanes to be in the range of 8-15dB over the entire range of operating temperature. For insertion loss ranges beyond 8-15dB please contact ADI for specific recommendations. The user is expected to send the insertion loss for the different lanes that they are planning to use. An idea of the insertion loss variation over temp for each lane is needed so as to get optimized recommendations from ADI.