My project is based on AD9694 and Xilinx FPGA, using Xilinx JESD204B IP core (the version is v7.2) 。The design requirement is to capture 4 channels of real signal。and output 4 lanes of data to FPGA using the Full Bandwidth mode.
On the FPGA side, I have set up a Microblaze soft core to run the ADC configuration program, which is modified from the ad9208 code from GitHub. Currently, my configuration is set to a 2-lane mode on the FPGA side, and I can see the output data of one channel which is SERDOUTAB0 (the SERDOUTAB0 is bond to lane0, and SERDOUTAB1 is bond to lane1, maybe lane1 should be bond to SERDOUTCD0, I haven't checked). However, once I configure the FPGA to a 4-lane mode, the FPGA receives no data on all lane.
re-examining the datasheet, I found that AB pair and CD pair are two separate links. Does this mean that I must also place two 2-lane RX IP cores on the FPGA side? In my understanding, if the four analog input channels a, b, c, and d use input format real and output format real parameters true, then the AD9694's SERDOUTAB0, SERDOUTAB1, SERDOUTCD0, SERDOUTCD1 is correspond to LANE0, LANE1, LANE2, LANE3 on the FPGA side, respectively. Is this understanding correct?
the configuration details is as follows.
jesd_param_t jesd_param_init = { .jesd_F = 2, /* octets per frame */ .jesd_K = 32, /* frames per multiframe */ .jesd_HD = false, /* high density */ .jesd_N = 16, /* converter resolution */ .jesd_NP = 16, /* bits per sample */ .jesd_M = 2, /* converters per device */ .jesd_CS = 0, /* control bits per sample */ .jesd_L = 2, /* lanes per device */ }; xilinx_jesd204b_param_t xil_204b_init = { .base_adr = RX_JESD_BASEADDR, .ila_en = 1, .lanesync_en = 1, .scramble_en = 0, .sysref_always_en = 0, .sysref_req_on_sync = 1, .sysref_dly_num = 0, /// 0 ~ 15 core clk delay .frmcnt = 32 , ///frames-per-multiframe .bytecnt = 2, ///bytes-per-frame .subclass = 1, //subclass .lanes = 4, ///lanes }; struct xil_gpio_init_param xilinx_gpio_init_param = { .type = GPIO_PL, .device_id = GPIO_DEVICE_ID }; struct ad9208_init_param ad9694_param = { .spi_init = &ad9694_spi_param, .gpio_powerdown = { .number = 3 , /* adc0_pwdn */ .platform_ops = &xil_gpio_ops, .extra = &xilinx_gpio_init_param }, .sampling_frequency_hz = 250000000, .input_div = 2, .powerdown_pin_en = false, .powerdown_mode = AD9208_POWERDOWN, /* Full Powerdown Mode */ /* duty cycle stabilizer enable */ .duty_cycle_stabilizer_en = false, .current_scale = AD9694_ADC_SCALE_1P68_VPP, /* analog input dc coupling enable */ .analog_input_mode = COUPLING_AC, .ext_vref_en = false, /* analog input neg buffer current */ .buff_curr_n = AD9208_BUFF_CURR_600_UA, /* analog input pos buffer current */ .buff_curr_p = AD9208_BUFF_CURR_600_UA, /* Number of Carrier Frequencies */ .fc_ch = AD9208_FULL_BANDWIDTH_MODE, .ddc = ad9694_ddc_init, .ddc_cnt = 0, /* ddc complex to real enable */ .ddc_output_format_real_en = true, /* ddc mixer real enable */ .ddc_input_format_real_en = true, .test_mode_ch0 = AD9208_TESTMODE_OFF, .test_mode_ch1 = AD9208_TESTMODE_OFF, /* SYSREF Config */ .sysref_lmfc_offset = 1, .sysref_edge_sel = true, .sysref_clk_edge_sel = true, .sysref_neg_window_skew = 0, .sysref_pos_window_skew = 0, .sysref_mode = AD9208_SYSREF_ONESHOT, .sysref_count = 2, .jesd_param = &jesd_param_init, .jesd_subclass = 1, };
and the ad9208_setup is also been slightly modified:
static int32_t ad9208_setup(struct ad9208_state *st) { ad9208_handle_t *ad9208_h = st->adc_h; ad9208_adc_data_frmt_t input_fmt, output_fmt; adi_chip_id_t chip_id; uint64_t sample_rate, lane_rate_kbps; uint8_t dcm, pll_stat; int32_t timeout, i, ret; ret = ad9208_init(ad9208_h); if (ret < 0) { LOG_E("ad9208 init failed (%d).", ret); return -ENODEV; } ret = ad9208_reset(ad9208_h, 0); if (ret < 0) { LOG_E("ad9298 reset failed (%d).", ret); ret = -ENODEV; goto error; } ret = ad9208_get_chip_id(ad9208_h, &chip_id); if (ret < 0) { LOG_E("ad9208_get_chip_id failed (%d).", ret); ret = -ENODEV; goto error; } if (chip_id.chip_type != AD9208_CHIP_TYPE) { LOG_E("Wrong chip type (%X).", chip_id.chip_type); ret = -EINVAL; goto error; } if (chip_id.prod_id != AD9208_CHIP_ID) { LOG_E("Unrecognized CHIP_ID (%X).", chip_id.prod_id); ret = -ENODEV; goto error; } ret = ad9208_adc_set_channel_select(ad9208_h, AD9208_ADC_CH_ALL); if (ret < 0) { LOG_E( "Failed to select channels (%d).", ret); goto error; } ret = ad9208_set_pdn_pin_mode(ad9208_h, st->powerdown_pin_en, st->powerdown_mode); if (ret < 0) { LOG_E("Failed to set PWDN pin mode (%d).", ret); goto error; } ret = ad9208_set_input_clk_duty_cycle_stabilizer(ad9208_h, st->duty_cycle_stabilizer_en); if (ret < 0) { LOG_E("Failed to set clk duty cycle stabilizer (%d).", ret); goto error; } sample_rate = st->sampling_frequency_hz * st->input_div; ret = ad9208_set_input_clk_cfg(ad9208_h, sample_rate, st->input_div); if (ret < 0) { LOG_E("Failed to set input clk config (%d).", ret); goto error; } ret = ad9208_adc_set_input_cfg(ad9208_h, st->analog_input_mode ? COUPLING_DC : COUPLING_AC, st->ext_vref_en, st->current_scale); if (ret < 0) { LOG_E("Failed to set adc input config: %d.", ret); goto error; } ret = ad9208_adc_set_fc_ch_mode(ad9208_h, st->fc_ch); if (ret < 0) { LOG_E("Failed to set channel mode: %d.", ret); goto error; } if (st->fc_ch == AD9208_FULL_BANDWIDTH_MODE) { dcm = 1; /* Full bandwidth */ } else { dcm = st->ddc[0].decimation; for (i = 1; i < st->ddc_cnt; i++) dcm = no_os_min_t(uint8_t, dcm, st->ddc[i].decimation); } ret = ad9208_adc_set_dcm_mode(ad9208_h, dcm); if (ret < 0) { LOG_E("Failed to set decimation mode: %d.", ret); goto error; } /* DDC Setup */ if (st->ddc_input_format_real_en) input_fmt = AD9208_DATA_FRMT_REAL; else input_fmt = AD9208_DATA_FRMT_COMPLEX; if (st->ddc_output_format_real_en) output_fmt = AD9208_DATA_FRMT_REAL; else output_fmt = AD9208_DATA_FRMT_COMPLEX; ret = ad9208_adc_set_data_format(ad9208_h, input_fmt, output_fmt); if (ret < 0) { LOG_E("Failed to set data format: %d.", ret); goto error; } ret = ad9208_jesd_syref_lmfc_offset_set(ad9208_h, st->sysref_lmfc_offset); if (ret < 0) { LOG_E("Failed to set SYSREF lmfc offset: %d.", ret); goto error; } ret = ad9208_jesd_syref_config_set(ad9208_h, st->sysref_edge_sel, st->sysref_clk_edge_sel, st->sysref_neg_window_skew, st->sysref_pos_window_skew); if (ret < 0) { LOG_E("Failed to set SYSREF sig capture settings: %d.", ret); goto error; } ret = ad9208_jesd_syref_mode_set(ad9208_h, st->sysref_mode, st->sysref_count); if (ret < 0) { LOG_E("Failed to Set JESD SYNCHRONIZATION Mode: %d.", ret); goto error; } ret = ad9208_jesd_set_if_config(ad9208_h, (jesd_param_t )*st->jesd_param, &lane_rate_kbps); LOG_D("LANE Rate(kbps): %d",lane_rate_kbps); if (ret < 0) { LOG_E("Failed to set JESD204 interface config (%d).", ret); goto error; } ret = ad9208_jesd_subclass_set(ad9208_h, st->jesd_subclass); if (ret < 0) { LOG_E("Failed to set subclass (%d).", ret); goto error; } ret = ad9208_jesd_enable_scrambler(ad9208_h, 0); if (ret < 0) { LOG_E("Failed to enable scrambler (%d).", ret); goto error; } //////////////////////////////////////////////////////////////// /// add mapping for (int32_t idx = 0; idx < 2; idx++) { ret = ad9208_adc_set_channel_enable(ad9208_h, idx); if (ret < 0) { LOG_E( "Failed to select channels (%d).", ret); goto error; } ret = ad9208_register_write(ad9208_h, AD9208_JESD_XBAR_CFG_REG, 0+idx*2); ret |= ad9208_register_write(ad9208_h, AD9208_JESD_XBAR_CFG_REG+1, 0+idx*2+1); if (ret < 0) { LOG_E("Failed to set lane xbar"); goto error; } /// 配置LID ret = ad9208_register_write(ad9208_h, AD9208_JESD_LID0_CFG_REG, 0+idx*2); ret |= ad9208_register_write(ad9208_h, AD9208_JESD_LID1_CFG_REG, 0+idx*2+1); } /// reopen channel set 0x0009 and 0x0008 to 0x03 ret = ad9208_adc_set_channel_select(ad9208_h, AD9208_ADC_CH_ALL); if (ret < 0) { LOG_E( "Failed to select channels (%d).", ret); goto error; } //////////////////////////////////////////////////// /// SYNC -> CMOS ad9208_register_write(ad9208_h, AD9208_JESD_LINK_CTRL2_REG, 0x10); ret = ad9208_jesd_enable_link(ad9208_h, 1); if (ret < 0) { LOG_E("Failed to enabled JESD204 link (%d).", ret); goto error; } ///... }
I also noticed the concept of a logic lane mentioned in the following table(JESD204B map JTX lane Assignment 2 ). I couldn't found any corresponding description elsewhere in the datasheet. Could you please explain what is a logic lane ?