AD9912: Add PLL bypass option (pll_en) like AD9910

This commit is contained in:
mwojcik 2022-12-20 14:18:44 +08:00 committed by Sébastien Bourdeauducq
parent dbb77b5356
commit 8dc6902c23
1 changed files with 17 additions and 9 deletions

View File

@ -25,12 +25,14 @@ class AD9912:
f_ref/clk_div*pll_n where f_ref is the reference frequency and clk_div f_ref/clk_div*pll_n where f_ref is the reference frequency and clk_div
is the reference clock divider (both set in the parent Urukul CPLD is the reference clock divider (both set in the parent Urukul CPLD
instance). instance).
:param pll_en: PLL enable bit, set to 0 to bypass PLL (default: 1).
Note that when bypassing the PLL the red front panel LED may remain on.
""" """
def __init__(self, dmgr, chip_select, cpld_device, sw_device=None, def __init__(self, dmgr, chip_select, cpld_device, sw_device=None,
pll_n=10): pll_n=10, pll_en=1):
self.kernel_invariants = {"cpld", "core", "bus", "chip_select", self.kernel_invariants = {"cpld", "core", "bus", "chip_select",
"pll_n", "ftw_per_hz"} "pll_n", "pll_en", "ftw_per_hz"}
self.cpld = dmgr.get(cpld_device) self.cpld = dmgr.get(cpld_device)
self.core = self.cpld.core self.core = self.cpld.core
self.bus = self.cpld.bus self.bus = self.cpld.bus
@ -39,8 +41,12 @@ class AD9912:
if sw_device: if sw_device:
self.sw = dmgr.get(sw_device) self.sw = dmgr.get(sw_device)
self.kernel_invariants.add("sw") self.kernel_invariants.add("sw")
self.pll_en = pll_en
self.pll_n = pll_n self.pll_n = pll_n
sysclk = self.cpld.refclk / [1, 1, 2, 4][self.cpld.clk_div] * pll_n if pll_en:
sysclk = self.cpld.refclk / [1, 1, 2, 4][self.cpld.clk_div] * pll_n
else:
sysclk = self.cpld.refclk
assert sysclk <= 1e9 assert sysclk <= 1e9
self.ftw_per_hz = 1 / sysclk * (int64(1) << 48) self.ftw_per_hz = 1 / sysclk * (int64(1) << 48)
@ -102,13 +108,15 @@ class AD9912:
raise ValueError("Urukul AD9912 product id mismatch") raise ValueError("Urukul AD9912 product id mismatch")
delay(50 * us) delay(50 * us)
# HSTL power down, CMOS power down # HSTL power down, CMOS power down
self.write(AD9912_PWRCNTRL1, 0x80, length=1) pwrcntrl1 = 0x80 | ((~self.pll_en & 1) << 4)
self.cpld.io_update.pulse(2 * us) self.write(AD9912_PWRCNTRL1, pwrcntrl1, length=1)
self.write(AD9912_N_DIV, self.pll_n // 2 - 2, length=1)
self.cpld.io_update.pulse(2 * us)
# I_cp = 375 µA, VCO high range
self.write(AD9912_PLLCFG, 0b00000101, length=1)
self.cpld.io_update.pulse(2 * us) self.cpld.io_update.pulse(2 * us)
if self.pll_en:
self.write(AD9912_N_DIV, self.pll_n // 2 - 2, length=1)
self.cpld.io_update.pulse(2 * us)
# I_cp = 375 µA, VCO high range
self.write(AD9912_PLLCFG, 0b00000101, length=1)
self.cpld.io_update.pulse(2 * us)
delay(1 * ms) delay(1 * ms)
@kernel @kernel