forked from M-Labs/artiq
sdram: clean up, make read_level robust to wrap around
* fix a few rust warnings * also do eye scans on kintex
This commit is contained in:
parent
3abb378fbe
commit
6fb0cbfcd3
|
@ -30,18 +30,19 @@ mod ddr {
|
||||||
ddrphy::wlevel_en_write(enabled as u8);
|
ddrphy::wlevel_en_write(enabled as u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(kusddrphy)]
|
#[cfg(ddrphy_wlevel)]
|
||||||
unsafe fn write_level_scan(logger: &mut Option<&mut fmt::Write>) {
|
unsafe fn write_level_scan(logger: &mut Option<&mut fmt::Write>) {
|
||||||
|
#[cfg(kusddrphy)]
|
||||||
log!(logger, "DQS initial delay: {} taps\n", ddrphy::wdly_dqs_taps_read());
|
log!(logger, "DQS initial delay: {} taps\n", ddrphy::wdly_dqs_taps_read());
|
||||||
log!(logger, "Write leveling scan:\n");
|
log!(logger, "Write leveling scan:\n");
|
||||||
|
|
||||||
enable_write_leveling(true);
|
enable_write_leveling(true);
|
||||||
spin_cycles(100);
|
spin_cycles(100);
|
||||||
|
|
||||||
let mut ddrphy_max_delay : u16 = DDRPHY_MAX_DELAY;
|
#[cfg(not(kusddrphy))]
|
||||||
#[cfg(kusddrphy)] {
|
let ddrphy_max_delay : u16 = DDRPHY_MAX_DELAY;
|
||||||
ddrphy_max_delay -= ddrphy::wdly_dqs_taps_read();
|
#[cfg(kusddrphy)]
|
||||||
}
|
let ddrphy_max_delay : u16 = DDRPHY_MAX_DELAY - ddrphy::wdly_dqs_taps_read();
|
||||||
|
|
||||||
for n in 0..DQS_SIGNAL_COUNT {
|
for n in 0..DQS_SIGNAL_COUNT {
|
||||||
let dq_addr = dfii::PI0_RDDATA_ADDR
|
let dq_addr = dfii::PI0_RDDATA_ADDR
|
||||||
|
@ -91,10 +92,10 @@ mod ddr {
|
||||||
enable_write_leveling(true);
|
enable_write_leveling(true);
|
||||||
spin_cycles(100);
|
spin_cycles(100);
|
||||||
|
|
||||||
let mut ddrphy_max_delay : u16 = DDRPHY_MAX_DELAY;
|
#[cfg(not(kusddrphy))]
|
||||||
#[cfg(kusddrphy)] {
|
let ddrphy_max_delay : u16 = DDRPHY_MAX_DELAY;
|
||||||
ddrphy_max_delay -= ddrphy::wdly_dqs_taps_read();
|
#[cfg(kusddrphy)]
|
||||||
}
|
let ddrphy_max_delay : u16 = DDRPHY_MAX_DELAY - ddrphy::wdly_dqs_taps_read();
|
||||||
|
|
||||||
let mut failed = false;
|
let mut failed = false;
|
||||||
for n in 0..DQS_SIGNAL_COUNT {
|
for n in 0..DQS_SIGNAL_COUNT {
|
||||||
|
@ -202,7 +203,6 @@ mod ddr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(kusddrphy)]
|
|
||||||
unsafe fn read_level_scan(logger: &mut Option<&mut fmt::Write>) {
|
unsafe fn read_level_scan(logger: &mut Option<&mut fmt::Write>) {
|
||||||
log!(logger, "Read leveling scan:\n");
|
log!(logger, "Read leveling scan:\n");
|
||||||
|
|
||||||
|
@ -280,7 +280,7 @@ mod ddr {
|
||||||
spin_cycles(15);
|
spin_cycles(15);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn read_level(logger: &mut Option<&mut fmt::Write>) {
|
unsafe fn read_level(logger: &mut Option<&mut fmt::Write>) -> bool {
|
||||||
log!(logger, "Read leveling: ");
|
log!(logger, "Read leveling: ");
|
||||||
|
|
||||||
// Generate pseudo-random sequence
|
// Generate pseudo-random sequence
|
||||||
|
@ -316,13 +316,15 @@ 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));
|
||||||
|
|
||||||
// Find the first (which=true) or last (which=false) tap that leads to a
|
// Find the first (min_delay) and last (max_delay) tap that bracket
|
||||||
// sufficiently high number of correct reads.
|
// the largest tap interval of correct reads.
|
||||||
let mut min_delay = 0;
|
let mut min_delay = 0;
|
||||||
let mut have_min_delay = false;
|
|
||||||
let mut max_delay = 0;
|
let mut max_delay = 0;
|
||||||
let mut have_max_delay = false;
|
|
||||||
let mut have_invalid = 0;
|
let mut first_valid = 0;
|
||||||
|
let mut seen_valid = 0;
|
||||||
|
let mut seen_invalid = 0;
|
||||||
|
let mut max_seen_valid = 0;
|
||||||
|
|
||||||
ddrphy::rdly_dq_rst_write(1);
|
ddrphy::rdly_dq_rst_write(1);
|
||||||
|
|
||||||
|
@ -345,22 +347,37 @@ mod ddr {
|
||||||
}
|
}
|
||||||
|
|
||||||
if valid {
|
if valid {
|
||||||
if !have_min_delay {
|
if seen_valid == 0 {
|
||||||
min_delay = delay;
|
first_valid = delay;
|
||||||
have_min_delay = true;
|
|
||||||
}
|
}
|
||||||
if !have_max_delay {
|
seen_valid += 1;
|
||||||
|
seen_invalid = 0;
|
||||||
|
if seen_valid > max_seen_valid {
|
||||||
|
min_delay = first_valid;
|
||||||
max_delay = delay;
|
max_delay = delay;
|
||||||
|
max_seen_valid = seen_valid;
|
||||||
}
|
}
|
||||||
} else if have_min_delay {
|
} else {
|
||||||
have_invalid += 1;
|
seen_invalid += 1;
|
||||||
if have_invalid >= 10 {
|
if seen_invalid >= DDRPHY_MAX_DELAY / 8 {
|
||||||
have_max_delay = true;
|
seen_valid = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ddrphy::rdly_dq_inc_write(1);
|
ddrphy::rdly_dq_inc_write(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if max_delay <= min_delay {
|
||||||
|
log!(logger, "Zero window: {}: {}-{}\n",
|
||||||
|
DQS_SIGNAL_COUNT - n - 1, min_delay, max_delay);
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if max_seen_valid <= 5 {
|
||||||
|
log!(logger, "Small window: {}: {}-{} ({})\n",
|
||||||
|
DQS_SIGNAL_COUNT - n - 1, min_delay, max_delay,
|
||||||
|
max_seen_valid);
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
let mean_delay = (min_delay + max_delay) / 2;
|
let mean_delay = (min_delay + max_delay) / 2;
|
||||||
log!(logger, "{}: {} ({} wide), ",
|
log!(logger, "{}: {} ({} wide), ",
|
||||||
DQS_SIGNAL_COUNT - n - 1, mean_delay,
|
DQS_SIGNAL_COUNT - n - 1, mean_delay,
|
||||||
|
@ -380,6 +397,7 @@ mod ddr {
|
||||||
spin_cycles(15);
|
spin_cycles(15);
|
||||||
|
|
||||||
log!(logger, "done\n");
|
log!(logger, "done\n");
|
||||||
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn level(logger: &mut Option<&mut fmt::Write>) -> bool {
|
pub unsafe fn level(logger: &mut Option<&mut fmt::Write>) -> bool {
|
||||||
|
@ -387,7 +405,6 @@ mod ddr {
|
||||||
{
|
{
|
||||||
let mut delay = [0; DQS_SIGNAL_COUNT];
|
let mut delay = [0; DQS_SIGNAL_COUNT];
|
||||||
let mut high_skew = [false; DQS_SIGNAL_COUNT];
|
let mut high_skew = [false; DQS_SIGNAL_COUNT];
|
||||||
#[cfg(kusddrphy)]
|
|
||||||
write_level_scan(logger);
|
write_level_scan(logger);
|
||||||
if !write_level(logger, &mut delay, &mut high_skew) {
|
if !write_level(logger, &mut delay, &mut high_skew) {
|
||||||
return false
|
return false
|
||||||
|
@ -395,9 +412,10 @@ mod ddr {
|
||||||
read_bitslip(logger, &delay, &high_skew);
|
read_bitslip(logger, &delay, &high_skew);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(kusddrphy)]
|
|
||||||
read_level_scan(logger);
|
read_level_scan(logger);
|
||||||
read_level(logger);
|
if !read_level(logger) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue