Post Go back to editing

AD9176-FMC-EBZ DAC on ZCU102 clocked with an external clock through J41

Category: Software
Product Number: AD9176-FMC-EBZ 2021011389896
Software Version: Vivado 2021.1

For our project we need to clock this dac with an external 2.6 to 3 GHz clock. We want to do this on the evaluation board without any kind of modification to avoid damage risk.

This removes the option of using direct clock to the dac from J31. Following schematic and and datasheet of HMC7044, we figured out that we can use J41 as a clock input, as it feeds the external VCO input on the PLL2 VCO MUX, and the input frequency range satisfies our needs. The board driving the DAC is ZCU102, on which we are using the reference design on your repository (version hdl_2021_R1) using JESD mode 20, plus no-os driver and reference main.c also provided in the repository.

Below is the way we are configuring the structures the way we think it needs to be done for our purpose.

 

    uint32_t hmc_freq_hz = 2600*1000*1000;
	uint32_t dac_freq_khz = 5200*1000;
	uint32_t hmc_divisor = 4;
	uint32_t ref_rate_khz = (hmc_freq_hz/1000)/hmc_divisor;
	//Lane rate = (M × N' × [10⁄8] × Fs) ∕ L = (1*16*1.25*dac_freq_khz)/8
	uint32_t lane_clk_khz = dac_freq_khz*2.5;
	uint32_t device_clk_khz = lane_clk_khz/40;


	struct xil_spi_init_param xil_spi_param = {
		.type = SPI_PS,
		.flags = 0
	};

	struct no_os_spi_init_param hmc7044_spi_param = {
		.device_id = SPI_DEVICE_ID,
		.max_speed_hz = 10000000,
		.mode = NO_OS_SPI_MODE_0,
		.chip_select = SPI_HMC7044_CS,
		.platform_ops = &xil_spi_ops,
		.extra = &xil_spi_param
	};

	struct hmc7044_chan_spec chan_spec[4] = {
		{.disable = 0, .num = 2, .divider = hmc_divisor, .driver_mode = 1},		/* DAC_CLK */
		{.disable = 0, .num = 3, .divider = 512, .driver_mode = 1},		/* DAC_SYSREF */
		{.disable = 0, .num = 12, .divider = hmc_divisor, .driver_mode = 2},		/* FPGA_CLK */
		{.disable = 0, .num = 13, .divider = 512, .driver_mode = 2},	/* FPGA_SYSREF */
	};

	struct hmc7044_init_param hmc7044_param = {
		.spi_init = &hmc7044_spi_param,
		.clkin_freq = {0, 2600000000, 0, 0},
		.vcxo_freq = 0,
		.pll2_freq = hmc_freq_hz,
		.pll1_loop_bw = 200,
		.sysref_timer_div = 1024,
		.clkin0_rfsync_en = false,
		.clkin1_vcoin_en = true,
		.pulse_gen_mode = 0,
		.in_buf_mode = {0, 0x5, 0, 0, 0},
		.gpi_ctrl = {0x00, 0x00, 0x00, 0x00},
		.gpo_ctrl = {0x1f, 0x2b, 0x00, 0x00},
		.num_channels = 4,
		.channels = chan_spec,
	};

	struct jesd204_tx_init tx_jesd_init = {
			.name = "tx_jesd",
			.base = TX_JESD_BASEADDR,
			.octets_per_frame = 1,//original value => 2
			.frames_per_multiframe = 32,
			.converters_per_device = 1,//original value => 4
			.converter_resolution = 16,
			.bits_per_sample = 16,
			.high_density = true,//original value => false
			.control_bits_per_sample = 0,
			.subclass = 1,
			.device_clk_khz = device_clk_khz,	/* (lane_clk_khz / 40) */
			.lane_clk_khz = lane_clk_khz,	/* LaneRate = ( M/L)*NP*(10/8)*DataRate */
		};

	struct adxcvr_init tx_adxcvr_init = {
			.name = "tx_adxcvr",
			.base = TX_XCVR_BASEADDR,
			.sys_clk_sel = 3,
			.out_clk_sel = 4,
			.lpm_enable = 1,
			.lane_rate_khz = lane_clk_khz,	/* LaneRate = ( M/L)*NP*(10/8)*DataRate */
			.ref_rate_khz = ref_rate_khz,		/* FPGA_CLK, output 12 of HMC 7044 mult. 32 o 40*/
		};

	struct no_os_spi_init_param ad9172_spi_param = {
		.max_speed_hz = 1000000,
		.mode = NO_OS_SPI_MODE_0,
		.chip_select = SPI_AD9172_CS,
		.platform_ops = &xil_spi_ops,
		.extra = &xil_spi_param
	};

	struct xil_gpio_init_param xilinx_gpio_init_param = {
		.type = GPIO_PS,
		.device_id = GPIO_DEVICE_ID
	};
	struct ad9172_init_param ad9172_param = {
		.spi_init = &ad9172_spi_param,	/* no_os_spi_init_param */
		.gpio_reset = {
			.number = 54 + 0,
			.platform_ops = &xil_gpio_ops,
			.extra = &xilinx_gpio_init_param
		},
		.gpio_txen0 = {
			.number = 54 + 22,
			.platform_ops = &xil_gpio_ops,
			.extra = &xilinx_gpio_init_param
		},
		.gpio_txen1 = {
			.number = 54 + 23,
			.platform_ops = &xil_gpio_ops,
			.extra = &xilinx_gpio_init_param
		},
		.dac_rate_khz = dac_freq_khz,		/* or sample rate */
		.dac_clkin_Hz = ref_rate_khz*1000,		/* DAC_CLK, output 2 of HMC 7044 */
		.jesd_link_mode = 20,
		.jesd_subclass = 1,
		.dac_interpolation = 1,
		.channel_interpolation = 1,
		.clock_output_config = 4,
		.syncoutb_type = SIGNAL_LVDS,
		.sysref_coupling = COUPLING_AC,
	};

	struct axi_dac_init tx_dac_init = {
		"tx_dac",
		TX_CORE_BASEADDR,
		8,
		NULL
	};

