Post Go back to editing

AD9371 + KCU105 no-OS evaluation procedure

I’m trying to get the AD9371 evaluation board and software running on the Xilinx KCU105 board using the AD9371 No‑OS Setup instructions on the Analog Devices wiki. I’m running into two, possibly related, issues:

  1. The console output from the MicroBlaze processor reports a DeframerStatus of 0x21. I believe that indicates a problem. Is that the AD9371 Deframer (Tx) or the FPGA Deframer (Rx)?
  2. The captured ADC data is all zeros.

 

FPGA code: hdl-2018_r1 (/projects/adrv9371x/kcu105)

Software and Scripts: no-OS-master downloaded 8/3/2018 (no‑OS‑master/ad9371)

AD9371FilterWizard v1.10

Transceiver Evaluation Software: MYK_v2068

RefClk: 15.36 MHz, 398 mVrms (FilterWizard AD9528 RefClkA set to 15.36).

Rx LO Frequency: 1.8 GHz

Test input: 1.820 GHz sine wave, -30 dBm

1. Does the console output indicate a problem? What are the likely causes?

2. Are there any known issues with the software and hdl versions I'm using that might cause this problem?

3. Do you have a set of myk.c and myk_ad9528init.c files that are known to work with the KCU105 board?

thanks.

Parents
  • Have you modified the AD9528 code to take 15.36MHz as reference ?

    Moving to NO_OS support subspace.for more comments.

  • I modified the AD9528 RefClkA Freq setting in the Filter Wizard to 15.36 MHz when I generated the profiles. Then I imported those profiles into TES and generated the C Script files (myk.c, myk.h, myk_ad9528init.c). myk_ad9528init.c appears to have the correct RefClkA frequency setting. I've attached the header files generated by TES. But I'm still using headless.c from no-OS-master as instructed on the wiki.

    /* AD9528 data structure initialization file */
    
    /**
    * \page Disclaimer Legal Disclaimer
    * Copyright 2015-2017 Analog Devices Inc.
    * Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file.
    *
    */
    
    
    #include <stdint.h>
    #include "common.h"
    #include "t_ad9528.h"
    
    static spiSettings_t clockSpiSettings =
    {
         1, /* aeronix - corrected to 1 */
         0,
         1,
         1,
         0,
         0,
         0,
         1,
         1,
         25000000   
    };
    
    ad9528pll1Settings_t clockPll1Settings =
    {
        15360000,
        1,
        3,
        0,
        1,
        0,
        122880000,
        2,
        8,
        0
    };
    
    ad9528pll2Settings_t clockPll2Settings =
    {
        3,
        10,
        30
    };
    
    ad9528outputSettings_t clockOutputSettings =
    {
        53237,
        {0,0,0,2,0,0,0,0,0,0,0,0,2,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {8,8,8,8,8,8,8,8,8,8,8,8,8,8},
        {0,153600000,0,120000,0,0,0,0,0,0,0,0,120000,153600000}
    };
    
    ad9528sysrefSettings_t clockSysrefSettings =
    {
       0,
       2,
       0,
       0,
       0,
       0,
       512
    };
    
    ad9528Device_t clockAD9528_ =
    {
        &clockSpiSettings,
        &clockPll1Settings,
        &clockPll2Settings,
        &clockOutputSettings,
        &clockSysrefSettings
    };
    

    /**
     * \brief Contains init setting structure declarations for the _instance API
     *
     * The top level structure mykonosDevice_t mykDevice uses keyword
     * extern to allow the application layer main() to have visibility
     * to these settings.
     * 
     * All data structures required for operation have been initialized with values which reflect these settings:
     * 
     * Device Clock:
     * Cus 153.6Mhz
     * 
     * Profiles:
     * Cus RX 100MHz, Iqrate 122.88MSPS, DEC5
     * Cus TX 6/100MHz, Iqrate 122.88MSPS, DEC5
     * Cus ORX 100MHz, Iqrate 122.88MSPS, DEC5
     * Cus SNIFFER 20MHz, Iqrate 30.72MSPS, DEC5
     * 
     */
    
    /**
      \page Disclaimer Legal Disclaimer
      Copyright 2015-2017 Analog Devices Inc.
      Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file.
     */
    
    #include <stddef.h>
    #include "t_mykonos.h"
    #include "t_mykonos_gpio.h"
    #include "myk.h"
    
    static int16_t txFirCoefs[] = {7,-244,182,-149,-81,909,-2806,20438,-2806,909,-81,-149,182,-244,7,0};
    
    static mykonosFir_t txFir =
    {
        6,              /* Filter gain in dB*/
        16,             /* Number of coefficients in the FIR filter*/
        &txFirCoefs[0]  /* A pointer to an array of filter coefficients*/
    };
    
    static int16_t rxFirCoefs[] = {-5,-26,32,51,-67,-116,140,212,-252,-367,429,595,-688,-931,1072,1427,-1650,-2188,2612,3496,-4802,-7591,9656,32317,32317,9656,-7591,-4802,3496,2612,-2188,-1650,1427,1072,-931,-688,595,429,-367,-252,212,140,-116,-67,51,32,-26,-5};
    
    static mykonosFir_t rxFir =
    {
        -6,             /* Filter gain in dB*/
        48,             /* Number of coefficients in the FIR filter*/
        &rxFirCoefs[0]  /* A pointer to an array of filter coefficients*/
    };
    
    static int16_t obsrxFirCoefs[] = {0,-21,18,39,-36,-87,81,157,-149,-269,260,432,-423,-672,668,1025,-1036,-1570,1650,2547,-2971,-5686,4361,18361,18361,4361,-5686,-2971,2547,1650,-1570,-1036,1025,668,-672,-423,432,260,-269,-149,157,81,-87,-36,39,18,-21,0};
    static mykonosFir_t obsrxFir =
    {
        0,              /* Filter gain in dB*/
        48,             /* Number of coefficients in the FIR filter*/
        &obsrxFirCoefs[0]/* A pointer to an array of filter coefficients*/
    };
    
    static int16_t snifferFirCoefs[] = {0,2,4,3,-4,-14,-21,-12,17,56,73,39,-53,-159,-198,-101,129,377,457,229,-274,-793,-951,-482,527,1564,1899,1011,-978,-3154,-4109,-2611,1669,7795,13807,17524,17524,13807,7795,1669,-2611,-4109,-3154,-978,1011,1899,1564,527,-482,-951,-793,-274,229,457,377,129,-101,-198,-159,-53,39,73,56,17,-12,-21,-14,-4,3,4,2,0};
    static mykonosFir_t snifferRxFir=
    {
        -6,             /* Filter gain in dB*/
        72,             /* Number of coefficients in the FIR filter*/
        &snifferFirCoefs[0]/* A pointer to an array of filter coefficients*/
    };
    
    static mykonosJesd204bFramerConfig_t rxFramer =
    {
        0,              /* JESD204B Configuration Bank ID -extension to Device ID (Valid 0..15)*/
        0,              /* JESD204B Configuration Device ID - link identification number. (Valid 0..255)*/
        0,              /* JESD204B Configuration starting Lane ID.  If more than one lane used, each lane will increment from the Lane0 ID. (Valid 0..31)*/
        2,              /* number of ADCs (0, 2, or 4) - 2 ADCs per receive chain*/
        32,             /* number of frames in a multiframe (default=32), F*K must be a multiple of 4. (F=2*M/numberOfLanes)*/
        1,              /* scrambling off if framerScramble= 0, if framerScramble>0 scramble is enabled.*/
        1,              /* 0=use internal SYSREF, 1= use external SYSREF*/
        0x03,           /* serializerLanesEnabled - bit per lane, [0] = Lane0 enabled, [1] = Lane1 enabled*/
        0x04,           /* serializerLaneCrossbar*/
        22,             /* serializerAmplitude - default 22 (valid (0-31)*/
        4,              /* preEmphasis - < default 4 (valid 0 - 7)*/
        0,              /* invertLanePolarity - default 0 ([0] will invert lane [0], bit1 will invert lane1)*/
        0,              /* lmfcOffset - LMFC_Offset offset value for deterministic latency setting*/
        0,              /* Flag for determining if SYSREF on relink should be set. Where, if > 0 = set, 0 = not set*/
        0,              /* Flag for determining if auto channel select for the xbar should be set. Where, if > 0 = set, '0' = not set*/
        0,              /* Selects SYNCb input source. Where, 0 = use RXSYNCB for this framer, 1 = use OBSRX_SYNCB for this framer*/
        0,              /* Flag for determining if CMOS mode for RX Sync signal is used. Where, if > 0 = CMOS, '0' = LVDS*/
        0,              /* Selects framer bit repeat or oversampling mode for lane rate matching. Where, 0 = bitRepeat mode (changes effective lanerate), 1 = overSample (maintains same lane rate between ObsRx framer and Rx framer and oversamples the ADC samples)*/
        0               /* Flag for determining if API will calculate the appropriate settings for framer lane outputs to physical lanes. Where, if '0' = API will set automatic lane crossbar, '1' = set to manual mode and the value in serializerLaneCrossbar will be used*/
    };
    
    static mykonosJesd204bFramerConfig_t obsRxFramer =
    {
        0,              /* JESD204B Configuration Bank ID -extension to Device ID (Valid 0..15)*/
        0,              /* JESD204B Configuration Device ID - link identification number. (Valid 0..255)*/
        0,              /* JESD204B Configuration starting Lane ID.  If more than one lane used, each lane will increment from the Lane0 ID. (Valid 0..31)*/
        2,              /* number of ADCs (0, 2, or 4) - 2 ADCs per receive chain*/
        32,             /* number of frames in a multiframe (default=32), F*K must be a multiple of 4. (F=2*M/numberOfLanes)*/
        1,              /* scrambling off if framerScramble= 0, if framerScramble>0 scramble is enabled.*/
        1,              /* 0=use internal SYSREF, 1= use external SYSREF*/
        0x0C,           /* serializerLanesEnabled - bit per lane, [0] = Lane0 enabled, [1] = Lane1 enabled*/
        0x40,           /* Lane crossbar to map framer lane outputs to physical lanes*/
        22,             /* serializerAmplitude - default 22 (valid (0-31)*/
        4,              /* preEmphasis - < default 4 (valid 0 - 7)*/
        0,              /* invertLanePolarity - default 0 ([0] will invert lane [0], bit1 will invert lane1)*/
        0,              /* lmfcOffset - LMFC_Offset offset value for deterministic latency setting*/
        0,              /* Flag for determining if SYSREF on relink should be set. Where, if > 0 = set, 0 = not set*/
        0,              /* Flag for determining if auto channel select for the xbar should be set. Where, if > 0 = set, '0' = not set*/
        1,              /* Selects SYNCb input source. Where, 0 = use RXSYNCB for this framer, 1 = use OBSRX_SYNCB for this framer*/
        0,              /* Flag for determining if CMOS mode for RX Sync signal is used. Where, if > 0 = CMOS, '0' = LVDS*/
        1,              /* Selects framer bit repeat or oversampling mode for lane rate matching. Where, 0 = bitRepeat mode (changes effective lanerate), 1 = overSample (maintains same lane rate between ObsRx framer and Rx framer and oversamples the ADC samples)*/
        0               /* Flag for determining if API will calculate the appropriate settings for framer lane outputs to physical lanes. Where, if '0' = API will set automatic lane crossbar, '1' = set to manual mode and the value in serializerLaneCrossbar will be used*/
    };
    
    static mykonosJesd204bDeframerConfig_t deframer =
    {
        0,              /* bankId extension to Device ID (Valid 0..15)*/
        0,              /* deviceId  link identification number. (Valid 0..255)*/
        0,              /* lane0Id Lane0 ID. (Valid 0..31)*/
        2,              /* M  number of DACss (0, 2, or 4) - 2 DACs per transmit chain */
        32,             /* K  #frames in a multiframe (default=32), F*K=multiple of 4. (F=2*M/numberOfLanes)*/
        1,              /* scramble  scrambling off if scramble= 0.*/
        1,              /* External SYSREF select. 0 = use internal SYSREF, 1 = external SYSREF*/
        0x0F,           /* Deserializer lane select bit field. Where, [0] = Lane0 enabled, [1] = Lane1 enabled, etc */
        0xE4,           /* Lane crossbar to map physical lanes to deframer lane inputs [1:0] = Deframer Input 0 Lane section, [3:2] = Deframer Input 1 lane select, etc */
        1,              /* Equalizer setting. Applied to all deserializer lanes. Range is 0..4*/
        0,              /* PN inversion per each lane.  bit[0] = 1 Invert PN of Lane 0, bit[1] = Invert PN of Lane 1, etc).*/
        0,              /* LMFC_Offset offset value to adjust deterministic latency. Range is 0..31*/
        0,              /* Flag for determining if SYSREF on relink should be set. Where, if > 0 = set, '0' = not set*/
        0,              /* Flag for determining if auto channel select for the xbar should be set. Where, if > 0 = set, '0' = not set*/
        0,              /* Flag for determining if CMOS mode for TX Sync signal is used. Where, if > 0 = CMOS, '0' = LVDS*/
        0               /* Flag for determining if API will calculate the appropriate settings for deframer lane in to physical lanes. Where, if '0' = API will set automatic lane crossbar, '1' = set to manual mode and the value in deserializerLaneCrossbar will be used*/
    };
    
    static mykonosRxGainControl_t rxGainControl =
    {
        MGC,            /* Current Rx gain control mode setting*/
        255,            /* Rx1 Gain Index, can be used in different ways for manual and AGC gain control*/
        255,            /* Rx2 Gain Index, can be used in different ways for manual and AGC gain control*/
        255,            /* Max gain index for the currently loaded Rx1 Gain table*/
        195,            /* Min gain index for the currently loaded Rx1 Gain table*/
        255,            /* Max gain index for the currently loaded Rx2 Gain table*/
        195,            /* Min gain index for the currently loaded Rx2 Gain table*/
        0,              /* Stores Rx1 RSSI value read back from the Mykonos*/
        0               /* Stores Rx2 RSSI value read back from the Mykonos*/
    };
    
    static mykonosORxGainControl_t orxGainControl =
    {
        MGC,            /* Current ORx gain control mode setting*/
        255,            /* ORx1 Gain Index, can be used in different ways for manual and AGC gain control*/
        255,            /* ORx2 Gain Index, can be used in different ways for manual and AGC gain control*/
        255,            /* Max gain index for the currently loaded ORx Gain table*/
        237             /* Min gain index for the currently loaded ORx Gain table*/
    };
    
    static mykonosSnifferGainControl_t snifferGainControl =
    {
        MGC,            /* Current Sniffer gain control mode setting*/
        255,            /* Current Sniffer gain index. Can be used differently for MANUAL Gain control/AGC*/
        255,            /* Max gain index for the currently loaded Sniffer Gain table*/
        203             /* Min gain index for the currently loaded Sniffer Gain table*/
    };
    
    static mykonosPeakDetAgcCfg_t rxPeakAgc =
    {
        0x1A,	/* apdHighThresh: */
        0x10,	/* apdLowThresh */
        0xB5,	/* hb2HighThresh */
        0x48,	/* hb2LowThresh */
        0x28,	/* hb2VeryLowThresh */
        0x06,	/* apdHighThreshExceededCnt */
        0x04,	/* apdLowThreshExceededCnt */
        0x06,	/* hb2HighThreshExceededCnt */
        0x04,	/* hb2LowThreshExceededCnt */
        0x04,	/* hb2VeryLowThreshExceededCnt */
        0x4,	/* apdHighGainStepAttack */
        0x2,	/* apdLowGainStepRecovery */
        0x4,	/* hb2HighGainStepAttack */
        0x2,	/* hb2LowGainStepRecovery */
        0x4,	/* hb2VeryLowGainStepRecovery */
        0x1,	/* apdFastAttack */
        0x1,	/* hb2FastAttack */
        0x1,	/* hb2OverloadDetectEnable */
        0x1,	/* hb2OverloadDurationCnt */
        0x1	/* hb2OverloadThreshCnt */
    };
    
    static mykonosPowerMeasAgcCfg_t rxPwrAgc =
    {
        0x01,	/* pmdUpperHighThresh */
        0x03,	/* pmdUpperLowThresh */
        0x0C,	/* pmdLowerHighThresh */
        0x00,	/* pmdLowerLowThresh */
        0x4,	/* pmdUpperHighGainStepAttack */
        0x2,	/* pmdUpperLowGainStepAttack */
        0x2,	/* pmdLowerHighGainStepRecovery */
        0x4,	/* pmdLowerLowGainStepRecovery */
        0x08,	/* pmdMeasDuration */
        0x02	/* pmdMeasConfig */
    };
    
    static mykonosAgcCfg_t rxAgcConfig =
    {
        255,	/* agcRx1MaxGainIndex */
        195,	/* agcRx1MinGainIndex */
        255,	/* agcRx2MaxGainIndex */
        195,	/* agcRx2MinGainIndex: */
        255,	/* agcObsRxMaxGainIndex */
        203,	/* agcObsRxMinGainIndex */
        1,		/* agcObsRxSelect */
        1,		/* agcPeakThresholdMode */
        1,		/* agcLowThsPreventGainIncrease */
        30720,	/* agcGainUpdateCounter */ /* aeronix - set to 250 us @ 122.88 MHz */
        4,	/* agcSlowLoopSettlingDelay */
        2,	/* agcPeakWaitTime */
        1,	/* agcResetOnRxEnable */
        0,	/* agcEnableSyncPulseForGainCounter */
        &rxPeakAgc,
        &rxPwrAgc
    };
    
    static mykonosPeakDetAgcCfg_t obsRxPeakAgc =
    {
        0x1A,	/* apdHighThresh: */
        0x10,	/* apdLowThresh */
        0xB5,	/* hb2HighThresh */
        0x48,	/* hb2LowThresh */
        0x28,	/* hb2VeryLowThresh */
        0x06,	/* apdHighThreshExceededCnt */
        0x04,	/* apdLowThreshExceededCnt */
        0x06,	/* hb2HighThreshExceededCnt */
        0x04,	/* hb2LowThreshExceededCnt */
        0x04,	/* hb2VeryLowThreshExceededCnt */
        0x4,	/* apdHighGainStepAttack */
        0x2,	/* apdLowGainStepRecovery */
        0x4,	/* hb2HighGainStepAttack */
        0x2,	/* hb2LowGainStepRecovery */
        0x4,	/* hb2VeryLowGainStepRecovery */
        0x1,	/* apdFastAttack */
        0x1,	/* hb2FastAttack */
        0x1,	/* hb2OverloadDetectEnable */
        0x1,	/* hb2OverloadDurationCnt */
        0x1		/* hb2OverloadThreshCnt */
    };
    
    static mykonosPowerMeasAgcCfg_t obsRxPwrAgc =
    {
        0x01,	/* pmdUpperHighThresh */
        0x03,	/* pmdUpperLowThresh */
        0x0C,	/* pmdLowerHighThresh */
        0x00,	/* pmdLowerLowThresh */
        0x4,	/* pmdUpperHighGainStepAttack */
        0x2,	/* pmdUpperLowGainStepAttack */
        0x2,	/* pmdLowerHighGainStepRecovery */
        0x4,	/* pmdLowerLowGainStepRecovery */
        0x08,	/* pmdMeasDuration */
        0x02	/* pmdMeasConfig */
    };
    
    static mykonosAgcCfg_t obsRxAgcConfig =
    {
        255,	/* agcRx1MaxGainIndex */
        195,	/* agcRx1MinGainIndex */
        255,	/* agcRx2MaxGainIndex */
        195,	/* agcRx2MinGainIndex: */
        255,	/* agcObsRxMaxGainIndex */
        203,	/* agcObsRxMinGainIndex */
        1,		/* agcObsRxSelect */
        1,		/* agcPeakThresholdMode */
        1,		/* agcLowThsPreventGainIncrease */
        30720,	/* agcGainUpdateCounter */ /* aeronix - set to 250 us @ 122.88 MHz */
        4,		/* agcSlowLoopSettlingDelay */
        2,		/* agcPeakWaitTime */
        1,		/* agcResetOnRxEnable */
        0,		/* agcEnableSyncPulseForGainCounter */
        &obsRxPeakAgc,
        &obsRxPwrAgc
    };
    
    static uint16_t rxAdcCustom[]={534,386,201,98,1280,491,1591,279,1306,104,792,28,48,39,23,187};
    
    static mykonosRxProfile_t rxProfile =
    {/* RX 100MHz, Iqrate 122.88MSPS, DEC5 */
        1,              /* The divider used to generate the ADC clock*/
        &rxFir,         /* Pointer to Rx FIR filter structure*/
        2,              /* Rx FIR decimation (1,2,4)*/
        5,              /* Decimation of Dec5 or Dec4 filter (5,4)*/
        1,              /* If set, and DEC5 filter used, will use a higher rejection DEC5 FIR filter (1=Enabled, 0=Disabled)*/
        1,              /* RX Half band 1 decimation (1 or 2)*/
        122880,         /* Rx IQ data rate in kHz*/
        100000000,      /* The Rx RF passband bandwidth for the profile*/
        100000,         /* Rx BBF 3dB corner in kHz*/
        &rxAdcCustom[0] /* pointer to custom ADC profile*/
    };
    static uint16_t orxAdcCustom[]={534,386,201,98,1280,491,1591,279,1306,104,792,28,48,39,23,187};
    
    static mykonosRxProfile_t orxProfile =
    {/* ORX 100MHz, Iqrate 122.88MSPS, DEC5 */
        1,              /* The divider used to generate the ADC clock*/
        &obsrxFir,      /* Pointer to Rx FIR filter structure or NULL*/
        2,              /* Rx FIR decimation (1,2,4)*/
        5,              /* Decimation of Dec5 or Dec4 filter (5,4)*/
        0,              /* If set, and DEC5 filter used, will use a higher rejection DEC5 FIR filter (1=Enabled, 0=Disabled)*/
        1,              /* RX Half band 1 decimation (1 or 2)*/
        122880,         /* Rx IQ data rate in kHz*/
        100000000,      /* The Rx RF passband bandwidth for the profile*/
        50000,          /* Rx BBF 3dB corner in kHz*/
        &orxAdcCustom[0] /* pointer to custom ADC profile*/
    };
    
    static uint16_t snifferAdcCustom[]={599,357,201,98,1280,112,1505,53,1331,21,820,40,48,40,23,191};
    
    static mykonosRxProfile_t snifferProfile =
    { /* SNIFFER 20MHz, Iqrate 30.72MSPS, DEC5 */
        1,              /* The divider used to generate the ADC clock*/
        &snifferRxFir,  /* Pointer to Rx FIR filter structure or NULL*/
        4,              /* Rx FIR decimation (1,2,4)*/
        5,              /* Decimation of Dec5 or Dec4 filter (5,4)*/
        0,              /* If set, and DEC5 filter used, will use a higher rejection DEC5 FIR filter (1=Enabled, 0=Disabled)*/
        2,              /* RX Half band 1 decimation (1 or 2)*/
        30720,          /* Rx IQ data rate in kHz*/
        20000000,       /* The Rx RF passband bandwidth for the profile*/
        20000,          /* Rx BBF 3dB corner in kHz*/
        &snifferAdcCustom[0] /* pointer to custom ADC profile*/
    };
    
    
    
    static mykonosTxProfile_t txProfile =
    { /* TX 6/100MHz, Iqrate 122.88MSPS, DEC5 */
        DACDIV_2p5,     /* The divider used to generate the DAC clock*/
        &txFir,         /* Pointer to Tx FIR filter structure*/
        1,              /* The Tx digital FIR filter interpolation (1,2,4)*/
        2,              /* Tx Halfband1 filter interpolation (1,2)*/
        2,              /* Tx Halfband2 filter interpolation (1,2)*/
        1,              /* TxInputHbInterpolation (1,2)*/
        122880,         /* Tx IQ data rate in kHz*/
        6000000,        /* Primary Signal BW*/
        100000000,      /* The Tx RF passband bandwidth for the profile*/
        100000,         /* The DAC filter 3dB corner in kHz*/
        50000,          /* Tx BBF 3dB corner in kHz*/
        0               /* Enable DPD, only valid for AD9373*/
    };
    
    static mykonosDigClocks_t mykonosClocks =
    {
        153600,         /* CLKPLL and device reference clock frequency in kHz*/
        9830400,        /* CLKPLL VCO frequency in kHz*/
        VCODIV_2,       /* CLKPLL VCO divider*/
        4               /* CLKPLL high speed clock divider*/
    };
    
    static mykonosRxSettings_t  rxSettings =
    {
        &rxProfile,     /* Rx datapath profile, 3dB corner frequencies, and digital filter enables*/
        &rxFramer,      /* Rx JESD204b framer configuration structure*/
        &rxGainControl, /* Rx Gain control settings structure*/
        &rxAgcConfig,   /* Rx AGC control settings structure*/
        1,              /* The desired Rx Channels to enable during initialization*/
        0,              /* Internal LO = 0, external LO*2 = 1*/
        1800000000U,    /* Rx PLL LO Frequency (internal or external LO)*/
        0               /* Flag to choose if complex baseband or real IF data are selected for Rx and ObsRx paths. Where, if > 0 = real IF data, '0' = zero IF (IQ) data*/
    };
    
    static mykonosDpdConfig_t dpdConfig =
    {
        5,              /* 1/2^(damping + 8) fraction of power `forgotten' per sample (default: `1/8192' = 5, valid 0 to 15), 0 = infinite damping*/
        1,              /* number of weights to use for int8_cpx weights weights member of this structure (default = 1)*/
        2,              /* DPD model version: one of four different generalized polynomial models: 0 = same as R0 silicon, 1-3 are new and the best one depends on the PA (default: 2)*/
        1,              /* 1 = Update saved model whenever peak Tx digital RMS is within 1dB of historical peak Tx RMS*/
        20,             /* Determines how much weight the loaded prior model has on DPD modeling (Valid 0 - 32, default 20)*/
        0,              /* Default off = 0, 1=enables automatic outlier removal during DPD modeling */
        512,            /* Number of samples to capture (default: 512, valid 64-32768)*/
        4096,           /* threshold for sample in AM-AM plot outside of 1:1 line to be thrown out. (default: 50% = 8192/2, valid 8192 to 1)*/
        0,              /* 16th of an ORx sample (16=1sample), (default 0, valid -64 to 64)*/
        255,            /* Default 255 (-30dBFs=(20Log10(value/8192)), (valid range  1 to 8191)*/
        {{64,0},{0,0},{0,0}}/* DPD model error weighting (real/imag valid from -128 to 127)*/
    };
    
    static mykonosClgcConfig_t clgcConfig =
    {
        -2000,          /* (value = 100 * dB (valid range -32768 to 32767) - total gain and attenuation from Mykonos Tx1 output to ORx1 input in (dB * 100)*/
        -2000,          /* (value = 100 * dB (valid range -32768 to 32767) - total gain and attenuation from Mykonos Tx2 output to ORx2 input in (dB * 100)*/
        0,              /* (valid range 0 - 40dB), no default, depends on PA, Protects PA by making sure Tx1Atten is not reduced below the limit*/
        0,              /* (valid range 0 - 40dB), no default, depends on PA, Protects PA by making sure Tx2Atten is not reduced below the limit*/
        75,             /* valid range 1-100, default 75*/
        75,             /* valid range 1-100, default 45*/
        0,              /* 0= allow CLGC to run, but Tx1Atten will not be updated. User can still read back power measurements.  1=CLGC runs, and Tx1Atten automatically updated*/
        0,              /* 0= allow CLGC to run, but Tx2Atten will not be updated. User can still read back power measurements.  1=CLGC runs, and Tx2Atten automatically updated*/
        0,              /* 16th of an ORx sample (16=1sample), (default 0, valid -64 to 64)*/
        255,            /* Default 255 (-30dBFs=(20Log10(value/8192)), (valid range  1 to 8191)*/
        600,            /* Threshold for Tx1 in order to stop tracking, value = 100 * dB, default 6db then value = 600*/
        600,            /* Threshold for Tx2 in order to stop tracking, value = 100 * dB, default 6db then value = 600*/
        0,              /* Threshold feature enable for Tx1, 0 = disable, 1 = enable, default = 0*/
        0               /* Threshold feature enable for Tx1, 0 = disable, 1 = enable, default = 0*/
    };
    
    static mykonosVswrConfig_t vswrConfig =
    {
        0,              /* 16th of an ORx sample (16=1sample), (default 0, valid -64 to 64)*/
        255,            /* Default 255 (-30dBFs=(20Log10(value/8192)), (valid range  1 to 8191)*/
        0,              /* 3p3V GPIO pin to use to control VSWR switch for Tx1 (valid 0-11) (output from Mykonos)*/
        1,              /* 3p3V GPIO pin to use to control VSWR switch for Tx2 (valid 0-11) (output from Mykonos)*/
        0,              /* 3p3v GPIO pin polarity for forward path of Tx1, opposite used for reflection path (1 = high level, 0 = low level)*/
        0,              /* 3p3v GPIO pin polarity for forward path of Tx2, opposite used for reflection path (1 = high level, 0 = low level)*/
        50,             /* Delay for Tx1 after flipping the VSWR switch until measurement is made. In us resolution*/
        50              /* Delay for Tx2 after flipping the VSWR switch until measurement is made. In us resolution*/
    };
    
    static mykonosTxSettings_t txSettings =
    {
        &txProfile,     /* Tx datapath profile, 3dB corner frequencies, and digital filter enables*/
        &deframer,      /* Mykonos JESD204b deframer config for the Tx data path*/
        TX1,            /* The desired Tx channels to enable during initialization*/
        0,              /* Internal LO=0, external LO*2 if =1*/
        1800000000U,    /* Tx PLL LO frequency (internal or external LO)*/
        TXATTEN_0P05_DB,/* Initial and current Tx1 Attenuation*/
        10000,          /* Initial and current Tx1 Attenuation mdB*/
        10000,          /* Initial and current Tx2 Attenuation mdB*/
        NULL,           /* DPD,CLGC,VSWR settings. Only valid for AD9373 device, set pointer to NULL otherwise*/
        NULL,           /* CLGC Config Structure. Only valid for AD9373 device, set pointer to NULL otherwise*/
        NULL            /* VSWR Config Structure. Only valid for AD9373 device, set pointer to NULL otherwise*/
    };
    
    static uint16_t lpbkAdcCustom[]={599,357,201,98,1280,112,1505,53,1331,21,820,40,48,40,23,191};
    
    static mykonosObsRxSettings_t obsRxSettings =
    {
        &orxProfile,    /* ORx datapath profile, 3dB corner frequencies, and digital filter enables*/
        &orxGainControl,/* ObsRx gain control settings structure*/
        &obsRxAgcConfig,/* ORx AGC control settings structure*/
        &snifferProfile,/* Sniffer datapath profile, 3dB corner frequencies, and digital filter enables*/
        &snifferGainControl,/* SnRx gain control settings structure*/
        &obsRxFramer,   /* ObsRx JESD204b framer configuration structure */
        (MYK_ORX1_ORX2 | MYK_SNRXA_B_C),/* obsRxChannel */
        OBSLO_TX_PLL,   /* (obsRxLoSource) The Obs Rx mixer can use the Tx Synth(TX_PLL) or Sniffer Synth (SNIFFER_PLL) */
        1800000000U,    /* SnRx PLL LO frequency in Hz */
        0,              /* Flag to choose if complex baseband or real IF data are selected for Rx and ObsRx paths. Where if > 0 = real IF data, '0' = complex data*/
        &lpbkAdcCustom[0],/* Custom Loopback ADC profile to set the bandwidth of the ADC response*/
        OBS_RXOFF       /* Default ObsRx channel to enter when radioOn called */
    };
    
    static mykonosArmGpioConfig_t armGpio =
    {
        0,	// useRx2EnablePin; /*!< 0= RX1_ENABLE controls RX1 and RX2, 1 = separate RX1_ENABLE/RX2_ENABLE pins */
        0,	// useTx2EnablePin; /*!< 0= TX1_ENABLE controls TX1 and TX2, 1 = separate TX1_ENABLE/TX2_ENABLE pins */
        0,	// txRxPinMode;     /*!< 0= ARM command mode, 1 = Pin mode to power up Tx/Rx chains */
        0,	// orxPinMode;      /*!< 0= ARM command mode, 1 = Pin mode to power up ObsRx receiver*/
    
        /*Mykonos ARM input GPIO pins -- Only valid if orxPinMode = 1 */
        0,	// orxTriggerPin; /*!< Select desired GPIO pin (valid 4-15) */
        0,	// orxMode2Pin;   /*!< Select desired GPIO pin (valid 0-18) */
        0,	// orxMode1Pin;   /*!< Select desired GPIO pin (valid 0-18) */
        0,	// orxMode0Pin;   /*!< Select desired GPIO pin (valid 0-18) */
    
        /* Mykonos ARM output GPIO pins  --  always available, even when pin mode not enabled*/
        0,	// rx1EnableAck;  /*!< Select desired GPIO pin (0-15), [4] = Output Enable */
        0,	// rx2EnableAck;  /*!< Select desired GPIO pin (0-15), [4] = Output Enable */
        0,	// tx1EnableAck;  /*!< Select desired GPIO pin (0-15), [4] = Output Enable */
        0,	// tx2EnableAck;  /*!< Select desired GPIO pin (0-15), [4] = Output Enable */
        0,	// orx1EnableAck;  /*!< Select desired GPIO pin (0-15), [4] = Output Enable */
        0,	// orx2EnableAck;  /*!< Select desired GPIO pin (0-15), [4] = Output Enable */
        0,	// srxEnableAck;  /*!< Select desired GPIO pin (0-15), [4] = Output Enable */
        0 	// txObsSelect;   /*!< Select desired GPIO pin (0-15), [4] = Output Enable */
        /* When 2Tx are used with only 1 ORx input, this GPIO tells the BBIC which Tx channel is   */
        /* active for calibrations, so BBIC can route correct RF Tx path into the single ORx input*/
    };
    
    static mykonosGpio3v3_t gpio3v3 =
    {
        0,				/*!< Oe per pin, 1=output, 0 = input */
        GPIO3V3_BITBANG_MODE,	/*!< Mode for GPIO3V3[3:0] */
        GPIO3V3_BITBANG_MODE,	/*!< Mode for GPIO3V3[7:4] */
        GPIO3V3_BITBANG_MODE,	/*!< Mode for GPIO3V3[11:8] */
    };
    
    static mykonosGpioLowVoltage_t gpio =
    {
        0,/* Oe per pin, 1=output, 0 = input */
        GPIO_MONITOR_MODE,/* Mode for GPIO[3:0] */
        GPIO_MONITOR_MODE,/* Mode for GPIO[7:4] */
        GPIO_MONITOR_MODE,/* Mode for GPIO[11:8] */
        GPIO_MONITOR_MODE,/* Mode for GPIO[15:12] */
        GPIO_MONITOR_MODE,/* Mode for GPIO[18:16] */
    };
    
    static mykonosAuxIo_t mykonosAuxIo =
    {
        0,	//auxDacEnableMask uint16_t
        {0,0,0,0,0,0,0,0,0,0},	 //AuxDacValue uint16[10]
        {0,0,0,0,0,0,0,0,0,0},	 //AuxDacSlope uint8[10]
        {0,0,0,0,0,0,0,0,0,0},	 //AuxDacVref uint8[10]
        &gpio3v3,	//pointer to gpio3v3 struct
        &gpio,	//pointer to gpio1v8 struct
        &armGpio
    };
    
    static spiSettings_t mykSpiSettings =
    {
        2, /* chip select index - valid 1~8 */ /* aeronix - corrected to 2 */
        0, /* the level of the write bit of a SPI write instruction word, value is inverted for SPI read operation */
        1, /* 1 = 16-bit instruction word, 0 = 8-bit instruction word */
        1, /* 1 = MSBFirst, 0 = LSBFirst */
        0, /* clock phase, sets which clock edge the data updates (valid 0 or 1) */
        0, /* clock polarity 0 = clock starts low, 1 = clock starts high */
        0, /* Not implemented in ADIs platform layer. SW feature to improve SPI throughput */
        1, /* Not implemented in ADIs platform layer. For SPI Streaming, set address increment direction. 1= next addr = addr+1, 0:addr=addr-1 */
        1  /* 1: Use 4-wire SPI, 0: 3-wire SPI (SDIO pin is bidirectional). NOTE: ADI's FPGA platform always uses 4-wire mode */
    };
    
    static mykonosTempSensorConfig_t tempSensor =
    {
        7,              /* 3-bit value that controls the AuxADC decimation factor when used for temp sensor calculations; AuxADC_decimation = 256 * 2^tempDecimation*/
        67,             /* 8-bit offset that gets added to temp sensor code internally*/
        1,              /* this bit overrides the factory-calibrated fuse offset and uses the value stored in the offset member*/
        15,             /* 4-bit code with a resolution of 1°C/LSB, each time a temperature measurement is performed, the device compares the current temperature against the previous value.*/
    };
    
    static mykonosTempSensorStatus_t tempStatus =
    {
        0,              /* 16-bit signed temperature value (in deg C) that is read back*/
        0,              /* If the absolute value of the difference is greater than the value in temperature configuration tempWindow, the windowExceeded flag is set.*/
        0,              /* when windowExceeded member gets set, this bit is set to 1 if current value is greater than previous value, else reset*/
        0,              /* when the reading is complete and a valid temperature value stored in tempCode.*/
    };
    
    mykonosDevice_t mykDevice =
    {
        &mykSpiSettings,    /* SPI settings data structure pointer */
        &rxSettings,        /* Rx settings data structure pointer */
        &txSettings,        /* Tx settings data structure pointer */
        &obsRxSettings,     /* ObsRx settings data structure pointer */
        &mykonosAuxIo,          /* Auxiliary IO settings data structure pointer */
        &mykonosClocks,     /* Holds settings for CLKPLL and reference clock */
        0                   /* Mykonos initialize function uses this as an output to remember which profile data structure pointers are valid */
    };
    

  • Don’t do that. For optimal performance keep the reference clock has high as possible. Better keep the 122.88 if possible. It might be the case that the FPGA gigabit transceiver can’t handle it.

  • The default AD9528 RefClkA frequency is 30.72 MHz (SMA input to AD9371 eval board). The AD9528 VCXO frequency is 122.88 MHz (fixed component on AD9371 eval board). We decreased the AD9528 RefClkA frequency to 15.36 MHz because our signal generator maxes out at 20 MHz. It works fine on the Zynq eval platform.

    The Ref/Device clock generated by the AD9528 and going to the AD9371 & FPGA is set to 153.6 MHz.

  • Sorry - I replied from my mobile yesterday. I didn't really catch that the AD9528 Reference clock is changed.

    I saw device clock 153600 and assumed that this was set to 15.36MHz.

    In case you leave the Device Clock at 122.88 and only change the AD9528 Reference clock, are you still getting these framer and deframer errors?

  • Yes. I set the device clock to 122.88 MHz (instead of 153.6 MHz) and received the same console output messages. According to UG-992 RxFramerStatus of 0x20 does not indicate an error, but it doesn't appear to have completed its initialization. The DeframerStatus of 0x21 does indicate an error (FS lost).

    I see a similar problem reported here, but the resolution was not specified.

    https://ez.analog.com/fpga/f/q-a/102662/ad9371-kcu105

    https://ez.analog.com/linux-device-drivers/microcontroller-no-os-drivers/f/q-a/102466/ad9371-kcu105-can-t-work/304788

  • I was able to get the RxFramerStatus and DeframerStatus to pass by dropping the Rx sample rate from 122.88 MHz to 61.44 MHz. I'll play with that some more later. Now the console output shows no errors, but I'm not getting any Rx data. The capture.tcl script reads from address 0x00800000 (8388608), but that always reads 0. I also tried 0x80800000 (the start address in headless.c). That looks more like Rx data, but the VisualAnalog FFT shows no energy. My Rx LO is set to 2.55 GHz and I'm injecting a -30 dBm sine wave at 2.551 GHz. So I'm looking for a peak at 1 MHz. I'm still experimenting. Just want to keep you up to date.

  • I was finally able to capture good Rx data on the AD9371+KCU105 evaluation board setup by reducing the Rx data rate to 30.72 Msps. However, even at that low data rate the setup does not always capture valid Rx data when running headless.c.

    Reducing the Rx data rate from my target 122.88 Msps to 30.72 Msps prevents the RxFramerStatus and DeframerStatus errors I was seeing. I now get this console output consistently at the 30.72 Msps rate.

    Please wait...
    RX_XCVR (GTH3) initialization OK
    TX_XCVR (GTH3) initialization OK
    RX_OS_XCVR (GTH3) initialization OK
    MCS successful
    CLKPLL locked
    AD9371 ARM version 5.1.1
    PLLs locked
    Calibrations completed successfully
    dac_setup dac core initialized (122 MHz).
    adc_setup adc core initialized (31 MHz).
    Done

    But that's not enough to guarantee a valid Rx capture. The JESD Link Rx module in the FPGA provides the LANE0_STATUS and LANE1_STATUS at 0x44aa0300 and 0x44aa0320. Those lane statuses must both be 0x00000032 to capture valid data (indicating ILAS_READY, IFS_READY and CGS_STATE=DATA). Often one or the other reports back a status of 0x10 or 0x30 (CGS_STATE=INIT) instead of 0x32.

    At an Rx data rate of 61.44 Msps I have never seen both lane statuses correct, but the console output does not indicate any errors.

    At what maximum sample rate has Analog Devices been able to consistently capture valid Rx data on the AD9371+KCU105 setup?

  • I would like some help getting the AD9371+KCU105 no-OS evaluation setup running with Rx and Tx sample rates of 122.88 Msps.

    Running the headless.c main loop multiple times I see one of these two outputs:

    1. Rx Framer Status is not 0x3e as expected.

    Please wait...
    RX_XCVR (GTH3) initialization OK
    TX_XCVR (GTH3) initialization OK
    RX_OS_XCVR (GTH3) initialization OK
    MCS successful
    CLKPLL locked
    AD9371 ARM version 5.1.1
    PLLs locked
    Calibrations completed successfully
    RxFramerStatus = 0x20
    dac_setup dac core initialized (122 MHz).
    adc_setup adc core initialized (123 MHz).
    Done
    ***-> debug start <-***
      Radio Status 3 (3=radioOn)
      Rx RF PLL Frequency 2550000000
      Rx1 Gain Index 255
      Rx Framer Status 20
      Deframer Status 68
      JESD Rx Lane0 Status 44aa0300, 00000000
      JESD Rx Lane1 Status 44aa0320, 00000000
    ***-> debug end <-***

    2. The configuration completes without errors, but the Rx Lane0 and Lane1 statuses are not 0x32 as expected.

    Please wait...
    RX_XCVR (GTH3) initialization OK
    TX_XCVR (GTH3) initialization OK
    RX_OS_XCVR (GTH3) initialization OK
    MCS successful
    CLKPLL locked
    AD9371 ARM version 5.1.1
    PLLs locked
    Calibrations completed successfully
    dac_setup dac core initialized (122 MHz).
    adc_setup adc core initialized (123 MHz).
    Done
    ***-> debug start <-***
      Radio Status 3 (3=radioOn)
      Rx RF PLL Frequency 2550000000
      Rx1 Gain Index 255
      Rx Framer Status 3e
      Deframer Status 68
      JESD Rx Lane0 Status 44aa0300, 00000010
      JESD Rx Lane1 Status 44aa0320, 00000010
    ***-> debug end <-***

    My Rx1 input can not be captured successfully in either case.

    I'm using the hdl-2018_r1 tree HDL code and no-Os software.

    Should the AD9371+KCU105 setup with the hdl-2018_r1 HDL and software support these rates?

    thanks.

  • Still waiting for a response...

    I'm using the hdl-2018_r1 tree HDL code and no-Os software.

    Should the AD9371+KCU105 setup with the hdl-2018_r1 HDL and software support these rates (Rx=122.88 MSPS, Tx=122.88 MSPS)?

Reply Children
  • Hi,

    Sorry for the delay. We will have a look.

    Thanks,

    Dragos

  • Thanks. I have one update. Last Friday I put the headless.c initialization sequence into a loop, checking the JESD Rx Lane0 and Lane1 status registers after each attempt. The loop ran 195 times before both lane statuses were 0x32. (This is with an Rx sample rate of 122.88 MSPS). At that point the initialization loop stopped and the code started looping on adc_capture. It's been running without any problems since Friday. So I suspect the problem is with initialization.

  • Here are my capture.bat and capture.tcl files (updated to xsdb) in case they are useful.

    @echo off
    
    IF "%PROCESSOR_ARCHITECTURE%"=="x86" set XSDB_DIR=C:\Xilinx\SDK\2017.4\bin
    IF "%PROCESSOR_ARCHITECTURE%"=="AMD64" set XSDB_DIR=C:\Xilinx\SDK\2017.4\bin
    
    %XSDB_DIR%\xsdb.bat capture.tcl
    
    pause
    

    connect -host localhost -port 3121
    targets -set -filter {name =~ "MicroBlaze #0"} -index 0
    #targets -set -filter {name =~ "MicroBlaze Debug*"} -index 0
    
    puts "Transfering data..."
    
    #set startAddress 8388608
    set startAddress 0x80800000
    #set startAddress 0x8a000000
    set readData [mrd $startAddress 32768]
    
    #set fp1 [ open iq_rx1.csv a ]
    #set fp2 [ open iq_rx2.csv a ]
    set fp1 [ open iq_rx1.csv w ]
    set fp2 [ open iq_rx2.csv w ]
    set fph1 [ open iq_rxh1.csv w ]
    set fph2 [ open iq_rxh2.csv w ]
    for {set index 1} {$index < 65536} {incr index 4} {
    	set data [lindex $readData $index]
    	set intData [expr 0x$data]
    	
    	set sampleI1 [expr {$intData & 0xFFFF}]
    	set sampleQ1 [expr {($intData >> 16) & 0xFFFF}]
    	
    	set data [lindex $readData [expr {$index + 2}]]
    	set intData [expr 0x$data]
    	
    	set sampleI2 [expr {$intData & 0xFFFF}]
    	set sampleQ2 [expr {($intData >> 16) & 0xFFFF}]
    	
    	puts $fp1 $sampleI1
    	puts $fp1 $sampleQ1
    	puts $fp2 $sampleI2
    	puts $fp2 $sampleQ2
    
    	puts $fph1 [format "%04x" $sampleI1]
    	puts $fph1 [format "%04x" $sampleQ1]
    	puts $fph2 [format "%04x" $sampleI2]
    	puts $fph2 [format "%04x" $sampleQ2]
    	
    }
    close $fp1
    close $fp2
    
    puts "Done."
    
    disconnect
    exit
    

  • Have you been able to reproduce the error?

    thanks.

  • Have you been able to reproduce the error?

    thanks.

  • Hi,

    I was able to replicate the issue. I will try to add a working 122.88 MSPS example on the GitHub. I will let you know the location.

    Thanks,

    Dragos

  • I've uploaded a 122.88 MSPS profile on the GitHub: https://github.com/analogdevicesinc/no-OS/tree/ad9371_rework/projects/ad9371/src/app Can you give it a try too?

    I've uploaded also a newer version of firmware and the corresponding API. The work is still in progress, but soon (after the Winter Holidays :) ), all the required files for a working project will be found on the GitHub.

    Dragos

  • We're back in the office today. I'll try it out. Thanks.

  • Just updating the profile (myk.c, myk.h and myk_ad9528init.c) with the files you provided did not fix the problem. I'm still using a modified version of myk_ad9528init.c because my AD9528 Ref clock is running at 15.36 MHz instead of 30.72. But that only affects the ad9528pll1Settings_t structure. Otherwise I'm using the new profile exactly. And I'm still seeing the same problem.

    The most significant changes seem to be in your new headless.c initialization sequence, but that requires the new driver files.

    1. Do you expect the new profile to fix the problem even using the old headless.c?

    2. Should I try the new drivers with the new headless.c or wait until you post the entire project?

    Thanks.

  • We should be able to upload the entire project this week, so if you can wait a few more days, it would be easier.

    Dragos