This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

DAC38J84: SerDes PLL is not locking

Part Number: DAC38J84
Other Parts Discussed in Thread: LMK04828

Dear TI Supporters,

The DAC38J84 SerDes PLL is not locking in our system. Will you help diagnose the problem?

We are integrating Abaco FMC144 with an Intel Arria 10 SoC Dev Kit.
There is no reference design; we have developed our code by referring to the DAC3XJ8X GUI v1.2 (in simulation mode) and the BSP made available by Abaco.
Our application operates the four converters independently.

The DAC38J84 DACCLK input is driven correctly, because the FPGA measures other DCLKoutX outputs at the desired frequency, and all DCLKoutX outputs are programmed at the same frequency.

The FPGA receives the expected SYSREF pulse train, as captured in signaltap.

Here are the key parameters:

LMFS: 4421
Sample rate: 148.5Msps
Ext CLK; bypass (disable/reset) DAC PLL
SYSREF: 2 pulses @ 1/32 DACCLK frequency
Interpolation: 1
Serdes linerate: 2970Mbps
K: 32
serdes clk div: 1
jesd clk div: 1
SerDes rate: 1/4
SerDes MPY: 20

Here is the DAC385J84 configuration sequence:

bool DAC_init(void)
{
bool allOK = TRUE;
alt_u16 reg_value;

// Step numbers are from Kang Hsia's adaptation of slaa696
// Step 4, toggle DAC_RESETB (manual sec 8.3 Step 5)
system_control_write(DEV, DEV_DAC_TXENABLE, FALSE); // make sure TX is disabled until after JESD_init()
system_control_write(DEV, DEV_DAC_RESET, TRUE); // toggle RESETb (inverted on the way to the pin in top-level verilog)
usleep(1); // ensure RESETb pulse width exceeds 25ns minimum
system_control_write(DEV, DEV_DAC_RESET, FALSE);
Send_DAC(0x02,0x2083); // [15:14] 16-bit DAC width, [13] zero invalid data, [7] enable SPI_DAC_SDO, [1] 2's complement, [0] = assert soft reset
Send_DAC(0x02,0x2082); // [15:14] 16-bit DAC width, [13] zero invalid data, [7] enable SPI_DAC_SDO, [1] 2's complement, [0] = clr soft reset
// Step 5, confirm PoR presets have loaded
reg_value = Read_DAC(0x7f);
if ((bit_field(reg_value, DAC_LOAD_STATUS, DAC_LOAD_STATUS) == 1)
    && (bit_field(reg_value, DAC_VENDOR_HI, DAC_VENDOR_LO) == DAC_VENDOR_ID)
    && (bit_field(reg_value, DAC_VERSION_HI, DAC_VERSION_LO) == DAC_VERSION_ID)) {
rubydbprint(DBSS_DAC,"DAC chip fusefarm loaded correctly.\r\n");
} else {
allOK = FALSE;
rubydbprint(DBSS_DAC,"DAC chip fusefarm failed to load, reading back error code %x, vendor code %u, version %u.\r\n",
bit_field(reg_value, DAC_ERR_CODE_HI, DAC_ERR_CODE_LO),
bit_field(reg_value, DAC_VENDOR_HI, DAC_VENDOR_LO),
bit_field(reg_value, DAC_VERSION_HI, DAC_VERSION_LO));
}
// Step 6, "program per application's need"
// Step 6.0 housekeeping not addressed in Kang's sequence
Send_DAC(0x4A,0x0f1e); // Hold the JESD state machine in reset during programming (not per Kang's sequence, but Abaco does this as the very 1st thing)
Send_DAC(0x04,0xf0f0); // [11:8] are lanes 3..0 SerDes lane errors and [3:0] are lanes 3..0 FIFO flags; mask the others
Send_DAC(0x05,0xef05); // mask SYSREF errors from unused links, (unused) PAP alarms, SerDes block 1, and unused DAC PLL
Send_DAC(0x06,0xffff); // mask all short tests and LOS alarms
Send_DAC(0x23,0xffff); // allow all subsystems to sleep when SLEEP is asserted (for live shutdown)
// Step 6.1, Clocking Configuration Registers: DAC PLL (unused): regs 0x31 to 0x33
Send_DAC(0x1A,0x0020); // [5] DAC PLL sleep
Send_DAC(0x24,0x0000); // [6:4] = 0 SYSREF pulses don't reset dividers, because DAC PLL is unused
Send_DAC(0x31,0x1000); // [12] = 1 PLL reset; [10] = 0 PLL disable (in favor of direct DACCLK to the core)
// Step 6.2, SerDes PLL and PMAs regs 0x3B to 0x3F
Send_DAC(0x3B,0x0000); // [15] bypass internal PLL, use DACCLK input as SerDes refclk; [14:11] divide refclk by 1
// Send_DAC(0x3C,0x18a0); // SerDes PLL [15] !EN div by 5 output; [12:11] high loop bandwidth; [10] !sleep; [9] = 0 high VCO freq. range; [8:1] MPY = 20
// Send_DAC(0x3C,0x00a0); // SerDes PLL [15] !EN div by 5 output; [12:11] medium loop bandwidth, per Abaco; [10] !sleep; [9] = 0 high VCO freq. range; [8:1] MPY = 20
Send_DAC(0x3C,0x10a0); // SerDes PLL [15] !EN div by 5 output; [12:11] low loop bandwidth, for poor clock; [10] !sleep; [9] = 0 high VCO freq. range; [8:1] MPY = 20
Send_DAC(0x3D,0x0088); // [7] EN offset compensation; [5] no EQ boost; [4:3] = 1 adaptive EQ; [2:0] = 0 for CDR algorithm 0
Send_DAC(0x3E,0x0148); // [15:13]: no LOS alarm in any lane; [10:8]: AC coupled termination; [6:5]: 1/4 rate; [4:2]: 20b 8b10b double-word width; [1]: !Sleep RX ccts
// Step 6.3, JESD204B parameters incl configuring JESD RX FSM regs 0x46 to 0x62
// Leave the Lane ID per PoR, at the risk of lane configuration errors, to avoid potentially confusing the receiver
// Send_DAC(0x46,0x0000); // set Lane ID to 0 for lanes 0 .. 2, to avoid JESD ILAS errors
// Send_DAC(0x47,0x010a); // set Lane ID to 0 for lane 3
Send_DAC(0x25,0x0000); // JESD clock rate == input clock rate
Send_DAC(0x4B,0x1f01); // both coded N+1: [12:8] elastic read buffer depth = 32 (== K); [7:0] 2 octets per SerDes frame (== F)
Send_DAC(0x4C,0x1f03); // both coded N+1: [12:8] JESD K = 32; [4:0] L = 4 lanes in use
Send_DAC(0x4D,0x0300); // both coded N+1: [15:8] M = 4 converters per link; [4:0] selects S = 1 sample per frame (@ 2 octets, that means 16b samples)
Send_DAC(0x4F,0x1c41); // [7] = 0 do not match a specific symbol, begin buffering the 1st non-K after ILAS completes; [0] = 1 enable JESD comma align
Send_DAC(0x51,0x00df); // [7:0] enable any of the errors to generate a sync request, except link configuration
Send_DAC(0x52,0x00df); // [7:0] enable any of the errors to count, except link configuration
Send_DAC(0x61,0x0001); // only link0 drives SYNCb
// Step 6.4, DSP blocks, all of the substantive ones bypassed.
// Step 6.4.a regs 0x00 to 0x02
Send_DAC(0x22,0x1be4); // [15:8] implement direct input correspondence; [7:0] implement output swizzle
Send_DAC(0x00,0x0018); // [15:12] disable analog functions; [11:8] interpolation = 1; [4:3] enable alarm out @ positive polarity
                       // [7],[5] don't disable outputs on alarm; [6] don't sum datapaths; [2:0] disable power amp protection & inv sync filters
// Reg 0x02 was initialised at the outset rather than here, to provide for SPI readback
// Step 6.4.b respective coefficients from regs 0x08 to 0x19
// ... all of the blocks controlled by these coefficients are bypassed
// Step 6.4.c DSP block initializers are set from regs 0x1E to 0x20
// ... all of the blocks controlled by these coefficients are bypassed
// Step 7, Verify SerDes PLL Lock Status
usleep(1000); // wait before testing PLL lock (Kang's lock acquisition interval calculation at the bottom of Step 7 implies ~20usec for 148.5MHz)
Send_DAC(0x6C,0x0000); // clear alarms
usleep(200);
reg_value = Read_DAC(0x6C); // test alarm_rw0_pll, confirm SERDES PLL is locked
if (bit_field(reg_value, DAC_SERDES_PLL_LOCK_ALARM, DAC_SERDES_PLL_LOCK_ALARM)) { // DAC_SERDES_PLL_LOCK_ALARM is position [3]
printf("DAC chip SerDes PLL is out of lock.\r\n");
allOK = FALSE;
}
else printf("DAC chip SerDes PLL is locked to DACCLK.\r\n");
// The remaining Steps initialisation Steps appear in DAC_JESD_arm() and DAC_JESD_disarm()
return allOK;
} // DAC_init

Would you kindly advise as to why the SerDes PLL is not locking?

Hopeful thanks --todd

  • Todd,

    initial inspection does not show any misconfiguration. Please advise if you can be certain that the clock going into the DAC is not locking intermittently. We need to be absolutely sure that the clock is stable for the SERDES PLL to lock correctly.

    Please also advise the DACCLK is 148.5MHz and all the lanes (in 0x4A) remains on for SRX1 to SRX4 for the remaining of the SERDES PLL lock check. Please note that the SRX1 to SRX4 lane enable shares the same register as JESD initialization register. 

  • Hi Kang,

    Thank you for this prompt reply.

    > Please advise if you can be certain that the clock going into the DAC is not locking intermittently.

    I added a loop that clears then checks the SerDes PLL lock alarm for 1024 iterations after initialization. The alarm is asserted on every iteration, which indicates that the PLL is never locking.

    > We need to be absolutely sure that the clock is stable for the SERDES PLL to lock correctly.

    The clock going into the DAC is generated on DCLKout2 by LMK04828 in bypass mode from a stable 3.3V reference. I cannot probe DCLKout2 directly, but I can probe DCLKout8. DCLKout8 is programmed with exactly the same configuration as DCLKout2. DCLKout8 appears jitter-free on the scope. Therefore, we can infer that the clock going into the DAC is stable.

    > Please also advise the DACCLK is 148.5MHz

    LMK DCLKout8 frequency measures 148.5MHz, so DACCLK on LMK DCLKout2 must be at the same frequency

    > all the lanes (in 0x4A) remains on for SRX1 to SRX4 for the remaining of the SERDES PLL lock check. Please note that the SRX1 to SRX4 lane enable shares the same register as JESD initialization register.

    Every write to 0x4A asserts bits [11:8], enabling Lanes 3, 2, 1, and 0.

    I would appreciate any further suggestions or insights you might offer.

    Gratefully --todd

  • Hi Todd,

    I have tried your setup on our EVM and the SERDES PLL 0 locks. I have tested two configuration: one at half rate and another one at quarter rate. The quarter rate setting matches your and I was able to get the SERDES PLL to lock. 

    Please check the two settings and see if there are other mismatches (besides 0x3C and 0x3E registers) that you have not posted could cause the SERDES PLL to unlock

    setup_worked - half rate.csv

    setup_worked - quarter rate.csv

  • Hi Kang,

    Thank you for performing these experiments and for sharing the CSV files with me.

    Per your suggestion, I am working to reconcile my settings with the settings in the CSV files.

    According to the manual and also the DAC3XJ8X GUI, selecting quarter rate sets register 0x3E to 0x148.

    However, in the file "setup worked - quarter rate.csv" the value for 0x3E is 0x108. This value appears to select full rate, rather than quarter rate.

    Will you kindly confirm that I am interpreting the values in the CSV files appropriately?

    Hopeful thanks --todd

  • Hi Todd,

    There is a line at line 187 later that configures 0x3E = 0x148. The configuration algorithm takes care of this within the last few steps.

    -Kang

  • Dear Kang,

    Thank you again for having taken the time and trouble to confirm our DAC38J84 configuration.

    I am delighted to report that the SerDes PLL is now locking reliably.

    Once again, you've been a real help!

    Sincerely --todd