Additionally, we modified the driver (hmc7044.c file, line 533), as there are some register options that can't be accessed through the structures (Reg 0x0003 to use external VCO).

	/* Select the VCO range */
	hmc7044_write(dev, HMC7044_REG_EN_CTRL_0,
		      (dev->rf_reseeder_en ? HMC7044_RF_RESEEDER_EN : 0) |
		      HMC7044_VCO_SEL(HMC7044_VCO_EXT/*high_vco_en ?
				      HMC7044_VCO_HIGH :
				      HMC7044_VCO_LOW*/) |
		      HMC7044_SYSREF_TIMER_EN | 0/*HMC7044_PLL2_EN*/ |
		      0/*HMC7044_PLL1_EN*/);

What the fpga spits out back to us is this:

tx_adxcvr: OK (13000000 kHz)
AD917x DAC Chip ID: 4
AD917x DAC Product ID: 9176
AD917x DAC Product Grade: 0
AD917x DAC Product Revision: 7
AD917x Revision: 1.1.1
PLL Input rate 650000000
PLL lock status 0,  DLL lock status: 1
Serdes PLL Locked (stat: 3)
code_grp_sync: 0
frame_sync_stat: 0
good_checksum_stat: 0
init_lane_sync_stat: 0
8 lanes @ 13000000 kBps
ad9172_init : AD936x Rev 1 successfully initialized
tx_jesd status:
        Link is enabled
        Measured Link Clock: 119.511 MHz
        Reported Link Clock: 325.000 MHz
        Lane rate: 13000.000 MHz
        Lane rate / 40: 325.000 MHz
        LMFC rate: 40.625 MHz
        SYNC~: asserted
        Link status: CGS
        SYSREF captured: Yes
        SYSREF alignment error: Yes
tx_dac: Successfully initialized (2087890625 Hz)
Set dds frequency at 200MHz
Bye

As you can see, it gets stuck in CGS mode, and no signal is coming out. Please guide us in some way to achieve what we are looking for, or it is even possible.

Thank you,

Alex

  • Hi Alex,

    To confirm, you want to disable both HMC PLLs and just use it as a clock fanout with a 2.6GHz clock signal input at clkin1? In the output your calculated link clock and reported link clock don't match, so there is at least some clocking miscalculation. You may want your hmc_divisor variable to be 8 rather than 4. With 4 you set the fpga clock and dac clock in channels from the hmc to be 2600/4=650MHz, but you have device_clk_hz in your jesd struct set as lane_clk_hz/40=325MHz. The DAC PLL not locking combined with the measured link clock rate of 119MHz suggests that the HMC channel outputs are not as expected/calculated. The DAC PLL is configured based on user input values, but it seems to be receiving the wrong frequency from HMC clkout2 (i.e. not 325MHz or 650MHz). I'm not sure what in the code is causing this. Two things I noticed that may or may not have impact:

    -any member of clkin_freq[] that has a non-zero value will be enabled as a reference path to PLL1. I believe if you have clkin1 enabled as a vco input you don't want to also have it enabled as a pll1 ref path, even though you have the plls disabled.

    -The buffer mode for clkin1 is set to 0x5 rather than 0x15 as in the example code.

    I will try to get more info on setting up the HMC as a clock fanout with PPLs disabled to see if there are necessary code changes here.

  • Hi, thanks for the quick response.

    Indeed, I'm just using HMC as a fanout, but taking advantage of the sysref generation. After applying your suggestions on clkin_freq[] and buffer mode, setting hmc_divisor to 8 reports Measured Link Clock: 69.250 MHz, and setting it to 2 just gives an adxcvr initialization error. Hope this helps.

  • Hi,

    It is now working with your suggestions. We had some leftover modifications in the drivers which messed up things.

    Thank you.