drtio: resync SYSREF when TSC is loaded

This commit is contained in:
Sebastien Bourdeauducq 2018-06-21 17:00:32 +08:00
parent 5a2a857a2f
commit e29536351d
3 changed files with 42 additions and 4 deletions

View File

@ -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*/);

View File

@ -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");
}

View File

@ -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())