Commit 45d1f6b7 authored by Andrey Filippov's avatar Andrey Filippov

Adding selection correct branch of read/write delays (considering full/half clock cycles)

parent 8ffbbc62
...@@ -3,6 +3,6 @@ ...@@ -3,6 +3,6 @@
-f /usr/local/verilog/x393_parameters.vh /usr/local/verilog/x393_cur_params_target.vh /usr/local/verilog/x393_localparams.vh -f /usr/local/verilog/x393_parameters.vh /usr/local/verilog/x393_cur_params_target.vh /usr/local/verilog/x393_localparams.vh
-l /usr/local/verilog/x393_cur_params_target.vh -l /usr/local/verilog/x393_cur_params_target.vh
-p PICKLE="/usr/local/verilog/x393_mcntrl.pickle -p PICKLE="/usr/local/verilog/x393_mcntrl.pickle
-c measure_all "ICWRPOASZ" 1 2 2 3 -c measure_all "ICWRPOASZ" 1 2 2 0xaa 3
-c set_phase_delays 15 'A' 'A' 1 None 0 -c set_phase_delays 15 'A' 'A' 1 None 0
-c save -c save
...@@ -847,7 +847,7 @@ class X393LMA(object): ...@@ -847,7 +847,7 @@ class X393LMA(object):
print() print()
return data_periods_map return data_periods_map
def lma_fit_dqi_dqsi(self, def lma_fit_dq_dqs(self,
lane, # byte lane lane, # byte lane
bin_size, bin_size,
clk_period, clk_period,
...@@ -885,8 +885,11 @@ class X393LMA(object): ...@@ -885,8 +885,11 @@ class X393LMA(object):
numLanes=2 numLanes=2
parametersKey='parameters' parametersKey='parameters'
errorKey='maxErrDqs' errorKey='maxErrDqs'
tDQKey='tDQ'
earlyKey,nominalKey,lateKey=('early','nominal','late')
# periods={earlyKey:-1,nominalKey:0,lateKey:1} #t0~= +1216 t1~=-1245
for lane in range(numLanes): for lane in range(numLanes):
lane_rslt.append(self.lma_fit_dqi_dqsi(lane, # byte lane lane_rslt.append(self.lma_fit_dq_dqs(lane, # byte lane
bin_size, bin_size,
clk_period, clk_period,
dly_step_ds, dly_step_ds,
...@@ -894,7 +897,56 @@ class X393LMA(object): ...@@ -894,7 +897,56 @@ class X393LMA(object):
data_set, data_set,
compare_prim_steps, compare_prim_steps,
scale_w, scale_w,
quiet)) quiet))
#fix parameters if they have average tDQ different by +/- period(s)
tDQ_avg=[]
for lane in range(numLanes):
tDQ_avg.append(sum(lane_rslt[lane][parametersKey][tDQKey])/len(lane_rslt[lane][parametersKey][tDQKey]))
per1_0=int(round((tDQ_avg[1]-tDQ_avg[0])/clk_period))
if abs(tDQ_avg[1]-tDQ_avg[0]) > clk_period/2:
if quiet <5:
print ("lma_fit_dq_dqs: Data lanes tDQ average differs by %.1fps (%d clocks), shifting to match"%(abs(tDQ_avg[1]-tDQ_avg[0]),per1_0))
if abs(per1_0) > 1:
raise Exception ("BUG: lma_fit_dq_dqs: dta lanes differ by more than a period (per1_0=%d periods) - should not happen"%(per1_0))
#see number of valid items in early,nominal,late branches of each lane
numInVar=[{},{}]
for lane in range(numLanes):
for k in lane_rslt[lane].keys():
if (k != parametersKey) and (k != errorKey):
numValid=0
try:
for ph in lane_rslt[lane][k]:
if not ph is None:
numValid+=1
except:
pass
numInVar[lane][k]=numValid
if quiet < 2:
print ("numInVar=",numInVar)
late_lane=(0,1)[per1_0<0] # for late_lane E,N,L -> x, E, N, for not late_lane: E,N,L -> N, L, x
move_late_lane= (0,1)[numInVar[late_lane][earlyKey] <= numInVar[1-late_lane][lateKey]] # currently both are 0 - nothing is lost
tDQ_delta=clk_period*(-1,1)[move_late_lane]
lane_to_change=(1,0)[late_lane ^ move_late_lane]
if quiet < 2:
print ("late_lane= ",late_lane)
print ("move_late_lane=",move_late_lane)
print ("lane_to_change=",lane_to_change)
print ("tDQ_delta= ",tDQ_delta)
# modify tDQ:
for b in range(len(lane_rslt[lane_to_change][parametersKey][tDQKey])):
lane_rslt[lane_to_change][parametersKey][tDQKey][b]+=tDQ_delta
if quiet < 2:
print ("lane_rslt[%d]['%s']['%s']=%s"%(lane_to_change,parametersKey,tDQKey, str(lane_rslt[lane_to_change][parametersKey][tDQKey])))
# modify variants:
if move_late_lane:
lane_rslt[lane_to_change][earlyKey], lane_rslt[lane_to_change][nominalKey], lane_rslt[lane_to_change][lateKey]= (
lane_rslt[lane_to_change][nominalKey],lane_rslt[lane_to_change][lateKey], None)
else:
lane_rslt[lane_to_change][lateKey], lane_rslt[lane_to_change][nominalKey], lane_rslt[lane_to_change][earlyKey]= (
lane_rslt[lane_to_change][nominalKey],lane_rslt[lane_to_change][earlyKey], None)
# If there are only 2 ENL variants, make 'Nominal' - the largest
rslt={} rslt={}
for k in lane_rslt[0].keys(): for k in lane_rslt[0].keys():
if (k != parametersKey) and (k != errorKey): if (k != parametersKey) and (k != errorKey):
...@@ -924,8 +976,17 @@ class X393LMA(object): ...@@ -924,8 +976,17 @@ class X393LMA(object):
rslt[parametersKey] = [] rslt[parametersKey] = []
for lane in range(numLanes): for lane in range(numLanes):
rslt[parametersKey].append(lane_rslt[lane][parametersKey]) rslt[parametersKey].append(lane_rslt[lane][parametersKey])
#per1_0
#print parameters?
if quiet <4:
print ("'%s' = ["%(parametersKey))
for lane_params in rslt[parametersKey]:
print("{")
for k,v in lane_params.items():
print('%s:%s'%(k,str(v)))
print("},")
print ("]")
rslt[errorKey]={} rslt[errorKey]={}
# print ("lane_rslt[0][errorKey]=",lane_rslt[0][errorKey])
for k in lane_rslt[0][errorKey].keys(): for k in lane_rslt[0][errorKey].keys():
for r in lane_rslt: # lane_rslt is list of two dictionaries for r in lane_rslt: # lane_rslt is list of two dictionaries
try: try:
...@@ -951,14 +1012,7 @@ class X393LMA(object): ...@@ -951,14 +1012,7 @@ class X393LMA(object):
else: else:
rslt[errorKey][k].append(None) rslt[errorKey][k].append(None)
# print ("lane_rslt[0][errorKey]=",lane_rslt[0][errorKey])
# print ("lane_rslt[1][errorKey]=",lane_rslt[1][errorKey])
# print ("combined: rslt['maxErrDqs']=",rslt['maxErrDqs'])
# print ("rslt=",rslt)
return rslt # byte lanes combined return rslt # byte lanes combined
# rslt['parameters']=parameters
# rslt['maxErrDqs']=DQvDQS_ERR # {enl}[dly]
......
This diff is collapsed.
...@@ -117,17 +117,18 @@ class X393McntrlBuffers(object): ...@@ -117,17 +117,18 @@ class X393McntrlBuffers(object):
def write_block_incremtal(self, def write_block_incremtal(self,
start_word_address, # input [29:0] start_word_address; start_word_address, # input [29:0] start_word_address;
num_words, # input integer num_words; # number of words to write (will be rounded up to multiple of 16) num_words, # input integer num_words; # number of words to write (will be rounded up to multiple of 16)
start_value): # input integer start_value; start_value, # input integer start_value;
quiet=1):
""" """
Fill buffer the incremental data (each next register is written with previous register data + 1 Fill buffer the incremental data (each next register is written with previous register data + 1
<start_word_address> full register address in AXI space (in 32-bit words, not bytes) @param start_word_address full register address in AXI space (in 32-bit words, not bytes)
<num_words> number of 32-bit words to generate/write @param num_words number of 32-bit words to generate/write
<start_value> value to write to the first register (to start_word_address) @start_value value to write to the first register (to start_word_address)
""" """
if self.verbose>0: if quiet < 2:
print("**** write_block_incremtal, start_word_address=0x%x, num_words=0x%x, start_value=0x%x "%(start_word_address,num_words,start_value)) print("**** write_block_incremtal, start_word_address=0x%x, num_words=0x%x, start_value=0x%x "%(start_word_address,num_words,start_value))
for i in range(0,num_words): for i in range(0,num_words):
if self.verbose>2: if quiet < 1:
print(" write_block_buf 0x%x:0x%x"%(start_word_address+i,start_value+i)) print(" write_block_buf 0x%x:0x%x"%(start_word_address+i,start_value+i))
self.x393_mem.axi_write_single_w(start_word_address+i, start_value+i) self.x393_mem.axi_write_single_w(start_word_address+i, start_value+i)
......
...@@ -533,21 +533,24 @@ class X393McntrlTiming(object): ...@@ -533,21 +533,24 @@ class X393McntrlTiming(object):
def axi_set_dqs_dqm_patterns(self, def axi_set_dqs_dqm_patterns(self,
dqs_patt=None, dqs_patt=None,
dqm_patt=None): dqm_patt=None,
quiet=1):
""" """
Set sequencer patterns for the DQ lines ON/OFF (defined by parameters) Set sequencer patterns for the DQ lines ON/OFF (defined by parameters)
<dqs_patt> DQS toggle pattern (if None - use DFLT_DQS_PATTERN (currently 0xaa) @param dqs_patt DQS toggle pattern (if None - use DFLT_DQS_PATTERN (currently 0xaa)
<dm_patt> DM pattern (if None - use DFLT_DQM_PATTERN (currently 0x00) should be 0 for now @param dm_patt DM pattern (if None - use DFLT_DQM_PATTERN (currently 0x00) should be 0 for now
@param quiet reduce output
""" """
if dqs_patt is None: if dqs_patt is None:
dqs_patt=vrlg.DFLT_DQS_PATTERN dqs_patt=vrlg.DFLT_DQS_PATTERN
if dqm_patt is None: if dqm_patt is None:
dqm_patt=vrlg.DFLT_DQM_PATTERN dqm_patt=vrlg.DFLT_DQM_PATTERN
patt = (dqs_patt & 0xff) | ((dqm_patt & 0xff) << 8) patt = (dqs_patt & 0xff) | ((dqm_patt & 0xff) << 8)
if self.DEBUG_MODE > 1: if quiet <2 :
print("SET DQS+DQM PATTERNS, patt= 0x%08x"%patt) print("SET DQS+DQM PATTERNS, patt= 0x%08x"%patt)
# set patterns for DM (always 0) and DQS - always the same (may try different for write lev.) # set patterns for DM (always 0) and DQS - always the same (may try different for write lev.)
self.x393_axi_tasks.write_contol_register(vrlg.MCONTR_PHY_16BIT_ADDR + vrlg.MCONTR_PHY_16BIT_PATTERNS, patt) # 32'h0055); self.x393_axi_tasks.write_contol_register(vrlg.MCONTR_PHY_16BIT_ADDR + vrlg.MCONTR_PHY_16BIT_PATTERNS, patt) # 32'h0055);
def util_test4(self): def util_test4(self):
# print("vrlg.globals():") # print("vrlg.globals():")
# print(vrlg.globals()) # print(vrlg.globals())
......
...@@ -38,7 +38,7 @@ from x393_mem import X393Mem ...@@ -38,7 +38,7 @@ from x393_mem import X393Mem
import x393_axi_control_status import x393_axi_control_status
from x393_mcntrl_buffers import X393McntrlBuffers from x393_mcntrl_buffers import X393McntrlBuffers
#from verilog_utils import * # concat, bits #from verilog_utils import * # concat, bits
from verilog_utils import concat, bits from verilog_utils import concat, bits, convert_mem16_to_w32, convert_w32_to_mem16
#from x393_axi_control_status import concat, bits #from x393_axi_control_status import concat, bits
import vrlg # global parameters import vrlg # global parameters
from time import sleep from time import sleep
...@@ -527,13 +527,13 @@ class X393PIOSequences(object): ...@@ -527,13 +527,13 @@ class X393PIOSequences(object):
""" """
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 @param ba 3-bit memory bank address
@ra 15-bit memory row address @param ra 15-bit memory row address
@ca 10-bit memory column address @param ca 10-bit memory column address
@num8 - number of 8-bursts (default=64, should be >2) @param num8 - number of 8-bursts (default=64, should be >2)
@extraTgl add extra 8-burst of toggling DQS @param extraTgl add extra 8-burst of toggling DQS
@sel - 0 - early, 1 - late read command @param sel - 0 - early, 1 - late read command
@verbose print data being written (default: False) @param verbose print data being written (default: False)
""" """
if verbose > 0: if verbose > 0:
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)) 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))
...@@ -974,15 +974,15 @@ class X393PIOSequences(object): ...@@ -974,15 +974,15 @@ class X393PIOSequences(object):
return self.x393_mcntrl_buffers.read_block_buf_chn (0, 2, num, show_rslt ) # chn=0, page=2, number of 32-bit words=num, show_rslt return self.x393_mcntrl_buffers.read_block_buf_chn (0, 2, num, show_rslt ) # chn=0, page=2, number of 32-bit words=num, show_rslt
def read_block(self, def read_block(self,
num, num,
show_rslt, show_rslt,
wait_complete=1): # Wait for operation to complete wait_complete=1): # Wait for operation to complete
""" """
Read block in PS PIO mode Read block in PS PIO mode
<num> number of 32-bit words to read @param num number of 32-bit words to read
<show_rslt> print read data @param show_rslt print buffer data read 1 - column, 16 - as 16-bit (memory words), 32 - as 32-bit (data words)
<wait_complete> wait read pattern operation to complete (0 - may initiate multiple PS PIO operations) @param wait_complete wait read pattern operation to complete (0 - may initiate multiple PS PIO operations)
returns list of the read data @return list of the read data
""" """
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)
...@@ -1012,6 +1012,117 @@ class X393PIOSequences(object): ...@@ -1012,6 +1012,117 @@ class X393PIOSequences(object):
# 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)
def write_block_inc(self,
num8=64, # max 512 16-bit words
startValue=0,
ca=0,
ra=0,
ba=0,
extraTgl=0, #
sel=1,
quiet=1):
"""
Program sequencer, fill buffer with incremented 16-bit wors (startValue, startValue+1...startValue+nrep*8-1)
and write buffer to memory
@param num8 number of 8-bursts (default=64, should be >2)
@param startValue - value of the first word to write
@param ca 10-bit memory column address
@param ra 15-bit memory row address
@param ba 3-bit memory bank address
@param extraTgl add extra 8-burst of toggling DQS
@param sel 0 - early, 1 - late read command
@param quiet reduce output
"""
self.set_write_block(ba=ba, # input[2:0]ba;
ra=ra, # input[14:0]ra;
ca=ca, # input[9:0]ca;
num8=num8,
extraTgl=extraTgl, #
sel=sel,
verbose=(0,1)[quiet < 2])
wdata16=[startValue+i for i in range(num8*8)]
wdata32=convert_mem16_to_w32(wdata16)
self.x393_mcntrl_buffers.write_block_buf_chn(0,0,wdata32,quiet) # fill block memory (channel, page, number)
self.write_block()
def set_and_read(self,
show_rslt=16,
num8=64, # max 512 16-bit words
ca=0,
ra=0,
ba=0,
sel=1,
quiet=1):
"""
Program sequencer, read block from memory and optionally print it
@param show_rslt: 0 - silent, 1 - as column, 16 - as 16-bit memory words, 32 - as 32-bit (system) words
@param num8 number of 8-bursts (default=64, should be >2)
@param ca 10-bit memory column address
@param ra 15-bit memory row address
@param ba 3-bit memory bank address
@param sel 0 - early, 1 - late read command
@param quiet reduce output
@return read data as 32-bit words
"""
self.set_read_block(ba=ba, # input[2:0]ba;
ra=ra, # input[14:0]ra;
ca=ca, # input[9:0]ca;
num8=num8,
sel=sel,
verbose=(0,1)[quiet < 2])
return self.read_block(num= num8*4,
show_rslt=show_rslt,
wait_complete=1) # Wait for operation to complete
def set_and_read_inc(self,
num8=64, # max 512 16-bit words
ca=0,
ra=0,
ba=0,
sel=1,
quiet=1):
"""
Program sequencer, read block from memory,optionally print it
Epecting incremental 16-bit data block, calculate number of leading and trailing
non-consecutive words and return them as a tuple
@param num8 number of 8-bursts (default=64, should be >2)
@param ca 10-bit memory column address
@param ra 15-bit memory row address
@param ba 3-bit memory bank address
@param sel 0 - early, 1 - late read command
@param quiet reduce output
@return read data as 32-bit words
"""
data32=self.set_and_read(
show_rslt=(0,16)[quiet<2],
num8=num8, # max 512 16-bit words
ca=ca,
ra=ra,
ba=ba,
sel=sel,
quiet=quiet+1)
data16=convert_w32_to_mem16(data32)
mid_index=len(data16)//2
data0= data16[mid_index]-mid_index
for i in range(mid_index-1,-1,-1):
if data16[i] != data0 + i:
first_bad=i+1
break
else:
first_bad= 0
for i in range(mid_index+1,len(data16)):
if data16[i] != data0 + i:
last_bad=len(data16)-i
break
else:
last_bad= 0
if quiet < 3:
print ("non_consecutive leading/trailing: %d /%d"%(first_bad, last_bad))
return (first_bad, last_bad)
def write_levelling(self, def write_levelling(self,
wait_complete=1, # Wait for operation to complete wait_complete=1, # Wait for operation to complete
...@@ -1160,6 +1271,7 @@ class X393PIOSequences(object): ...@@ -1160,6 +1271,7 @@ class X393PIOSequences(object):
def task_set_up(self, def task_set_up(self,
dqs_pattern=None,
quiet = 1): quiet = 1):
""" """
Initial setup of the memory controller, including: Initial setup of the memory controller, including:
...@@ -1173,7 +1285,7 @@ class X393PIOSequences(object): ...@@ -1173,7 +1285,7 @@ class X393PIOSequences(object):
I/O delays I/O delays
clock phase clock phase
write buffer latency write buffer latency
<set_per_pin_delays> - 1 - set individual (per-pin) I/O delays, 0 - use common for the whole class @param dqs_pattern None - use Verilog parameter, other values 0xaa or 0x55 - DQS output value per 1/2 SDCLK period
Returns 1 if phase was set, 0 if it failed Returns 1 if phase was set, 0 if it failed
""" """
#reset memory controller #reset memory controller
...@@ -1185,7 +1297,9 @@ class X393PIOSequences(object): ...@@ -1185,7 +1297,9 @@ class X393PIOSequences(object):
# set dq /dqs tristate on/off patterns # set dq /dqs tristate on/off patterns
self.x393_mcntrl_timing.axi_set_tristate_patterns() self.x393_mcntrl_timing.axi_set_tristate_patterns()
# set patterns for DM (always 0) and DQS - always the same (may try different for write lev.) # set patterns for DM (always 0) and DQS - always the same (may try different for write lev.)
self.x393_mcntrl_timing.axi_set_dqs_dqm_patterns() self.x393_mcntrl_timing.axi_set_dqs_dqm_patterns(dqs_patt=dqs_pattern, # use default
dqm_patt=None, # use default
quiet=1)
# prepare all sequences # prepare all sequences
self.set_all_sequences(quiet) self.set_all_sequences(quiet)
# prepare write buffer # prepare write buffer
......
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