Commit 6989d804 authored by Andrey Filippov's avatar Andrey Filippov

working on DQS+DQ inpute delays adjustment

parent 4f1a1c28
...@@ -45,6 +45,10 @@ from x393_mcntrl_buffers import X393McntrlBuffers ...@@ -45,6 +45,10 @@ from x393_mcntrl_buffers import X393McntrlBuffers
#from x393_axi_control_status import concat, bits #from x393_axi_control_status import concat, bits
#from time import sleep #from time import sleep
from verilog_utils import checkIntArgs,smooth2d from verilog_utils import checkIntArgs,smooth2d
import get_test_dq_dqs_data # temporary to test processing
import x393_lma
#import vrlg #import vrlg
NUM_FINE_STEPS= 5 NUM_FINE_STEPS= 5
...@@ -210,16 +214,18 @@ class X393McntrlAdjust(object): ...@@ -210,16 +214,18 @@ class X393McntrlAdjust(object):
low_delay, low_delay,
high_delay, high_delay,
num=8, num=8,
sel=1, # 0 - early, 1 - late read command (shift by a SDCLK period)
quiet=2 ): quiet=2 ):
""" """
Scan DQS input delay values using pattern read mode Scan DQS input delay values using pattern read mode
<low_delay> low delay value (in 'hardware' format, sparse) <low_delay> low delay value (in 'hardware' format, sparse)
<high_delay> high delay value (in 'hardware' format, sparse) <high_delay> high delay value (in 'hardware' format, sparse)
<num> number of 64-bit words to process <num> number of 64-bit words to process
<sel> 0 - early, 1 - late read command (shift by a SDCLK period)
<quiet> less output <quiet> less output
""" """
checkIntArgs(('low_delay','high_delay','num'),locals()) checkIntArgs(('low_delay','high_delay','num'),locals())
self.x393_pio_sequences.set_read_pattern(num+1) # do not use first/last pair of the 32 bit words self.x393_pio_sequences.set_read_pattern(num+1,sel) # do not use first/last pair of the 32 bit words
low = self.split_delay(low_delay) low = self.split_delay(low_delay)
high = self.split_delay(high_delay) high = self.split_delay(high_delay)
results = [] results = []
...@@ -286,16 +292,18 @@ class X393McntrlAdjust(object): ...@@ -286,16 +292,18 @@ class X393McntrlAdjust(object):
low_delay, low_delay,
high_delay, high_delay,
num=8, num=8,
sel=1,# 0 - early, 1 - late read command (shift by a SDCLK period)
quiet=2 ): quiet=2 ):
""" """
Scan DQ input delay values using pattern read mode Scan DQ input delay values using pattern read mode
<low_delay> low delay value (in 'hardware' format, sparse) <low_delay> low delay value (in 'hardware' format, sparse)
<high_delay> high delay value (in 'hardware' format, sparse) <high_delay> high delay value (in 'hardware' format, sparse)
<num> number of 64-bit words to process <num> number of 64-bit words to process
<sel> 0 - early, 1 - late read command (shift by a SDCLK period)
<quiet> less output <quiet> less output
""" """
checkIntArgs(('low_delay','high_delay','num'),locals()) checkIntArgs(('low_delay','high_delay','num'),locals())
self.x393_pio_sequences.set_read_pattern(num+1) # do not use first/last pair of the 32 bit words self.x393_pio_sequences.set_read_pattern(num+1,sel) # do not use first/last pair of the 32 bit words
low = self.split_delay(low_delay) low = self.split_delay(low_delay)
high = self.split_delay(high_delay) high = self.split_delay(high_delay)
results = [] results = []
...@@ -363,6 +371,7 @@ class X393McntrlAdjust(object): ...@@ -363,6 +371,7 @@ class X393McntrlAdjust(object):
low_delay, low_delay,
high_delay, high_delay,
num=8, num=8,
sel=1, # 0 - early, 1 - late read command (shift by a SDCLK period)
falling=0, # 0 - use rising as delay increases, 1 - use falling falling=0, # 0 - use rising as delay increases, 1 - use falling
smooth=10, smooth=10,
quiet=2): quiet=2):
...@@ -372,6 +381,7 @@ class X393McntrlAdjust(object): ...@@ -372,6 +381,7 @@ class X393McntrlAdjust(object):
<low_delay> low delay value (in 'hardware' format, sparse) <low_delay> low delay value (in 'hardware' format, sparse)
<high_delay> high delay value (in 'hardware' format, sparse) <high_delay> high delay value (in 'hardware' format, sparse)
<num> number of 64-bit words to process <num> number of 64-bit words to process
<sel> 0 - early, 1 - late read command (shift by a SDCLK period)
<falling> 0 - use rising edge as delay increases, 1 - use falling one <falling> 0 - use rising edge as delay increases, 1 - use falling one
In 'falling' mode results are the longest DQ idelay In 'falling' mode results are the longest DQ idelay
when bits switch from correct to incorrect, when bits switch from correct to incorrect,
...@@ -382,7 +392,7 @@ class X393McntrlAdjust(object): ...@@ -382,7 +392,7 @@ class X393McntrlAdjust(object):
""" """
checkIntArgs(('low_delay','high_delay','num'),locals()) checkIntArgs(('low_delay','high_delay','num'),locals())
low = self.split_delay(low_delay) low = self.split_delay(low_delay)
data_raw=self.scan_dq_idelay(low_delay,high_delay,num,quiet) data_raw=self.scan_dq_idelay(low_delay,high_delay,num,sel,quiet)
data=[] data=[]
delays=[] delays=[]
for i,d in enumerate(data_raw): for i,d in enumerate(data_raw):
...@@ -1318,7 +1328,7 @@ class X393McntrlAdjust(object): ...@@ -1318,7 +1328,7 @@ class X393McntrlAdjust(object):
quiet=1 quiet=1
): ):
""" """
Find DQS odelay for each phase value Find DQS output delay for each phase value
Depends on adjust_cmda_odelay results Depends on adjust_cmda_odelay results
""" """
if not self.adjustment_state['cmda_bspe']: if not self.adjustment_state['cmda_bspe']:
...@@ -1643,4 +1653,359 @@ class X393McntrlAdjust(object): ...@@ -1643,4 +1653,359 @@ class X393McntrlAdjust(object):
self.adjustment_state.update(rdict) self.adjustment_state.update(rdict)
# print (self.adjustment_state) # print (self.adjustment_state)
return rdict return rdict
def adjust_pattern(self,
limit_step=0.125, # initial delay step as a fraction of the period
max_phase_err=0.1,
quiet=1,
start_dly=0): #just to check dependence
"""
for each DQS input delay find 4 DQ transitions for each DQ bit,
then use them to find finedelay for each of the DQS and DQ,
linear coefficients (a,b) for each DQ vs DQS and asymmetry
(late 0->1, early 1->0) for each of the DQ and DQS
"""
nrep=8
max_lin_dly=159
timing=self.x393_mcntrl_timing.get_dly_steps()
#steps={'DLY_FINE_STEP': 0.01, 'DLY_STEP': 0.078125, 'PHASE_STEP': 0.022321428571428572, 'SDCLK_PERIOD': 2.5}
dly_step=int(5*limit_step*timing['SDCLK_PERIOD']/timing['DLY_STEP']+0.5)
step180= int(5*0.5* timing['SDCLK_PERIOD'] / timing['DLY_STEP'] +0.5)
if quiet<2:
print ("timing)=%s, dly_step=%d step180=%d"%(str(timing),dly_step,step180))
self.x393_pio_sequences.set_read_pattern(nrep+3) # set sequence once
def patt_dqs_step(dqs_lin):
patt_cache=[None]*(max_lin_dly+1) # cache for holding already measured delays
def measure_patt(dly,force_meas=False):
if (patt_cache[dly] is None) or force_meas:
self.x393_mcntrl_timing.axi_set_dq_idelay(self.combine_delay(dly),quiet=quiet)
patt= self.x393_pio_sequences.read_levelling(nrep,
-1, # sel=1, # 0 - early, 1 - late read command (shift by a SDCLK period), -1 - use current sequence
quiet+1)
patt_cache[dly]=patt
if quiet < 1:
print ('measure_patt(%d,%s) - new measurement'%(dly,str(force_meas)))
else:
patt=patt_cache[dly]
if quiet < 1:
print ('measure_patt(%d,%s) - using cache'%(dly,str(force_meas)))
return patt
def get_sign(data,edge=None):
"""
edge: 0 - first 16, 1 - second 16
return -1 if all <0.5
return +1 if all >0.5
return 0 otherwise
"""
if edge == 0:
return get_sign(data[:16])
if edge == 1:
# return -get_sign(data[16:])
return get_sign(data[16:])
m1=True
p1=True
for d in data:
m1 &= (d < 0.5)
p1 &= (d > 0.5)
if not (m1 or p1):
break
else:
if m1:
return -1
elif p1:
return 1
return 0
rslt=[None]*16 # each bit will have [inphase][dqs_falling]
self.x393_mcntrl_timing.axi_set_dqs_idelay(self.combine_delay(dqs_lin),quiet=quiet)
d_low=[None]*2 # first - lowest when all are -+, second - when all are +-
d_high=[None]*2 # first - when all are +- after -+, second - when all are -+ after +-
dly=0
notLast=True
needSigns=None
lowGot=None
highGot=None
while (dly <= max_lin_dly) and notLast:
notLast= dly < max_lin_dly
patt=measure_patt(dly) # ,force_meas=False)
signs=(get_sign(patt,0),get_sign(patt,1))
if quiet < 1:
print ('dly=%d lowGot=%s, highGot=%s, signs=%s'%(dly,str(lowGot),str(highGot),str(signs)))
if lowGot is None : # looking for the first good sample
if (signs==(-1,1)) or (signs==(1,-1)) :
if signs[0] == -1: # == (-1,1):
lowGot=0
else:
lowGot=1
d_low[lowGot] = dly
needSigns=((1,-1),(-1,1))[lowGot]
dly += step180-dly_step # almost 180 degrees
else: # at least one is 0
dly += dly_step # small step
if quiet < 1:
print ('lowGot was None : dly=%d, lowGot=%s, needSigns=%s'%(dly,str(lowGot),str(needSigns)))
elif highGot is None : # only one good sample is available so far
if signs == needSigns:
highGot=lowGot
d_high[highGot] = dly
d_low[1-lowGot] = dly
needSigns=((-1,1),(1,-1))[lowGot]
dly += step180-dly_step # almost 180 degrees
else:
dly += dly_step # small step
if quiet < 1:
print ('highGot was None : dly=%d, lowGot=%s, highGot=%s, needSigns=%s'%(dly,str(lowGot),str(lowGot),str(needSigns)))
else: # looking for the 3-rd sample
if signs == needSigns:
highGot=1-highGot
d_high[highGot] = dly
break
else:
dly += dly_step # small step
dly = min (dly,max_lin_dly)
if highGot is None:
if quiet < 3:
print ("Could not find initial bounds for DQS input delay = %d d_low=%s, d_high=%s"%(dqs_lin,str(d_low),str(d_high)))
return None
if quiet < 2:
print ("DQS input delay = %d , preliminary bounds: d_low=%s, d_high=%s"%(dqs_lin,str(d_low),str(d_high)))
for inPhase in range(2):
if not d_high[inPhase] is None:
# Try to squeeze d_low, d_high closer to reduce scan range
while d_high[inPhase]>d_low[inPhase]:
dly=(d_high[inPhase] + d_low[inPhase])//2
patt=measure_patt(dly) # ,force_meas=False)
signs=(get_sign(patt,0),get_sign(patt,1))
if signs==(-1,1):
if inPhase:
d_high[inPhase]=dly
else:
if d_low[inPhase]==dly:
break
d_low[inPhase]=dly
elif signs==(1,-1):
if inPhase:
if d_low[inPhase]==dly:
break
d_low[inPhase]=dly
else:
d_high[inPhase]=dly
else: # uncertain result
break
if quiet < 2:
print ("DQS input delay = %d , squeezed bounds: d_low=%s, d_high=%s"%(dqs_lin,str(d_low),str(d_high)))
#Improve squeezing - each limit to the last
for inPhase in range(2):
if not d_high[inPhase] is None:
# Try to squeeze d_low first
d_uncertain=d_high[inPhase]
while d_uncertain > d_low[inPhase]:
dly=(d_uncertain + d_low[inPhase])//2
patt=measure_patt(dly) # ,force_meas=False)
signs=(get_sign(patt,0),get_sign(patt,1))
if signs==(-1,1):
if inPhase:
d_uncertain=dly
else:
if d_low[inPhase]==dly:
break
d_low[inPhase]=dly
elif signs==(1,-1):
if inPhase:
if d_low[inPhase]==dly:
break
d_low[inPhase]=dly
else:
d_uncertain=dly
else: # uncertain result
d_uncertain=dly
#now udjust upper limit
while d_high[inPhase] > d_uncertain:
dly=(d_high[inPhase] + d_uncertain)//2
patt=measure_patt(dly) # ,force_meas=False)
signs=(get_sign(patt,0),get_sign(patt,1))
if signs==(-1,1):
if inPhase:
d_high[inPhase]=dly
else:
if d_uncertain==dly:
break
d_uncertain=dly
elif signs==(1,-1):
if inPhase:
if d_uncertain==dly:
break
d_uncertain=dly
else:
d_high[inPhase]=dly
else: # uncertain result
if d_uncertain==dly:
break
d_uncertain=dly
if quiet < 2:
print ("DQS input delay = %d , tight squeezed bounds: d_low=%s, d_high=%s"%(dqs_lin,str(d_low),str(d_high)))
# scan ranges, find closest solutions
best_dly= [[],[]]
best_diff=[[],[]]
for inPhase in range(2):
if not d_high[inPhase] is None:
patt=None
for dly in range(d_low[inPhase],d_high[inPhase]+1):
patt_prev=patt
patt=measure_patt(dly) # ,force_meas=False) - will be stored in cache
if patt_prev is None: #first run
best_dly[inPhase]=[d_low[inPhase]]*32
for p in patt:
best_diff[inPhase].append(p-0.5)
else: # all the rest
for b in range(32):
positiveJump=((not inPhase) and (b<16)) or (inPhase and (b >= 16)) # may be 0, False, True
signs=((-1,1)[patt_prev[b]>0.5],(-1,1)[patt[b]>0.5])
if (positiveJump and (signs==(-1,1))) or (not positiveJump and (signs==(1,-1))):
if abs(patt_prev[b]-0.5) < abs(patt[b]-0.5): # store previos sample
best_dly[inPhase][b]=dly-1
best_diff[inPhase][b]=patt_prev[b]-0.5
else:
best_dly[inPhase][b]=dly
best_diff[inPhase][b]=patt[b]-0.5
if not positiveJump:
best_diff[inPhase][b] *= -1 # inver sign, so sign always means <0 - delay too low, >0 - too high
# rslt=[None]*16 # each bit will have [inphase][dqs_falling], each - a pair of (delay,diff)
for b in range(16):
rslt[b]=[[None]*2,[None]*2] # [inphase][dqs_falling]
for inPhase in range(2):
if not d_high[inPhase] is None:
rslt[b][inPhase]= [(best_dly[inPhase][b],best_diff[inPhase][b]),(best_dly[inPhase][b+16],best_diff[inPhase][b+16])]
if quiet < 2:
print ("%d: rslt=%s"%(dqs_lin,str(rslt)))
return rslt
# meas_data=[]
# for ldly in range(max_lin_dly+1):
# if quiet <3:
# print ("%d(0x%x):"%(ldly,self.combine_delay(ldly)),end=" ")
# sys.stdout.flush()
# meas_data.append(patt_dqs_step(ldly))
# if quiet <3:
# print ()
meas_data=[None]*(max_lin_dly+1)
#start_dly
for sdly in range(max_lin_dly+1):
ldly = (start_dly+sdly)%(max_lin_dly+1)
# for ldly in range(max_lin_dly+1):
if quiet <3:
print ("%d(0x%x):"%(ldly,self.combine_delay(ldly)),end=" ")
sys.stdout.flush()
meas_data[ldly] = patt_dqs_step(ldly)
if quiet <3:
print ()
if quiet < 3:
print ("DQS",end=" ")
for f in ('ir','if','or','of'):
for b in range (16):
print ("%s_%d"%(f,b),end=" ")
print()
for ldly, data in enumerate(meas_data):
print("%d"%ldly,end=" ")
if data:
for typ in ((0,0),(0,1),(1,0),(1,1)):
for pData in data: # 16 DQs, each None nor a pair of lists for inPhase in (0,1), each a pair of edges, each a pair of (dly,diff)
if pData:
if pData[typ[0]] and pData[typ[0]][typ[1]]:
print ("%d"%pData[typ[0]][typ[1]][0],end=" ")
'''
try:
print ("%d"%pData[typ[0]][typ[1]][0],end=" ")
except:
print (".", end=" ")
'''
else:
print ("?", end=" ")
else:
print ("x",end=" ")
print()
if quiet < 2:
print ("\nDifferences from 0.5:")
print ("DQS",end=" ")
for f in ('ir','if','or','of'):
for b in range (16):
print ("%s_%d"%(f,b),end=" ")
print()
for ldly, data in enumerate(meas_data):
print("%d"%ldly,end=" ")
if data:
for typ in ((0,0),(0,1),(1,0),(1,1)):
for pData in data: # 16 DQs, each None nor a pair of lists for inPhase in (0,1), each a pair of edges, each a pair of (dly,diff)
if pData:
if pData[typ[0]] and pData[typ[0]][typ[1]]:
print ("%.2f"%pData[typ[0]][typ[1]][1],end=" ")
'''
try:
print ("%d"%pData[typ[0]][typ[1]][0],end=" ")
except:
print (".", end=" ")
'''
else:
print ("?", end=" ")
else:
print ("x",end=" ")
print()
print("\n\n")
# print ("meas_data=%s"%str(meas_data))
print ("meas_data=[")
for d in meas_data:
print("%s,"%(str(d)))
print("]")
#meas_data=[
'''
adjust_cmda_odelay 0 1 0.1 3
adjust_write_levelling 0 1 0 .1 3
adjust_pattern 0.125 0.1 1
'''
def proc_test_data(self,
lane=0,
bin_size=5,
primary_set=2,
quiet=1):
meas_data=get_test_dq_dqs_data.get_data()
meas_delays=[]
for data in meas_data:
if data:
bits=[None]*16
for b,pData in enumerate(data):
if pData:
"""
bits[b]=[[None,None],[None,None]]
for inPhase in (0,1):
if pData[inPhase]:
for e in (0,1):
if pData[inPhase][e]:
bits[b][inPhase][e]=pData[inPhase][e][0]
"""
bits[b]=[None]*4
for inPhase in (0,1):
if pData[inPhase]:
for e in (0,1):
if pData[inPhase][e]:
bits[b][inPhase*2+e]=pData[inPhase][e][0]
meas_delays.append(bits)
if quiet<1:
x393_lma.test_data(meas_delays,quiet)
lma=x393_lma.X393LMA()
lma.init_parameters(
lane,
bin_size,
2500.0, # clk_period,
78.0, # dly_step_ds,
primary_set,
meas_delays,
quiet)
\ No newline at end of file
...@@ -178,12 +178,14 @@ class X393McntrlTiming(object): ...@@ -178,12 +178,14 @@ class X393McntrlTiming(object):
self.axi_set_phase() self.axi_set_phase()
def axi_set_dq_idelay(self, # sets same delay to all dq idelay def axi_set_dq_idelay(self, # sets same delay to all dq idelay
delay=None): # input [7:0] delay; delay=None, # input [7:0] delay;
quiet=1):
""" """
Set all DQ input delays to the same value Set all DQ input delays to the same value
<delay> 8-bit (5+3) delay value to use or a tuple/list with a pair for (lane0, lane1) <delay> 8-bit (5+3) delay value to use or a tuple/list with a pair for (lane0, lane1)
Each of the two elements in the delay tuple/list may be a a common integer or a list/tuple itself Each of the two elements in the delay tuple/list may be a a common integer or a list/tuple itself
if delay is None will restore default values if delay is None will restore default values
<quiet> reduce output
""" """
# print("====axi_set_dq_idelay %s"%str(delay)) # print("====axi_set_dq_idelay %s"%str(delay))
...@@ -194,7 +196,7 @@ class X393McntrlTiming(object): ...@@ -194,7 +196,7 @@ class X393McntrlTiming(object):
delay[1].append(vrlg.get_default_field("DLY_LANE1_IDELAY",i)) delay[1].append(vrlg.get_default_field("DLY_LANE1_IDELAY",i))
if isinstance(delay,(int,long)): if isinstance(delay,(int,long)):
delay=(delay,delay) delay=(delay,delay)
if self.DEBUG_MODE > 1: if quiet < 2:
print("SET DQ IDELAY="+hexMultiple(delay)) # hexMultiple print("SET DQ IDELAY="+hexMultiple(delay)) # hexMultiple
self.axi_set_multiple_delays(vrlg.LD_DLY_LANE0_IDELAY, 0, 8, delay[0], "DLY_LANE0_IDELAY") self.axi_set_multiple_delays(vrlg.LD_DLY_LANE0_IDELAY, 0, 8, delay[0], "DLY_LANE0_IDELAY")
self.axi_set_multiple_delays(vrlg.LD_DLY_LANE1_IDELAY, 0, 8, delay[1], "DLY_LANE1_IDELAY") self.axi_set_multiple_delays(vrlg.LD_DLY_LANE1_IDELAY, 0, 8, delay[1], "DLY_LANE1_IDELAY")
......
...@@ -610,12 +610,14 @@ class X393PIOSequences(object): ...@@ -610,12 +610,14 @@ class X393PIOSequences(object):
# Set MR3, read nrep*8 words, save to buffer (port0). No ACTIVATE/PRECHARGE are needed/allowed # Set MR3, read nrep*8 words, save to buffer (port0). No ACTIVATE/PRECHARGE are needed/allowed
def set_read_pattern (self, def set_read_pattern (self,
nrep, # input integer nrep; nrep, # input integer nrep;
sel=1, # 0 - early, 1 - late read command (shift by a SDCLK period)
verbose=0): verbose=0):
""" """
Setup read pattern sequence at parameter defined address in the sequencer memory Setup read pattern sequence at parameter defined address in the sequencer memory
<nrep> number of times pattern burst is read <nrep> number of times pattern burst is read
<sel> 0 - early, 1 - late read command (shift by a SDCLK period)
<verbose> print data being written (default: False) <verbose> print data being written (default: False)
""" """
...@@ -633,49 +635,49 @@ class X393PIOSequences(object): ...@@ -633,49 +635,49 @@ class X393PIOSequences(object):
self.x393_mem.axi_write_single_w(cmd_addr, data, verbose) self.x393_mem.axi_write_single_w(cmd_addr, data, verbose)
cmd_addr += 1 cmd_addr += 1
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST # skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)# tMOD data=self.func_encode_skip( 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)# tMOD
self.x393_mem.axi_write_single_w(cmd_addr, data, verbose) self.x393_mem.axi_write_single_w(cmd_addr, data, verbose)
cmd_addr += 1 cmd_addr += 1
# first read # first read
#@ read #@ read
# addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST # addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data=self.func_encode_cmd( 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0) data=self.func_encode_cmd( 0, 0, 2, 0, 0, sel, 0, 0, 0, 1, 1, 0, 0, 0)
self.x393_mem.axi_write_single_w(cmd_addr, data, verbose) self.x393_mem.axi_write_single_w(cmd_addr, data, verbose)
cmd_addr += 1 cmd_addr += 1
# nop (combine with previous?) # nop (combine with previous?)
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST # skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0) data=self.func_encode_skip( 0, 0, 0, 0, 0, sel, 0, 0, 0, 1, 1, 0, 0)
self.x393_mem.axi_write_single_w(cmd_addr, data, verbose) self.x393_mem.axi_write_single_w(cmd_addr, data, verbose)
cmd_addr += 1 cmd_addr += 1
#repeat remaining reads #repeat remaining reads
# for (i = 1; i < nrep; i = i + 1) begin # for (i = 1; i < nrep; i = i + 1) begin
for _ in range(1,nrep): for _ in range(1,nrep):
# addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST # addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data=self.func_encode_cmd( 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0) data=self.func_encode_cmd( 0, 0, 2, 0, 0, sel, 0, 0, 0, 1, 1, 0, 1, 0)
self.x393_mem.axi_write_single_w(cmd_addr, data, verbose) self.x393_mem.axi_write_single_w(cmd_addr, data, verbose)
cmd_addr += 1 cmd_addr += 1
# nop - all 3 below are the same? - just repeat? # nop - all 3 below are the same? - just repeat?
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST # skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0) data=self.func_encode_skip( 0, 0, 0, 0, 0, sel, 0, 0, 0, 1, 0, 0, 0)
self.x393_mem.axi_write_single_w(cmd_addr, data, verbose) self.x393_mem.axi_write_single_w(cmd_addr, data, verbose)
cmd_addr += 1 cmd_addr += 1
# nop # nop
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST # skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0) data=self.func_encode_skip( 0, 0, 0, 0, 0, sel, 0, 0, 0, 1, 0, 0, 0)
self.x393_mem.axi_write_single_w(cmd_addr, data, verbose) self.x393_mem.axi_write_single_w(cmd_addr, data, verbose)
cmd_addr += 1 cmd_addr += 1
# nop # nop
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST # skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0) data=self.func_encode_skip( 0, 0, 0, 0, 0, sel, 0, 0, 0, 1, 0, 0, 0)
self.x393_mem.axi_write_single_w(cmd_addr, data, verbose) self.x393_mem.axi_write_single_w(cmd_addr, data, verbose)
cmd_addr += 1 cmd_addr += 1
# nop, no write buffer - next page # nop, no write buffer - next page
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST # skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1) data=self.func_encode_skip( 0, 0, 0, 0, 0, sel, 0, 0, 0, 1, 0, 0, 1)
self.x393_mem.axi_write_single_w(cmd_addr, data, verbose) self.x393_mem.axi_write_single_w(cmd_addr, data, verbose)
cmd_addr += 1 cmd_addr += 1
# skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST # skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data=self.func_encode_skip( 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0) data=self.func_encode_skip( 1, 0, 0, 0, 0, sel, 0, 0, 0, 1, 0, 0, 0)
self.x393_mem.axi_write_single_w(cmd_addr, data, verbose) self.x393_mem.axi_write_single_w(cmd_addr, data, verbose)
cmd_addr += 1 cmd_addr += 1
# Turn off read pattern mode # Turn off read pattern mode
...@@ -995,6 +997,55 @@ class X393PIOSequences(object): ...@@ -995,6 +997,55 @@ class X393PIOSequences(object):
print ("WLEV lanes ratios: %f %f, non 0x00/0x01 bytes: %f"%(rslt[0],rslt[1],rslt[2])) print ("WLEV lanes ratios: %f %f, non 0x00/0x01 bytes: %f"%(rslt[0],rslt[1],rslt[2]))
return rslt return rslt
def read_levelling(self,
nrep,
sel=1, # 0 - early, 1 - late read command (shift by a SDCLK period), -1 - use current sequence
quiet=1):
"""
Read and process data in 'read patter' mode
refresh may be off, delays: cmda_edelay, dq_idelay, dqs_idelauy should be set
<nrep> number of times pattern burst is read (8-bursts), actually will be read nrep+3, nut the first/last will be discarded
<sel> 0 - early, 1 - late read command (shift by a SDCLK period)
"""
if sel>=0:
self.set_read_pattern(nrep+3,sel) # do not use first/last pair of the 32 bit words
buf= self.read_pattern((4*(nrep+1)+2), # num,
(0,1)[quiet<1], # show_rslt,
1) # Wait for operation to complete
buf= buf[4:] # discard first 4*32-bit words
if quiet <1:
hbuf=[]
for dd in buf:
hbuf.append(hex(dd))
print(hbuf)
# with "good" data each word in buf should be 0xff00ff00
for d in buf:
if d !=0xffffffff:
break
else: # Maybe it is not needed with correct cmda_odelay ?
if quiet<3:
print ("Got a block of bad data during read pattern")
return None
data=[0]*32 # for each bit - even, then for all - odd
for w in range (4 * nrep):
lane=w%2
for wb in range(32):
g=(wb/8)%2
b=wb%8+lane*8+16*g
if (buf[w+2] & (1<<wb) != 0):
data[b]+=1
scale=1.0/(4*nrep)
for i in range(32):
data[i]*=scale
if quiet < 2:
for i in range(32):
print("%.2f"%data[i],end=" ")
print()
return data
def restart_ddr3(self, def restart_ddr3(self,
wait_complete=True, wait_complete=True,
quiet=1): quiet=1):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment