forked from M-Labs/artiq
kusddrphy: use first and last tap that yield many valid reads
This commit is contained in:
parent
ed2e0c8b34
commit
845784c180
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue