AD9081
Recommended for New Designs
The AD9081 mixed signal front end (MxFE®) is a highly integrated device with four 16-bit, 12 GSPS maximum sample rate, RF digital-to-analog converter...
Datasheet
AD9081 on Analog.com
ADF4371
Recommended for New Designs
The ADF4371 allows implementation of fractional-N or Integer N phase-locked loop (PLL) frequency synthesizers when used with an external loop filter and...
Datasheet
ADF4371 on Analog.com
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.
I moved this thread from Linux to the No-OS forum, since this code isn't using the Linux driver.
There is actually a branch here:
https://github.com/analogdevicesinc/no-OS/commits/ad9081_jesd204_fsm
Which should handle multi chip synchronization. I think this work is currently merged into the main branch.
-Michael