Hardware
- AD9082_FMCA_EBZ
- HMC7044
- ZCU102
- Schematic: Link to Schematic of AD9082-FMCA-EBZ
Software
- Yocto Linux
- adi_hmc7044.c
- adi_ad9082.c
Description
I'm trying to work with this ad9082-fmca-ebz board and am struggling to bring up the clocking chip. PLL lock for the hmc7044 seems intermittent/unreliable. I'm confident my hardware design is solid but if symptoms point to hardware issues, I can re-evaluate. troubleshooting ad9082 is another matter and probably a separate post.
Function in Question
int hmc7044_testing(void)
{
AD9082_UserData ud9082 = {
.gpiochipName = "gpiochip1"
};
initUserData(&ud9082);
adi_ad9082_hal_t hal9082 = {
.user_data = (void*)&ud9082,
.sdo = SPI_SDO,
.msb = 1,
.addr_inc = SPI_ADDR_INC_AUTO,
.spi_xfer = ad9082_mySpiTransfer,
.delay_us = ad9082_myDelayUs,
.hw_open = ad9082_myHwOpen,
.hw_close = ad9082_myHwClose,
.log_write = ad9082_myLogWrite,
.tx_en_pin_ctrl = ad9082_myTxEnPinCtrl,
.reset_pin_ctrl = ad9082_myResetPinCtrl
};
adi_ad9082_info_t info9082 = {
.dev_freq_hz = 3000000000ULL,
.dac_freq_hz = 12000000000ULL,
.adc_freq_hz = 4000000000ULL,
.dev_rev = 0,
.jesd_rx_lane_rate = 10000000000ULL
};
adi_ad9082_ser_lane_settings_t lane_cfg[8];
for(int i = 0; i < 8; i++) {
lane_cfg[i].swing_setting = AD9082_SER_SWING_1000;
lane_cfg[i].pre_emp_setting = AD9082_SER_PRE_EMP_0DB;
lane_cfg[i].post_emp_setting = AD9082_SER_POST_EMP_0DB;
}
uint8_t lane_map_tx[2][8] = {
{0,1,2,3,4,5,6,7},
{0}
};
adi_ad9082_ser_settings_t ser_cfg = {
.invert_mask = 0,
.lane_settings = {0},
.lane_mapping = {{0}}
};
memcpy(ser_cfg.lane_settings, lane_cfg, sizeof(lane_cfg));
memcpy(ser_cfg.lane_mapping, lane_map_tx, sizeof(lane_map_tx));
adi_ad9082_des_settings_t des_cfg = {0};
adi_ad9082_serdes_settings_t serdes_cfg = {
.ser_settings = ser_cfg,
.des_settings = des_cfg
};
adi_ad9082_clk_t clk_cfg = {
.sysref_mode = SYSREF_CONT
};
adi_ad9082_device_t ad9082 = {
.hal_info = hal9082,
.dev_info = info9082,
.serdes_info = serdes_cfg,
.clk_info = clk_cfg
};
adi_ad9082_device_hw_open(&ad9082);
HMC7044_UserData ud7044 = {
.gpiochipName = "gpiochip1",
.readEnPin = 79,
.writeEnPin = 80,
.syncPin = 81
};
adi_hmc7044_hal_t hal7044 = {
.user_data = &ud7044,
.spi_xfer = hmc7044_mySpiTransfer,
.delay_us = hmc7044_myDelayUs,
.reset_pin_ctrl= hmc7044_myResetPinCtrl,
.hw_open = hmc7044_myHwOpen,
.hw_close = hmc7044_myHwClose
};
adi_hmc7044_device_t hmc = {
.hal_info = hal7044
};
printf("DEBUG: Opening HMC7044\n");
adi_hmc7044_device_hw_open(&hmc);
int32_t err = 0;
const uint64_t fpga_clk = 250000000ULL;
const uint64_t dev_clk = 125000000ULL;
const uint64_t sysref_clk = 1000000ULL;
const uint64_t ref_in = 100000000ULL;
const uint64_t clk_3g = 3000000000ULL;
uint8_t prio[] = {0,1,2,3};
uint16_t out_ch =
HMC7044_OP_CH_0 |
HMC7044_OP_CH_2 |
HMC7044_OP_CH_3 |
HMC7044_OP_CH_6 |
HMC7044_OP_CH_8 |
HMC7044_OP_CH_10 |
HMC7044_OP_CH_12;
uint64_t out_freqs[14] = {
fpga_clk/2,
0,
clk_3g,
sysref_clk,
0,0,
fpga_clk/2,
0,
fpga_clk,
0,
fpga_clk/2,
0,
fpga_clk,
0
};
err = adi_hmc7044_device_init(&hmc); print_err(err);
err = adi_hmc7044_device_reset(&hmc, 0); print_err(err);
for(int i=0;i<14;i++) {
err = adi_hmc7044_output_config_set(&hmc, i, HMC7044_OP_SIG_CH_DIV, 0,0,0);
print_err(err);
}
err = adi_hmc7044_input_reference_set(&hmc, 0, IPBUFFER_INTERNAL_100_OHM_EN | IPBUFFER_AC_COUPLED_MODE_EN, 1);
print_err(err);
err = adi_hmc7044_vco_sel_set(&hmc, HMC7044_VCO_INTERNAL_3GHZ, 0);
print_err(err);
err = adi_hmc7044_output_sync_config_set(&hmc, 3, (clk_cfg.sysref_mode == SYSREF_ONESHOT), 1, 1);
print_err(err);
err = adi_hmc7044_sysref_config_set(&hmc,
(clk_cfg.sysref_mode == SYSREF_ONESHOT) ? HMC7044_SYSREF_1_PULSE : HMC7044_SYSREF_CONTINUOUS_MODE);
print_err(err);
err = adi_hmc7044_clk_config(
&hmc, HMC7044_CLK_IN_0,
prio,
ref_in, /* primary reference */
ref_in, /* secondary unused */
out_ch,
out_freqs);
print_err(err);
// err = adi_hmc7044_output_config_set(&hmc, 2, HMC7044_OP_SIG_CH_DIV, 1, 1, 1); print_err(err);
// err = adi_hmc7044_output_config_set(&hmc, 3, HMC7044_OP_SIG_CH_DIV, 192, 1, 1); print_err(err);
// err = adi_hmc7044_output_config_set(&hmc, 6, HMC7044_OP_SIG_CH_DIV, 12, 0, 1); print_err(err);
// err = adi_hmc7044_output_config_set(&hmc, 10, HMC7044_OP_SIG_CH_DIV, 12, 0, 1); print_err(err);
// err = adi_hmc7044_output_config_set(&hmc, 12, HMC7044_OP_SIG_CH_DIV, 12, 0, 1); print_err(err);
// err = adi_hmc7044_output_config_set(&hmc, 13, HMC7044_OP_SIG_CH_DIV, 192, 0, 1);print_err(err);
err = adi_hmc7044_device_sysref_enable_control_set(&hmc, 1, 1);
print_err(err);
err = adi_hmc7044_high_performance_set(&hmc); print_err(err);
err = adi_hmc7044_reg_update(&hmc); print_err(err);
err = adi_hmc7044_reseed_request_set(&hmc); print_err(err);
uint8_t pll_status = 0;
printf("Waiting for HMC7044 PLL lock...\n");
for(int i=0; i<50; i++) {
adi_hmc7044_device_pll_lock_status_get(&hmc, &pll_status);
printf("PLL: %s\r",
(pll_status == HMC7044_PLL1_AND_PLL2_LOCK_ST) ? "Both LOCKED" :
(pll_status == HMC7044_PLL1_LOCK_ST) ? "PLL1 only" :
(pll_status == HMC7044_PLL2_LOCK_ST) ? "PLL2 only" :
"UNLOCKED");
fflush(stdout);
usleep(20000);
}
adi_ad9082_device_hw_close(&ad9082);
if(pll_status != HMC7044_PLL1_AND_PLL2_LOCK_ST) {
printf("\r\nPLLs were not locked\r\n");
return 0;
} else {
printf("\r\nHMC7044 LOCKED. Clocking OK.\n");
return 1;
}
}