From e29536351dfd41334f1081dc76bbbb831ffe7113 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 21 Jun 2018 17:00:32 +0800 Subject: [PATCH] drtio: resync SYSREF when TSC is loaded --- artiq/firmware/runtime/main.rs | 7 ++++++- artiq/firmware/satman/main.rs | 27 +++++++++++++++++++++++++-- artiq/gateware/drtio/core.py | 12 +++++++++++- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/artiq/firmware/runtime/main.rs b/artiq/firmware/runtime/main.rs index 8e407d4c5..1e39f9968 100644 --- a/artiq/firmware/runtime/main.rs +++ b/artiq/firmware/runtime/main.rs @@ -56,6 +56,11 @@ mod moninj; #[cfg(has_rtio_analyzer)] mod analyzer; +#[cfg(has_ad9154)] +const SYSREF_PHASE_FPGA: u16 = 32; +#[cfg(has_ad9154)] +const SYSREF_PHASE_DAC: u16 = 61; + fn startup() { irq::set_mask(0); irq::set_ie(true); @@ -109,7 +114,7 @@ fn startup() { /* must be the first SPI init because of HMC830 SPI mode selection */ board_artiq::hmc830_7043::init().expect("cannot initialize HMC830/7043"); #[cfg(has_ad9154)] - board_artiq::ad9154::init(44, 61); + board_artiq::ad9154::init(SYSREF_PHASE_FPGA, SYSREF_PHASE_DAC); #[cfg(has_allaki_atts)] board_artiq::hmc542::program_all(8/*=4dB*/); diff --git a/artiq/firmware/satman/main.rs b/artiq/firmware/satman/main.rs index 302a0ef95..4e3a1a4c5 100644 --- a/artiq/firmware/satman/main.rs +++ b/artiq/firmware/satman/main.rs @@ -26,6 +26,16 @@ fn drtio_reset_phy(reset: bool) { } } +fn drtio_tsc_loaded() -> bool { + unsafe { + let tsc_loaded = (csr::DRTIO[0].tsc_loaded_read)() == 1; + if tsc_loaded { + (csr::DRTIO[0].tsc_loaded_write)(1); + } + tsc_loaded + } +} + fn process_aux_packet(packet: drtioaux::Packet) -> Result<(), drtioaux::Error> { // In the code below, *_chan_sel_write takes an u8 if there are fewer than 256 channels, // and u16 otherwise; hence the `as _` conversion. @@ -238,6 +248,12 @@ fn drtio_link_rx_up() -> bool { } } +const SIPHASER_PHASE: u16 = 32; +#[cfg(has_ad9154)] +const SYSREF_PHASE_FPGA: u16 = 32; +#[cfg(has_ad9154)] +const SYSREF_PHASE_DAC: u16 = 61; + #[no_mangle] pub extern fn main() -> i32 { clock::init(); @@ -262,7 +278,7 @@ pub extern fn main() -> i32 { /* must be the first SPI init because of HMC830 SPI mode selection */ hmc830_7043::init().expect("cannot initialize HMC830/7043"); #[cfg(has_ad9154)] - board_artiq::ad9154::init(32, 61); + board_artiq::ad9154::init(SYSREF_PHASE_FPGA, SYSREF_PHASE_DAC); #[cfg(has_allaki_atts)] board_artiq::hmc542::program_all(8/*=4dB*/); @@ -272,16 +288,23 @@ pub extern fn main() -> i32 { } info!("link is up, switching to recovered clock"); si5324::siphaser::select_recovered_clock(true).expect("failed to switch clocks"); - si5324::siphaser::calibrate_skew(32).expect("failed to calibrate skew"); + si5324::siphaser::calibrate_skew(SIPHASER_PHASE).expect("failed to calibrate skew"); drtioaux::reset(0); drtio_reset(false); drtio_reset_phy(false); while drtio_link_rx_up() { process_errors(); process_aux_packets(); + #[cfg(has_hmc830_7043)] + { + if drtio_tsc_loaded() { + hmc830_7043::hmc7043::sysref_rtio_align(SYSREF_PHASE_FPGA); + } + } } drtio_reset_phy(true); drtio_reset(true); + drtio_tsc_loaded(); info!("link is down, switching to local crystal clock"); si5324::siphaser::select_recovered_clock(false).expect("failed to switch clocks"); } diff --git a/artiq/gateware/drtio/core.py b/artiq/gateware/drtio/core.py index 61c1d2eb4..38c6d8a2a 100644 --- a/artiq/gateware/drtio/core.py +++ b/artiq/gateware/drtio/core.py @@ -2,6 +2,7 @@ from types import SimpleNamespace from migen import * from migen.genlib.resetsync import AsyncResetSynchronizer +from migen.genlib.cdc import PulseSynchronizer from misoc.interconnect.csr import * from artiq.gateware.rtio.sed.core import * @@ -34,6 +35,7 @@ class DRTIOSatellite(Module): lane_count=8, fifo_depth=128): self.reset = CSRStorage(reset=1) self.reset_phy = CSRStorage(reset=1) + self.tsc_loaded = CSR() self.clock_domains.cd_rio = ClockDomain() self.clock_domains.cd_rio_phy = ClockDomain() @@ -92,6 +94,14 @@ class DRTIOSatellite(Module): self.comb += self.rt_packet.cri.counter.eq(coarse_ts << fine_ts_width) self.coarse_ts = coarse_ts + ps_tsc_load = PulseSynchronizer("rtio", "sys") + self.submodules += ps_tsc_load + self.comb += ps_tsc_load.i.eq(self.rt_packet.tsc_load) + self.sync += [ + If(self.tsc_loaded.re, self.tsc_loaded.w.eq(0)), + If(ps_tsc_load.o, self.tsc_loaded.w.eq(1)) + ] + self.submodules.outputs = ClockDomainsRenamer("rio")( SED(channels, fine_ts_width, "sync", lane_count=lane_count, fifo_depth=fifo_depth, @@ -112,7 +122,7 @@ class DRTIOSatellite(Module): self.link_layer) def get_csrs(self): - return ([self.reset, self.reset_phy] + + return ([self.reset, self.reset_phy, self.tsc_loaded] + self.link_layer.get_csrs() + self.link_stats.get_csrs() + self.rt_errors.get_csrs() + self.aux_controller.get_csrs())