forked from M-Labs/artiq
1
0
Fork 0

kusddrphy: use first and last tap that yield many valid reads

This commit is contained in:
Robert Jördens 2018-03-19 17:54:26 +00:00
parent ed2e0c8b34
commit 845784c180
1 changed files with 17 additions and 31 deletions

View File

@ -1,7 +1,6 @@
#[cfg(has_ddrphy)] #[cfg(has_ddrphy)]
mod ddr { mod ddr {
use core::{ptr, fmt}; use core::{ptr, fmt};
use core::cell::Cell;
use csr::{dfii, ddrphy}; use csr::{dfii, ddrphy};
use sdram_phy::{self, spin_cycles}; use sdram_phy::{self, spin_cycles};
use sdram_phy::{DFII_COMMAND_CS, DFII_COMMAND_WE, DFII_COMMAND_CAS, DFII_COMMAND_RAS, use sdram_phy::{DFII_COMMAND_CS, DFII_COMMAND_WE, DFII_COMMAND_CAS, DFII_COMMAND_RAS,
@ -317,13 +316,14 @@ mod ddr {
for n in 0..DQS_SIGNAL_COUNT { for n in 0..DQS_SIGNAL_COUNT {
ddrphy::dly_sel_write(1 << (DQS_SIGNAL_COUNT - n - 1)); ddrphy::dly_sel_write(1 << (DQS_SIGNAL_COUNT - n - 1));
ddrphy::rdly_dq_rst_write(1); let find_edge = |which| {
// Find the first (which=true) or last (which=false) tap that leads to a
let delay = Cell::new(0); // sufficiently high number of correct reads.
let incr_delay_until = |expected| { let mut last_valid = 0;
while delay.get() < DDRPHY_MAX_DELAY { ddrphy::rdly_dq_rst_write(1);
let mut working = true; for delay in 0..DDRPHY_MAX_DELAY {
for _ in 0..1024 { let mut valid = true;
for _ in 0..256 {
sdram_phy::command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS| sdram_phy::command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|
DFII_COMMAND_RDDATA); DFII_COMMAND_RDDATA);
spin_cycles(15); spin_cycles(15);
@ -333,40 +333,26 @@ mod ddr {
let addr = DFII_PIX_RDDATA_ADDR[p].offset(offset as isize); let addr = DFII_PIX_RDDATA_ADDR[p].offset(offset as isize);
let data = prs[DFII_PIX_DATA_SIZE * p + offset]; let data = prs[DFII_PIX_DATA_SIZE * p + offset];
if ptr::read_volatile(addr) as u8 != data { if ptr::read_volatile(addr) as u8 != data {
working = false; valid = false;
} }
} }
} }
} }
if working == expected { if valid {
break last_valid = delay;
if which {
break;
}
} }
delay.set(delay.get() + 1);
ddrphy::rdly_dq_inc_write(1); ddrphy::rdly_dq_inc_write(1);
} }
last_valid
}; };
// Find smallest working delay // Find smallest working delay
incr_delay_until(true); let min_delay = find_edge(true);
let min_delay = delay.get(); let max_delay = find_edge(false);
// Get a bit further into the working zone
#[cfg(kusddrphy)]
for _ in 0..32 {
delay.set(delay.get() + 1);
ddrphy::rdly_dq_inc_write(1);
}
#[cfg(not(kusddrphy))]
{
delay.set(delay.get() + 1);
ddrphy::rdly_dq_inc_write(1);
}
// Find largest working delay
incr_delay_until(false);
let max_delay = delay.get();
log!(logger, "{}:{:02}-{:02} ", DQS_SIGNAL_COUNT - n - 1, log!(logger, "{}:{:02}-{:02} ", DQS_SIGNAL_COUNT - n - 1,
min_delay, max_delay); min_delay, max_delay);