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.

LMK04821: difficulty setting up fixed digital delay

Part Number: LMK04821


We are trying to set up the LMK04821 with fixed digital delay. We have programmed the registers as described on p. 42 of the data sheet, toggled the sync polarity, but this doesn't seem to affect the output phase. We toggle the sync polarity programmatically (i.e., by setting, and unsetting 0x143:5). Does the length of the sync pulse matter?

It is also a bit unclear to us, what the meaning of registers 0x101, 0x109 etc. are. On p. 42, the data sheet claims that 

"In both delay modes, the regular clock divider is substituted with an alternative divide value. The substitute divide
value consists of two values, DCLKoutX_DDLY_CNTH and DCLKoutX_DDLY_CNTL. The minimum
_CNTH/_CNTL value is 2 and the maximum _CNTH/_CNTL value is 16. This results in a minimum alternative
divide value of 4 and a maximum of 32."

but it is not explained, what the substitute divide value actually does. In the example given below 

"These steps should be followed:
1. Set DCLKout0_DDLY_CNTH = 4 and DCLKout2_DDLY_CNTH = 4. First part of delay for each clock.
2. Set DCLKout0_DDLY_CNTL = 4 and DCLKout2_DDLY_CNTL = 5. Second part of delay for each clock...."

the sum of the two sub-registers is 8, and 9, respectively, and not 8. 

Here are our register settings: 50 MHz input clock, 100 MHz outputs on channels 0, and 2, and 12.5 MHz system reference clock on channels 1, 3.

var registers = {
2 : 0x00, /* 0x0002 POWER_DOWN */
256 : 0x0f, /* 0x0100 CLK0 settings */
257 : 0x00,
259 : 0x00,
260 : 0x30,
261 : 0x00,
262 : 0x00,
263 : 0x11,
264 : 0x0F, /* 0x0108 */
265 : 0x00,
267 : 0x00,
268 : 0x30,
269 : 0x00,
270 : 0x00,
271 : 0x11,
272 : 0x0f,
273 : 0x00,
275 : 0x00,
276 : 0x00,
277 : 0x00,
278 : 0xFF,
279 : 0x00,
280 : 0x00,
281 : 0x55,
283 : 0x00,
284 : 0x00,
285 : 0x00,
286 : 0xFF,
287 : 0x00,
288 : 0x00,
289 : 0x55,
291 : 0x00,
292 : 0x00,
293 : 0x00,
294 : 0xFF,
295 : 0x00,
296 : 0x00,
297 : 0x55,
299 : 0x00,
300 : 0x00,
301 : 0x00,
302 : 0xFF,
303 : 0x00,
304 : 0x00,
305 : 0x55,
307 : 0x00,
308 : 0x00,
309 : 0x00,
310 : 0xFF,
311 : 0x00,
312 : 0x20,
313 : 0x03,
314 : 0x00,
315 : 0x78,
316 : 0x00,
317 : 0x00,
318 : 0x03,
319 : 0x0D,
320 : 0x00,
321 : 0x00,
322 : 0x00,
323 : 0x0b,
324 : 0x83,
325 : 0x7f,
326 : 0x10,
327 : 0x98,
328 : 0x0a,
329 : 0x02,
330 : 0x0a, /* 0x014a, reset_type/reset_mux */
331 : 0x16,
332 : 0x00,
333 : 0x00,
334 : 0x00,
335 : 0x7f,
336 : 0x03,
337 : 0x02,
338 : 0x00,
339 : 0x00,
340 : 0x00, /* 0x0154, CLKin0_R[7:0], 5*/
341 : 0x00,
342 : 0x04,
343 : 0x00,
344 : 0x00,
345 : 0x00,
346 : 0x01, /* 0x015A, PLL1_N[7:4], 4 */
347 : 0x98,
348 : 0x20,
349 : 0x00,
350 : 0x00,
351 : 0x0b, /* 0x015f PLL1_LD_TYPE, PLL1_LD_MUX; with 0x04 or 0x03, one can toggle the LED */
352 : 0x00,
353 : 0x01, /* 0x02 */
354 : 0xa4, /* 0xa5 */
355 : 0x00,
356 : 0x00,
357 : 0x02, /* from here, the order of registers is no longer monotonic */
369 : 0xaa,
370 : 0x02,
372 : 0x00,
380 : 0x15,
381 : 0x33,
358 : 0x00,
359 : 0x00,
360 : 0x03,
361 : 0x41,
362 : 0x00,
363 : 0x40,
364 : 0x00,
365 : 0x00,
366 : 0x13, /* 0x016e PLL2_LD_TYPE, PLL2_LD_MUX; 0x06 is open-drain output, 0x04/0x03 toggles the LED */
371 : 0x00,
8189 : 0x00,
8190 : 0x00,
8191 : 0x53,
}

and here is the function that should set the delays on channels 0, and 2. We are certain that the communication between the host and the clock generator is error free, and that the register settings reach the LMK04821. 

async function write_phase() {
// write phase of channel 0, 0x101
write_phase_register(257)
await sleep(300)

// write phase of channel 2, 0x109
write_phase_register(265)
await sleep(300)

// clear 0x106
registers['262'] = 0
write_phase_register(262)
await sleep(300)

// clear 0x10e
registers['270'] = 0
write_phase_register(270)
await sleep(300)

// clear 0x144:0, 0x144:1
registers['324'] = 128
write_phase_register(324)
await sleep(300)

// toggle 0x143:5
registers['323'] = 27
write_phase_register(323)
await sleep(2000)
registers['323'] = 11
write_phase_register(323)
await sleep(3000)

// set 0x106:7
registers['262'] = 128
write_phase_register(262)
await sleep(300)

// set 0x10e:7
registers['270'] = 128
write_phase_register(270)
await sleep(300)

// set 0x144:0, 0x144:1
registers['324'] = 131
write_phase_register(324)
await sleep(300)

console.log('wrote phase sequence')
}
  • Hello,

    Sorry for the delay, we will respond in 24 hours.

    Regards,
    Hao

  • Hello zvoros,

    First, keep in mind that this is the fixed digital delay. No matter how many times the synchronization procedure is repeated, the phase between the two outputs should be reproducible to the same offset as long as the digital delay registers are the same value between synchronizations.

    The substitute divide values can be thought of as explicitly telling the divider how long to hold the output high or low. For fixed digital delay this is essentially irrelevant because the output state is muted while the digital delay is counted. However, this becomes important for dynamic digital delay, where the output is not muted during the phase update. For dynamic digital delay, it makes sense to specify the number of VCO cycles that the output clock should remain high/low during the delay shift cycle, to better control the duty cycle of the shift period.

    In the example given, the delay values sum to 8 and 9, implying that the first clock should be delayed by 8 VCO cycles and the second clock should be delayed by 9 VCO cycles. In fixed digital delay, all you will see is a single-cycle VCO delay extra before the second clock starts up, relative to the first clock. In dynamic digital delay, you will see that the second clock has a single clock cycle in which the output remains low for 5 VCO cycles, effectively creating one VCO cycle of delay on the second clock relative to the first clock.

    Give me a little bit more time to decipher the register write sequence you provided; I believe I understand what's being done, but I'd like to confirm by duplicating your programming on a board in our lab. I'll aim for later today to provide an update.

    Regards,

    Derek Payne

  • Greetings Derek,

    Many thanks for your feedback!

    First, keep in mind that this is the fixed digital delay. No matter how many times the synchronization procedure is repeated, the phase between the two outputs should be reproducible to the same offset as long as the digital delay registers are the same value between synchronizations.

    This is clear, and this is what we need: our setup is static in the sense that once we know what the parameters are, we are not going to change them. 

    I also forgot to mention in my original post that we are trying to get this done in the nested zero-delay dual-loop configuration, as shown in Fig. 20 of the data sheet. We come in with a 50-MHz reference signal, and want to generate 12.5 MHz, and 100 MHz out of this. The outputs should be phase-locked with the reference. We close the PLL through the 12.5-MHz SYSREF. 

    We can set pretty much everything, frequencies, global digital delay of SYSREF, local digital delays of the SYSREF outputs, local analogue delays of both the device clock, and the SYSREF output. The only thing missing is the local digital delay of the device clock. We would like lo be able to delay the phase with respect to the SYSREF over 360 degrees, i.e., 10 ns. The analogue delays alone don't get us there. 

    I have also noted that the our original sequence, which was the implementation of the instructions in Section 9.3.3. of the data sheet, didn't work reliably. I think one step was missing. I have modified the code, and now we have this: 

    async function write_phase() {
        // write phase of channel 0, 0x101
        write_phase_register(257)
        await sleep(300)

        // write phase of channel 2, 0x109
        write_phase_register(265)
        await sleep(300)

        // clear 0x106
        registers['262'] = 0
        write_phase_register(262)
        await sleep(300)

        // clear 0x10e
        registers['270'] = 0
        write_phase_register(270)
        await sleep(300)

        // clear 0x144:0, 0x144:1, 0x144:7
        registers['324'] = 0
        write_phase_register(324)
        await sleep(300)

        registers['323'] = 145
        write_phase_register(323)
        await sleep(200)
        // toggle 0x143:5
        registers['323'] = 177
        write_phase_register(323)
        await sleep(2000)
        registers['323'] = 145
        write_phase_register(323)
        await sleep(3000)
        registers['323'] = 17
        write_phase_register(323)
        await sleep(200)
       
        // set 0x106:7
        registers['262'] = 128
        write_phase_register(262)
        await sleep(300)

        // set 0x10e:7
        registers['270'] = 128
        write_phase_register(270)
        await sleep(300)

        // set 0x144:0, 0x144:1, 0x144:7
        registers['324'] = 131
        write_phase_register(324)
        await sleep(300)

        console.log('wrote phase sequence')
    }

    With this, we can reliably set everything, except the digital delays of the device clocks. 

  • Zvoros,

    As far as I can tell, the second sequence is doing everything correctly to set the fixed digital delays - when I test your SYNC procedure in the lab with different CNTH/CNTL values I get the expected device clock to SYSREF phase variation. I did notice that you have both CNTH/CNTL registers for 0/2 outputs set to 0 in the first block of settings, and that your sync procedure writes these registers but doesn't explicitly update them. Are you updating these as you go and trying to check the phase position of device clocks with respect to SYSREFs? For example if you perform the synchronization routine with CNTH+CNTL=4 vs if CNTH+CNTL=5, you should see a single VCO cycle difference of device clock to SYSREF phase.

    Regards,

    Derek Payne

  • Greetings Derek,

    Thanks for your reply!

    I did notice that you have both CNTH/CNTL registers for 0/2 outputs set to 0 in the first block of settings, and that your sync procedure writes these registers but doesn't explicitly update them.

    So, does this imply that a step is missing?  Or do you mean that you don't find the registers['265'] = ... statement in this section:

      // write phase of channel 2, 0x109
        write_phase_register(265)
        await sleep(300)

    The GUI callback writes the appropriate value into the register array, hence the missing registers['265'] = ... statement. Here is the stream of values that land on the LMK, when we want to change the phase of DCLKout0, and DCLKout2: 

    [65928]
    [67960]
    [67072]
    [69120]
    [82944]
    [82833]
    [82865]
    [82833]
    [82705]
    [67200]
    [69248]
    [83075]

    The first two numbers are the 0x101, and 0x109 registers, plus their respective values. These correspond to 136, and 120, i.e., these should give us digital delays equal to 16 (8 + 8), and 32 (16 + 16) VCO cycles. 

    If, instead of what can be seen above, we write 

    [65894]
    [67960]
    [67072]
    [69120]
    [82944]
    [82833]
    [82865]
    [82833]
    [82705]
    [67200]
    [69248]
    [83075]

    we should get 12 (6 + 6), and 32 (16 + 16) VCO cycles, respectively, i.e., if we measure the phase between SDCLKout1, and DCLKout0, we should see an extra phase shift of approx. 2400 ps (we run on the 3-GHz VCO with a divider of 2). Yet, there is absolutely nothing.

    I presume, the settings of the second output are irrelevant, since we are measuring phases between SDCLKout1, and DCLKout0, and we trigger the oscilloscope on SDCLKout1. The phase of SDCLKout1 is locked to the 50-MHz reference signal, as it should be.

    I believe, we can also rule out problems with the communication between the PC and the LMK, because all other settings result in changes that we would expect. I understand that we are working with a custom piece of hardware and out own software, and not the evaluation board, but I think we a number of debug options, and all seem to indicate that we are all right in this regard. 

  • Zvoros,

    Thanks for the clarification, I meant the registers['265']=... portion and it is clear to me that the appropriate registers are being written to change the delay. No step missing there.

    Upon double-checking, I don't see a write to register 0x139 (313) to change the state of the SYSREF_MUX. The original value you used to program the SYSREF_MUX is to continuous SYSREF, which suggests that the SYSREF divider output is being used as the SYNC signal instead of the toggling of the SYNC_POL bit. While historically I haven't seen issues with using the SYSREF divider output as its own source, but it doesn't seem like this was your intention, and I suspect it might be part of the cause of your trouble. Do results change if SYSREF_MUX is set to 0 (normal SYNC) during the SYNC procedure, before clearing the bits in 0x144?

    Regards,

    Derek Payne

  • Derek,

    Upon double-checking, I don't see a write to register 0x139 (313) to change the state of the SYSREF_MUX. The original value you used to program the SYSREF_MUX is to continuous SYSREF, which suggests that the SYSREF divider output is being used as the SYNC signal instead of the toggling of the SYNC_POL bit.

    I think this was the missing link. The following sequence seems to do the trick: 

    async function write_phase() {
        // write phase of channel 0, 0x101
        write_phase_register(257)
        await sleep(300)

        // write phase of channel 2, 0x109
        write_phase_register(265)
        await sleep(300)

        // clear 0x106
        registers['262'] = 0
        write_phase_register(262)
        await sleep(300)

        // clear 0x10e
        registers['270'] = 0
        write_phase_register(270)
        await sleep(300)

        // clear 0x139:0, 0x139:1
        registers['313'] = 0
        write_phase_register(313)
        await sleep(300)

        // clear 0x144:0, 0x144:1, 0x144:7
       registers['324'] = 0
       write_phase_register(324)
       await sleep(300)

        registers['323'] = 17 
        write_phase_register(323)
        await sleep(200)
        // toggle 0x143:5
        registers['323'] = 49 
        write_phase_register(323)
        await sleep(2000)
        registers['323'] = 17 
        write_phase_register(323)
        await sleep(3000)
        registers['323'] = 17
        write_phase_register(323)
        await sleep(200)

        // set 0x106:7
        registers['262'] = 128
        write_phase_register(262)
        await sleep(300)

        // set 0x10e:7
        registers['270'] = 128
        write_phase_register(270)
        await sleep(300)

        // set 0x144:0, 0x144:1, 0x144:7
        registers['324'] = 131
        write_phase_register(324)
        await sleep(300)

        // set 0x139:0, 0x139:1
        registers['313'] = 3
        write_phase_register(313)
        await sleep(300)


        console.log('wrote phase sequence')
    }

    Many thanks for bearing with us. 

    Best,

    Zoltán