mirror of https://github.com/m-labs/artiq.git
firmware: clean up SYSREF phase management
This commit is contained in:
parent
05e908a0fd
commit
5a2a857a2f
|
@ -703,11 +703,11 @@ fn dac_sysref_scan(dacno: u8, center_phase: u16) {
|
||||||
|
|
||||||
info!("AD9154-{} SYSREF scan...", dacno);
|
info!("AD9154-{} SYSREF scan...", dacno);
|
||||||
|
|
||||||
hmc7043::cfg_dac_sysref(dacno, center_phase);
|
hmc7043::sysref_offset_dac(dacno, center_phase);
|
||||||
clock::spin_us(10000);
|
clock::spin_us(10000);
|
||||||
let mut sync_error_last = dac_get_sync_error(dacno);
|
let mut sync_error_last = dac_get_sync_error(dacno);
|
||||||
for d in 0..128 {
|
for d in 0..128 {
|
||||||
hmc7043::cfg_dac_sysref(dacno, center_phase - d);
|
hmc7043::sysref_offset_dac(dacno, center_phase - d);
|
||||||
clock::spin_us(10000);
|
clock::spin_us(10000);
|
||||||
let sync_error = dac_get_sync_error(dacno);
|
let sync_error = dac_get_sync_error(dacno);
|
||||||
if sync_error != sync_error_last {
|
if sync_error != sync_error_last {
|
||||||
|
@ -717,11 +717,11 @@ fn dac_sysref_scan(dacno: u8, center_phase: u16) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hmc7043::cfg_dac_sysref(dacno, center_phase);
|
hmc7043::sysref_offset_dac(dacno, center_phase);
|
||||||
clock::spin_us(10000);
|
clock::spin_us(10000);
|
||||||
sync_error_last = dac_get_sync_error(dacno);
|
sync_error_last = dac_get_sync_error(dacno);
|
||||||
for d in 0..128 {
|
for d in 0..128 {
|
||||||
hmc7043::cfg_dac_sysref(dacno, center_phase + d);
|
hmc7043::sysref_offset_dac(dacno, center_phase + d);
|
||||||
clock::spin_us(10000);
|
clock::spin_us(10000);
|
||||||
let sync_error = dac_get_sync_error(dacno);
|
let sync_error = dac_get_sync_error(dacno);
|
||||||
if sync_error != sync_error_last {
|
if sync_error != sync_error_last {
|
||||||
|
@ -743,12 +743,7 @@ fn dac_sysref_scan(dacno: u8, center_phase: u16) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dac_sysref_cfg(dacno: u8, phase: u16) {
|
fn init_dac(dacno: u8, sysref_phase: u16) -> Result<(), &'static str> {
|
||||||
info!("AD9154-{} setting SYSREF phase to {}", dacno, phase);
|
|
||||||
hmc7043::cfg_dac_sysref(dacno, phase);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn init_dac(dacno: u8) -> Result<(), &'static str> {
|
|
||||||
let dacno = dacno as u8;
|
let dacno = dacno as u8;
|
||||||
// Reset the DAC, detect and configure it
|
// Reset the DAC, detect and configure it
|
||||||
dac_reset(dacno);
|
dac_reset(dacno);
|
||||||
|
@ -757,15 +752,14 @@ fn init_dac(dacno: u8) -> Result<(), &'static str> {
|
||||||
// Run the PRBS, STPL and SYSREF scan tests
|
// Run the PRBS, STPL and SYSREF scan tests
|
||||||
dac_prbs(dacno)?;
|
dac_prbs(dacno)?;
|
||||||
dac_stpl(dacno, 4, 2)?;
|
dac_stpl(dacno, 4, 2)?;
|
||||||
let sysref_phase = 61;
|
|
||||||
dac_sysref_scan(dacno, sysref_phase);
|
dac_sysref_scan(dacno, sysref_phase);
|
||||||
// Set SYSREF phase and reconfigure the DAC
|
// Set SYSREF phase and reconfigure the DAC
|
||||||
dac_sysref_cfg(dacno, sysref_phase);
|
hmc7043::sysref_offset_dac(dacno, sysref_phase);
|
||||||
dac_cfg_retry(dacno)?;
|
dac_cfg_retry(dacno)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init() {
|
pub fn init(sysref_phase_fpga: u16, sysref_phase_dac: u16) {
|
||||||
// Release the JESD clock domain reset late, as we need to
|
// Release the JESD clock domain reset late, as we need to
|
||||||
// set up clock chips before.
|
// set up clock chips before.
|
||||||
jesd_unreset();
|
jesd_unreset();
|
||||||
|
@ -774,10 +768,12 @@ pub fn init() {
|
||||||
// the HMC7043 input clock (which defines slip resolution)
|
// the HMC7043 input clock (which defines slip resolution)
|
||||||
// is 2x the DAC clock, so there are two possible phases from
|
// is 2x the DAC clock, so there are two possible phases from
|
||||||
// the divider states. This deterministically selects one.
|
// the divider states. This deterministically selects one.
|
||||||
hmc7043::sysref_rtio_align();
|
hmc7043::sysref_rtio_align(sysref_phase_fpga);
|
||||||
|
|
||||||
for dacno in 0..csr::AD9154.len() {
|
for dacno in 0..csr::AD9154.len() {
|
||||||
match init_dac(dacno as u8) {
|
// We assume DCLK and SYSREF traces are matched on the PCB
|
||||||
|
// (they are on Sayma) so only one phase is needed.
|
||||||
|
match init_dac(dacno as u8, sysref_phase_dac) {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(e) => error!("failed to initialize AD9154-{}: {}", dacno, e)
|
Err(e) => error!("failed to initialize AD9154-{}: {}", dacno, e)
|
||||||
}
|
}
|
||||||
|
|
|
@ -318,13 +318,13 @@ pub mod hmc7043 {
|
||||||
info!(" ...done");
|
info!(" ...done");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cfg_dac_sysref(dacno: u8, phase: u16) {
|
pub fn sysref_offset_dac(dacno: u8, phase_offset: u16) {
|
||||||
/* Analog delay resolution: 25ps
|
/* Analog delay resolution: 25ps
|
||||||
* Digital delay resolution: 1/2 input clock cycle = 416ps for 1.2GHz
|
* Digital delay resolution: 1/2 input clock cycle = 416ps for 1.2GHz
|
||||||
* 16*25ps = 400ps: limit analog delay to 16 steps instead of 32.
|
* 16*25ps = 400ps: limit analog delay to 16 steps instead of 32.
|
||||||
*/
|
*/
|
||||||
let analog_delay = (phase % 17) as u8;
|
let analog_delay = (phase_offset % 17) as u8;
|
||||||
let digital_delay = (phase / 17) as u8;
|
let digital_delay = (phase_offset / 17) as u8;
|
||||||
spi_setup();
|
spi_setup();
|
||||||
if dacno == 0 {
|
if dacno == 0 {
|
||||||
write(0x00d5, analog_delay);
|
write(0x00d5, analog_delay);
|
||||||
|
@ -337,9 +337,9 @@ pub mod hmc7043 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cfg_fpga_sysref(phase: u16) {
|
fn sysref_offset_fpga(phase_offset: u16) {
|
||||||
let analog_delay = (phase % 17) as u8;
|
let analog_delay = (phase_offset % 17) as u8;
|
||||||
let digital_delay = (phase / 17) as u8;
|
let digital_delay = (phase_offset / 17) as u8;
|
||||||
spi_setup();
|
spi_setup();
|
||||||
write(0x0111, analog_delay);
|
write(0x0111, analog_delay);
|
||||||
write(0x0112, digital_delay);
|
write(0x0112, digital_delay);
|
||||||
|
@ -355,15 +355,13 @@ pub mod hmc7043 {
|
||||||
unsafe { csr::sysref_sampler::sample_result_read() == 1 }
|
unsafe { csr::sysref_sampler::sample_result_read() == 1 }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sysref_rtio_align() {
|
pub fn sysref_rtio_align(phase_offset: u16) {
|
||||||
info!("aligning SYSREF with RTIO...");
|
info!("aligning SYSREF with RTIO...");
|
||||||
|
|
||||||
let phase_offset = 44;
|
|
||||||
let mut slips0 = 0;
|
let mut slips0 = 0;
|
||||||
let mut slips1 = 0;
|
let mut slips1 = 0;
|
||||||
|
|
||||||
// meet setup/hold (assuming FPGA timing margins are OK)
|
// meet setup/hold (assuming FPGA timing margins are OK)
|
||||||
cfg_fpga_sysref(phase_offset);
|
sysref_offset_fpga(phase_offset);
|
||||||
// if we are already in the 1 zone, get out of it
|
// if we are already in the 1 zone, get out of it
|
||||||
while sysref_sample() {
|
while sysref_sample() {
|
||||||
sysref_slip();
|
sysref_slip();
|
||||||
|
@ -374,12 +372,11 @@ pub mod hmc7043 {
|
||||||
sysref_slip();
|
sysref_slip();
|
||||||
slips1 += 1;
|
slips1 += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
info!(" ...done ({}/{} slips), verifying timing margin", slips0, slips1);
|
info!(" ...done ({}/{} slips), verifying timing margin", slips0, slips1);
|
||||||
|
|
||||||
let mut margin = None;
|
let mut margin = None;
|
||||||
for d in 0..phase_offset {
|
for d in 0..phase_offset {
|
||||||
cfg_fpga_sysref(phase_offset - d);
|
sysref_offset_fpga(phase_offset - d);
|
||||||
if !sysref_sample() {
|
if !sysref_sample() {
|
||||||
margin = Some(d);
|
margin = Some(d);
|
||||||
break;
|
break;
|
||||||
|
@ -387,7 +384,7 @@ pub mod hmc7043 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// meet setup/hold
|
// meet setup/hold
|
||||||
cfg_fpga_sysref(phase_offset);
|
sysref_offset_fpga(phase_offset);
|
||||||
|
|
||||||
if margin.is_some() {
|
if margin.is_some() {
|
||||||
let margin = margin.unwrap();
|
let margin = margin.unwrap();
|
||||||
|
|
|
@ -109,7 +109,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();
|
board_artiq::ad9154::init(44, 61);
|
||||||
#[cfg(has_allaki_atts)]
|
#[cfg(has_allaki_atts)]
|
||||||
board_artiq::hmc542::program_all(8/*=4dB*/);
|
board_artiq::hmc542::program_all(8/*=4dB*/);
|
||||||
|
|
||||||
|
|
|
@ -262,7 +262,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();
|
board_artiq::ad9154::init(32, 61);
|
||||||
#[cfg(has_allaki_atts)]
|
#[cfg(has_allaki_atts)]
|
||||||
board_artiq::hmc542::program_all(8/*=4dB*/);
|
board_artiq::hmc542::program_all(8/*=4dB*/);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue