diff --git a/artiq/firmware/libboard_artiq/wrpll.rs b/artiq/firmware/libboard_artiq/wrpll.rs index 40ae88e43..84c34b67e 100644 --- a/artiq/firmware/libboard_artiq/wrpll.rs +++ b/artiq/firmware/libboard_artiq/wrpll.rs @@ -281,6 +281,15 @@ pub fn init() { clock::spin_us(10_000); // Settling Time after FS Change unsafe { csr::wrpll::helper_reset_write(0); } + + info!("DDMTD test:"); + for _ in 0..20 { + unsafe { + csr::wrpll::ddmtd_main_arm_write(1); + while csr::wrpll::ddmtd_main_arm_read() != 0 {} + info!("{}", csr::wrpll::ddmtd_main_tag_read()); + } + } } pub fn select_recovered_clock(rc: bool) { diff --git a/artiq/gateware/drtio/wrpll/core.py b/artiq/gateware/drtio/wrpll/core.py index d4a4435a7..ee2099648 100644 --- a/artiq/gateware/drtio/wrpll/core.py +++ b/artiq/gateware/drtio/wrpll/core.py @@ -3,10 +3,11 @@ from migen.genlib.resetsync import AsyncResetSynchronizer from misoc.interconnect.csr import * from artiq.gateware.drtio.wrpll.si549 import Si549 +from artiq.gateware.drtio.wrpll.ddmtd import DDMTD class WRPLL(Module, AutoCSR): - def __init__(self, helper_clk_pads, main_dcxo_i2c, helper_dxco_i2c): + def __init__(self, helper_clk_pads, main_dcxo_i2c, helper_dxco_i2c, ddmtd_inputs, N=15): self.helper_reset = CSRStorage(reset=1) self.clock_domains.cd_helper = ClockDomain() @@ -19,3 +20,6 @@ class WRPLL(Module, AutoCSR): self.submodules.main_dcxo = Si549(main_dcxo_i2c) self.submodules.helper_dcxo = Si549(helper_dxco_i2c) + + self.submodules.ddmtd_helper = DDMTD(N, ddmtd_inputs.rec_clk) + self.submodules.ddmtd_main = DDMTD(N, ddmtd_inputs.main_xo) diff --git a/artiq/gateware/drtio/wrpll/ddmtd.py b/artiq/gateware/drtio/wrpll/ddmtd.py new file mode 100644 index 000000000..3708371b5 --- /dev/null +++ b/artiq/gateware/drtio/wrpll/ddmtd.py @@ -0,0 +1,62 @@ +from migen import * +from migen.genlib.cdc import PulseSynchronizer, MultiReg +from misoc.interconnect.csr import * + + +class DDMTDEdgeDetector(Module): + def __init__(self, i): + self.rising = Signal() + + history = Signal(4) + deglitched = Signal() + self.sync.helper += history.eq(Cat(history[1:], i)) + self.comb += deglitched.eq(i | history[0] | history[1] | history[2] | history[3]) + + deglitched_r = Signal() + self.sync.helper += [ + deglitched_r.eq(deglitched), + self.rising.eq(deglitched & ~deglitched_r) + ] + + +class DDMTD(Module, AutoCSR): + def __init__(self, N, i): + self.arm = CSR() + self.tag = CSRStatus(N) + + # in helper clock domain + self.h_tag = Signal(N) + self.h_tag_update = Signal() + + # # # + + ed = DDMTDEdgeDetector(i) + self.submodules += ed + + counter = Signal(N) + self.sync.helper += [ + counter.eq(counter + 1), + self.h_tag_update.eq(0), + If(ed.rising, + self.h_tag_update.eq(1), + self.h_tag.eq(counter) + ) + ] + + tag_update_ps = PulseSynchronizer("helper", "sys") + self.submodules += tag_update_ps + self.comb += tag_update_ps.i.eq(self.h_tag_update) + tag_update = Signal() + self.sync += tag_update.eq(tag_update_ps.o) + + tag = Signal(N) + self.h_tag.attr.add("no_retiming") + self.specials += MultiReg(self.h_tag, tag) + + self.sync += [ + If(self.arm.re & self.arm.r, self.arm.w.eq(1)), + If(tag_update, + If(self.arm.w, self.tag.status.eq(tag)), + self.arm.w.eq(0), + ) + ] diff --git a/artiq/gateware/targets/sayma_amc.py b/artiq/gateware/targets/sayma_amc.py index 8487fdf40..6cb234f51 100755 --- a/artiq/gateware/targets/sayma_amc.py +++ b/artiq/gateware/targets/sayma_amc.py @@ -139,7 +139,8 @@ class SatelliteBase(MiniSoC): self.submodules.wrpll = WRPLL( helper_clk_pads=platform.request("ddmtd_helper_clk"), main_dcxo_i2c=platform.request("ddmtd_main_dcxo_i2c"), - helper_dxco_i2c=platform.request("ddmtd_helper_dcxo_i2c")) + helper_dxco_i2c=platform.request("ddmtd_helper_dcxo_i2c"), + ddmtd_inputs=platform.request("ddmtd_inputs")) self.csr_devices.append("wrpll") else: self.comb += platform.request("filtered_clk_sel").eq(1)