This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AFE7950: I want to understand how the SYSREF input signal is configured for operation in either pulsed mode or continuous mode in both the AFE Device and TI's Xilinx JESD FPGA IP Core

Part Number: AFE7950
Other Parts Discussed in Thread: LMK04828

We have a design up and running where SYSREF is set up running in continuous mode . We want to be sure that this does not require any explicit configuration of the AFE device or explicit configuration for the FPGA JESDI core from TI. I have looked at the document (AFE79xx_ConfigurationGuide_SBAA417_Jun2020.pdf) that  is supplied and see no reference to an explicit configuration of the SYSREF signal for the AFE device. Also the IP Guide (TI204c-IP-Users-Guide) makes no reference to configuration of the SYSREF signal.  The reason I pose this question is that we periodically see intermittent failure to initialize the AFE JEDI Link on the RX side (ADC side of the AFE) 

  • Hi Joseph,

    By default the configuration should be set to expect a continuous sysref, with the 'sysParams.continuousSysref' parameter set to 'True' by default. 

    When you see the failures on the link, are any errors reported on the FPGA side when initializing the link? 

    Regards,

    David Chaparro

  • The only failure we see is that the  rx_lane_data_valid is '0'.

  • Are you saying that this parameter is set for the AFE ? And that the FPGA does not have the equivalent setting and expects a continuous sysref signal?

  • I wanted to follow-up our discussion on the failure that we are seeing with more information. I am not sure this is a sysref issue.

    Our design has a problem initializing the JESDI interface between TI FPGA  IP and the AFE7950 ,reliably. The ADC side of the JESDI interface is failing to  initialize reliably about 50-60% of the time.

    The signaling on the JESDI RX  interface in the FPGA displays as shown below in the included image(first image) when it fails.

    The rx_sync_reset is held asserted while the 7950 initializes, but on completion of the AFE initialization and release of rx_sync_reset the receive interface doesn’t seem to be syncing and won’t start up.

    From this is can be observed that the ila_rx_data_valid never goes high     and the rx_sync_n never goes high . However it can be seen that the lmfc pulse trains realigns just at the point where the sysref align count goes from 0 to 1. Also there is zero errors in the error counters.

    The included failing image (second image) is what we see when the initialization completes correctly :

     

    So how can we diagnose what is causing the initialization to fail? Is there any status that can be probed on the testports  1,2,3 that can provide some insight as to why the failing sequence above occurs ?

     

    Also is there an update to the IP JESDI core?

    Thanks

    Joe

  • Hi Joseph,

    Yes, this is a parameter that can be set in your bringup script. If not set, then by default it will be set to 'True'. The FPGA does not have the same parameter so there are no changes that you would need to make. 

    One way to test if this is a sysref issue is to make it so that SYSREF is not required. On the AFE side you can set it so that the AFE uses an internally generated SYSREF and in the FPGA you can set it so that SYSREF is not required. The changes for both of these are given below.

    1. In the AFE script: sysParams.useSpiSysref = True

    2. In the TI IP set cfg_rx_det_latency_en= 1'b0 (in the TI_204c_IP_ref.sv file) and tie sysref inputs to '0'

    Another test would be to lower the SYSREF frequency. The max frequency will be reported by the AFE GUI but an integer factor of the max frequency will also work.

    Regards,

    David Chaparro 

  • Hi David,

    Thanks for reply.

    I tried your suggestion today and found I have the same problem on the ADC side where the RX will periodically not initialize . So it looks like this problem is not related to sysref signal . Can you suggest any other status that we can gather to establish why this is unreliable? 

    Thanks

  • Hi Joseph,

    Is the configuration that you are testing the same as the provided reference designs? If different can you share the script you are using to program the AFE?

    Is this testing using the AFE79xxEVM or is this a custom design? 

    Regards,

    David Chaparro 

  • This is a custom design based on the AFE79EVM.The following block diagram should inform you of how we have architected our custom design:

    Here is the LATTE code source that we use to configure the AFE in this design:

    '''

    '''
    setupParams.skipFpga                = 1
    sysParams                           = AFE.systemParams  
    setupParams.fpgaRefClk              = 156.25
    AFE.systemStatus.loadTrims          = 1

    #sysParams.fbEnable = [False]*2
    sysParams.fbEnable = [False]*2
    sysParams.FRef                      = 156.25
    sysParams.FadcRx                    = 2500.0
    sysParams.FadcFb                    = 2500.0
    sysParams.Fdac                      = 2500.0*4

    sysParams.enableDacInterleavedMode  = False  #DAC interleave mode to save power consumption. Fs/2 - Fin spur occurs

    sysParams.modeTdd                   = 0    
                                            # 0- Single TDD Pin for all Channels
                                            # 1- Separate Control for 2T/2R/1F
                                            # 2- Separate Control for 1T/1R/1F          

    sysParams.topLevelSystemMode        = 'StaticTDDMode'
    sysParams.RRFMode                   = 0   #4T4R2F FDD mode
    sysParams.jesdSystemMode            = [3,3]
                                            #SystemMode 0:  2R1F-FDD                        ; rx1-rx2-fb-fb
                                            #SystemMode 1:  1R1F-FDD                        ; rx1-rx1-fb-fb
                                            #SystemMode 2:  2R-FDD                          ; rx1-rx1-rx2-rx2
                                            #SystemMode 3:  1R                              ; rx1-rx1-rx1-rx1
                                            #SystemMode 4:  1F                              ; fb-fb-fb-fb
                                            #SystemMode 5:  1R1F-TDD                        ; rx1/fb-rx1/fb-rx1/fb-rx1/fb
                                            #SystemMode 8:  1R1F-TDD 1R-FDD (FB-2Lanes)(RX1 RX2 interchanged)       ; rx2/fb-rx2/fb-rx1-rx1


    sysParams.jesdLoopbackEn            = 0 #Make it 1 to Enable the JESDTX to JESDRX internal loopback
    sysParams.LMFSHdRx                  =['28810', '28810', '28810', '28810']  
                                            # The 2nd and 4th are valid only for jesdSystemMode values in (2,6,7,8). For other modes, select 4 converter modes for 1st and 3rd.
    sysParams.LMFSHdFb                  = ["22210","22210"]

    sysParams.LMFSHdTx                  = ["28810","28810","28810","28810"]

    sysParams.jesdTxProtocol            = [0,0]    #8b/10b
    sysParams.jesdRxProtocol            = [0,0]    #8b/10b
    sysParams.serdesFirmware            = True      # If you want to lead any firmware, please speify the path here. Otherwise it will not write any firmware
    sysParams.jesdTxLaneMux             = [0,1,2,3,4,5,6,7]
    #sysParams.jesdTxLaneMux                = [7,6,5,4,3,2,1,0]
    #sysParams.jesdTxLaneMux                = [[6,7,4,5],[0,1,2,3]]
                                                    # Enter which lanes you want in each location.
                                                    # Note that across 2T Mux is not possible in 0.5.
                                                    # For example, if you want to exchange the first two lines of each 2T, this should be [[1,0,2,3],[5,4,6,7]]
    sysParams.jesdRxLaneMux             = [0,1,2,3,4,5,6,7]
    #sysParams.jesdRxLaneMux                = [7,6,5,4,3,2,1,0]
    #sysParams.jesdRxLaneMux                = [[6,7,4,5],[0,1,2,3]]
                                                    # Enter which lanes you want in each location.
                                                    # Note that across 2R Mux is not possible in 0.5.
                                                    # For example, if you want to exchange the first two lines of each 2R, this should be [[1,0,2,3],[5,4,6,7]]

    sysParams.jesdRxRbd                 = [4, 4]

    # scrambler
    sysParams.rxJesdTxScr               = [True]*4
    sysParams.fbJesdTxScr               = [True]*2
    sysParams.jesdRxScr                 = [True]*4




    sysParams.rxJesdTxK                 = [8]*4
    sysParams.fbJesdTxK                 = [8]*2
    sysParams.jesdRxK                   = [8]*4

       
    sysParams.ncoFreqMode               = "1KHz"

    sysParams.txNco0                    =   [[3500,3500],       #Band0, Band1 for TxA for NCO0
                                            [3500,3500],        #Band0, Band1 for TxB for NCO0
                                            [3500,3500],        #Band0, Band1 for TxC for NCO0
                                            [3500,3500]]        #Band0, Band1 for TxD for NCO0

    sysParams.rxNco0                    =   [[3500,3500],       #Band0, Band1 for RxA for NCO0
                                            [3500,3500],        #Band0, Band1 for RxB for NCO0
                                            [3500,3500],        #Band0, Band1 for RxC for NCO0
                                            [3500,3500]]        #Band0, Band1 for RxD for NCO0
    sysParams.fbNco0                    =   [1500,1800]         #FBA, FBC for NCO0

    sysParams.numBandsRx                = [0]*4                 # 0 for single, 1 for dual
    sysParams.numBandsFb                = [0,0]            
    sysParams.numBandsTx                = [0,0,0,0]

    sysParams.ddcFactorRx               = [20]*4    # DDC decimation factor for RX A, B, C and D
    sysParams.ddcFactorFb               = [20]*2
    sysParams.ducFactorTx               = [80]*4

    AFE.systemStatus.loadTrims          =1

    ## The following parameters sets up the LMK04828 clocking schemes
    #lmkParams.xtalFreq                  =   122.88
    #lmkParams.lmkVcoFreq                =   2949.12 #For 122.88,245.76

    lmkParams.xtalFreq                  =   156.25
    lmkParams.lmkVcoFreq                =   2968.75

    #lmkParams.xtalFreq                  =   156.25
    #lmkParams.lmkVcoFreq                =   2500.0

    lmkParams.pllEn                     =   True#False
    #lmkParams.inputClk                 =   1474.56#737.28
    lmkParams.lmkFrefClk                =   True

    ## The following parameters sets up the register and macro dumps
    logDumpInst.setFileName(ASTERIX_DIR+DEVICES_DIR+r"\Afe79xxPg1.txt")
    logDumpInst.logFormat               = 0x00
    logDumpInst.rewriteFile             = 1
    logDumpInst.rewriteFileFormat4      = 1
    device.optimizeWrites               = 0
    device.rawWriteLogEn                = 1

    ## The following parameters sets up the SYNCIN and SYNCOUT to interface with the TSW14J57
    sysParams.jesdABLvdsSync            = False
    sysParams.jesdCDLvdsSync            = False
    sysParams.rxJesdTxSyncMux           = [0,0,0,0]
    sysParams.fbJesdTxSyncMux           = [0,0]
    sysParams.jesdRxSyncMux             = [0,0,0,0]     #[0,0,1,1]
    sysParams.syncLoopBack              = True


    # ## The following parameters sets up the AGC
    # sysParams.agcParams[0].agcMode = 1 ##internal AGC
    # sysParams.agcParams[0].gpioRstEnable = 0 ##disable GPIO based reset to AGC detector
    # sysParams.agcParams[0].atken = [0, 1, 0] ##enable big and small step attack
    # sysParams.agcParams[0].decayen = [0,1,0] ##enable big and small step decay
    # sysParams.agcParams[0].atksize = [2,1,0] ## bigs step = 2dB, small step = 1dB
    # sysParams.agcParams[0].decaysize = [2,1,0] ##big step = 2dB, small step = 1dB
    # sysParams.agcParams[0].atkthreshold = [-1, -2, -14] ##attack threshold
    # sysParams.agcParams[0].decaythreshold = [-14, -6, -20] ##decay threshold
    # sysParams.agcParams[0].atkwinlength = [170, 170] ## detector time constant expressed inn absolute time in ns.
    # sysParams.agcParams[0].decaywinlength = 87380 ##detector time constant expressed in absolute time in ns. All detectors use the same value for decay time constant
    # sysParams.agcParams[0].atkNumHitsAbs = [8,8] ##absolute number of times signal crosses threshold. These crossing are with respect to the FADC/8 clock
    # sysParams.agcParams[0].decayNumHitsAbs = [100,100] ##absolute number of times signal crosses threshold. These crossing are with respect to the FADC/8 clock
    # sysParams.agcParams[0].minDsaAttn = 0 ##minimum DSA attenuation used by AGC
    # sysParams.agcParams[0].maxDsaAttn = 22 ##maximum DSA attenuation used by AGC
    # sysParams.agcParams[0].totalGainRange = 22 ##total gain range used by ALC for gain compensation
    # sysParams.agcParams[0].minAttnAlc = 0 ##minimum attenuation used by ALC for compensation when useMinAttnAgc = 0
    # sysParams.agcParams[0].useMinAttnAgc = 1 ##enable ALC to use minimum attenuation from AGC for which compensation is required.
    # sysParams.agcParams[0].alcEn = 1
    # sysParams.agcParams[0].alcMode = 0 ##floating point DGC
    # sysParams.agcParams[0].fltPtMode = 0 ##if exponent > 0, dont send MSB
    # sysParams.agcParams[0].fltPtFmt = 1 ##3 bit exponent


    ## The following parameters sets up the GPIOs
    sysParams.gpioMapping={
            'H8': 'ADC_SYNC0',
            'H7': 'ADC_SYNC1',
            'N8': 'ADC_SYNC2',
            'N7': 'ADC_SYNC3',
            'H9': 'DAC_SYNC0',
            'G9': 'DAC_SYNC1',
            'N9': 'DAC_SYNC2',
            'P9': 'DAC_SYNC3',
            'P14': 'GLOBAL_PDN',
            'K14': 'FBABTDD',
            'R6': 'FBCDTDD',
            'H15': ['TXATDD','TXBTDD'],
            'V5': ['TXCTDD','TXDTDD'],
            'E7': ['RXATDD','RXBTDD'],
            'R15': ['RXCTDD','RXDTDD']}
           
    #AFE.systemParams.papParams[0]['enable'] = True
    #AFE.systemParams.papParams[1]['enable'] = True
    #AFE.systemParams.papParams[2]['enable'] = True
    #AFE.systemParams.papParams[3]['enable'] = True
           

    ## Initiates LMK04828 and AFE79xx Bring-up
    #lmk.logClassInst=logDumpInst
    setupParams.skipLmk =   False
    AFE.initializeConfig()
    lmkParams.sysrefFreq = AFE.systemStatus.sysrefFreq
    AFE.LMK.lmkConfig()

  • Hi Joseph,

    Thank you for sharing your script. We have reviewed and tested your script and we were able to get the link up without any errors, so the AFE configuration looks be correct.

    To further debug the issue we have a couple of follow-up questions: 

    1. Can you confirm that you are following the bringup procedure below? 
      1. Program clocks and verify they are stable.
      2. Release master_reset_n and verify that the qpll locks.
      3. Release tx_sync_reset_n.
      4. Program AFE.
      5. Release rx_sync_reset_n.
    2. Is the instability issue seen on both the ADC and DAC links?
      1. When seeing the link issue are you able to get the link back up by performing a JESD re-sync?
        1. In Latte the command to do this is AFE.adcDacSync(1)
    3. Is your FPGA programming the AFE or do you still use Latte? 
    4. During the AFE bringup are you failing any of the readchecks or polls? 

    Regards,

    David Chaparro 

  • Yes we follow all the steps you mention in question 1 . You will see the flow of our AFE/FPGA IP  initialization process in the following python script(which to answer your question 3 is run on an ARM processor in an FPGA SOC device talking to the AFE over the SPI interface) :

    # sysref off
    run(["bf-cli-util", "ltc", "--sysrefoff"])
    
    # reset everything
    hal.regs_afe.control['afe_master_reset_n'] = 0
    hal.regs_afe.control['afe_tx_sync_reset'] = 1
    hal.regs_afe.control['afe_rx_sync_reset'] = 1
    hal.regs_afe.control['afe_master_reset_n'] = 1
    time.sleep(.1)
    hal.regs_afe.control['afe_tx_sync_reset'] = 0
    
    
    # reset afe
    run(["bf-cli-util", "afe", "--reset"])
    time.sleep(1)
    run(["bf-cli-util", "afe", "-p", "/work/afe_8b10b_nosysref.txt"])
    hal.regs_afe.control['afe_rx_sync_reset'] = 0
    time.sleep(1)
    
    while (hal.afe_get_jesd() == 0):
        print("afe resync")
        run(["bf-cli-util", "afe", "-p", "/work/afe_resync.txt"])
        time.sleep(1)
    print("AFE TX lock OK")
    
    # reset JESD RX side
    hal.regs_afe.control['afe_rx_sync_reset'] = 0
    time.sleep(1)
    
    The instability is seen on both ADC and DAC but principally on the ADC direction. To answer your question about
    using the afe_resync process: Yes we use it to try and mitigate but this does not result in achieving lock in the
    ADC direction . You can see where we call this function in the script based on a failure to lock.
    run(["bf-cli-util", "afe", "-p", "/work/afe_resync.txt"])
    Yes when the ADC failure to lock occurs we are passing all the readchecks or polls. See the included report below from a run of
    the initialization that the ADC failed to lock (ie RX lock in our messages):
    POLL_READ_MASK_CHECK 0x4 from register 0xf0 with mask 0x4
    READ_MASK_CHECK 0x0 from register 0xf0 with mask 0x8
    READ 00 from register 0f1
    READ 07 from register 0f0
    READ 07 from register 0f0
    READ 07 from register 0f0
    READ 07 from register 0f0
    READ 00 from register 0f3
    READ 00 from register 0f2
    READ 00 from register 0f7
    READ 00 from register 0f6
    READ 00 from register 0f5
    READ 00 from register 0f4
    READ 07 from register 0f0
    POLL_READ_MASK_CHECK 0x1 from register 0xf0 with mask 0x1
    READ 07 from register 0f0
    POLL_READ_MASK_CHECK 0x4 from register 0xf0 with mask 0x4
    READ_MASK_CHECK 0x0 from register 0xf0 with mask 0x8
    READ 00 from register 0f1
    READ 07 from register 0f0
    READ 07 from register 0f0
    READ 07 from register 0f0
    READ 07 from register 0f0
    READ 00 from register 0f3
    READ 00 from register 0f2
    READ 00 from register 0f7
    READ 00 from register 0f6
    READ 00 from register 0f5
    READ 00 from register 0f4
    WRITE_MASK 0x0 to register 0x18 with mask 0xdf
    WRITE_MASK 0x1 to register 0x12 with mask 0xf0
    WRITE_MASK 0x0 to register 0x14c4 with mask 0xfe
    WRITE_MASK 0x2 to register 0x12 with mask 0xf0
    WRITE_MASK 0x0 to register 0x14c4 with mask 0xfe
    WRITE_MASK 0x4 to register 0x12 with mask 0xf0
    WRITE_MASK 0x0 to register 0x14c4 with mask 0xfe
    WRITE_MASK 0x8 to register 0x12 with mask 0xf0
    WRITE_MASK 0x0 to register 0x14c4 with mask 0xfe
    WRITE_MASK 0x0 to register 0x12 with mask 0xf0
    WRITE_MASK 0x10 to register 0x12 with mask 0xcf
    WRITE_MASK 0x0 to register 0x14c4 with mask 0xfe
    WRITE_MASK 0x20 to register 0x12 with mask 0xcf
    WRITE_MASK 0x0 to register 0x14c4 with mask 0xfe
    READ 07 from register 0f0
    POLL_READ_MASK_CHECK 0x1 from register 0xf0 with mask 0x1
    DELAY 1 miliseconds
    READ 07 from register 0f0
    POLL_READ_MASK_CHECK 0x4 from register 0xf0 with mask 0x4
    READ_MASK_CHECK 0x0 from register 0xf0 with mask 0x8
    READ 00 from register 0f1
    READ 07 from register 0f0
    READ 07 from register 0f0
    READ 07 from register 0f0
    READ 07 from register 0f0
    READ 00 from register 0f3
    READ 00 from register 0f2
    READ 00 from register 0f7
    READ 00 from register 0f6
    READ 00 from register 0f5
    READ 00 from register 0f4
    READ 07 from register 0f0
    POLL_READ_MASK_CHECK 0x1 from register 0xf0 with mask 0x1
    DELAY 1 miliseconds
    READ 07 from register 0f0
    POLL_READ_MASK_CHECK 0x4 from register 0xf0 with mask 0x4
    READ_MASK_CHECK 0x0 from register 0xf0 with mask 0x8
    READ 00 from register 0f1
    READ 07 from register 0f0
    READ 07 from register 0f0
    READ 07 from register 0f0
    READ 07 from register 0f0
    READ 00 from register 0f3
    READ 00 from register 0f2
    READ 00 from register 0f7
    READ 00 from register 0f6
    READ 00 from register 0f5
    READ 00 from register 0f4
    DELAY 1 miliseconds
    READ_MASK_CHECK 0x0 from register 0x11b with mask 0xff
    READ_MASK_CHECK 0x0 from register 0x11a with mask 0xff
    READ_MASK_CHECK 0x0 from register 0x119 with mask 0xff
    READ_MASK_CHECK 0x0 from register 0x118 with mask 0xff
    READ_MASK_CHECK 0x0 from register 0x11f with mask 0xff
    READ_MASK_CHECK 0x0 from register 0x11e with mask 0xff
    READ_MASK_CHECK 0x0 from register 0x11d with mask 0xff
    READ_MASK_CHECK 0x0 from register 0x11c with mask 0xff
    READ_MASK_CHECK 0x3 from register 0xee with mask 0xf
    READ_MASK_CHECK 0xa from register 0xa2 with mask 0xff
    READ_MASK_CHECK 0x5 from register 0xa4 with mask 0xff
    Done with uploading AFE configuration
    Total number of commands: 17264
    Read command count: 816
    Write command count: 16165
    Read check command count: 88
    Poll command count: 127
    Wait command count: 68
    Total number of errors: 0
    AFE init done



  • Hi Joseph,


    When doing the the test with no sysref, have you disabled the sysref to both the AFE and FPGA. To not use Sysref on the FPGA side the below changes should be made. Can you try these on your setup and see if the results change? 

    1. The sysref signal should be internally tied to '0'. 

    2. The deterministic latency parameter, located in the TI_204c_IP_ref.sv file, should be tied to '0'.

    Can you also confirm that the sysref frequency is set to the appropriate value reported by the Latte software? 

    Regards,

    David Chaparro 

  • Yes we have assigned  sysref to 0 and deterministic latency parameter is set to zero . Here is the code snippet fron .sv file:

     //assign rx_sysref = sysref; assign rx_sysref = 1'b0; //assign tx_sysref = sysref; assign tx_sysref = 1'b0; // Enable deterministic latency assign cfg_rx_det_latency_en = 1'b0; assign rx_clr_sysref_realign_count = 1'b0; assign tx_clr_sysref_realign_count = 1'b0;

    Sysref is frequency wise set to the value  required by LATTE.

  • Hi David, We are still stuck with this failure causing intermittent initialization of the JESD core. Do you have any further suggestions on how to instrument and observe why the TI IP core on the RX side is failing to lock. Is there registers on the RX side in the AFE ADC that we can interrogate to figure out what is causing the instability ?

    Also can mark this issue as UNRESOLVED?

    Thanks

  • Do you have any further support you can offer on solving this issue?

    Thanks

    Joe

  • Hi Joseph,

    Apologies for the delay I was out of office Thursday and Friday.

    One test that can be done to check if the error is related to the AFE or FPGA side is to configure the AFE in the JESD Loopback, where internally the ADC JESD lanes will be looped to the DAC JESD lanes. If you are able to see the DAC JESD link establish consistently then this would point to an issue with the FPGA side.

    To do the JESD loopback you can make the following changes to your configuration: 

    sysParams.syncLoopBack = False #JESD Sync signal is connected to FPGA
    
    sysParams.jesdLoopbackEn = 1 #Make it 1 to Enable the JESDTX to JESDRX internal loopback

    Can you try this on your setup and see if the DAC JESD link is stable? 

    Regards,

    David Chaparro 

  • I  will try this  to see if It delivers further insight on our intermittency .

    Thanks