Hi All,
I'm developing a custom application for multichip syncronization with AD9081. I follow the specifications indicated in:
"">www.analog.com/.../power-up-phase-determinism-using-multichip-synchronization.html" Fig.2 and the following instructions in UG-1578:
My code is the following:
/*! * @brief Standalone Linux Application * * @copyright copyright(c) 2018 analog devices, inc. all rights reserved. * This software is proprietary to Analog Devices, Inc. and its * licensor. By using this software you agree to the terms of the * associated analog devices software license agreement. */ /*! * @addtogroup __ADI_AD9081_APP__ * @{ */ /*============= I N C L U D E S ============*/ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <math.h> #include "adi_ad9081.h" #include "adi_ad9081_config.h" #include "adi_ad9081_hal.h" #include "adi_hmc7043.h" #include "adi_adf4371.h" #include "pl.h" #include "NCO_settings.h" #include "fw_settings.h" #include "uc_settings.h" /*============= D A T A ====================*/ #define STAGE1 (1<<0) #define STAGE2 (1<<1) #define STAGE3 (1<<2) #define STAGE4 (1<<3) #define SYNC_MS_GPIO_NUM 0 #define TRIGGER_SRC 0 #define EXTRA_LFMC_NUM 0 #define MS_SYNC_ENB 1 #define MXFE_NUMBER 4 /*============= C O D E ====================*/ /** * div_s64_rem - signed 64bit divide with 32bit divisor with remainder */ static inline int64_t div_s64_rem(int64_t dividend, int32_t divisor, int32_t *remainder) { *remainder = dividend % divisor; return dividend / divisor; } /** * div_s64 - signed 64bit divide with 32bit divisor */ static inline int64_t div_s64(int64_t dividend, int32_t divisor) { int32_t remainder; return div_s64_rem(dividend, divisor, &remainder); } int32_t adi_ad9081_adc_nco_sync(adi_ad9081_device_t *device, uint8_t trigger_src, uint8_t extra_lmfc_num) { int err; AD9081_NULL_POINTER_RETURN(device); AD9081_LOG_FUNC(); err = adi_ad9081_hal_bf_set(device, REG_MAIN_AUTO_CLK_GATING_ADDR, 0x00000400, 7); AD9081_ERROR_RETURN(err); err = adi_ad9081_adc_ddc_coarse_sync_enable_set(device, AD9081_ADC_CDDC_ALL, 1); AD9081_ERROR_RETURN(err); err = adi_ad9081_adc_ddc_coarse_sync_next_set(device, AD9081_ADC_CDDC_ALL, 1); AD9081_ERROR_RETURN(err); err = adi_ad9081_adc_ddc_coarse_trig_nco_reset_enable_set( device, AD9081_ADC_CDDC_ALL, 0); AD9081_ERROR_RETURN(err); err = adi_ad9081_adc_ddc_fine_sync_enable_set(device, AD9081_ADC_FDDC_ALL, 1); AD9081_ERROR_RETURN(err); err = adi_ad9081_adc_ddc_fine_sync_next_set(device, AD9081_ADC_FDDC_ALL, 1); AD9081_ERROR_RETURN(err); err = adi_ad9081_adc_ddc_fine_trig_nco_reset_enable_set( device, AD9081_ADC_FDDC_ALL, 0); AD9081_ERROR_RETURN(err); err = adi_ad9081_device_nco_sync_mode_set(device, 0); AD9081_ERROR_RETURN(err); err = adi_ad9081_device_nco_sync_sysref_mode_set(device, trigger_src); AD9081_ERROR_RETURN(err); AD9081_ERROR_RETURN(err); err = adi_ad9081_device_nco_sync_extra_lmfc_num_set(device, extra_lmfc_num); AD9081_ERROR_RETURN(err); err = adi_ad9081_adc_ddc_coarse_sync_next_set(device, AD9081_ADC_CDDC_ALL, 0); AD9081_ERROR_RETURN(err); err = adi_ad9081_adc_ddc_fine_sync_next_set(device, AD9081_ADC_FDDC_ALL, 0); AD9081_ERROR_RETURN(err); err = adi_ad9081_adc_ddc_coarse_sync_next_set(device, AD9081_ADC_CDDC_ALL, 1); AD9081_ERROR_RETURN(err); err = adi_ad9081_adc_ddc_fine_sync_next_set(device, AD9081_ADC_FDDC_ALL, 1); AD9081_ERROR_RETURN(err); err = adi_ad9081_device_nco_sync_reset_via_sysref_set(device, 0); AD9081_ERROR_RETURN(err); err = adi_ad9081_device_nco_sync_reset_via_sysref_set(device, 1); AD9081_ERROR_RETURN(err); return API_CMS_ERROR_OK; } int adi_ad9081_device_gpio_set_highz(adi_ad9081_device_t *device, uint8_t gpio_index) { int err; AD9081_NULL_POINTER_RETURN(device); AD9081_LOG_FUNC(); AD9081_INVALID_PARAM_RETURN(gpio_index > 5); if ((gpio_index & 1) == 0) { err = adi_ad9081_hal_bf_set(device, REG_GPIO_CFG0_ADDR + (gpio_index >> 1), 0x0400, 0); AD9081_ERROR_RETURN(err); } else { err = adi_ad9081_hal_bf_set(device, REG_GPIO_CFG0_ADDR + (gpio_index >> 1), 0x0404, 0); AD9081_ERROR_RETURN(err); } return API_CMS_ERROR_OK; } int32_t adi_ad9081_jesd_sysref_monitor_phase_get(adi_ad9081_device_t *device, uint16_t *sysref_phase) { int32_t err; uint8_t phase0_val; uint8_t phase1_val; AD9081_NULL_POINTER_RETURN(device); AD9081_NULL_POINTER_RETURN(sysref_phase); AD9081_LOG_FUNC(); /* Write strobe to trigger a value update */ err = adi_ad9081_hal_bf_set(device, REG_SYSREF_PHASE0_ADDR, 0x800, 0x00); err = adi_ad9081_hal_bf_get(device, REG_SYSREF_PHASE0_ADDR, 0x800, &phase0_val, sizeof(uint8_t)); err = adi_ad9081_hal_bf_get(device, REG_SYSREF_PHASE1_ADDR, 0x400, &phase1_val, sizeof(uint8_t)); *sysref_phase = (phase1_val << 8) + phase0_val; AD9081_ERROR_RETURN(err); return API_CMS_ERROR_OK; } int32_t ad9081_multichip_sync(adi_ad9081_device_t *device, uint8_t isMaster) { int32_t err; uint32_t sysref_average_cnt_exp = 4; /*exp of sysref average count 2^4 = 16*/ /* ONESHOT SYNC */ printf ("*******************************\n"); printf ("***** STAGE1 ONESHOT SYNC *****\n"); printf ("*******************************\n"); /*Force a digital reset of the jesd link*/ err = adi_ad9081_hal_bf_set(device, REG_FORCE_LINK_RESET_REG_ADDR, BF_FORCE_LINK_DIGITAL_RESET_INFO, 0); /* not paged */ if (err != API_CMS_ERROR_OK) { printf ("ad9081_jesd_tx_link_dig_reset: error %d\n",err); return err; } printf ("ad9081_jesd_tx_link_dig_reset DONE\n"); pl_wait_us(NULL,4000); /* JESD OneShot Sync */ /*Enable SYSREF Averaging Mode*/ err = adi_ad9081_hal_bf_set(device, REG_SYNC_DEBUG0_ADDR, BF_AVRG_FLOW_EN_INFO, 1); if (err != API_CMS_ERROR_OK) { printf ("REG_SYNC_DEBUG0_ADDR: error %d\n",err); return err; } printf ("Enable Bit for SYSREF AVERAGED\n"); /* Sets how many SYSREF pulses are averaged before one shot synchronization or monitoring. The number of SYSREF pulses to be averaged is calculated by 2^N . When set to 0, SYSREF will be in sampled mode and no averaging is done. This bit field must be set prior to enabling one shot mode. */ err = adi_ad9081_hal_bf_set(device, REG_SYSREF_AVERAGE_ADDR, BF_SYSREF_AVERAGE_INFO, BF_SYSREF_AVERAGE(sysref_average_cnt_exp)); if (err != API_CMS_ERROR_OK) { printf ("SYSREF_AVERAGE SET: error %d\n",err); return err; } printf ("SYSREF_AVERAGE SET\n"); err = adi_ad9081_jesd_oneshot_sync(device); if (err != API_CMS_ERROR_OK) { printf ("adi_ad9081_jesd_oneshot_sync: error %d\n",err); return err; } printf ("adi_ad9081_jesd_oneshot_sync done\n"); err = adi_ad9081_hal_bf_set(device, REG_SYNC_DEBUG0_ADDR, BF_AVRG_FLOW_EN_INFO, 0); if (err != API_CMS_ERROR_OK) { printf ("REG_SYSREF_AVERAGE_ADDR: error %d\n",err); return err; } printf ("Disable Bit for SYSREF AVERAGED \n"); err = adi_ad9081_hal_bf_set(device, REG_SYSREF_AVERAGE_ADDR, BF_SYSREF_AVERAGE_INFO, BF_SYSREF_AVERAGE(0)); if (err != API_CMS_ERROR_OK) { printf ("SYSREF_AVERAGE SET: error %d\n",err); return err; } printf ("SYSREF_AVERAGE SET 0\n"); /*OCCORRE INSERIRE L'ABILITAZIONE DELLA RICHIUSURA DEL GPIO0. POI VEDIAMO COME FARE. if (phy->ms_sync_en_gpio) gpiod_set_value(phy->ms_sync_en_gpio, 1);*/ /* We need to make sure the master-slave master GPIO is enabled before we move on */ err = adi_ad9081_device_nco_sync_gpio_set(device, SYNC_MS_GPIO_NUM, 1); if (err != API_CMS_ERROR_OK) { printf ("adi_ad9081_device_nco_sync_gpio_set SET: error %d\n",err); return err; } printf ("adi_ad9081_device_nco_sync_gpio_set DONE\n"); printf ("\n"); /* NCO SYNC */ printf ("*******************************\n"); printf ("******* STAGE2 NCO SYNC *******\n"); printf ("*******************************\n"); /* NCO Sync */ err = adi_ad9081_device_nco_sync_pre(device); if (err != API_CMS_ERROR_OK) { printf ("adi_ad9081_device_nco_sync_pre: error %d\n",err); return err; } printf ("adi_ad9081_device_nco_sync_pre DONE\n"); #if MS_SYNC_ENB err = adi_ad9081_adc_nco_master_slave_sync(device, isMaster, 1, SYNC_MS_GPIO_NUM, EXTRA_LFMC_NUM); if (err!=API_CMS_ERROR_OK) { printf("adi_ad9081_adc_nco_master_slave_sync master: error %d\n",err); return err; } printf("adi_ad9081_adc_nco_master_slave_sync master set DONE\n"); #else err =adi_ad9081_adc_nco_sync(device, 0, 0); if (err!= API_CMS_ERROR_OK) { printf("adi_ad9081_adc_nco_sync: error %d\n",err); return err; } printf ("adi_ad9081_adc_nco_sync DONE \n"); #endif printf ("\n"); /* Post NCO Master Slave */ printf ("********************************\n"); printf ("* STAGE3 Post NCO Master Slave *\n"); printf ("********************************\n"); /* Do some post-settings for nco sync.*/ err =adi_ad9081_device_nco_sync_post(device); if (err!= API_CMS_ERROR_OK) { printf("adi_ad9081_device_nco_sync_post: error %d\n",err); return err; } printf ("adi_ad9081_device_nco_sync_post DONE \n"); /* Put GPIO in HighZ*/ err =adi_ad9081_device_gpio_set_highz(device, SYNC_MS_GPIO_NUM); if (err!= API_CMS_ERROR_OK) { printf("adi_ad9081_device_gpio_set_highz: error %d\n",err); return err; } printf ("adi_ad9081_device_gpio_set_highz DONE \n"); /*Force a digital reset of the jesd link*/ err = adi_ad9081_hal_bf_set(device, REG_FORCE_LINK_RESET_REG_ADDR, BF_FORCE_LINK_DIGITAL_RESET_INFO, 0); /* not paged */ if (err != API_CMS_ERROR_OK) { printf ("ad9081_jesd_tx_link_dig_reset: error %d\n",err); return err; } printf ("ad9081_jesd_tx_link_dig_reset DONE\n"); printf ("\n"); pl_wait_us(NULL,4000); AD9081_ERROR_RETURN(err); return API_CMS_ERROR_OK; } int32_t adf4371_phase_adjust(adi_adf4371_device_t *device) { int32_t reg10Val; uint8_t ADF4371_PhaseAdjust; uint32_t phaseWord; int32_t err; ADF4371_PhaseAdjust = 90; while (ADF4371_PhaseAdjust>0){ if (ADF4371_PhaseAdjust>360){ phaseWord = round(359.99997*16777216/360); ADF4371_PhaseAdjust = ADF4371_PhaseAdjust - 360; } else { phaseWord = round(ADF4371_PhaseAdjust*16777216/360); ADF4371_PhaseAdjust = 0; } /*Turn On Sigma-Delta*/ err = adf4371_spi_reg_set(device, 0x2B, 0x04); if (err!=API_CMS_ERROR_OK) { printf("Turn On Sigma-Delta: error %d\n",err); return err; } printf("Turn On Sigma-Delta\n"); /*Turn Off Autocalibration*/ err = adf4371_spi_reg_set(device, 0x12, 0x00); if (err!=API_CMS_ERROR_OK) { printf("Turn Off Autocalibration: error %d\n",err); return err; } printf("Turn Off Autocalibration\n"); /*Turn On Phase Adjust*/ err = adf4371_spi_reg_set(device, 0x1A, 0x40); if (err!=API_CMS_ERROR_OK) { printf("Turn Off Autocalibration: error %d\n",err); return err; } printf("Turn On Phase Adjust\n"); /*Adjusting PLL phaseword 5_6*/ err = adf4371_spi_reg_set(device, 0x1B, phaseWord & 0x0000FF); if (err!=API_CMS_ERROR_OK) { printf("Adjusting PLL: reg 0x1B: error %d\n",err); return err; } printf("Adjusting PLL: reg 0x1B\n"); /*Adjusting PLL phaseword 3_4*/ err = adf4371_spi_reg_set(device, 0x1C, phaseWord & 0x00FF00); if (err!=API_CMS_ERROR_OK) { printf("Adjusting PLL: reg 0x1C: error %d\n",err); return err; } printf("Adjusting PLL: reg 0x1C\n"); /*Adjusting PLL phaseword 1_2*/ err = adf4371_spi_reg_set(device, 0x1D, phaseWord & 0xFF0000); if (err!=API_CMS_ERROR_OK) { printf("Adjusting PLL: reg 0x1D: error %d\n",err); return err; } printf("Adjusting PLL: reg 0x1D\n"); /*Read register 10*/ err = adf4371_spi_reg_get(device, 0x10, ®10Val); if (err!=API_CMS_ERROR_OK) { printf("Reading register 10 ADF4371: error %d\n",err); return err; } /*Write register 10*/ err = adf4371_spi_reg_set(device, 0x10, reg10Val); if (err!=API_CMS_ERROR_OK) { printf("Writing register 10 ADF4371: error %d\n",err); return err; } printf("Register 10 ADF4371 updated\n"); } AD9081_ERROR_RETURN(err); return API_CMS_ERROR_OK; } uint32_t sumSysref(uint16_t sysref_phase[], uint32_t item) { uint32_t i; uint32_t sum; sum=0; for (i=0;i<item;i++) { sum+=sysref_phase[i]; } return sum; } int32_t main(int argc, char *argv[]) { int32_t err; int32_t i; uint8_t isMaster; uint32_t mxfeEnabledTmp; uint8_t mxfeEnabled[MXFE_NUMBER]; int32_t stageType; int32_t stageTmp; int32_t revisionC = 1; uint8_t rev[3]; uint16_t sysref_phase[MXFE_NUMBER]; uint8_t numTimesForOneShotSync; if (argc > 1) { stageTmp = atoi(argv[1]); if (stageTmp==0) stageType = STAGE1; if (stageTmp==1) stageType = STAGE2; if (stageTmp==2) stageType = STAGE3; if (stageTmp==3) stageType = STAGE4; sscanf (argv[2],"0x%x",&mxfeEnabledTmp); for (i=0;i<MXFE_NUMBER;i++) { if (mxfeEnabledTmp&(1<<i)) { mxfeEnabled[i] = 1; } else { mxfeEnabled[i] = 0; } } } else { printf("stage is mandatory\n"); printf("\n"); printf("Usage: mcs [stage] [mxfe Enabled]\n"); printf("\n"); printf(" [stage]: mandatory\n"); printf(" 0: Stage1: OneShot SYNC \n"); printf(" 1: Stage2: NCO Master Slave \n"); printf(" 2: Stage3: Post NCO Master Slave\n"); printf(" 3: Stage4: SYSREF-LEMC Phase Adjustment\n"); printf(" [mxfe Enabled]: optional\n"); printf("\n"); return API_CMS_ERROR_OK; } if (stageTmp > 0) { printf("\n"); printf("Running stage: "); if (stageType&STAGE1) printf ("OneShot SYNC "); if (stageType&STAGE2) printf ("NCO MASTER SLAVE "); if (stageType&STAGE3) printf ("POST NCO MASTER SLAVE "); if (stageType&STAGE4) printf ("SYSREF-LEMC Phase Adjustment "); printf("\n"); } /* connect to platform */ adi_ad9081_device_t ad9081_dev[MXFE_NUMBER] = { { .hal_info = { .sdo = SPI_SDO, .msb = SPI_MSB_FIRST, .addr_inc = SPI_ADDR_INC_AUTO, .log_write = pl_log_write, .delay_us = pl_wait_us, .spi_xfer = pl_spi_xfer_ad9081, .reset_pin_ctrl = pl_hw_rst_pin_ctrl_ad9081, }, .serdes_info = { .ser_settings = { /* ad9081 jtx */ .lane_settings = { {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, }, .invert_mask = 0x00, /* in the array set id of LOGICAL line of link0, link1 */ .lane_mapping = { { 0, 1, 2, 3, 4, 5, 6, 7 }, { 0, 1, 2, 3, 4, 5, 6, 7 } }, // .lane_mapping = { { 3, 2, 1, 0, 7, 6, 5, 4 }, { 3, 2, 1, 0, 7, 6, 5, 4 } }, }, .des_settings = { /* ad9081 jrx */ .boost_mask = 0xff, .invert_mask = 0x00, .ctle_filter = { 2, 2, 2, 2, 2, 2, 2, 2 }, /* in the array set id of LOGICAL line of link0, link1 */ .lane_mapping = { { 0, 1, 2, 3, 4, 5, 6, 7 }, { 0, 1, 2, 3, 4, 5, 6, 7 } }, // .lane_mapping = { { 3, 2, 1, 0, 7, 6, 5, 4 }, { 3, 2, 1, 0, 7, 6, 5, 4 } }, } } }, { .hal_info = { .sdo = SPI_SDO, .msb = SPI_MSB_FIRST, .addr_inc = SPI_ADDR_INC_AUTO, .log_write = pl_log_write, .delay_us = pl_wait_us, .spi_xfer = pl_spi_xfer_ad9081, .reset_pin_ctrl = pl_hw_rst_pin_ctrl_ad9081, }, .serdes_info = { .ser_settings = { /* ad9081 jtx */ .lane_settings = { {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, }, .invert_mask = 0x00, /* in the array set id of LOGICAL line of link0, link1 */ .lane_mapping = { { 0, 1, 2, 3, 4, 5, 6, 7 }, { 0, 1, 2, 3, 4, 5, 6, 7 } }, }, .des_settings = { /* ad9081 jrx */ .boost_mask = 0xff, .invert_mask = 0x00, .ctle_filter = { 2, 2, 2, 2, 2, 2, 2, 2 }, /* in the array set id of LOGICAL line of link0, link1 */ .lane_mapping = { { 0, 1, 2, 3, 4, 5, 6, 7 }, { 0, 1, 2, 3, 4, 5, 6, 7 } }, } } }, { .hal_info = { .sdo = SPI_SDO, .msb = SPI_MSB_FIRST, .addr_inc = SPI_ADDR_INC_AUTO, .log_write = pl_log_write, .delay_us = pl_wait_us, .spi_xfer = pl_spi_xfer_ad9081, .reset_pin_ctrl = pl_hw_rst_pin_ctrl_ad9081, }, .serdes_info = { .ser_settings = { /* ad9081 jtx */ .lane_settings = { {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, }, .invert_mask = 0x00, /* in the array set id of LOGICAL line of link0, link1 */ .lane_mapping = { { 0, 1, 2, 3, 4, 5, 6, 7 }, { 0, 1, 2, 3, 4, 5, 6, 7 } }, }, .des_settings = { /* ad9081 jrx */ .boost_mask = 0xff, .invert_mask = 0x00, .ctle_filter = { 2, 2, 2, 2, 2, 2, 2, 2 }, /* in the array set id of LOGICAL line of link0, link1 */ .lane_mapping = { { 0, 1, 2, 3, 4, 5, 6, 7 }, { 0, 1, 2, 3, 4, 5, 6, 7 } }, } } }, { .hal_info = { .sdo = SPI_SDO, .msb = SPI_MSB_FIRST, .addr_inc = SPI_ADDR_INC_AUTO, .log_write = pl_log_write, .delay_us = pl_wait_us, .spi_xfer = pl_spi_xfer_ad9081, .reset_pin_ctrl = pl_hw_rst_pin_ctrl_ad9081, }, .serdes_info = { .ser_settings = { /* ad9081 jtx */ .lane_settings = { {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, {.swing_setting = AD9081_SER_SWING_850, .pre_emp_setting = AD9081_SER_PRE_EMP_0DB, .post_emp_setting = AD9081_SER_POST_EMP_0DB}, }, .invert_mask = 0x00, /* in the array set id of LOGICAL line of link0, link1 */ .lane_mapping = { { 0, 1, 2, 3, 4, 5, 6, 7 }, { 0, 1, 2, 3, 4, 5, 6, 7 } }, }, .des_settings = { /* ad9081 jrx */ .boost_mask = 0xff, .invert_mask = 0x00, .ctle_filter = { 2, 2, 2, 2, 2, 2, 2, 2 }, /* in the array set id of LOGICAL line of link0, link1 */ .lane_mapping = { { 0, 1, 2, 3, 4, 5, 6, 7 }, { 0, 1, 2, 3, 4, 5, 6, 7 } }, } } } }; adi_hmc7043_device_t hmc7043_dev = { .hal_info = { .spi_xfer = pl_spi_xfer_hmc7043, .delay_us = pl_wait_us, .log_write = pl_log_write, } }; adi_adf4371_device_t adf4371_dev[MXFE_NUMBER] = { { .hal_info = { .spi_xfer = pl_spi_xfer_adf4371, .delay_us = pl_wait_us, .log_write = pl_log_write, } }, { .hal_info = { .spi_xfer = pl_spi_xfer_adf4371, .delay_us = pl_wait_us, .log_write = pl_log_write, } }, { .hal_info = { .spi_xfer = pl_spi_xfer_adf4371, .delay_us = pl_wait_us, .log_write = pl_log_write, } }, { .hal_info = { .spi_xfer = pl_spi_xfer_adf4371, .delay_us = pl_wait_us, .log_write = pl_log_write, } } }; system_device_t system_dev = { .hal_info = { } }; pl_hw_open("log_mcs");; /* create user data */ for (i=0;i<MXFE_NUMBER;i++) { if (err = pl_user_data_create_ad9081(&ad9081_dev[i], MXFE_SPI_BASE_ADDRESS, MXFE_SPI_BASE_ADDRESS, i), err != API_CMS_ERROR_OK) return err; } for (i=0;i<MXFE_NUMBER;i++) { if (err = pl_user_data_create_adf4371(&adf4371_dev[i], ADF4371_SPI_BASE_ADDRESS, ADF4371_CS_BASE_ADDRESS, i), err != API_CMS_ERROR_OK) return err; } if (err = pl_user_data_create_hmc7043(&hmc7043_dev, HMC7043_SPI_BASE_ADDRESS, 0), err != API_CMS_ERROR_OK) return err; if (err = pl_user_data_create_system(&system_dev, CLK_CTRL_BASE_ADDRESS, MXFE_EN_BASE_ADDRESS, MXFE_CTRL_BASE_ADDRESS, SYSTEM_CTRL_BASE_ADDRESS, HMC425A_CTRL_BASE_ADDRESS), err != API_CMS_ERROR_OK) return err; /* show api version */ if (err = adi_ad9081_device_api_revision_get(&ad9081_dev[0], &rev[0], &rev[1], &rev[2]), err != API_CMS_ERROR_OK) return err; printf("AD9081 API v%d.%d.%d\n", rev[0], rev[1], rev[2]); printf ("\n"); for (i=0;i<MXFE_NUMBER;i++) { if (!mxfeEnabled[i]) sysref_phase[i]=0; else sysref_phase[i]=1; } numTimesForOneShotSync = 0; while(sumSysref(sysref_phase, MXFE_NUMBER)>0) { for (i=0;i<MXFE_NUMBER;i++) { if (!mxfeEnabled[i]) continue; if (i==MXFE_NUMBER-1) isMaster=1; else isMaster=0; printf ("\n"); printf ("MxFE#%d\n",i); printf ("*********************************\n"); printf ("*STAGE4 SYSREF-LEMC Phase adjust*\n"); printf ("*********************************\n"); /* MCS */ err =ad9081_multichip_sync(&ad9081_dev[i], isMaster); if (err!=API_CMS_ERROR_OK) { printf("ad9081_multichip_sync: error %d\n",err); return err; } printf("ad9081_multichip_sync\n"); } for (i=0;i<MXFE_NUMBER;i++) { if (!mxfeEnabled[i]) continue; /* Monitor SYSREF-LEMC PHASE*/ err =adi_ad9081_jesd_sysref_monitor_phase_get(&ad9081_dev[i], &sysref_phase[i]); if (err!=API_CMS_ERROR_OK) { printf("adi_ad9081_jesd_sysref_monitor_phase_get: error %d\n",err); return err; } printf("Sysref-LEMC Phase = %d\n",sysref_phase[i]); } if (sumSysref(sysref_phase, MXFE_NUMBER)==0){ for (i=0;i<MXFE_NUMBER;i++) { if (!mxfeEnabled[i]) continue; /*Check one more time to confirm*/ err =adi_ad9081_jesd_sysref_monitor_phase_get(&ad9081_dev[i], &sysref_phase[i]); if (err!=API_CMS_ERROR_OK) { printf("adi_ad9081_jesd_sysref_monitor_phase_get: error %d\n",err); return err; } printf("Sysref-LEMC Phase = %d\n",sysref_phase[i]); } } else { for (i=0;i<MXFE_NUMBER;i++) { if (!mxfeEnabled[i]) continue; if (sysref_phase[i]!=0) /*SYSREF->LEMC Phase Is Not Stable, Adjust PLL/Synthesizer To Compensate*/ printf ("Adjusting Sysref-LEMC Phase of MxFE#%d\n",i); printf("Sysref-LEMC Phase before allignment = %d\n",sysref_phase[i]); adf4371_phase_adjust(&adf4371_dev[i]); printf("PLL %d Phase Adjusted By 90 Degrees\n",i); } } numTimesForOneShotSync++; printf("Num times for one shot sync: %d\n",numTimesForOneShotSync); } /* free resource and close platform */ for (i=0;i<MXFE_NUMBER;i++) { if (err = pl_user_data_free(&ad9081_dev[i].hal_info.user_data), err != API_CMS_ERROR_OK) return err; } for (i=0;i<MXFE_NUMBER;i++) { if (err = pl_user_data_free(&adf4371_dev[i].hal_info.user_data), err != API_CMS_ERROR_OK) return err; } if (err = pl_user_data_free(&hmc7043_dev.hal_info.user_data), err != API_CMS_ERROR_OK) return err; if (err = pl_user_data_free(&system_dev.hal_info.user_data), err != API_CMS_ERROR_OK) return err; printf ("\n"); pl_hw_close(); printf ("Exit application\n"); printf("\n"); return API_CMS_ERROR_OK; }
I'm not able to reach a stable phase between SYSREF-LEMC signals. I'm reaching a min value of sysref-lemc and after is manifested a slip to a max value. I've missed something in my code?
Can someone provide me a document that describes the One shot sync procedure?
Thank you so much!
Best regards.
Adding more infos
[edited by: LGChiriac at 2:16 PM (GMT -5) on 22 Nov 2022]