forked from M-Labs/artiq
sayma: fix/cleanup DRTIO-DAC sync interaction
This commit is contained in:
parent
facc0357d8
commit
61d4614b61
|
@ -2,7 +2,7 @@ use board_misoc::config;
|
|||
#[cfg(si5324_as_synthesizer)]
|
||||
use board_artiq::si5324;
|
||||
#[cfg(has_drtio)]
|
||||
use board_misoc::csr;
|
||||
use board_misoc::{csr, clock};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum RtioClock {
|
||||
|
@ -161,6 +161,10 @@ pub fn init() {
|
|||
unsafe {
|
||||
csr::drtio_transceiver::stable_clkin_write(1);
|
||||
}
|
||||
clock::spin_us(1500); // wait for CPLL/QPLL lock
|
||||
unsafe {
|
||||
csr::drtio_transceiver::txenable_write(0xffffffffu32 as _);
|
||||
}
|
||||
|
||||
#[cfg(has_rtio_crg)]
|
||||
{
|
||||
|
|
|
@ -160,7 +160,6 @@ pub mod jesd204sync {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
fn measure_ddmdt_phase_raw() -> Result<i32, &'static str> {
|
||||
Ok(jdac::basic_request(0, jdac_common::DDMTD_SYSREF_RAW, 0)? as i32)
|
||||
}
|
||||
|
@ -567,4 +566,12 @@ pub mod jesd204sync {
|
|||
error!("failed to align SYSREF at DAC: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resync_dacs() -> Result<(), &'static str> {
|
||||
info!("resychronizing DACs");
|
||||
for dacno in 0..csr::JDCG.len() {
|
||||
ad9154_sync(dacno as u8)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -465,6 +465,10 @@ pub extern fn main() -> i32 {
|
|||
csr::drtio_transceiver::stable_clkin_write(1);
|
||||
}
|
||||
clock::spin_us(1500); // wait for CPLL/QPLL lock
|
||||
#[cfg(not(has_jdcg))]
|
||||
unsafe {
|
||||
csr::drtio_transceiver::txenable_write(0xffffffffu32 as _);
|
||||
}
|
||||
#[cfg(has_wrpll)]
|
||||
wrpll::diagnostics();
|
||||
init_rtio_crg();
|
||||
|
@ -493,6 +497,11 @@ pub extern fn main() -> i32 {
|
|||
let mut hardware_tick_ts = 0;
|
||||
|
||||
loop {
|
||||
#[cfg(has_jdcg)]
|
||||
unsafe {
|
||||
// Hide from uplink until RTM is ready
|
||||
csr::drtio_transceiver::txenable_write(0xfffffffeu32 as _);
|
||||
}
|
||||
while !drtiosat_link_rx_up() {
|
||||
drtiosat_process_errors();
|
||||
for mut rep in repeaters.iter_mut() {
|
||||
|
@ -510,33 +519,12 @@ pub extern fn main() -> i32 {
|
|||
#[cfg(has_wrpll)]
|
||||
wrpll::select_recovered_clock(true);
|
||||
|
||||
#[cfg(has_jdcg)]
|
||||
{
|
||||
/*
|
||||
* One side of the JESD204 elastic buffer is clocked by the Si5324, the other
|
||||
* by the RTM.
|
||||
* The elastic buffer can operate only when those two clocks are derived from
|
||||
* the same oscillator.
|
||||
* This is the case when either of those conditions is true:
|
||||
* (1) The DRTIO master and the RTM are clocked directly from a common external
|
||||
* source, *and* the Si5324 has locked to the recovered clock.
|
||||
* This clocking scheme provides less noise and phase drift at the DACs.
|
||||
* (2) The RTM clock is connected to the Si5324 output.
|
||||
* To handle those cases, we simply keep the JESD204 core in reset unless the
|
||||
* Si5324 is locked to the recovered clock.
|
||||
*/
|
||||
jdcg::jesd::reset(false);
|
||||
if repeaters[0].is_up() {
|
||||
let _ = jdcg::jdac::init();
|
||||
}
|
||||
}
|
||||
|
||||
drtioaux::reset(0);
|
||||
drtiosat_reset(false);
|
||||
drtiosat_reset_phy(false);
|
||||
|
||||
#[cfg(has_jdcg)]
|
||||
let mut rep0_was_up = repeaters[0].is_up();
|
||||
let mut was_up = false;
|
||||
while drtiosat_link_rx_up() {
|
||||
drtiosat_process_errors();
|
||||
process_aux_packets(&mut repeaters, &mut routing_table, &mut rank);
|
||||
|
@ -548,8 +536,14 @@ pub extern fn main() -> i32 {
|
|||
info!("TSC loaded from uplink");
|
||||
#[cfg(has_jdcg)]
|
||||
{
|
||||
if rep0_was_up {
|
||||
jdcg::jesd204sync::sysref_auto_align();
|
||||
// We assume that the RTM on repeater0 is up.
|
||||
// Uplink should not send a TSC load command unless the link is
|
||||
// up, and we are hiding when the RTM is down.
|
||||
if let Err(e) = jdcg::jesd204sync::sysref_rtio_align() {
|
||||
error!("failed to align SYSREF with TSC ({})", e);
|
||||
}
|
||||
if let Err(e) = jdcg::jesd204sync::resync_dacs() {
|
||||
error!("DAC resync failed after SYSREF/TSC realignment ({})", e);
|
||||
}
|
||||
}
|
||||
for rep in repeaters.iter() {
|
||||
|
@ -563,12 +557,29 @@ pub extern fn main() -> i32 {
|
|||
}
|
||||
#[cfg(has_jdcg)]
|
||||
{
|
||||
let rep0_is_up = repeaters[0].is_up();
|
||||
if rep0_is_up && !rep0_was_up {
|
||||
let is_up = repeaters[0].is_up();
|
||||
if is_up && !was_up {
|
||||
/*
|
||||
* One side of the JESD204 elastic buffer is clocked by the jitter filter
|
||||
* (Si5324 or WRPLL), the other by the RTM.
|
||||
* The elastic buffer can operate only when those two clocks are derived from
|
||||
* the same oscillator.
|
||||
* This is the case when either of those conditions is true:
|
||||
* (1) The DRTIO master and the RTM are clocked directly from a common external
|
||||
* source, *and* the jitter filter has locked to the recovered clock.
|
||||
* This clocking scheme may provide less noise and phase drift at the DACs.
|
||||
* (2) The RTM clock is connected to the jitter filter output.
|
||||
* To handle those cases, we simply keep the JESD204 core in reset unless the
|
||||
* jitter filter is locked to the recovered clock.
|
||||
*/
|
||||
jdcg::jesd::reset(false);
|
||||
let _ = jdcg::jdac::init();
|
||||
jdcg::jesd204sync::sysref_auto_align();
|
||||
unsafe {
|
||||
csr::drtio_transceiver::txenable_write(0xffffffffu32 as _); // unhide
|
||||
}
|
||||
}
|
||||
rep0_was_up = rep0_is_up;
|
||||
was_up = is_up;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ class ChannelInterface:
|
|||
class TransceiverInterface(AutoCSR):
|
||||
def __init__(self, channel_interfaces):
|
||||
self.stable_clkin = CSRStorage()
|
||||
self.txenable = CSRStorage(len(channel_interfaces))
|
||||
self.clock_domains.cd_rtio = ClockDomain()
|
||||
for i in range(len(channel_interfaces)):
|
||||
name = "rtio_rx" + str(i)
|
||||
|
|
|
@ -29,6 +29,7 @@ class GTHSingle(Module):
|
|||
|
||||
# # #
|
||||
|
||||
self.txenable = Signal()
|
||||
nwords = dw//10
|
||||
self.submodules.encoder = encoder = ClockDomainsRenamer("rtio_tx")(
|
||||
Encoder(nwords, True))
|
||||
|
@ -467,7 +468,6 @@ class GTHSingle(Module):
|
|||
i_GTREFCLK0=refclk,
|
||||
|
||||
# TX clock
|
||||
|
||||
o_TXOUTCLK=self.txoutclk,
|
||||
i_TXSYSCLKSEL=0b00,
|
||||
i_TXPLLCLKSEL=0b00,
|
||||
|
@ -487,7 +487,7 @@ class GTHSingle(Module):
|
|||
o_TXSYNCOUT=self.txsyncout,
|
||||
|
||||
# TX data
|
||||
|
||||
i_TXINHIBIT=~self.txenable,
|
||||
i_TXCTRL0=Cat(*[txdata[10*i+8] for i in range(nwords)]),
|
||||
i_TXCTRL1=Cat(*[txdata[10*i+9] for i in range(nwords)]),
|
||||
i_TXDATA=Cat(*[txdata[10*i:10*i+8] for i in range(nwords)]),
|
||||
|
@ -675,6 +675,8 @@ class GTH(Module, TransceiverInterface):
|
|||
self.submodules.tx_phase_alignment = GTHTXPhaseAlignement(self.gths)
|
||||
|
||||
TransceiverInterface.__init__(self, channel_interfaces)
|
||||
for n, gth in enumerate(self.gths):
|
||||
self.comb += gth.txenable.eq(self.txenable.storage[n])
|
||||
self.clock_domains.cd_rtiox = ClockDomain(reset_less=True)
|
||||
if create_buf:
|
||||
# GTH PLLs recover on their own from an interrupted clock input,
|
||||
|
|
|
@ -19,6 +19,7 @@ class GTPSingle(Module):
|
|||
# # #
|
||||
|
||||
self.stable_clkin = Signal()
|
||||
self.txenable = Signal()
|
||||
self.submodules.encoder = encoder = ClockDomainsRenamer("rtio_tx")(
|
||||
Encoder(2, True))
|
||||
self.submodules.decoders = decoders = [ClockDomainsRenamer("rtio_rx")(
|
||||
|
@ -611,7 +612,7 @@ class GTPSingle(Module):
|
|||
i_TXDEEMPH =0,
|
||||
i_TXDIFFCTRL =0b1000,
|
||||
i_TXDIFFPD =0,
|
||||
i_TXINHIBIT =0,
|
||||
i_TXINHIBIT =~self.txenable,
|
||||
i_TXMAINCURSOR =0b0000000,
|
||||
i_TXPISOPD =0,
|
||||
# Transmit Ports - TX Fabric Clock Output Control Ports
|
||||
|
@ -747,8 +748,11 @@ class GTP(Module, TransceiverInterface):
|
|||
self.submodules.tx_phase_alignment = GTPTXPhaseAlignement(self.gtps)
|
||||
|
||||
TransceiverInterface.__init__(self, channel_interfaces)
|
||||
for gtp in self.gtps:
|
||||
self.comb += gtp.stable_clkin.eq(self.stable_clkin.storage)
|
||||
for n, gtp in enumerate(self.gtps):
|
||||
self.comb += [
|
||||
gtp.stable_clkin.eq(self.stable_clkin.storage),
|
||||
gtp.txenable.eq(self.txenable.storage[n])
|
||||
]
|
||||
|
||||
self.comb += [
|
||||
self.cd_rtio.clk.eq(self.gtps[master].cd_rtio_tx.clk),
|
||||
|
|
Loading…
Reference in New Issue