Hi, I am using artiq 4.0 in trapped ion experiments. I want to use an external clock to synchronize the DDS with other devices.
I only have two clocks, with frequecies 10MHz and 1GHz. Unforutunately, according to the file ad9910.py(C:\Users***\anaconda3\envs\artiq-kasli\Lib\site-packages\artiq\coredevice\ad9910.py), neither clock could be used.

There are two problems.

1.

In line 92, we know that sysclk = refclk*pll_n/4. In line 95 and 96, as ref_period = 1e-9 is set in device_db.py file, we know sysclk = 1e9, so if we use refclk = 10MHz, pll_n = 400, and if we use refclk = 1GHz, pll_n = 4.
However, in line 89 "assert 12<= pll_n <= 127", these two cannot work.

When I change the ref_period to 1e-8, in line 98-100, sysclk/1e6 = 100, which is not included in those six situations.

So how I can use these two external clock reference to dds board?

I try to change these values, but it seems these value are decided by hardware. When I change theses value, for example, 12<= pll_n<=1270, the program when wrong with "PLL time out" error(in line 245), which is because the 'sat' value got from urukul board cannot satisfied lock condition.

  1. Our version of Artiq is 4.0, but the ad99100.py file in the repository of github is 6.0 version. There are many different between these two version. In 6.0 version, 'init' function of ad9910.py has an option called "pll_en", which control whether system bypass the pll(phase lock loop) progress.

See next two picture, first is 4.0

, second and third is 6.0

So I want to know what happen if the system bypass the pll progress, how system can use external refernce clock signal as system clock signal?

`class AD9910:
"""
AD9910 DDS channel on Urukul.

This class supports a single DDS channel and exposes the DDS,
the digital step attenuator, and the RF switch.

:param chip_select: Chip select configuration. On Urukul this is an
    encoded chip select and not "one-hot": 3 to address multiple chips
    (as configured through CFG_MASK_NU), 4-7 for individual channels.
:param cpld_device: Name of the Urukul CPLD this device is on.
:param sw_device: Name of the RF switch device. The RF switch is a
    TTLOut channel available as the :attr:`sw` attribute of this instance.
:param pll_n: DDS PLL multiplier. The DDS sample clock is
    f_ref/4*pll_n where f_ref is the reference frequency (set in the parent
    Urukul CPLD instance).
:param pll_cp: DDS PLL charge pump setting.
:param pll_vco: DDS PLL VCO range selection.
:param sync_delay_seed: SYNC_IN delay tuning starting value.
    To stabilize the SYNC_IN delay tuning, run :meth:`tune_sync_delay` once
    and set this to the delay tap number returned (default: -1 to signal no
    synchronization and no tuning during :meth:`init`).
:param io_update_delay: IO_UPDATE pulse alignment delay.
    To align IO_UPDATE to SYNC_CLK, run :meth:`tune_io_update_delay` and
    set this to the delay tap number returned.
"""
kernel_invariants = {"chip_select", "cpld", "core", "bus",
                     "ftw_per_hz", "pll_n", "io_update_delay",
                     "sysclk_per_mu"}

def __init__(self, dmgr, chip_select, cpld_device, sw_device=None,
             pll_n=40, pll_cp=7, pll_vco=5, sync_delay_seed=-1,
             io_update_delay=0):
    self.cpld = dmgr.get(cpld_device)
    self.core = self.cpld.core
    self.bus = self.cpld.bus
    assert 3 <= chip_select <= 7
    self.chip_select = chip_select
    if sw_device:
        self.sw = dmgr.get(sw_device)
        self.kernel_invariants.add("sw")
    assert 12 <= pll_n <= 127
    self.pll_n = pll_n
    assert self.cpld.refclk/4 <= 60e6
    sysclk = self.cpld.refclk*pll_n/4  # Urukul clock fanout divider
    assert sysclk <= 1e9
    self.ftw_per_hz = (1 << 32)/sysclk
    self.sysclk_per_mu = int(round(sysclk*self.core.ref_period))
    assert self.sysclk_per_mu == sysclk*self.core.ref_period
    assert 0 <= pll_vco <= 5
    vco_min, vco_max = [(370, 510), (420, 590), (500, 700),
                        (600, 880), (700, 950), (820, 1150)][pll_vco]
    assert vco_min <= sysclk/1e6 <= vco_max
    self.pll_vco = pll_vco
    assert 0 <= pll_cp <= 7
    self.pll_cp = pll_cp
    if sync_delay_seed >= 0 and not self.cpld.sync_div:
        raise ValueError("parent cpld does not drive SYNC")
    self.sync_delay_seed = sync_delay_seed
    self.io_update_delay = io_update_delay
    self.phase_mode = PHASE_MODE_CONTINUOUS`

AFAIK it is unknown whether 10 MHz reference frequency input can work. The loop filter isn't design for that frequency.
On top of that my guess is that the PLL parameters for 10 MHz reference you choose are not supported by the DDS chip (AD9910).
As you say correctly: For PLL bypass with 1 GHz reference , disable the PLL.

    rjo
    Thank you for replying, I have found that in https://github.com/sinara-hw/Urukul/wiki "Clock Input" Section, it's said that "AD9910 PLL accepts clocks between 3.2MHz and 60MHz (12.8 and 240 with divider), PLL multiplication factors between 12 and 127 (48 and 508 with divider)"

    So 10MHz and 1GHz really are not supported, as you guess!

    But I am still confused on the "bypass", how dds can use the external clock without PLL?

    With pll_en=0. In artiq 4 that feature was probably not yet implemented.

      rjo
      Yes, it's added on artiq 5.0, but I guess the hardware does not change with just upgrade the artiq code.