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)] #[cfg(has_rtio_analyzer)]
mod analyzer; mod analyzer;
#[cfg(has_ad9154)]
const SYSREF_PHASE_FPGA: u16 = 32;
#[cfg(has_ad9154)]
const SYSREF_PHASE_DAC: u16 = 61;
fn startup() { fn startup() {
irq::set_mask(0); irq::set_mask(0);
irq::set_ie(true); irq::set_ie(true);
@ -109,7 +114,7 @@ fn startup() {
/* must be the first SPI init because of HMC830 SPI mode selection */ /* must be the first SPI init because of HMC830 SPI mode selection */
board_artiq::hmc830_7043::init().expect("cannot initialize HMC830/7043"); board_artiq::hmc830_7043::init().expect("cannot initialize HMC830/7043");
#[cfg(has_ad9154)] #[cfg(has_ad9154)]
board_artiq::ad9154::init(44, 61); board_artiq::ad9154::init(SYSREF_PHASE_FPGA, SYSREF_PHASE_DAC);
#[cfg(has_allaki_atts)] #[cfg(has_allaki_atts)]
board_artiq::hmc542::program_all(8/*=4dB*/); 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<!>> { 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, // In the code below, *_chan_sel_write takes an u8 if there are fewer than 256 channels,
// and u16 otherwise; hence the `as _` conversion. // 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] #[no_mangle]
pub extern fn main() -> i32 { pub extern fn main() -> i32 {
clock::init(); clock::init();
@ -262,7 +278,7 @@ pub extern fn main() -> i32 {
/* must be the first SPI init because of HMC830 SPI mode selection */ /* must be the first SPI init because of HMC830 SPI mode selection */
hmc830_7043::init().expect("cannot initialize HMC830/7043"); hmc830_7043::init().expect("cannot initialize HMC830/7043");
#[cfg(has_ad9154)] #[cfg(has_ad9154)]
board_artiq::ad9154::init(32, 61); board_artiq::ad9154::init(SYSREF_PHASE_FPGA, SYSREF_PHASE_DAC);
#[cfg(has_allaki_atts)] #[cfg(has_allaki_atts)]
board_artiq::hmc542::program_all(8/*=4dB*/); board_artiq::hmc542::program_all(8/*=4dB*/);
@ -272,16 +288,23 @@ pub extern fn main() -> i32 {
} }
info!("link is up, switching to recovered clock"); info!("link is up, switching to recovered clock");
si5324::siphaser::select_recovered_clock(true).expect("failed to switch clocks"); 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); drtioaux::reset(0);
drtio_reset(false); drtio_reset(false);
drtio_reset_phy(false); drtio_reset_phy(false);
while drtio_link_rx_up() { while drtio_link_rx_up() {
process_errors(); process_errors();
process_aux_packets(); 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_phy(true);
drtio_reset(true); drtio_reset(true);
drtio_tsc_loaded();
info!("link is down, switching to local crystal clock"); info!("link is down, switching to local crystal clock");
si5324::siphaser::select_recovered_clock(false).expect("failed to switch clocks"); 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 import *
from migen.genlib.resetsync import AsyncResetSynchronizer from migen.genlib.resetsync import AsyncResetSynchronizer
from migen.genlib.cdc import PulseSynchronizer
from misoc.interconnect.csr import * from misoc.interconnect.csr import *
from artiq.gateware.rtio.sed.core import * from artiq.gateware.rtio.sed.core import *
@ -34,6 +35,7 @@ class DRTIOSatellite(Module):
lane_count=8, fifo_depth=128): lane_count=8, fifo_depth=128):
self.reset = CSRStorage(reset=1) self.reset = CSRStorage(reset=1)
self.reset_phy = CSRStorage(reset=1) self.reset_phy = CSRStorage(reset=1)
self.tsc_loaded = CSR()
self.clock_domains.cd_rio = ClockDomain() self.clock_domains.cd_rio = ClockDomain()
self.clock_domains.cd_rio_phy = 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.comb += self.rt_packet.cri.counter.eq(coarse_ts << fine_ts_width)
self.coarse_ts = coarse_ts 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")( self.submodules.outputs = ClockDomainsRenamer("rio")(
SED(channels, fine_ts_width, "sync", SED(channels, fine_ts_width, "sync",
lane_count=lane_count, fifo_depth=fifo_depth, lane_count=lane_count, fifo_depth=fifo_depth,
@ -112,7 +122,7 @@ class DRTIOSatellite(Module):
self.link_layer) self.link_layer)
def get_csrs(self): 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.link_layer.get_csrs() + self.link_stats.get_csrs() +
self.rt_errors.get_csrs() + self.aux_controller.get_csrs()) self.rt_errors.get_csrs() + self.aux_controller.get_csrs())