From bbac92442f5db6d12cf4a080c58d686e58226207 Mon Sep 17 00:00:00 2001
From: Sebastien Bourdeauducq <sb@m-labs.hk>
Date: Thu, 24 Jan 2019 20:13:43 +0800
Subject: [PATCH] sayma: check hmc7043 slip period

---
 artiq/firmware/libboard_artiq/hmc830_7043.rs |  8 +--
 artiq/firmware/libboard_artiq/jesd204sync.rs | 56 ++++++++++++++------
 2 files changed, 44 insertions(+), 20 deletions(-)

diff --git a/artiq/firmware/libboard_artiq/hmc830_7043.rs b/artiq/firmware/libboard_artiq/hmc830_7043.rs
index 8156c5d36..b3972d911 100644
--- a/artiq/firmware/libboard_artiq/hmc830_7043.rs
+++ b/artiq/firmware/libboard_artiq/hmc830_7043.rs
@@ -156,10 +156,10 @@ pub mod hmc7043 {
     use board_misoc::{csr, clock};
 
     // All frequencies assume 1.2GHz HMC830 output
-    const DAC_CLK_DIV: u16 = 1;               // 1200MHz
-    const FPGA_CLK_DIV: u16 = 8;              // 150MHz
-    const SYSREF_DIV: u16 = 128;              // 9.375MHz
-    const HMC_SYSREF_DIV: u16 = SYSREF_DIV*8; // 1.171875MHz (must be <= 4MHz)
+    pub const DAC_CLK_DIV: u16 = 1;               // 1200MHz
+    pub const FPGA_CLK_DIV: u16 = 8;              // 150MHz
+    pub const SYSREF_DIV: u16 = 128;              // 9.375MHz
+    const HMC_SYSREF_DIV: u16 = SYSREF_DIV*8;     // 1.171875MHz (must be <= 4MHz)
 
     // enabled, divider, output config
     const OUTPUT_CONFIG: [(bool, u16, u8); 14] = [
diff --git a/artiq/firmware/libboard_artiq/jesd204sync.rs b/artiq/firmware/libboard_artiq/jesd204sync.rs
index c4cc18810..8d66f81bc 100644
--- a/artiq/firmware/libboard_artiq/jesd204sync.rs
+++ b/artiq/firmware/libboard_artiq/jesd204sync.rs
@@ -67,6 +67,42 @@ fn sysref_cal_fpga() -> Result<u16, &'static str> {
     return Err("failed to reach 1->0 transition with fine delay");
 }
 
+fn sysref_rtio_slip_to(target: bool) -> Result<u16, &'static str> {
+    let mut slips = 0;
+    while sysref_sample() != target {
+        hmc7043::sysref_slip();
+        slips += 1;
+        if slips > 1024 {
+            return Err("failed to reach SYSREF transition");
+        }
+    }
+    Ok(slips)
+}
+
+fn sysref_rtio_check_period(phase_offset: u16) -> Result<(), &'static str> {
+    const N: usize = 32;
+    let mut nslips = [0; N];
+    let mut error = false;
+
+    // meet setup/hold (assuming FPGA timing margins are OK)
+    hmc7043::sysref_offset_fpga(phase_offset);
+    // if we are already in the 1 zone, get out of it
+    sysref_rtio_slip_to(false)?;
+    for i in 0..N {
+        nslips[i] = sysref_rtio_slip_to(i % 2 == 0)?;
+        if nslips[i] != hmc7043::SYSREF_DIV/2 {
+            error = true;
+        }
+    }
+    if error {
+        info!("  SYSREF slip half-periods: {:?}", nslips);
+        return Err("unexpected SYSREF slip half-periods seen");
+    } else {
+        info!("  SYSREF slip half-periods at FPGA have expected length ({})", hmc7043::SYSREF_DIV/2);
+    }
+    Ok(())
+}
+
 fn sysref_rtio_align(phase_offset: u16) -> Result<(), &'static str> {
     // This needs to take place before DAC SYSREF scan, as
     // the HMC7043 input clock (which defines slip resolution)
@@ -75,26 +111,14 @@ fn sysref_rtio_align(phase_offset: u16) -> Result<(), &'static str> {
 
     info!("aligning SYSREF with RTIO...");
 
-    let mut slips0 = 0;
-    let mut slips1 = 0;
+    sysref_rtio_check_period(phase_offset)?;
+
     // meet setup/hold (assuming FPGA timing margins are OK)
     hmc7043::sysref_offset_fpga(phase_offset);
     // if we are already in the 1 zone, get out of it
-    while sysref_sample() {
-        hmc7043::sysref_slip();
-        slips0 += 1;
-        if slips0 > 1024 {
-            return Err("failed to reach 1->0 transition");
-        }
-    }
+    let slips0 = sysref_rtio_slip_to(false)?;
     // get to the edge of the 0->1 transition (our final setpoint)
-    while !sysref_sample() {
-        hmc7043::sysref_slip();
-        slips1 += 1;
-        if slips1 > 1024 {
-            return Err("failed to reach 0->1 transition");
-        }
-    }
+    let slips1 = sysref_rtio_slip_to(true)?;
     info!("  ...done ({}/{} slips)", slips0, slips1);
 
     let mut margin_minus = None;