Commit fbf5fddb authored by Andrey Filippov's avatar Andrey Filippov

adding measurement of DQ_ODELAY vs DQS_ODELAY

parent 1417d17e
...@@ -166,7 +166,7 @@ class X393LMA(object): ...@@ -166,7 +166,7 @@ class X393LMA(object):
use np.nan instead of the None data use np.nan instead of the None data
np.isnan() test np.isnan() test
, dtype=np.float , dtype=np.float
@compare_prim_steps while scanning, compare this delay with 1 less by primary(not fine) step, @param compare_prim_steps while scanning, compare this delay with 1 less by primary(not fine) step,
save None for fraction in unknown (previous -0.5, next +0.5) save None for fraction in unknown (previous -0.5, next +0.5)
""" """
halfStep=0.5 halfStep=0.5
...@@ -546,15 +546,15 @@ class X393LMA(object): ...@@ -546,15 +546,15 @@ class X393LMA(object):
each of 2x2 elements (DQ delay values) or null each of 2x2 elements (DQ delay values) or null
Create data set template - for each DQS delay and inPhase Create data set template - for each DQS delay and inPhase
- branch - number of full periods to add - branch - number of full periods to add
@lane byte lane to process @param lane byte lane to process
@bin_size bin size for the histograms (should be 5/10/20/40) @param bin_size bin size for the histograms (should be 5/10/20/40)
@clk_period SDCLK period in ps @param clk_period SDCLK period in ps
@dly_step_ds IDELAY step (from the datasheet) @param dly_step_ds IDELAY step (from the datasheet)
@primary_set which of the data edge series to use as leading (other will be trailing by 180) @param primary_set which of the data edge series to use as leading (other will be trailing by 180)
@data_set measured data set @param data_set measured data set
@compare_prim_steps while scanning, compare this delay with 1 less by primary(not fine) step, @param compare_prim_steps while scanning, compare this delay with 1 less by primary(not fine) step,
save None for fraction in unknown (previous -0.5, next +0.5) save None for fraction in unknown (previous -0.5, next +0.5)
@quiet reduce output @param quiet reduce output
""" """
num_hist_steps=2*((DLY_STEPS+bin_size-1)//bin_size) num_hist_steps=2*((DLY_STEPS+bin_size-1)//bin_size)
...@@ -756,7 +756,7 @@ class X393LMA(object): ...@@ -756,7 +756,7 @@ class X393LMA(object):
hist_estimated, hist_estimated,
quiet=1): quiet=1):
""" """
@compare_prim_steps while scanning, compare this delay with 1 less by primary(not fine) step, @param compare_prim_steps while scanning, compare this delay with 1 less by primary(not fine) step,
save None for fraction in unknown (previous -0.5, next +0.5) save None for fraction in unknown (previous -0.5, next +0.5)
""" """
...@@ -864,16 +864,16 @@ class X393LMA(object): ...@@ -864,16 +864,16 @@ class X393LMA(object):
After initial parametersn are created - run LMA to find optimal ones, After initial parametersn are created - run LMA to find optimal ones,
then return up to 3 varints (early, nominal, late) providing the best then return up to 3 varints (early, nominal, late) providing the best
DQ input delay for each DQS one DQ input delay for each DQS one
@lane byte lane to process (or non-number - process all byte lanes of the device) @param lane byte lane to process (or non-number - process all byte lanes of the device)
@bin_size bin size for the histograms (should be 5/10/20/40) @param bin_size bin size for the histograms (should be 5/10/20/40)
@clk_period SDCLK period in ps @param clk_period SDCLK period in ps
@dly_step_ds IDELAY step (from the datasheet) @param dly_step_ds IDELAY step (from the datasheet)
@primary_set which of the data edge series to use as leading (other will be trailing by 180) @param primary_set which of the data edge series to use as leading (other will be trailing by 180)
@data_set measured data set @param data_set measured data set
@compare_prim_steps while scanning, compare this delay with 1 less by primary(not fine) step, @param compare_prim_steps while scanning, compare this delay with 1 less by primary(not fine) step,
save None for fraction in unknown (previous -0.5, next +0.5) save None for fraction in unknown (previous -0.5, next +0.5)
@scale_w weight for "uncertain" values (where samples chane from all 0 to all 1 in one step) @param scale_w weight for "uncertain" values (where samples chane from all 0 to all 1 in one step)
@quiet reduce output @param quiet reduce output
@return 3-element dictionary of ('early','nominal','late'), each being None or a 160-element list, @return 3-element dictionary of ('early','nominal','late'), each being None or a 160-element list,
each element being either None, or a list of 3 best DQ delay values for the DQS delay (some mey be None too) each element being either None, or a list of 3 best DQ delay values for the DQS delay (some mey be None too)
""" """
......
...@@ -214,8 +214,8 @@ class X393McntrlAdjust(object): ...@@ -214,8 +214,8 @@ class X393McntrlAdjust(object):
quiet=2): quiet=2):
""" """
Set specified phase and matching cmda_odelay while temporarily turning off refresh Set specified phase and matching cmda_odelay while temporarily turning off refresh
@phase phase to set, signed short @param phase phase to set, signed short
@quiet reduce output @param quiet reduce output
@return cmda_odelay linear value or None if there is no valid cmda output delay for this phase @return cmda_odelay linear value or None if there is no valid cmda output delay for this phase
""" """
if not "cmda_bspe" in self.adjustment_state: if not "cmda_bspe" in self.adjustment_state:
...@@ -791,7 +791,7 @@ class X393McntrlAdjust(object): ...@@ -791,7 +791,7 @@ class X393McntrlAdjust(object):
self.x393_pio_sequences.set_read_block(*brc) self.x393_pio_sequences.set_read_block(*brc)
if (use_odelay==0) : if (use_odelay==0) :
self.x393_pio_sequences.write_block(1) # Wait for operation to complete self.x393_pio_sequences.write_block(0,1) # Wait for operation to complete
if verbose: print("++++++++ block written once") if verbose: print("++++++++ block written once")
#now scanning - first DQS, then try with DQ (post-adjustment - best fit) #now scanning - first DQS, then try with DQ (post-adjustment - best fit)
results = [] results = []
...@@ -806,7 +806,7 @@ class X393McntrlAdjust(object): ...@@ -806,7 +806,7 @@ class X393McntrlAdjust(object):
else: else:
if verbose: print("******** axi_set_dqs_odelay(0x%x)"%enc_dly) if verbose: print("******** axi_set_dqs_odelay(0x%x)"%enc_dly)
self.x393_mcntrl_timing.axi_set_dqs_odelay(enc_dly) self.x393_mcntrl_timing.axi_set_dqs_odelay(enc_dly)
self.x393_pio_sequences.write_block(1) # Wait for operation to complete self.x393_pio_sequences.write_block(0,1) # Wait for operation to complete
if verbose: print("-------- block written AGAIN") if verbose: print("-------- block written AGAIN")
else: else:
if (use_dq!=0): if (use_dq!=0):
...@@ -1947,6 +1947,7 @@ class X393McntrlAdjust(object): ...@@ -1947,6 +1947,7 @@ class X393McntrlAdjust(object):
# meas_data.append(patt_dqs_step(ldly)) # meas_data.append(patt_dqs_step(ldly))
# if quiet <3: # if quiet <3:
# print () # print ()
# main method code
meas_data=[None]*(max_lin_dly+1) meas_data=[None]*(max_lin_dly+1)
#start_dly #start_dly
for sdly in range(max_lin_dly+1): for sdly in range(max_lin_dly+1):
...@@ -2196,7 +2197,7 @@ class X393McntrlAdjust(object): ...@@ -2196,7 +2197,7 @@ class X393McntrlAdjust(object):
phase, phase,
quiet) quiet)
if not phase_ok: if not phase_ok:
return None # no vlaid CMDA ODELAY exists for this phase return None # no valid CMDA ODELAY exists for this phase
# try branches (will exit on first match) # try branches (will exit on first match)
for branch in dqsi_lohi.keys(): for branch in dqsi_lohi.keys():
low=dqsi_lohi[branch][0] low=dqsi_lohi[branch][0]
...@@ -2325,16 +2326,574 @@ class X393McntrlAdjust(object): ...@@ -2325,16 +2326,574 @@ class X393McntrlAdjust(object):
return dqsi_vs_phase return dqsi_vs_phase
def measure_dqo_dqso(self,
compare_prim_steps = True, # while scanning, compare this delay with 1 less by primary(not fine) step,
# save None for fraction in unknown (previous -0.5, next +0.5)
frac_step=0.125,
sel=1,
quiet=1,
start_dly=0): #just to check dependence
"""
Scan dqs odelay (setting phase appropriately), write
0x0000/0xffff/0x0000/0xffff (same as fixed pattern) data and read it with known dqsi/dqi
values (maybe even set different phase for read?), discarding first and last 1.5 8-bursts
Measure 4 different transitions for each data bit (rising DQS/rising DQ, falling DQS/falling DQ,
rising DQS/falling DQ and falling DQS/rising DQ (that allows to measure duty cycles fro both
DQS and DQ lines
"""
self.load_hardcoded_data() # TODO: REMOVE LATER
try:
dqi_dqsi=self.adjustment_state['dqi_dqsi']
except:
print ("No DQ IDELAY vs. DQS IDELAY data available, exiting")
return
dqsi_phase=self.adjustment_state['dqsi_phase']
num_lanes=len(dqsi_phase)
cmda_bspe=self.adjustment_state['cmda_bspe']
wlev_dqs_bspe=self.adjustment_state['wlev_dqs_bspe']
brc=(5, # 3'h5, # bank
0x1234, # 15'h1234, # row address
0x100) # 10'h100 # column address
nrep=8 # number of 8-bursts to compare (actual will have 3 more, first/last will be discarded
extraTgl=0 # data is repetitive,so extra toggle is not needed (an there is an extra 8-burst anyway)
timing=self.x393_mcntrl_timing.get_dly_steps()
dly_step=int(NUM_FINE_STEPS*frac_step*timing['SDCLK_PERIOD']/timing['DLY_STEP']+0.5)
numPhaseSteps= int(timing['SDCLK_PERIOD']/timing['PHASE_STEP']+0.5)
step180= int(NUM_FINE_STEPS*0.5* timing['SDCLK_PERIOD'] / timing['DLY_STEP'] +0.5)
"""
dqsi_valid={} #[None]*NUM_DLY_STEPS
for k,v in dqi_dqsi.items():
if v:
dqsi_valid[k]=[False]*NUM_DLY_STEPS
for dly in range(NUM_DLY_STEPS):
if v[dly]:
for d in v[dly]:
if d is None:
break
else: # All values are not None
dqsi_valid[k][dly]=True
if not dqsi_valid:
print ("No Valid DQ IDELAY vs. DQS IDELAY data is available, exiting")
return
if quiet <1:
print ('dqi_dqsi=%s'%(str(dqi_dqsi)))
print("\n\n")
if quiet <2:
print ('dqsi_valid=%s'%(str(dqsi_valid)))
"""
#Calculate phase for the best match for the DQS output delay (for both lanes - use average). If
# solution for different lanes point to the opposite ends of the phase range - keep previous
# do not look outside of +/- frac_step
def get_phase_for_dqso():
phase_dqso=[]
last_phase=0
for dly in range(NUM_DLY_STEPS):
best_phases= []
for lane in range(num_lanes):
best_diff= frac_step*NUM_DLY_STEPS
best_phase=None
for phase in range(numPhaseSteps):
try:
dly_phase=wlev_dqs_bspe[lane][phase]['ldly']
except:
dly_phase=None
if (not dly_phase is None) and (cmda_bspe[phase % numPhaseSteps] is None): # check that CMDA odelay exists for this phase
dly_phase=None
"""
# Make sure that dqsi and dqi exist for the phase
if dqsi_dqi_for_phase[phase] is None:
dly_phase=None
if dly==65:
print("lane=%d dly=%d, dqsi_dqi_for_phase[%d]=%s (%s)"%(lane, dly,phase,str(dqsi_dqi_for_phase[phase]),str(dly_phase)))
"""
if not dly_phase is None:
adiff=abs(dly_phase-dly)
if adiff < best_diff:
best_diff = adiff
best_phase = phase
if best_phase is None:
best_phases=None # At least one of the lanes does not have an acceptable solution (should not normally happen)
break
# print("lane=%d dly=%d, best_phase=%s best_diff=%s"%(lane, dly,str(best_phase),str(best_diff)))
best_phases.append(best_phase)
if best_phases is None:
phase_dqso.append(None)
continue
else:
diff_per= max(best_phases)-min(best_phases) > numPhaseSteps/2 # different ends
#find which one is closer to last_phase, modify the other one by +/- period
sp=0.0
for lane in range(num_lanes):
if diff_per and (best_phases[lane] >= numPhaseSteps/2):
best_phases[lane] -= numPhaseSteps
sp+=best_phases[lane]
sp /= num_lanes # average phase for all lanes
sp=int(round(sp))
# only if results for lanes are on the different ends - if they agree - just take an average
if diff_per and (abs(sp-last_phase) > abs(sp+numPhaseSteps-last_phase)):
sp += numPhaseSteps
sp=max(sp,0)
# May be that both best phases were OK, but their average falls into the gap - find closest
if dqsi_dqi_for_phase[sp] is None:
best_dist=numPhaseSteps
best_phase=None
for phase in range(numPhaseSteps):
if not dqsi_dqi_for_phase[phase] is None:
dist = min(abs(phase-sp),abs(phase+numPhaseSteps-sp),abs(phase-numPhaseSteps-sp))
if dist < best_dist:
best_dist=dist
best_phase=phase
if best_dist >= frac_step*numPhaseSteps:
# print("Could not find phase substitute for %d, %s is too far "%(sp, str(best_phase)))
best_phase=None
# else:
# print("Using substitute %d for %d"%(best_phase,sp))
sp= best_phase
sp=min(sp,numPhaseSteps-1)
# print("dly=%d best_phases=%s"%(dly, str(best_phases)))
phase_dqso.append(sp)
return phase_dqso
def get_dqsi_dqi_for_phase():
# Mark DQS idelay values that have all DQ delays valid
# for each phase check that DQS input delay value exists and store DQi varinat (early/nominal/late
dqsi_dqi_phase=[None]*numPhaseSteps
inv_vars=('early','late')
for phase in range (numPhaseSteps):
# print (phase, end=" ")
dqsi=[]
for lane_data in dqsi_phase:
dqsi.append(lane_data[phase])
if None in dqsi:
continue # Keep False
for k, dqi_dqsi_v in dqi_dqsi.items():
# print (" k=%s"%(k), end=" ")
if not dqi_dqsi_v:
continue # need to continue with next phase
dqi=[]
for lane, dqsi_lane in enumerate(dqsi):
# print (" lane=%d"%(lane), end=" ")
dq_lane=dqi_dqsi_v[dqsi_lane] #list of 16 DQ values for dqsi_lane or None
if (dq_lane is None) or (None in dq_lane[8*lane:8*(lane+1)]):
break
dqi += dq_lane[8*lane:8*(lane+1)]
else:
dqsi_dqi_phase[phase]={'dqsi':dqsi,
'dqi':dqi,
'invert':k in inv_vars,
'variant':k } # dqsi - a pair of dqs input delays, dqi - dq delays for the same phase
break
# print()
return dqsi_dqi_phase
def dqs_step(dqs_lin):
patt_cache=[None]*NUM_DLY_STEPS # cache for holding already measured delays
def measure_block(dly,invert_patt, force_meas=False):
if (patt_cache[dly] is None) or force_meas:
self.x393_mcntrl_timing.axi_set_dq_odelay(self.combine_delay(dly),quiet=quiet)
self.x393_pio_sequences.write_block() #page= 0, wait_complete=1)
patt= self.x393_pio_sequences.read_levelling(nrep,
-2, # Actually read block, but pre-process as a pattern
quiet+1)
#invert pattern if using early/late (not nominal) variants
# if (invert_patt):
# for i in range(len(patt)):
# patt[i]=1.0-patt[i]
patt_cache[dly]=patt
if quiet < 1:
print ('measure_block(%d,%s) - new measurement'%(dly,str(force_meas)))
else:
patt=patt_cache[dly]
if quiet < 1:
print ('measure_block(%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_odelay(self.combine_delay(dqs_lin),quiet=quiet)
#set phase, cmda_odelay, dqsi, dqi to match this delay
phase=phase_dqso[dqs_lin]
if phase is None: # no good phase exist for the specified dqs_odelay
if quiet <2:
print("No dood phase for DQS odelay = %d"%(dqs_lin))
return None
# set phase
# TODO: maybe keep last phase set and do not change it if required is not too far from the last set
# Set phase (and cmda_odelay as needed)
if quiet < 2:
print ("set_phase_with_refresh(%d), dqs_odelay=%d"%(phase,dqs_lin))
phase_ok=self.set_phase_with_refresh( # check result for not None
phase,
quiet)
if not phase_ok:
print ("Failed to set phase=%d for dly=%d- that should not happen (phase_dqso)- "%(phase,dqs_lin))
return None # no valid CMDA ODELAY exists for this phase
#set DQS IDELAY and DQ IDELAY matching phase
dqs_idelay=dqsi_dqi_for_phase[phase]['dqsi'] # 2-element list
dq_idelay= dqsi_dqi_for_phase[phase]['dqi'] # 16-element list
invert_patt= dqsi_dqi_for_phase[phase]['invert'] # 16-element list
self.x393_mcntrl_timing.axi_set_dqs_idelay(self.combine_delay(dqs_idelay),quiet=quiet)
self.x393_mcntrl_timing.axi_set_dq_idelay(self.combine_delay(dq_idelay),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 < NUM_DLY_STEPS) and notLast:
notLast= dly < NUM_DLY_STEPS-1
patt=measure_block(dly,invert_patt) # ,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,NUM_DLY_STEPS-1)
if highGot is None:
if quiet < 3:
print ("Could not find initial bounds for DQS output 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_block(dly,invert_patt) # ,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 output 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_block(dly,invert_patt) # ,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_block(dly,invert_patt) # ,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 output delay = %d , tight squeezed bounds: d_low=%s, d_high=%s"%(dqs_lin,str(d_low),str(d_high)))
# scan ranges, find closest solutions
#compare_prim_steps
best_dly= [[],[]]
best_diff=[[],[]]
for inPhase in range(2):
if not d_high[inPhase] is None:
# patt=None
best_dly[inPhase]=[d_low[inPhase]]*32
best_diff[inPhase]=[None]*32
# for b,p in enumerate(patt):
# positiveJump=((not inPhase) and (b<16)) or (inPhase and (b >= 16)) # may be 0, False, True
# if positiveJump:
# best_diff[inPhase].append(p-0.5)
# else:
# best_diff[inPhase].append(0.5-p)
for dly in range(d_low[inPhase]+1,d_high[inPhase]+1):
# patt_prev=patt
#as measured data is cached, there is no need to specially maintain patt_prev from earlier measurement
dly_prev= max(0,dly-(1,NUM_FINE_STEPS)[compare_prim_steps])
patt_prev=measure_block(dly_prev,invert_patt) # ,force_meas=False) - will be stored in cache
patt= measure_block(dly,invert_patt) # ,force_meas=False) - will be stored in cache
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 positiveJump:
diffs_prev_this=(patt_prev[b]-0.5,patt[b]-0.5)
else:
diffs_prev_this=(0.5-patt_prev[b],0.5-patt[b])
if abs(diffs_prev_this[0]) <= abs(diffs_prev_this[1]): # store previos sample
if (best_diff[inPhase][b] is None) or (abs (diffs_prev_this[0])<abs(best_diff[inPhase][b])):
best_dly[inPhase][b]=dly_prev # dly-1
best_diff[inPhase][b]=diffs_prev_this[0]
if quiet < 1:
print ("*%d:%0.3f:%0.3f%s"%(b,diffs_prev_this[0],diffs_prev_this[1],str(signs)),end="")
else:
if (best_diff[inPhase][b] is None) or (abs (diffs_prev_this[1])<abs(best_diff[inPhase][b])):
best_dly[inPhase][b]=dly # dly-1
best_diff[inPhase][b]=diffs_prev_this[1]
if quiet < 1:
print ("?%d:%0.3f:%0.3f%s"%(b,diffs_prev_this[0],diffs_prev_this[1],str(signs)),end="")
if quiet < 1:
print("\n dly=%d dly_prev=%d:"%(dly,dly_prev),end=" ")
for b in range(32):
if best_diff[inPhase][b] == -0.5:
best_diff[inPhase][b] = None # will have to add half-interval (0.5 or 2.5)
# 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
# main method code
#(wlev_dqs_bspe[lane][phase]['ldly']
# if (not wlev_dqs_bspe[lane][phase] is None) and (not wlev_dqs_bspe[lane][phase]['ldly'] is None):
if quiet<2:
print ("timing=%s, dly_step=%d step180=%d"%(str(timing),dly_step,step180))
wdata16=(0,0xffff)*(4*(nrep+3))
wdata32=self.convert_mem16_to_w32(wdata16)
dqsi_dqi_for_phase=get_dqsi_dqi_for_phase()
phase_dqso=get_phase_for_dqso() # uses dqsi_dqi_for_phase
if quiet < 2:
for i, v in enumerate(phase_dqso):
print("%d %s"%(i,str(v)))
for p, v in enumerate(dqsi_dqi_for_phase):
print("%d"%(p),end=" ")
if v:
for dqsi in v['dqsi']:
print(dqsi,end=" ")
for dqi in v['dqi']:
print(dqi,end=" ")
print(v['invert'],end=" ")
print(v['variant'],end=" ")
print()
if self.DRY_MODE:
return
self.x393_mcntrl_buffers.write_block_buf_chn(0,0,wdata32); # fill block memory (channel, page, number)
self.x393_pio_sequences.set_write_block(*(brc+(nrep+3,extraTgl,sel))) # set sequence once
self.x393_pio_sequences.set_read_block(*(brc+(nrep+3,sel))) # set sequence once
#With the data to write being the same as pattern data, try using the same measurements as for the pattern
meas_data=[None]*(NUM_DLY_STEPS)
#start_dly
for sdly in range(NUM_DLY_STEPS):
ldly = (start_dly+sdly)%(NUM_DLY_STEPS)
# 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] = dqs_step(ldly)
if quiet <3:
print ()
if quiet < 3:
print("\n\nMeasured data, integer portion, measured with %s steps"%(("fine","primary")[compare_prim_steps]))
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("\n\nMasked measured data, integer portion, measured with %s steps"%(("fine","primary")[compare_prim_steps]))
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]] and (not pData[typ[0]][typ[1]][1] is None):
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]] and (not pData[typ[0]][typ[1]][1] is None):
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()
if quiet < 3:
print("\n\nMeasured data, comparing current data with the earlier by one %s step"%(("fine","primary")[compare_prim_steps]))
print("When the fractional (second in the tuple) data is exactly -0.5, the actual result is in the range %s from the integer delay"%
(("+0.0..+1.0","+0.0..+%d"%NUM_FINE_STEPS)[compare_prim_steps]))
print ("meas_data=[")
for d in meas_data:
print("%s,"%(str(d)))
print("]")
rdict={"patt_prim_steps": compare_prim_steps,
"patt_meas_data": meas_data} # TODO: May delete after LMA fitting
self.adjustment_state.update(rdict)
#dly_step
# compare_prim_steps
#meas_data=[
''' '''
adjust_cmda_odelay 0 1 0.1 3 adjust_cmda_odelay 0 1 0.1 3
adjust_write_levelling 0 1 0 .1 3 adjust_write_levelling 0 1 0 .1 3
...@@ -2364,14 +2923,14 @@ class X393McntrlAdjust(object): ...@@ -2364,14 +2923,14 @@ class X393McntrlAdjust(object):
quiet=1): quiet=1):
""" """
Run DQ vs DQS fitting for one data lane (0 or 1) using earlier acquired hard-coded data Run DQ vs DQS fitting for one data lane (0 or 1) using earlier acquired hard-coded data
@lane byte lane to process (or non-number - process all byte lanes of the device) @param lane byte lane to process (or non-number - process all byte lanes of the device)
@bin_size bin size for the histograms (should be 5/10/20/40) @param bin_size bin size for the histograms (should be 5/10/20/40)
@primary_set which of the data edge series to use as leading (other will be trailing by 180) @param primary_set which of the data edge series to use as leading (other will be trailing by 180)
@data_set_number select one of the hard-coded data sets (sets 0 and 1 use comparing with the data 1 fine step below @param data_set_number select one of the hard-coded data sets (sets 0 and 1 use comparing with the data 1 fine step below
set #2 (default) used measurement with previous primary step measurement (will not suffer from set #2 (default) used measurement with previous primary step measurement (will not suffer from
fine range wider than on primary step) fine range wider than on primary step)
If not number or <0 - use measured data If not number or <0 - use measured data
@scale_w weight for "uncertain" values (where samples change from all 0 to all 1 in one step) @param scale_w weight for "uncertain" values (where samples change from all 0 to all 1 in one step)
For sufficient data 0.0 is OK (and seems to work better)- only "analog" samples are considered For sufficient data 0.0 is OK (and seems to work better)- only "analog" samples are considered
@return 3-element dictionary of ('early','nominal','late'), each being None or a 160-element list, @return 3-element dictionary of ('early','nominal','late'), each being None or a 160-element list,
each element being either None, or a list of 3 best DQ delay values for the DQS delay (some mey be None too) each element being either None, or a list of 3 best DQ delay values for the DQS delay (some mey be None too)
...@@ -2448,13 +3007,13 @@ class X393McntrlAdjust(object): ...@@ -2448,13 +3007,13 @@ class X393McntrlAdjust(object):
quiet=1): quiet=1):
""" """
Run DQSI vs PHASE fitting for one data lane (0 or 1) using earlier acquired hard-coded data Run DQSI vs PHASE fitting for one data lane (0 or 1) using earlier acquired hard-coded data
@lane byte lane to process (or non-number - process all byte lanes of the device) @param lane byte lane to process (or non-number - process all byte lanes of the device)
@bin_size_ps histogram bin size (in ps) @param bin_size_ps histogram bin size (in ps)
@data_set_number select one of the hard-coded data sets (sets 0 and 1 use comparing with the data 1 fine step below @param data_set_number select one of the hard-coded data sets (sets 0 and 1 use comparing with the data 1 fine step below
set #0 (default) used measurement with previous primary step measurement (will not suffer from set #0 (default) used measurement with previous primary step measurement (will not suffer from
fine range wider than on primary step) fine range wider than on primary step)
If not number or <0 - use measured data If not number or <0 - use measured data
@scale_w weight for "uncertain" values (where samples change from all 0 to all 1 in one step) @param scale_w weight for "uncertain" values (where samples change from all 0 to all 1 in one step)
For sufficient data 0.0 is OK (and seems to work better)- only "analog" samples are considered For sufficient data 0.0 is OK (and seems to work better)- only "analog" samples are considered
@return 3-element dictionary of ('early','nominal','late'), each being None or a 160-element list, @return 3-element dictionary of ('early','nominal','late'), each being None or a 160-element list,
each element being either None, or a list of 3 best DQ delay values for the DQS delay (some mey be None too) each element being either None, or a list of 3 best DQ delay values for the DQS delay (some mey be None too)
......
...@@ -135,9 +135,9 @@ class X393McntrlBuffers(object): ...@@ -135,9 +135,9 @@ class X393McntrlBuffers(object):
num_words_or_data_list): # input integer num_words; # number of words to write (will be rounded up to multiple of 16) num_words_or_data_list): # input integer num_words; # number of words to write (will be rounded up to multiple of 16)
""" """
Fill specified buffer with the pattern data Fill specified buffer with the pattern data
<chn> 4-bit buffer channel (0..4) to write data to @param chn 4-bit buffer channel (0..4) to write data to
<page> 2-bit buffer page to write to @param page 2-bit buffer page to write to
<num_words_or_data_list> number of 32-bit words to generate/write or a list with integer data @param num_words_or_data_list> number of 32-bit words to generate/write or a list with integer data
""" """
print("===write_block_buf_chn() chn=0x%x, page=0x%x"%(chn,page), end=" ") print("===write_block_buf_chn() chn=0x%x, page=0x%x"%(chn,page), end=" ")
if isinstance (num_words_or_data_list,list): if isinstance (num_words_or_data_list,list):
......
...@@ -283,7 +283,7 @@ class X393McntrlTests(object): ...@@ -283,7 +283,7 @@ class X393McntrlTests(object):
self.x393_mcntrl_timing.axi_set_dq_odelay(dq_odelay) self.x393_mcntrl_timing.axi_set_dq_odelay(dq_odelay)
if (not dqs_odelay is None) and (dqs_odelay != []): if (not dqs_odelay is None) and (dqs_odelay != []):
self.x393_mcntrl_timing.axi_set_dqs_odelay(dqs_odelay) self.x393_mcntrl_timing.axi_set_dqs_odelay(dqs_odelay)
return self.x393_pio_sequences.write_block(wait_complete) # Wait for operation to complete return self.x393_pio_sequences.write_block(0,wait_complete) # Wait for operation to complete
def test_read_block(self, def test_read_block(self,
dq_idelay=None, dq_idelay=None,
......
...@@ -82,7 +82,7 @@ class X393McntrlTiming(object): ...@@ -82,7 +82,7 @@ class X393McntrlTiming(object):
<phase> 8-bit clock phase value (None will use default) <phase> 8-bit clock phase value (None will use default)
<wait_phase_en> compare phase shift to programmed (will not work if the program was restarted) <wait_phase_en> compare phase shift to programmed (will not work if the program was restarted)
<wait_seq> read and re-send status request to make sure status reflects new data (just for testing, too fast for Python) <wait_seq> read and re-send status request to make sure status reflects new data (just for testing, too fast for Python)
<quiet> reduce output @param quiet reduce output
Returns 1 if success, 0 if timeout (or no wait was performed) Returns 1 if success, 0 if timeout (or no wait was performed)
""" """
if phase is None: if phase is None:
...@@ -182,10 +182,10 @@ class X393McntrlTiming(object): ...@@ -182,10 +182,10 @@ class X393McntrlTiming(object):
quiet=1): 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) @param 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 @param quiet reduce output
""" """
# print("====axi_set_dq_idelay %s"%str(delay)) # print("====axi_set_dq_idelay %s"%str(delay))
...@@ -203,12 +203,15 @@ class X393McntrlTiming(object): ...@@ -203,12 +203,15 @@ class X393McntrlTiming(object):
self.x393_axi_tasks.write_contol_register (vrlg.DLY_SET,0);# // set all delays self.x393_axi_tasks.write_contol_register (vrlg.DLY_SET,0);# // set all delays
def axi_set_dq_odelay(self, def axi_set_dq_odelay(self,
delay=None): # input [7:0] delay; delay=None, # input [7:0] delay;
quiet=1):
""" """
Set all DQ OUTput delays to the same value Set all DQ OUTput delays to the same value
<delay> 8-bit (5+3) delay value to use or a tuple/list with a pair for (lane0, lane1) @param 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
@param quiet reduce output
""" """
if delay is None: if delay is None:
delay=[[],[]] delay=[[],[]]
...@@ -217,7 +220,7 @@ class X393McntrlTiming(object): ...@@ -217,7 +220,7 @@ class X393McntrlTiming(object):
delay[1].append(vrlg.get_default_field("DLY_LANE1_ODELAY",i)) delay[1].append(vrlg.get_default_field("DLY_LANE1_ODELAY",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 ODELAY="+hexMultiple(delay)) # hexMultiple print("SET DQ ODELAY="+hexMultiple(delay)) # hexMultiple
self.axi_set_multiple_delays(vrlg.LD_DLY_LANE0_ODELAY, 0, 8, delay[0], "DLY_LANE0_ODELAY"); self.axi_set_multiple_delays(vrlg.LD_DLY_LANE0_ODELAY, 0, 8, delay[0], "DLY_LANE0_ODELAY");
self.axi_set_multiple_delays(vrlg.LD_DLY_LANE1_ODELAY, 0, 8, delay[1], "DLY_LANE1_ODELAY"); self.axi_set_multiple_delays(vrlg.LD_DLY_LANE1_ODELAY, 0, 8, delay[1], "DLY_LANE1_ODELAY");
...@@ -228,9 +231,9 @@ class X393McntrlTiming(object): ...@@ -228,9 +231,9 @@ class X393McntrlTiming(object):
quiet=1): quiet=1):
""" """
Set all DQs input delays to the same value Set all DQs 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) @param delay 8-bit (5+3) delay value to use or a tuple/list with a pair for (lane0, lane1)
if delay is None will restore default values if delay is None will restore default values
<quiet> reduce output @param quiet reduce output
""" """
if delay is None: if delay is None:
delay=(vrlg.get_default_field("DLY_LANE0_IDELAY",8),vrlg.get_default_field("DLY_LANE1_IDELAY",8)) delay=(vrlg.get_default_field("DLY_LANE0_IDELAY",8),vrlg.get_default_field("DLY_LANE1_IDELAY",8))
...@@ -247,9 +250,9 @@ class X393McntrlTiming(object): ...@@ -247,9 +250,9 @@ class X393McntrlTiming(object):
quiet=1): quiet=1):
""" """
Set all DQs OUTput delays to the same value Set all DQs OUTput delays to the same value
<delay> 8-bit (5+3) delay value to use or a tuple/list with a pair for (lane0, lane1) @param delay 8-bit (5+3) delay value to use or a tuple/list with a pair for (lane0, lane1)
if delay is None will restore default values if delay is None will restore default values
<quiet> reduce output @param quiet reduce output
""" """
if delay is None: if delay is None:
...@@ -267,9 +270,9 @@ class X393McntrlTiming(object): ...@@ -267,9 +270,9 @@ class X393McntrlTiming(object):
quiet=1): quiet=1):
""" """
Set all DM output delays to the same value Set all DM output delays to the same value
<delay> 8-bit (5+3) delay value to use or a tuple/list with a pair for (lane0, lane1) @param delay 8-bit (5+3) delay value to use or a tuple/list with a pair for (lane0, lane1)
if delay is None will restore default values if delay is None will restore default values
<quiet> reduce output @param quiet reduce output
""" """
if delay is None: if delay is None:
delay=(vrlg.get_default_field("DLY_LANE0_ODELAY",9),vrlg.get_default_field("DLY_LANE1_ODELAY",9)) delay=(vrlg.get_default_field("DLY_LANE0_ODELAY",9),vrlg.get_default_field("DLY_LANE1_ODELAY",9))
...@@ -287,11 +290,11 @@ class X393McntrlTiming(object): ...@@ -287,11 +290,11 @@ class X393McntrlTiming(object):
quiet=1): quiet=1):
""" """
Set all command/address output delays to the same value (or a list/tuple of the individual ones) Set all command/address output delays to the same value (or a list/tuple of the individual ones)
<delay> 8-bit (5+3) delay value to use or list/tuple containing individual values @param delay 8-bit (5+3) delay value to use or list/tuple containing individual values
List elements may be None, those values will not be overwritten List elements may be None, those values will not be overwritten
if delay is None will restore default values if delay is None will restore default values
<indx> if present, delay only applies to the specified index (delay should be int/long) @param indx if present, delay only applies to the specified index (delay should be int/long)
<quiet> reduce output @param quiet reduce output
""" """
if delay is None: if delay is None:
delay=[] delay=[]
...@@ -317,10 +320,10 @@ class X393McntrlTiming(object): ...@@ -317,10 +320,10 @@ class X393McntrlTiming(object):
quiet=1): quiet=1):
""" """
Set output delays for address lines only Set output delays for address lines only
<delay> 8-bit (5+3) delay value to use or list/tuple containing individual values @param delay 8-bit (5+3) delay value to use or list/tuple containing individual values
List elements may be None, those values will not be overwritten List elements may be None, those values will not be overwritten
if delay is None will restore default values if delay is None will restore default values
<indx> if present, delay only applies to the specified index (delay should be int/long) @param indx if present, delay only applies to the specified index (delay should be int/long)
""" """
if delay is None: if delay is None:
delay=[] delay=[]
...@@ -345,10 +348,10 @@ class X393McntrlTiming(object): ...@@ -345,10 +348,10 @@ class X393McntrlTiming(object):
indx=None): # address index indx=None): # address index
""" """
Set output delays for bank lines only Set output delays for bank lines only
<delay> 8-bit (5+3) delay value to use or list/tuple containing individual values @param delay 8-bit (5+3) delay value to use or list/tuple containing individual values
List elements may be None, those values will not be overwritten List elements may be None, those values will not be overwritten
if delay is None will restore default values if delay is None will restore default values
<indx> if present, delay only applies to the specified index (delay should be int/long) @param indx if present, delay only applies to the specified index (delay should be int/long)
""" """
bank_offset=24 bank_offset=24
if delay is None: if delay is None:
...@@ -374,10 +377,10 @@ class X393McntrlTiming(object): ...@@ -374,10 +377,10 @@ class X393McntrlTiming(object):
indx=None): # address index indx=None): # address index
""" """
Set output delays for command lines only. command=(we,ras,cas,cke,odt) Set output delays for command lines only. command=(we,ras,cas,cke,odt)
<delay> 8-bit (5+3) delay value to use or list/tuple containing individual values @param delay 8-bit (5+3) delay value to use or list/tuple containing individual values
List elements may be None, those values will not be overwritten List elements may be None, those values will not be overwritten
if delay is None will restore default values if delay is None will restore default values
<indx> if present, delay only applies to the specified index (delay should be int/long) @param indx if present, delay only applies to the specified index (delay should be int/long)
""" """
command_offset=24+3 command_offset=24+3
if delay is None: if delay is None:
...@@ -410,7 +413,7 @@ class X393McntrlTiming(object): ...@@ -410,7 +413,7 @@ class X393McntrlTiming(object):
<reg_addr> control register address of the first register in the range <reg_addr> control register address of the first register in the range
<offset> add this offset to address <offset> add this offset to address
<number> number of registers to write <number> number of registers to write
<delay> 8-bit (5+3) delay value to use or list/tuple containing individual values @param delay 8-bit (5+3) delay value to use or list/tuple containing individual values
List elements may be None, those values will not be overwritten List elements may be None, those values will not be overwritten
<vname> Verilog parameter name <vname> Verilog parameter name
""" """
...@@ -439,7 +442,7 @@ class X393McntrlTiming(object): ...@@ -439,7 +442,7 @@ class X393McntrlTiming(object):
delay=None): # input [3:0] delay; delay=None): # input [3:0] delay;
""" """
Set write to buffer latency Set write to buffer latency
<delay> 4-bit write to buffer signal delay (in mclk clock cycles) @param delay 4-bit write to buffer signal delay (in mclk clock cycles)
if delay is None will restore default values if delay is None will restore default values
""" """
if delay is None: if delay is None:
......
...@@ -452,7 +452,6 @@ class X393PIOSequences(object): ...@@ -452,7 +452,6 @@ class X393PIOSequences(object):
@num8 - number of 8-bursts to read (maximal 64, min- 2) @num8 - number of 8-bursts to read (maximal 64, min- 2)
@sel - 0 - early, 1 - late read command @sel - 0 - early, 1 - late read command
@verbose print data being written (default: False) @verbose print data being written (default: False)
""" """
cmd_addr = vrlg.MCONTR_CMD_WR_ADDR + vrlg.READ_BLOCK_OFFSET cmd_addr = vrlg.MCONTR_CMD_WR_ADDR + vrlg.READ_BLOCK_OFFSET
# activate # activate
...@@ -520,17 +519,20 @@ class X393PIOSequences(object): ...@@ -520,17 +519,20 @@ class X393PIOSequences(object):
ca, # input[9:0]ca; ca, # input[9:0]ca;
num8=64, num8=64,
extraTgl=0, # extraTgl=0, #
sel=1,
verbose=0): verbose=0):
""" """
Setup write block sequence at parameter defined address in the sequencer memory Setup write block sequence at parameter defined address in the sequencer memory
<ba> 3-bit memory bank address @ba 3-bit memory bank address
<ra> 15-bit memory row address @ra 15-bit memory row address
<ca> 10-bit memory column address @ca 10-bit memory column address
<num8> - number of 8-bursts (default=64, should be >2) @num8 - number of 8-bursts (default=64, should be >2)
<verbose> print data being written (default: False) @extraTgl add extra 8-burst of toggling DQS
@sel - 0 - early, 1 - late read command
@verbose print data being written (default: False)
""" """
print("===set_write_block ba=0x%x, ra=0x%x, ca=0x%x"%(ba,ra,ca)) print("===set_write_block ba=0x%x, ra=0x%x, ca=0x%x, num8=%d extraTgl=%d, sel=%d, verbose=%d"%(ba,ra,ca,num8,extraTgl,sel, verbose))
cmd_addr = vrlg.MCONTR_CMD_WR_ADDR + vrlg.WRITE_BLOCK_OFFSET cmd_addr = vrlg.MCONTR_CMD_WR_ADDR + vrlg.WRITE_BLOCK_OFFSET
# activate # activate
# 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
...@@ -545,7 +547,7 @@ class X393PIOSequences(object): ...@@ -545,7 +547,7 @@ class X393PIOSequences(object):
# first write, 3 rd_buf # first write, 3 rd_buf
# write # write
# 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(ca&0x3ff, ba, 3, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0) # B_RD moved 1 cycle earlier data=self.func_encode_cmd(ca&0x3ff, ba, 3, 1, 0, sel, 0, 0, 0, 0, 0, 1, 0, 0) # B_RD moved 1 cycle earlier
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 4-th rd_buf # nop 4-th rd_buf
...@@ -557,24 +559,24 @@ class X393PIOSequences(object): ...@@ -557,24 +559,24 @@ class X393PIOSequences(object):
for i in range(1,num8-2): # 62) : #(i = 1; i < 62; i = i + 1) begin for i in range(1,num8-2): # 62) : #(i = 1; i < 62; i = i + 1) begin
# write # write
# 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((ca&0x3ff)+(i<<3), ba, 3, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0) data=self.func_encode_cmd((ca&0x3ff)+(i<<3), ba, 3, 1, 0, sel, 1, 1, 1, 0, 0, 1, 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
# 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((ca&0x3ff)+(62<<3), ba, 3, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0) # write w/o nop # data=self.func_encode_cmd((ca&0x3ff)+(62<<3), ba, 3, 1, 0, sel, 1, 1, 1, 0, 0, 1, 0, 0) # write w/o nop
data=self.func_encode_cmd((ca&0x3ff)+((num8-2)<<3), ba, 3, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0) # write w/o nop data=self.func_encode_cmd((ca&0x3ff)+((num8-2)<<3), ba, 3, 1, 0, sel, 1, 1, 1, 0, 0, 1, 0, 0) # write w/o nop
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, ba, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0) # nop with buffer read off data=self.func_encode_skip( 0, 0, ba, 1, 0, sel, 1, 1, 1, 0, 0, 0, 0) # nop with buffer read off
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
# One last write pair w/o buffer # One last write pair w/o buffer
# 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((ca&0x3ff)+(63<<3), ba, 3, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0) # write with nop # data=self.func_encode_cmd((ca&0x3ff)+(63<<3), ba, 3, 1, 0, sel, 1, 1, 1, 0, 0, 0, 1, 0) # write with nop
data=self.func_encode_cmd((ca&0x3ff)+((num8-1)<<3),ba, 3, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0) # write with nop data=self.func_encode_cmd((ca&0x3ff)+((num8-1)<<3),ba, 3, 1, 0, sel, 1, 1, 1, 0, 0, 0, 1, 0) # write with nop
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
...@@ -589,7 +591,7 @@ class X393PIOSequences(object): ...@@ -589,7 +591,7 @@ class X393PIOSequences(object):
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( extraTgl, 0, ba, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0) data=self.func_encode_skip( extraTgl, 0, ba, sel, 0, 0, 1, 1, 1, 0, 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
# ODT off, it has latency # ODT off, it has latency
...@@ -945,18 +947,20 @@ class X393PIOSequences(object): ...@@ -945,18 +947,20 @@ class X393PIOSequences(object):
return self.x393_mcntrl_buffers.read_block_buf_chn (0, 3, num, show_rslt ) # chn=0, page=3, number of 32-bit words=num, show_rslt return self.x393_mcntrl_buffers.read_block_buf_chn (0, 3, num, show_rslt ) # chn=0, page=3, number of 32-bit words=num, show_rslt
def write_block(self, def write_block(self,
wait_complete): # Wait for operation to complete page=0,
wait_complete=1): # Wait for operation to complete
""" """
Write block in PS PIO mode Write block in PS PIO mode
<wait_complete> wait write block operation to complete (0 - may initiate multiple PS PIO operations) @param page buffer page to use
@param wait_complete wait write block operation to complete (0 - may initiate multiple PS PIO operations)
""" """
# write_block_buf_chn; # fill block memory - already set in set_up task # write_block_buf_chn; # fill block memory - already set in set_up task
self.schedule_ps_pio ( # schedule software-control memory operation (may need to check FIFO status first) self.schedule_ps_pio ( # schedule software-control memory operation (may need to check FIFO status first)
vrlg.WRITE_BLOCK_OFFSET, # input [9:0] seq_addr; # sequence start address vrlg.WRITE_BLOCK_OFFSET, # input [9:0] seq_addr; # sequence start address
0, # input [1:0] page; # buffer page number page, # input [1:0] page; # buffer page number
0, # input urgent; # high priority request (only for competion with other channels, will not pass in this FIFO) 0, # input urgent; # high priority request (only for competion with other channels, will not pass in this FIFO)
1, # input chn; # channel buffer to use: 0 - memory read, 1 - memory write 1, # input chn; # channel buffer to use: 0 - memory read, 1 - memory write
wait_complete) # `PS_PIO_WAIT_COMPLETE )# wait_complete; # Do not request a newer transaction from the scheduler until previous memory transaction is finished wait_complete) # `PS_PIO_WAIT_COMPLETE )# wait_complete; # Do not request a newer transaction from the scheduler until previous memory transaction is finished
# temporary - for debugging: # temporary - for debugging:
# self.wait_ps_pio_done(vrlg.DEFAULT_STATUS_MODE,1) # wait previous memory transaction finished before changing delays (effective immediately) # self.wait_ps_pio_done(vrlg.DEFAULT_STATUS_MODE,1) # wait previous memory transaction finished before changing delays (effective immediately)
...@@ -1003,19 +1007,25 @@ class X393PIOSequences(object): ...@@ -1003,19 +1007,25 @@ class X393PIOSequences(object):
def read_levelling(self, def read_levelling(self,
nrep, nrep,
sel=1, # 0 - early, 1 - late read command (shift by a SDCLK period), -1 - use current sequence sel=1, # 0 - early, 1 - late read command (shift by a SDCLK period), -1 - use current sequence
quiet=1): quiet=1):
""" """
Read and process data in 'read patter' mode Read and process data in 'read patter' mode
refresh may be off, delays: cmda_edelay, dq_idelay, dqs_idelauy should be set 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 @param 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) @param sel 0 - early, 1 - late read command (shift by a SDCLK period) -1 - use pre-programmed sequence,
-2 - use (pre-programmed) read_block sequence
""" """
if sel>=0: if sel>=0:
self.set_read_pattern(nrep+3,sel) # do not use first/last pair of the 32 bit words 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, if sel == -2:
(0,1)[quiet<1], # show_rslt, buf= self.read_block((4*(nrep+1)+2), # num,
1) # Wait for operation to complete (0,1)[quiet<1], # show_rslt,
1) # Wait for operation to complete
else:
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 buf= buf[4:] # discard first 4*32-bit words
if quiet <1: if quiet <1:
hbuf=[] hbuf=[]
......
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