Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mirny/ADF5356 driver doesn't have 52-bits precision #2305

Open
thomasfire opened this issue Jan 11, 2024 · 1 comment
Open

mirny/ADF5356 driver doesn't have 52-bits precision #2305

thomasfire opened this issue Jan 11, 2024 · 1 comment

Comments

@thomasfire
Copy link
Contributor

According to datasheet, the chip has 52-bits precision available, however set_frequency function doesn't allow sub-Hz values.

Customer shared their way to use 38 bits:

   @portable
    def calculate_pll(self,f_vco: TFloat, f_pfd: TInt64):
        """
        Calculate fractional-N PLL parameters such that

        ``f_vco`` = ``f_pfd`` * (``n`` + (``frac1`` + ``frac2``/``mod2``) / ``mod1``)

        where
            ``mod1 = 2**24`` and ``mod2 <= 2**28``

        :param f_vco: target VCO frequency
        :param f_pfd: PFD frequency
        :return: ``(n, frac1, (frac2_msb, frac2_lsb), (mod2_msb, mod2_lsb))``
        """
        f_pfd = int64(f_pfd)
        f_vco = float(f_vco)

        # integral part
        n, r = int32(f_vco // f_pfd), f_vco % f_pfd

        # main fractional part
        r *= ADF5356_MODULUS1
        frac1, frac2 = int32(r // f_pfd), int64(r % f_pfd)

        # auxiliary fractional part
        mod2 = f_pfd

        ### ADD THIS TO FIX THE PROBLEM TEMPORARILY, restricts mod2 to within 14 bits (will only write LSB) ###
        while mod2 > (ADF5356_MAX_MODULUS2 >> 14):
            mod2 >>= 1
            frac2 >>= 1
        ### END EDIT ###

        gcd_div = gcd(frac2, mod2)
        mod2 //= gcd_div
        frac2 //= gcd_div
       
        return n, frac1, split_msb_lsb_28b(frac2), split_msb_lsb_28b(mod2)
@ldaokang
Copy link

Thanks for opening this issue for this problem. To provide more context, we are currently on Artiq 7 and measuring the frequency output of the Mirny around 5 GHz on a frequency counter. We noticed that there was a Hz-level frequency error when operating at f = 5GHz, which is much larger than the specified 52-bit precision of the chip.

mirny_error

Frequency was set using the artiq.coredevice.adf5356.set_frequency command. In this test, I am using a f_ref = 125 MHz, and get f_PFD = 125 MHz. At 5 GHz, from the fractional-N PLL formula, we get n = 40, frac1 = frac2 = 0, mod2 = 1 (mod1 = 2^24, fixed). As the set frequency deviates from the round 5GHz, only frac2 and mod2 change (frac1 only changes every 125MHz / 2^24 = 7.45 Hz).

frac2 and mod2 are 28-bit integers nominally, which are each separated into a 14-bit MSB and 14-bit LSB and written to registers 2 and 13 on the ADF5356 chip. From the measured error, I guessed that the MSB on either frac2 or mod2 was wrongly bit-shifted by 1. After messing around a bit, it was only when I coerced them both to 14-bit (such that only the LSB registry was written) did that remove the frequency error (up to the new resolution of 38-bit).

mirny_msb_lsb

I'm not sure why writing the MSB register for frac2 and mod2 (REG13) is problematic.

(Also note that the native artiq.coredevice.adf5356.set_frequency command rounds the set frequency to the nearest Hz, but it seems like it can be set to a float and that works fine as well)

More details:
Our frequency counter was referenced to 10 MHz from our maser, and the Mirny is clocked externally to a 125 MHz DDS which is also referenced to the 10 MHz maser. The device_db entry:

device_db["mirny2_cpld"] = {
    "type": "local",
    "module": "artiq.coredevice.mirny",
    "class": "Mirny",
    "arguments": {
        "spi_device": "spi_mirny2",
        "refclk": 125000000.0,
        "clk_sel": "sma"
    },
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants