Post Go back to editing

ADRV9029 Inquiry about DPD abnormal symptoms.ㅁㅇ

Category: Hardware
Product Number: ADRV9029

Hello,

I would like to inquire because there is a phenomenon in which the DPD does not operate during DPD measurement.

Changed the Tx Analog Atten value of ADRV9029 from -5dB to -35dB. At this time, DPD Mean ORX Power changed from -15 to -45, and DPD Peak ORX Power changed from -5 to -10.

Logically, I think DPD Peak ORX Power should change to around -35. DPD doesn't seem to work well due to this issue.

Why isn't my DPD Peak ORX Power changing?

In my opinion, the signal from LO inside the ADRV9029 passes through the ADC and is input to the DPD Path.

If not, for some reason the DPD Peak ORX Power value does not change even if I adjust the Tx Analog Atten value of ADRV9029?

For reference, on boards where DPD operates normally, the DPD Peak ORX Power has changed to -35.

Thanks in advance.

Thread Notes

  • Even if I change dpdPeakSearchWindowSize, DPD still doesn't seem to work properly.
    There seems to be some improvement, but compared to other ports, error code 0x341d occurs in the Tx2 port and DPD does not seem to be operating properly.

    Please take a look below and give me some advice.

  • Set the below parameter to 25 and check.

  • Even if you set dpdIndirectRegularizationValue=25, the result is the same.

    Is there anything else I need to check?

  • Are you seeing this issue only on TX2 channel?

    You can try relaxing the DPD robustness threshold settings. Set Threshold0 to 5 and Threshold1 to 10 and check if it improves.

    Attached the example script that you can use for implementing C code in your customer board.

    #################################################################################
    #GUI Version: 0.0.0.939
    #DLL Version: 0.0.0.857
    #Cmd Server Version: 0.0.0.857
    #FPGA Version: 0xD9000007
    #ARM Version: 0.0.0.503
    #StreamVersion: 0.0.0.73
    #Author: Anand Kumar
    #Precondition: Ensure that the DPD tracking cal is disabled before running this script
    #Description: This script sets up the DPD robustness framework, and reads back the metrics and action mask after setting up the DPD 
    # Specifically, the DPD LUT updates are skipped if indirect error is greater than 5%
    # If the direct EVM is persistently greater than 5% for at least 10 update periods, the DPD is reset.
    #################################################################################
    
    #Import Reference to the DLL
    import System
    import clr
    import time
    from System import Array
    clr.AddReferenceToFileAndPath("C:\\Program Files\\Analog Devices\\ADRV9025 Transceiver Evaluation Software_x64_FULL\\adrvtrx_dll.dll")
    from adrv9010_dll import AdiEvaluationSystem
    from adrv9010_dll import Types
    from adrv9010_dll import Ad9528Types
    
    def spiRead(address):
        data = adrv9010.Hal.SpiByteRead(address, 0)
        print "SPI Read Address " + hex(address) + ": " + hex(data[1])
    
    def spiWrite(address, data):
        adrv9010.Hal.SpiByteWrite(address, data)
        print "SPI Write Address " + hex(address) + ": " + hex(data)
    
    def dpdStabilityCondnSetup(txChannelMask = 0xF):
        DEFAULT_WARNING_PERCENTAGE = 3
        DEFAULT_ERROR_PERCENTAGE = 8
        DEFAULT_WARNING_dBFS = -36
        DEFAULT_ERROR_dBFS = -40  
        ERROR_PERSISTENT_COUNT = 10
    	
        dpdFaultConditionArr = Array.CreateInstance(Types.adi_adrv9010_DpdFaultCondition_t, 10)
        dpdFaultConditionArr[0] = Types.adi_adrv9010_DpdFaultCondition_t()
        dpdFaultConditionArr[0].dpdMetric = Types.adi_adrv9010_DpdMetric_e.ADI_ADRV9010_DPD_METRIC_INDIRECT_EVM
        dpdFaultConditionArr[0].comparator = Types.adi_adrv9010_DpdComparator_e.ADI_ADRV9010_DPD_COMPARATOR_GREATER_THAN
        dpdFaultConditionArr[0].threshold0 = (DEFAULT_WARNING_PERCENTAGE)
        dpdFaultConditionArr[0].threshold1 = (DEFAULT_ERROR_PERCENTAGE)
        dpdFaultConditionArr[0].persistentCount = ERROR_PERSISTENT_COUNT
    
        dpdFaultConditionArr[1] = Types.adi_adrv9010_DpdFaultCondition_t()
        dpdFaultConditionArr[1].dpdMetric = Types.adi_adrv9010_DpdMetric_e.ADI_ADRV9010_DPD_METRIC_DIRECT_EVM
        dpdFaultConditionArr[1].comparator = Types.adi_adrv9010_DpdComparator_e.ADI_ADRV9010_DPD_COMPARATOR_GREATER_THAN
        dpdFaultConditionArr[1].threshold0 = (DEFAULT_WARNING_PERCENTAGE)
        dpdFaultConditionArr[1].threshold1 = (DEFAULT_ERROR_PERCENTAGE)
        dpdFaultConditionArr[1].persistentCount = ERROR_PERSISTENT_COUNT
    
        dpdFaultConditionArr[2] = Types.adi_adrv9010_DpdFaultCondition_t()
        dpdFaultConditionArr[2].dpdMetric = Types.adi_adrv9010_DpdMetric_e.ADI_ADRV9010_DPD_METRIC_SELECT_ERROR
        dpdFaultConditionArr[2].comparator = Types.adi_adrv9010_DpdComparator_e.ADI_ADRV9010_DPD_COMPARATOR_GREATER_THAN
        dpdFaultConditionArr[2].threshold0 = (DEFAULT_WARNING_PERCENTAGE)
        dpdFaultConditionArr[2].threshold1 = (DEFAULT_ERROR_PERCENTAGE)
        dpdFaultConditionArr[2].persistentCount = ERROR_PERSISTENT_COUNT
    
        dpdFaultConditionArr[3] = Types.adi_adrv9010_DpdFaultCondition_t()
        dpdFaultConditionArr[3].dpdMetric = Types.adi_adrv9010_DpdMetric_e.ADI_ADRV9010_DPD_METRIC_INDIRECT_ERROR
        dpdFaultConditionArr[3].comparator = Types.adi_adrv9010_DpdComparator_e.ADI_ADRV9010_DPD_COMPARATOR_GREATER_THAN
        dpdFaultConditionArr[3].threshold0 = (DEFAULT_WARNING_PERCENTAGE)
        dpdFaultConditionArr[3].threshold1 = (DEFAULT_ERROR_PERCENTAGE)
        dpdFaultConditionArr[3].persistentCount = ERROR_PERSISTENT_COUNT
    
        dpdFaultConditionArr[4] = Types.adi_adrv9010_DpdFaultCondition_t()
        dpdFaultConditionArr[4].dpdMetric = Types.adi_adrv9010_DpdMetric_e.ADI_ADRV9010_DPD_METRIC_MEAN_TU_POWER
        dpdFaultConditionArr[4].comparator = Types.adi_adrv9010_DpdComparator_e.ADI_ADRV9010_DPD_COMPARATOR_LESS_THAN
        dpdFaultConditionArr[4].threshold0 = (-25 * 100)
        dpdFaultConditionArr[4].threshold1 = (-40 * 100)
        dpdFaultConditionArr[4].persistentCount = ERROR_PERSISTENT_COUNT
    
        dpdFaultConditionArr[5] = Types.adi_adrv9010_DpdFaultCondition_t()
        dpdFaultConditionArr[5].dpdMetric = Types.adi_adrv9010_DpdMetric_e.ADI_ADRV9010_DPD_METRIC_PEAK_TU_POWER
        dpdFaultConditionArr[5].comparator = Types.adi_adrv9010_DpdComparator_e.ADI_ADRV9010_DPD_COMPARATOR_LESS_THAN
        dpdFaultConditionArr[5].threshold0 = (DEFAULT_WARNING_dBFS * 100)
        dpdFaultConditionArr[5].threshold1 = (DEFAULT_ERROR_dBFS * 100)
        dpdFaultConditionArr[5].persistentCount = ERROR_PERSISTENT_COUNT
    
        dpdFaultConditionArr[6] = Types.adi_adrv9010_DpdFaultCondition_t()
        dpdFaultConditionArr[6].dpdMetric = Types.adi_adrv9010_DpdMetric_e.ADI_ADRV9010_DPD_METRIC_PEAK_TX_POWER
        dpdFaultConditionArr[6].comparator = Types.adi_adrv9010_DpdComparator_e.ADI_ADRV9010_DPD_COMPARATOR_LESS_THAN
        dpdFaultConditionArr[6].threshold0 = (DEFAULT_WARNING_dBFS * 100)
        dpdFaultConditionArr[6].threshold1 = (DEFAULT_ERROR_dBFS * 100)
        dpdFaultConditionArr[6].persistentCount = ERROR_PERSISTENT_COUNT
    
        dpdFaultConditionArr[7] = Types.adi_adrv9010_DpdFaultCondition_t()
        dpdFaultConditionArr[7].dpdMetric = Types.adi_adrv9010_DpdMetric_e.ADI_ADRV9010_DPD_METRIC_MEAN_TX_POWER
        dpdFaultConditionArr[7].comparator = Types.adi_adrv9010_DpdComparator_e.ADI_ADRV9010_DPD_COMPARATOR_LESS_THAN
        dpdFaultConditionArr[7].threshold0 = (DEFAULT_WARNING_dBFS * 100)
        dpdFaultConditionArr[7].threshold1 = (DEFAULT_ERROR_dBFS * 100)
        dpdFaultConditionArr[7].persistentCount = ERROR_PERSISTENT_COUNT
    
        dpdFaultConditionArr[8] = Types.adi_adrv9010_DpdFaultCondition_t()
        dpdFaultConditionArr[8].dpdMetric = Types.adi_adrv9010_DpdMetric_e.ADI_ADRV9010_DPD_METRIC_PEAK_ORX_POWER
        dpdFaultConditionArr[8].comparator = Types.adi_adrv9010_DpdComparator_e.ADI_ADRV9010_DPD_COMPARATOR_LESS_THAN
        dpdFaultConditionArr[8].threshold0 = (DEFAULT_WARNING_dBFS * 100)
        dpdFaultConditionArr[8].threshold1 = (DEFAULT_ERROR_dBFS * 100)
        dpdFaultConditionArr[8].persistentCount = ERROR_PERSISTENT_COUNT
    
        dpdFaultConditionArr[9] = Types.adi_adrv9010_DpdFaultCondition_t()
        dpdFaultConditionArr[9].dpdMetric = Types.adi_adrv9010_DpdMetric_e.ADI_ADRV9010_DPD_METRIC_MEAN_ORX_POWER
        dpdFaultConditionArr[9].comparator = Types.adi_adrv9010_DpdComparator_e.ADI_ADRV9010_DPD_COMPARATOR_LESS_THAN
        dpdFaultConditionArr[9].threshold0 = (DEFAULT_WARNING_dBFS * 100)
        dpdFaultConditionArr[9].threshold1 = (DEFAULT_ERROR_dBFS * 100)
        dpdFaultConditionArr[9].persistentCount = ERROR_PERSISTENT_COUNT
    
        link.platform.board.Adrv9010Device.Dfe.DpdFaultConditionSet(txChannelMask, dpdFaultConditionArr, 10)
    
    def dpdRecoveryActionConfigSet(txChannelMask = 0x0F):
        print"***************************************"
        print"Setting up Recovery Actions for DPD Robustness"   
        
        #Setup Recovery Action
        dpdRecoveryActionArr = Array.CreateInstance(Types.adi_adrv9010_DpdRecoveryActionConfig_t, 4)   
    
        #Configure Recovery Action for violation of threshold0
        dpdRecoveryActionArr[0] = Types.adi_adrv9010_DpdRecoveryActionConfig_t()
        dpdRecoveryActionArr[0].dpdErrorState = Types.adi_adrv9010_DpdErrorState_e.ADI_ADRV9010_DPD_ERR_STATE_0
        dpdRecoveryActionArr[0].dpdRecoveryAction.dpdMetricsMask = int(Types.adi_adrv9010_DpdMetric_e.ADI_ADRV9010_DPD_METRIC_DIRECT_EVM)
        dpdRecoveryActionArr[0].dpdRecoveryAction.dpdMetricsMask |= int(Types.adi_adrv9010_DpdMetric_e.ADI_ADRV9010_DPD_METRIC_INDIRECT_ERROR)
        dpdRecoveryActionArr[0].dpdRecoveryAction.dpdMetricsMask |= int(Types.adi_adrv9010_DpdMetric_e.ADI_ADRV9010_DPD_METRIC_SELECT_ERROR)
        dpdRecoveryActionArr[0].dpdRecoveryAction.dpdMetricsMask |= int(Types.adi_adrv9010_DpdMetric_e.ADI_ADRV9010_DPD_METRIC_MEAN_TU_POWER)
        dpdRecoveryActionArr[0].dpdRecoveryAction.dpdActionMask = int(Types.adi_adrv9010_DpdRecoveryAction_e.ADI_ADRV9010_DPD_RECOVERY_ACTION_SKIP_LUTS_UPDATE)
    
        #Configure Recovery Action for violation of threshold1
        dpdRecoveryActionArr[1] = Types.adi_adrv9010_DpdRecoveryActionConfig_t()
        dpdRecoveryActionArr[1].dpdErrorState = Types.adi_adrv9010_DpdErrorState_e.ADI_ADRV9010_DPD_ERR_STATE_1
        dpdRecoveryActionArr[1].dpdRecoveryAction.dpdMetricsMask = int(Types.adi_adrv9010_DpdMetric_e.ADI_ADRV9010_DPD_METRIC_DIRECT_EVM)
        dpdRecoveryActionArr[1].dpdRecoveryAction.dpdMetricsMask |= int(Types.adi_adrv9010_DpdMetric_e.ADI_ADRV9010_DPD_METRIC_INDIRECT_ERROR)
        dpdRecoveryActionArr[1].dpdRecoveryAction.dpdActionMask = 0#int(Types.adi_adrv9010_DpdRecoveryAction_e.ADI_ADRV9010_DPD_RECOVERY_ACTION_SKIP_LUTS_UPDATE)
    
        #Configure Recovery Action for persistent violation of threshold0
        thresh0ActionMaskPersistent = 0
        thresh0ActionMaskPersistent |= int(Types.adi_adrv9010_DpdRecoveryAction_e.ADI_ADRV9010_DPD_RECOVERY_ACTION_SKIP_LUTS_UPDATE)
        thresh0ActionMaskPersistent |= int(Types.adi_adrv9010_DpdRecoveryAction_e.ADI_ADRV9010_DPD_RECOVERY_ACTION_RESET_FIRST_DPD_FLAG)
        thresh0ActionMaskPersistent |= int(Types.adi_adrv9010_DpdRecoveryAction_e.ADI_ADRV9010_DPD_RECOVERY_ACTION_REVERT_LUTS_TO_UNITY)
        thresh0ActionMaskPersistent |= int(Types.adi_adrv9010_DpdRecoveryAction_e.ADI_ADRV9010_DPD_RECOVERY_ACTION_RESET_ADAPTATION_STATE)
    	
        dpdRecoveryActionArr[2] = Types.adi_adrv9010_DpdRecoveryActionConfig_t()
        dpdRecoveryActionArr[2].dpdErrorState = Types.adi_adrv9010_DpdErrorState_e.ADI_ADRV9010_DPD_ERR_STATE_PERSISTENT_0
        dpdRecoveryActionArr[2].dpdRecoveryAction.dpdMetricsMask = int(Types.adi_adrv9010_DpdMetric_e.ADI_ADRV9010_DPD_METRIC_DIRECT_EVM)
        dpdRecoveryActionArr[2].dpdRecoveryAction.dpdMetricsMask |= int(Types.adi_adrv9010_DpdMetric_e.ADI_ADRV9010_DPD_METRIC_INDIRECT_ERROR)
        dpdRecoveryActionArr[2].dpdRecoveryAction.dpdMetricsMask |= int(Types.adi_adrv9010_DpdMetric_e.ADI_ADRV9010_DPD_METRIC_SELECT_ERROR)
        dpdRecoveryActionArr[2].dpdRecoveryAction.dpdActionMask = thresh0ActionMaskPersistent
    
        #Configure Recovery Action for persistent violation of threshold1
        thresh1ActionMaskPersistent = 0
        thresh1ActionMaskPersistent |= int(Types.adi_adrv9010_DpdRecoveryAction_e.ADI_ADRV9010_DPD_RECOVERY_ACTION_SKIP_LUTS_UPDATE)
        thresh1ActionMaskPersistent |= int(Types.adi_adrv9010_DpdRecoveryAction_e.ADI_ADRV9010_DPD_RECOVERY_ACTION_REVERT_LUTS_TO_UNITY)
        thresh1ActionMaskPersistent |= int(Types.adi_adrv9010_DpdRecoveryAction_e.ADI_ADRV9010_DPD_RECOVERY_ACTION_RESET_ADAPTATION_STATE) 
        thresh1ActionMaskPersistent |= int(Types.adi_adrv9010_DpdRecoveryAction_e.ADI_ADRV9010_DPD_RECOVERY_ACTION_RESET_FIRST_DPD_FLAG) 
        thresh1ActionMaskPersistent |= int(Types.adi_adrv9010_DpdRecoveryAction_e.ADI_ADRV9010_DPD_RECOVERY_ACTION_6DB_DIG_ATTEN)	
    
        dpdRecoveryActionArr[3] = Types.adi_adrv9010_DpdRecoveryActionConfig_t()
        dpdRecoveryActionArr[3].dpdErrorState = Types.adi_adrv9010_DpdErrorState_e.ADI_ADRV9010_DPD_ERR_STATE_PERSISTENT_1
        dpdRecoveryActionArr[3].dpdRecoveryAction.dpdMetricsMask = int(Types.adi_adrv9010_DpdMetric_e.ADI_ADRV9010_DPD_METRIC_DIRECT_EVM)
        dpdRecoveryActionArr[3].dpdRecoveryAction.dpdMetricsMask |= int(Types.adi_adrv9010_DpdMetric_e.ADI_ADRV9010_DPD_METRIC_INDIRECT_ERROR)
        dpdRecoveryActionArr[3].dpdRecoveryAction.dpdActionMask = 0#thresh1ActionMaskPersistent    
    
        #Program the recovery action in the device
        link.platform.board.Adrv9010Device.Dfe.DpdRecoveryActionSet(txChannelMask, dpdRecoveryActionArr, 4)
        print"***************************************"
    
    def dpdRecoveryActionConfigGet():
        print"***************************************"
        print"Reading back Recovery Actions for DPD Robustness"  
        dpdRecoveryActionFromDevice = Types.adi_adrv9010_DpdRecoveryActionConfig_t()
        [recAction, dpdRecoveryActionFromDevice] = link.platform.board.Adrv9010Device.Dfe.DpdRecoveryActionGet(Types.adi_adrv9010_TxChannels_e.ADI_ADRV9010_TX1, Types.adi_adrv9010_DpdErrorState_e.ADI_ADRV9010_DPD_ERR_STATE_0, dpdRecoveryActionFromDevice)
        print "Recovery Action - Metrics Mask Error State 0 =",dpdRecoveryActionFromDevice.dpdRecoveryAction.dpdMetricsMask
        print "Recovery Action - Action Mask Error State 0 =",dpdRecoveryActionFromDevice.dpdRecoveryAction.dpdActionMask
        print " "
    
        dpdRecoveryActionFromDevice = Types.adi_adrv9010_DpdRecoveryActionConfig_t()
        [recAction, dpdRecoveryActionFromDevice] = link.platform.board.Adrv9010Device.Dfe.DpdRecoveryActionGet(Types.adi_adrv9010_TxChannels_e.ADI_ADRV9010_TX1, Types.adi_adrv9010_DpdErrorState_e.ADI_ADRV9010_DPD_ERR_STATE_1, dpdRecoveryActionFromDevice)
        print "Recovery Action - Metrics Mask Error State 1 =",dpdRecoveryActionFromDevice.dpdRecoveryAction.dpdMetricsMask
        print "Recovery Action - Action Mask Error State 1 =",dpdRecoveryActionFromDevice.dpdRecoveryAction.dpdActionMask
        print " "
    
        dpdRecoveryActionFromDevice = Types.adi_adrv9010_DpdRecoveryActionConfig_t()
        [recAction, dpdRecoveryActionFromDevice] = link.platform.board.Adrv9010Device.Dfe.DpdRecoveryActionGet(Types.adi_adrv9010_TxChannels_e.ADI_ADRV9010_TX1, Types.adi_adrv9010_DpdErrorState_e.ADI_ADRV9010_DPD_ERR_STATE_PERSISTENT_0, dpdRecoveryActionFromDevice)
        print "Recovery Action - Metrics Mask Persistent 0 =",dpdRecoveryActionFromDevice.dpdRecoveryAction.dpdMetricsMask
        print "Recovery Action - Action Mask Persistent 0 =",dpdRecoveryActionFromDevice.dpdRecoveryAction.dpdActionMask
        print " "
    
        dpdRecoveryActionFromDevice = Types.adi_adrv9010_DpdRecoveryActionConfig_t()
        [recAction, dpdRecoveryActionFromDevice] = link.platform.board.Adrv9010Device.Dfe.DpdRecoveryActionGet(Types.adi_adrv9010_TxChannels_e.ADI_ADRV9010_TX1, Types.adi_adrv9010_DpdErrorState_e.ADI_ADRV9010_DPD_ERR_STATE_PERSISTENT_1, dpdRecoveryActionFromDevice)
        print "Recovery Action - Metrics Mask Persistent 1 =",dpdRecoveryActionFromDevice.dpdRecoveryAction.dpdMetricsMask
        print "Recovery Action - Action Mask Persistent 1 =",dpdRecoveryActionFromDevice.dpdRecoveryAction.dpdActionMask
        print " "
    
    #Create an Instance of the Class
    link = AdiEvaluationSystem.Instance	
    connect = False
    
    if (link.IsConnected() == False):
        connect = True
        link.platform.board.Client.Connect("192.168.1.145", 55556) 
        print "Connecting"
    
    if (link.IsConnected()):
        adrv9010 = link.Adrv9010Get(1)
        print "Connected"
        ##### YOUR CODE GOES HERE #####
        dpdStabilityCondnSetup()
        dpdRecoveryActionConfigSet()
        dpdRecoveryActionConfigGet()
        print "DPD Recovery Actions Configuration Complete"
    else:
        print "Not Connected"
    
    if (connect):
        link.platform.board.Client.Disconnect()
        print "Disconnected"

  • I tried modifying the threshold value, but DPD still does not work well.

    Are there any other debug points?

  • There is one strange thing.

    Currently, our product's heat dissipation structure is designed to dissipate heat through a heat sink, and heat is dissipated into the heat sink through the thermal PAD attached to the top of the ADRV9025.

    The strange thing is that if you blow air on the heat sink with a fan, the DPD of TX2 operates normally as shown below.

  • I don't think its related to the temperature. Has this issue been related to temperature, i guess the other Tx channels be also affected.

    Can you just enable DPD on Tx2 channel alone and see if you get into this error?

    What is the Tx to ORX mapping, is it 1 to 1, what is the TX to ORX timing?

    It can be a PA related issue as well. Can you check from this perspecitve?

  • I don't think it's a heat problem, but the test results seem to indicate a heat problem, so I'm planning to replace the ADRV9025 and test it.

    And a strange phenomenon is that when testing the Tx2 channel alone, no error occurs.
    Even when testing with 2Tx (Tx2 and Tx3 channels), no error occurs.

    I don't know for what reason.

    And Tx and ORx Mapping is 1:1 Mapping.
    (Tx0 --> ORx0 ~~~~ Tx3 --> ORx3)
    It may be a PA issue, but I don't expect it to be a PA issue.

    I don't know what causes this phenomenon to occur.

  • Is this FDD or TDD?

    What is the TX to ORX switching timing?

    One reason could be Isolation issue.

  • It is composed of TDD and controls 4-ORx port in 3 Pin Mode.

    Isolation is one of the questionable parts. Currently, the top layer of the PCB is the RF Path, the ORx Path is the bottom layer, and it is mechanically shielded, so I think isolation is secured to some extent. However, we will continue to review issues related to isolation.