Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
X
x393
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
x393
Commits
45d1f6b7
Commit
45d1f6b7
authored
Apr 09, 2015
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Adding selection correct branch of read/write delays (considering full/half clock cycles)
parent
8ffbbc62
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
793 additions
and
53 deletions
+793
-53
hargs-auto
py393/hargs-auto
+1
-1
x393_lma.py
py393/x393_lma.py
+65
-11
x393_mcntrl_adjust.py
py393/x393_mcntrl_adjust.py
+582
-14
x393_mcntrl_buffers.py
py393/x393_mcntrl_buffers.py
+7
-6
x393_mcntrl_timing.py
py393/x393_mcntrl_timing.py
+7
-4
x393_pio_sequences.py
py393/x393_pio_sequences.py
+131
-17
No files found.
py393/hargs-auto
View file @
45d1f6b7
...
...
@@ -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
-l /usr/local/verilog/x393_cur_params_target.vh
-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 save
py393/x393_lma.py
View file @
45d1f6b7
...
...
@@ -847,7 +847,7 @@ class X393LMA(object):
print
()
return
data_periods_map
def
lma_fit_dq
i_dqsi
(
self
,
def
lma_fit_dq
_dqs
(
self
,
lane
,
# byte lane
bin_size
,
clk_period
,
...
...
@@ -885,8 +885,11 @@ class X393LMA(object):
numLanes
=
2
parametersKey
=
'parameters'
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
):
lane_rslt
.
append
(
self
.
lma_fit_dq
i_dqsi
(
lane
,
# byte lane
lane_rslt
.
append
(
self
.
lma_fit_dq
_dqs
(
lane
,
# byte lane
bin_size
,
clk_period
,
dly_step_ds
,
...
...
@@ -894,7 +897,56 @@ class X393LMA(object):
data_set
,
compare_prim_steps
,
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
%.1
fps (
%
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
=
{}
for
k
in
lane_rslt
[
0
]
.
keys
():
if
(
k
!=
parametersKey
)
and
(
k
!=
errorKey
):
...
...
@@ -924,8 +976,17 @@ class X393LMA(object):
rslt
[
parametersKey
]
=
[]
for
lane
in
range
(
numLanes
):
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
]
=
{}
# print ("lane_rslt[0][errorKey]=",lane_rslt[0][errorKey])
for
k
in
lane_rslt
[
0
][
errorKey
]
.
keys
():
for
r
in
lane_rslt
:
# lane_rslt is list of two dictionaries
try
:
...
...
@@ -951,14 +1012,7 @@ class X393LMA(object):
else
:
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
# rslt['parameters']=parameters
# rslt['maxErrDqs']=DQvDQS_ERR # {enl}[dly]
...
...
py393/x393_mcntrl_adjust.py
View file @
45d1f6b7
...
...
@@ -46,7 +46,11 @@ import x393_lma
import
time
import
vrlg
#NUM_FINE_STEPS= 5
NUM_DLY_STEPS
=
NUM_FINE_STEPS
*
32
# =160
NUM_DLY_STEPS
=
NUM_FINE_STEPS
*
32
# =160
DQI_KEY
=
'dqi'
DQO_KEY
=
'dqo'
ODD_KEY
=
'odd'
class
X393McntrlAdjust
(
object
):
DRY_MODE
=
True
# True
...
...
@@ -211,12 +215,16 @@ class X393McntrlAdjust(object):
filter_dqso
=
2
,
filter_dqsi
=
2
,
filter_cmda
=
2
,
filter_read
=
0
,
filter_write
=
0
,
filter_rsel
=
None
,
filter_wsel
=
None
,
keep_all
=
False
,
set_table
=
True
,
quiet
=
quiet
+
2
)
self
.
adjustment_state
[
'delays_phase'
]
=
delays_phase
except
:
print
(
"Failed to execute
get_'
delays_vs_phase' command"
)
print
(
"Failed to execute
'get_
delays_vs_phase' command"
)
return
False
elif
quiet
<
2
:
print
(
"using provided delays_phase"
)
...
...
@@ -2312,6 +2320,10 @@ class X393McntrlAdjust(object):
filter_dqso
=
2
,
filter_dqsi
=
2
,
filter_cmda
=
2
,
filter_read
=
0
,
filter_write
=
0
,
filter_rsel
=
None
,
filter_wsel
=
None
,
keep_all
=
False
,
set_table
=
True
,
quiet
=
quiet
+
2
)
...
...
@@ -2381,6 +2393,10 @@ class X393McntrlAdjust(object):
filter_dqso
=
0
,
#2,
filter_dqsi
=
1
,
#2,
filter_cmda
=
filter_cmda
,
#2, # special mode - try to keep cmda low, with setup violation to test marginal phase
filter_read
=
0
,
filter_write
=
0
,
filter_rsel
=
None
,
filter_wsel
=
None
,
keep_all
=
False
,
set_table
=
False
,
# True,
quiet
=
quiet
+
2
)
...
...
@@ -2836,21 +2852,488 @@ class X393McntrlAdjust(object):
# Restore default write levelling sequence
self
.
x393_pio_sequences
.
set_write_lev
(
16
,
False
)
# write leveling - 'good' mode (if it was not set so)
return
cmd_odelay
return
cmd_odelay
def
set_read_branch
(
self
,
wbuf_dly
=
9
,
quiet
=
1
):
"""
Try read mode branches and find sel (early/late read command) and wbuf delay,
if possible
Detect shift by 1/2 clock cycle (should not happen), if it does proq_dqi_dqsi with duifferent prim_set (^2) is needed
delay vs. phase should be already calibrated
@param wbuf_dly - initial wbuf delay to try
@quiet reduce output
@return dictionary with key(s) (early,nominal,late) containing dictionary of {'wbuf_dly':xx, 'sel':Y}
optionally result may contain key 'odd' with a list of varinats that resulted in odd number of wrong words
if the remaining number of errors is odd
"""
if
wbuf_dly
is
None
:
wbuf_dly
=
vrlg
.
DFLT_WBUF_DELAY
try
:
delays_phase
=
self
.
adjustment_state
[
'delays_phase'
]
except
:
print
(
"Delays for phases (self.adjustment_state['delays_phase']) are not set, running 'get_delays_vs_phase' command "
)
try
:
delays_phase
=
self
.
get_delays_vs_phase
(
filter_dqo
=
2
,
filter_dqi
=
2
,
filter_dqso
=
2
,
filter_dqsi
=
2
,
filter_cmda
=
2
,
filter_read
=
0
,
filter_write
=
0
,
filter_rsel
=
None
,
filter_wsel
=
None
,
keep_all
=
False
,
set_table
=
True
,
quiet
=
quiet
+
2
)
self
.
adjustment_state
[
'delays_phase'
]
=
delays_phase
except
:
print
(
"Failed to execute get_'delays_vs_phase' command"
)
return
False
#find one valid phase per existing branch
phase_var
=
{}
for
phase
,
dlys
in
enumerate
(
delays_phase
):
try
:
for
k
,
v
in
dlys
[
DQI_KEY
]
.
items
():
if
(
not
k
in
phase_var
)
and
(
not
None
in
v
):
phase_var
[
k
]
=
phase
except
:
pass
if
quiet
<
2
:
print
(
"phase_var="
,
phase_var
)
written
=
False
#write/used block parameters
startValue
=
0
ca
=
0
ra
=
0
ba
=
0
extraTgl
=
1
# just in case
wsel
=
1
rslt
=
{}
odd_list
=
[]
for
var
,
phase
in
phase_var
.
items
():
OK
=
self
.
set_phase_delays
(
phase
=
phase
,
refresh
=
True
,
quiet
=
quiet
+
1
)
# all the rest are defaults
if
not
OK
:
raise
Exception
(
"set_read_branch(): failed to set phase =
%
d"
%
(
phase
))
if
not
written
:
#write_block_inc, it may turn out to be shifted, have problems at the beginning or end - write is not set up yet
self
.
x393_pio_sequences
.
write_block_inc
(
num8
=
64
,
# max 512 16-bit words
startValue
=
startValue
,
ca
=
ca
,
ra
=
ra
,
ba
=
ba
,
extraTgl
=
extraTgl
,
sel
=
wsel
,
quiet
=
quiet
+
1
)
written
=
True
wbuf_dly_max
=
12
wdly
=
max
(
0
,
min
(
wbuf_dly
,
wbuf_dly_max
))
rsel
=
0
#set_and_read_inc 8 16 0 0 1 1
last_wstep
=
0
read_problems
=
None
for
_
in
range
(
20
):
self
.
x393_mcntrl_timing
.
axi_set_wbuf_delay
(
wdly
)
read_problems
=
self
.
x393_pio_sequences
.
set_and_read_inc
(
num8
=
8
,
# max 512 16-bit words
ca
=
ca
+
16
,
ra
=
ra
,
ba
=
ba
,
sel
=
rsel
,
quiet
=
quiet
+
1
)
if
(
read_problems
[
0
]
>=
4
)
or
((
rsel
==
0
)
and
(
read_problems
[
0
]
>=
2
)):
if
last_wstep
<
0
:
if
quiet
<
1
:
print
(
"reversed wstep to +1 at wdly =
%
d"
%
(
wdly
))
break
last_wstep
=
1
wdly
+=
1
if
wdly
>=
wbuf_dly_max
:
print
(
"Exceeded maximal write buffer delay =
%
d while setting up read for branch '
%
s', phase=
%
d"
%
(
wdly
,
var
,
phase
))
read_problems
=
None
break
# continue with next branch
continue
if
(
read_problems
[
1
]
>
4
)
or
(
rsel
and
(
read_problems
[
1
]
==
4
)):
if
last_wstep
>
0
:
if
quiet
<
1
:
print
(
"reversed wstep to -1 at wdly =
%
d"
%
(
wdly
))
break
last_wstep
=-
1
wdly
-=
1
if
wdly
<
1
:
print
(
"Exceeded minimal write buffer delay =
%
d while setting up read for branch '
%
s', phase=
%
d"
%
(
wdly
,
var
,
phase
))
read_problems
=
None
break
# continue with next branch
continue
break
# close to target
if
read_problems
is
None
:
continue
# could not get initial wbuf delay
# read_problems_initial=read_problems
read_problems_min
=
read_problems
best_dw
,
best_sel
=
(
0
,
0
)
if
quiet
<
2
:
print
(
"var="
,
var
)
print
(
"Read_problems_min="
,
read_problems_min
)
print
(
"wdly="
,
wdly
)
print
(
"rsel="
,
rsel
)
print
(
"sum(read_problems_min)="
,
sum
(
read_problems_min
))
if
sum
(
read_problems_min
)
>
0
:
for
dw
,
sel
in
((
-
1
,
0
),(
-
1
,
1
),(
0
,
0
),(
0
,
1
),(
1
,
0
),(
1
,
1
)):
self
.
x393_mcntrl_timing
.
axi_set_wbuf_delay
(
wdly
+
dw
)
read_problems
=
self
.
x393_pio_sequences
.
set_and_read_inc
(
num8
=
8
,
# max 512 16-bit words
ca
=
ca
+
16
,
ra
=
ra
,
ba
=
ba
,
sel
=
sel
^
rsel
,
quiet
=
quiet
+
1
)
if
sum
(
read_problems
)
<
sum
(
read_problems_min
):
read_problems_min
=
read_problems
best_dw
,
best_sel
=
dw
,
sel
if
sum
(
read_problems_min
)
==
0
:
break
wdly
+=
best_dw
rsel
^=
best_sel
if
quiet
<
2
:
print
(
"-Read_problems_min="
,
read_problems_min
)
print
(
"-wdly="
,
wdly
)
print
(
"-rsel="
,
rsel
)
print
(
"-sum(read_problems_min)="
,
sum
(
read_problems_min
))
if
sum
(
read_problems_min
)
==
0
:
rslt
[
var
]
=
{
'wbuf_dly'
:
wdly
,
'sel'
:
rsel
}
if
quiet
<
2
:
print
(
"-rslt="
,
rslt
)
elif
(
read_problems_min
[
0
]
%
2
)
or
(
read_problems_min
[
1
]
%
2
):
odd_list
.
append
(
var
)
if
quiet
<
3
:
print
(
"Failed to find read settings for varinat '
%
s', phase=
%
d - best start read errors=
%
d, end read errors=
%
d"
%
(
var
,
phase
,
read_problems_min
[
0
],
read_problems_min
[
1
]))
print
(
"Odd number of wrong read words means that there is a half clock period shift, you may need to change"
)
print
(
"primary_set parameter of proc_dqi_dqsi() from 2 to 0"
)
else
:
if
quiet
<
2
:
print
(
"Failed to find read settings for varinat '
%
s', phase=
%
d - best start read errors=
%
d, end read errors=
%
d"
%
(
var
,
phase
,
read_problems_min
[
0
],
read_problems_min
[
1
]))
if
quiet
<
2
:
print
(
"odd_list="
,
odd_list
)
for
var
,
v
in
rslt
.
items
():
try
:
self
.
x393_mcntrl_timing
.
axi_set_wbuf_delay
(
v
[
'wbuf_dly'
])
break
except
:
pass
if
odd_list
:
rslt
[
ODD_KEY
]
=
odd_list
self
.
adjustment_state
[
'read_variants'
]
=
rslt
if
quiet
<
3
:
print
(
'read_variants='
,
rslt
)
return
rslt
def
set_write_branch
(
self
,
dqs_pattern
=
None
,
quiet
=
1
):
"""
Try write mode branches and find sel (early/late write command), even if it does not match read settings
Read mode should already be set up
if possible
Detect shift by 1/2 clock cycle (should not happen), if it does proq_dqi_dqsi with duifferent prim_set (^2) is needed
delay vs. phase should be already calibrated
@param dqs_pattern - 0x55/0xaa - DQS output toggle pattern. When it is 0x55 primary_set_out is reversed ?
@quiet reduce output
@return dictioray with a key(s) (early,nominal,late) containing dictionary of {'wbuf_dly':xx, 'sel':Y} or value 'ODD'
if the remaining number of errors is odd
"""
#write/used block parameters
startValue
=
0
num8
=
8
# 8 bursts to read/write
ca
=
0
ra
=
0
ba
=
0
extraTgl
=
1
# just in case
wsel
=
1
rslt
=
{}
readVarKey
=
'read_variants'
if
dqs_pattern
is
None
:
dqs_pattern
=
vrlg
.
DFLT_DQS_PATTERN
else
:
# only set if not None
self
.
x393_mcntrl_timing
.
axi_set_dqs_dqm_patterns
(
dqs_patt
=
dqs_pattern
,
# use default
dqm_patt
=
None
,
# use default
quiet
=
quiet
+
2
)
try
:
delays_phase
=
self
.
adjustment_state
[
'delays_phase'
]
except
:
print
(
"Delays for phases (self.adjustment_state['delays_phase']) are not set, running 'get_delays_vs_phase' command "
)
try
:
delays_phase
=
self
.
get_delays_vs_phase
(
filter_dqo
=
2
,
filter_dqi
=
2
,
filter_dqso
=
2
,
filter_dqsi
=
2
,
filter_cmda
=
2
,
filter_read
=
0
,
filter_write
=
0
,
filter_rsel
=
None
,
filter_wsel
=
None
,
keep_all
=
False
,
set_table
=
True
,
quiet
=
quiet
+
2
)
self
.
adjustment_state
[
'delays_phase'
]
=
delays_phase
except
:
print
(
"Failed to execute get_'delays_vs_phase' command"
)
return
False
try
:
readVars
=
self
.
adjustment_state
[
readVarKey
]
except
:
raise
Exception
(
"Read variants are not set up, need to run command set_read_branch90 first"
)
#verify read varinats have valid (not "ODD") branch
readBranch
=
None
for
var
in
readVars
:
if
var
!=
ODD_KEY
:
readBranch
=
var
break
else
:
raise
Exception
(
"No valid read variant is found, can not proceed with write setup"
)
readPhase
=
None
#find one valid phase per existing branch
phase_var
=
{}
read_phase_var
=
{}
for
phase
,
dlys
in
enumerate
(
delays_phase
):
try
:
for
k
,
v
in
dlys
[
DQO_KEY
]
.
items
():
if
not
None
in
v
:
if
not
k
in
phase_var
:
phase_var
[
k
]
=
phase
if
not
k
in
read_phase_var
:
# read phase is not set yet for this write variant
if
not
None
in
dlys
[
DQI_KEY
][
readBranch
]:
# usually will fail here
phase_var
[
k
]
=
phase
read_phase_var
[
k
]
=
phase
readPhase
=
phase
# will hold phase that
except
:
pass
if
quiet
<
2
:
print
(
"phase_var="
,
phase_var
)
print
(
"readPhase="
,
readPhase
)
print
(
"read_phase_var="
,
read_phase_var
)
if
not
phase_var
:
raise
Exception
(
"Could not find any valid phase for writing to consider"
)
if
readPhase
is
None
:
#find some phase to correctly read data, even if it does not match any write phase
for
phase
,
dlys
in
enumerate
(
delays_phase
):
try
:
if
not
None
in
dlys
[
DQI_KEY
][
readBranch
]:
# usually will fail here
readPhase
=
phase
break
except
:
pass
else
:
raise
Exception
(
"Could not find any valid phase to read block correctly"
)
#see if any of the write varinats does not have read phase - use default readPhase
for
var
in
phase_var
:
if
not
var
in
read_phase_var
:
read_phase_var
[
var
]
=
readPhase
if
quiet
<
2
:
print
(
"phase_var="
,
phase_var
)
print
(
"readPhase="
,
readPhase
)
print
(
"read_phase_var="
,
read_phase_var
)
if
quiet
<
1
:
print
(
"readVars="
,
readVars
)
self
.
x393_mcntrl_timing
.
axi_set_wbuf_delay
(
readVars
[
readBranch
][
'wbuf_dly'
])
rsel
=
readVars
[
readBranch
][
'sel'
]
odd_list
=
[]
for
var
,
phase
in
phase_var
.
items
():
problems_min
=
None
best_wsel
=
None
for
wsel
in
range
(
2
):
OK
=
self
.
set_phase_delays
(
phase
=
phase
,
refresh
=
True
,
quiet
=
quiet
+
2
)
# all the rest are defaults
if
not
OK
:
raise
Exception
(
"set_read_branch(): failed to set phase =
%
d"
%
(
phase
))
self
.
x393_pio_sequences
.
write_block_inc
(
num8
=
num8
,
# max 512 16-bit words
startValue
=
startValue
,
ca
=
ca
,
ra
=
ra
,
ba
=
ba
,
extraTgl
=
extraTgl
,
sel
=
wsel
,
quiet
=
quiet
+
1
)
startValue
+=
0x200
startValue
&=
0xffff
if
phase
!=
read_phase_var
[
var
]:
OK
=
self
.
set_phase_delays
(
phase
=
read_phase_var
[
var
],
refresh
=
True
,
quiet
=
quiet
+
2
)
# all the rest are defaults
if
not
OK
:
raise
Exception
(
"set_read_branch(): failed to set phase =
%
d"
%
(
phase
))
problems
=
self
.
x393_pio_sequences
.
set_and_read_inc
(
num8
=
num8
,
# max 512 16-bit words
ca
=
ca
,
ra
=
ra
,
ba
=
ba
,
sel
=
rsel
,
quiet
=
quiet
+
1
)
if
(
problems_min
is
None
)
or
(
sum
(
problems
)
<
sum
(
problems_min
)):
problems_min
=
problems
best_wsel
=
wsel
if
sum
(
problems_min
)
==
0
:
rslt
[
var
]
=
{
'sel'
:
best_wsel
}
elif
(
problems_min
[
0
]
%
2
)
or
(
problems_min
[
1
]
%
2
):
odd_list
.
append
(
var
)
if
quiet
<
3
:
print
(
"Failed to find write settings for varinat '
%
s', phase=
%
d - best start write errors=
%
d, end write errors=
%
d, wsel=
%
d"
%
(
var
,
phase
,
problems_min
[
0
],
problems_min
[
1
],
best_wsel
))
print
(
"Odd number of wrong read words means that there is a half clock period shift, you may need to change"
)
print
(
"primary_set parameter of proc_dqo_dqso() 2 <->0 or change DQS pattern (0x55<->0xAA)"
)
print
(
"Using of DQS PATTERN of 0xAA (output will start from 0, not 1) is not optimal, it requires extra toggling"
)
print
(
"of the DQS line after the end of block write"
)
else
:
if
quiet
<
2
:
print
(
"Failed to find write settings for varinat '
%
s', phase=
%
d - best start read errors=
%
d, end read errors=
%
d, wsel=
%
d"
%
(
var
,
phase
,
problems_min
[
0
],
problems_min
[
1
],
best_wsel
))
if
odd_list
:
rslt
[
ODD_KEY
]
=
odd_list
self
.
adjustment_state
[
'write_variants'
]
=
rslt
if
quiet
<
3
:
print
(
'write_variants='
,
rslt
)
return
rslt
def
get_phase_range
(
self
,
rsel
=
None
,
# None (any) or 0/1
wsel
=
None
,
# None (any) or 0/1
quiet
=
3
):
"""
@param rsel filter by early/late read command (in two-clock command cycle - 'sel') Valid values: None, 0 or 1
@param wsel filter by early/late write command (in two-clock command cycle - 'sel') Valid values: None, 0 or 1
@param quiet reduce output
@return {'optimal_phase': optimal phase, 'rsel': read_sel, 'wsel': write_sel, 'min_phase': minimal_phase, 'max_phase': maximal_phase}
'max_phase' may be lower than 'min_phase' if the range rolls over
"""
# self.load_mcntrl('dbg/state_0x55.pickle')
try
:
read_variants
=
self
.
adjustment_state
[
'read_variants'
]
except
:
read_variants
=
None
try
:
write_variants
=
self
.
adjustment_state
[
'write_variants'
]
except
:
write_variants
=
None
try
:
delays_phase
=
self
.
get_delays_vs_phase
(
filter_dqo
=
2
,
filter_dqi
=
2
,
filter_dqso
=
2
,
filter_dqsi
=
2
,
filter_cmda
=
2
,
filter_read
=
True
,
filter_write
=
True
,
filter_rsel
=
rsel
,
filter_wsel
=
wsel
,
keep_all
=
False
,
set_table
=
True
,
# quiet=quiet+2)
quiet
=
quiet
)
self
.
adjustment_state
[
'delays_phase'
]
=
delays_phase
except
:
print
(
"Failed to execute 'get_delays_vs_phase' command"
)
return
None
phase_starts
=
[]
numPhases
=
len
(
delays_phase
)
for
phase
,
dlys
in
enumerate
(
delays_phase
):
if
(
not
dlys
is
None
)
and
(
delays_phase
[(
phase
-
1
)
%
numPhases
]
is
None
):
phase_starts
.
append
(
phase
)
phase_lengths
=
[]
if
phase_starts
:
for
phase_start
in
phase_starts
:
for
phase
in
range
(
phase_start
+
1
,
phase_start
+
numPhases
):
p
=
phase
%
numPhases
if
delays_phase
[
p
]
is
None
:
phase_lengths
.
append
((
p
-
phase_start
)
%
numPhases
)
break
best_len
=
max
(
phase_lengths
)
best_start
=
phase_starts
[
phase_lengths
.
index
(
best_len
)]
else
:
# no ends, maybe all None, or all non-None
if
delays_phase
[
0
]
is
None
:
return
None
else
:
# all are valid
best_start
=
0
best_len
=
numPhases
#find center
rslt
=
{}
optimal_phase
=
(
best_start
+
best_len
//
2
)
%
numPhases
rslt
[
'optimal_phase'
]
=
optimal_phase
rslt
[
'min_phase'
]
=
best_start
rslt
[
'max_phase'
]
=
(
best_start
+
best_len
-
1
)
%
numPhases
read_var
=
"A"
write_var
=
"A"
if
quiet
<
2
:
print
(
"result="
,
rslt
)
print
(
"phase_starts="
,
phase_starts
)
print
(
"phase_lengths="
,
phase_lengths
)
if
not
read_variants
is
None
:
# find common variants in read_variants and delays_phase[optimal_phase] - in the future there may be several of them!
variants
=
[]
for
var
in
read_variants
.
keys
():
if
quiet
<
1
:
print
(
"var="
,
var
)
print
(
"delays_phase[optimal_phase]="
,
delays_phase
[
optimal_phase
])
print
(
"delays_phase[optimal_phase][DQI_KEY]="
,
delays_phase
[
optimal_phase
][
DQI_KEY
])
if
var
in
delays_phase
[
optimal_phase
][
DQI_KEY
]:
variants
.
append
(
var
)
if
variants
:
rslt
[
'rsel'
]
=
read_variants
[
variants
[
0
]][
'sel'
]
read_var
=
variants
[
0
][
0
]
.
upper
()
if
not
write_variants
is
None
:
# find common variants in write_variants and delays_phase[optimal_phase] - in the future there may be several of them!
variants
=
[]
for
var
in
write_variants
.
keys
():
if
var
in
delays_phase
[
optimal_phase
][
DQO_KEY
]:
variants
.
append
(
var
)
if
variants
:
rslt
[
'wsel'
]
=
write_variants
[
variants
[
0
]][
'sel'
]
write_var
=
variants
[
0
][
0
]
.
upper
()
if
quiet
<
4
:
print
(
"result="
,
rslt
)
#set delays to set Verilog parameters. TODO: save sel-s somehow too?
self
.
set_phase_delays
(
phase
=
optimal_phase
,
inp_period
=
read_var
,
out_period
=
write_var
,
refresh
=
False
,
delays_phase
=
delays_phase
,
# if None - use global
quiet
=
quiet
)
return
rslt
def
measure_all
(
self
,
tasks
=
"ICWRPOASZ"
,
prim_steps
=
1
,
primary_set_in
=
2
,
primary_set_out
=
2
,
dqs_pattern
=
0xaa
,
quiet
=
3
):
"""
@param tasks - "C" cmda, "W' - write levelling, "R" - read levelling (DQI-DQSI), "P" - dqs input phase (DQSI-PHASE),
"O" - output timing (DQ odelay vs DQS odelay), "A" - address/bank lines output delays, "Z" - print results
@param prim_steps - compare measurement with current delay with one lower by 1 primary step (5 fine delay steps), 0 -
compare with one fine step lower
@param primary_set_in - which of the primary sets to use when processing DQi/DQSi results (2 - normal, 0 - other DQS phase)
@param primary_set_out - which of the primary sets to use when processing DQo/DQSo results (2 - normal, 0 - other DQS phase)
@param dqs_pattern - 0x55/0xaa - DQS output toggle pattern. When it is 0x55 primary_set_out is reversed ?
@param quiet reduce output
"""
# dqs_pattern=0x55 # 0xaa
max_phase_err
=
0.1
frac_step
=
0.125
# read_sel=1 # set DDR3 command in the second cycle of two (0 - during the first omne)
...
...
@@ -2874,9 +3357,8 @@ class X393McntrlAdjust(object):
{
'key'
:
'I'
,
'func'
:
self
.
x393_pio_sequences
.
task_set_up
,
'comment'
:
'Initial setup - memory controller, sequnces'
,
'params'
:{
'quiet'
:
quiet
+
1
}},
'params'
:{
'dqs_pattern'
:
dqs_pattern
,
'quiet'
:
quiet
+
1
}},
{
'key'
:
'C'
,
'func'
:
self
.
adjust_cmda_odelay
,
'comment'
:
'Measuring CMDA output delay for each clock phase'
,
...
...
@@ -2971,6 +3453,10 @@ class X393McntrlAdjust(object):
'filter_dqso'
:
2
,
'filter_dqsi'
:
2
,
'filter_cmda'
:
2
,
'filter_read'
:
0
,
'filter_write'
:
0
,
'filter_rsel'
:
None
,
'filter_wsel'
:
None
,
'keep_all'
:
False
,
'set_table'
:
True
,
'quiet'
:
quiet
+
1
}},
...
...
@@ -3089,7 +3575,7 @@ class X393McntrlAdjust(object):
if
quiet
<
1
:
x393_lma
.
test_data
(
meas_delays
,
compare_prim_steps
,
quiet
)
lma
=
x393_lma
.
X393LMA
()
rslt
=
lma
.
lma_fit_dq
i_dqsi
(
lane
,
rslt
=
lma
.
lma_fit_dq
_dqs
(
lane
,
bin_size
,
1000.0
*
self
.
x393_mcntrl_timing
.
get_dly_steps
()[
'SDCLK_PERIOD'
],
# 2500.0, # clk_period,
78.0
,
# dly_step_ds,
...
...
@@ -3235,7 +3721,7 @@ class X393McntrlAdjust(object):
if
quiet
<
1
:
x393_lma
.
test_data
(
meas_delays
,
compare_prim_steps
,
quiet
)
lma
=
x393_lma
.
X393LMA
()
rslt
=
lma
.
lma_fit_dq
i_dqsi
(
lane
,
rslt
=
lma
.
lma_fit_dq
_dqs
(
lane
,
bin_size
,
1000.0
*
self
.
x393_mcntrl_timing
.
get_dly_steps
()[
'SDCLK_PERIOD'
],
# 2500.0, # clk_period,
78.0
,
# dly_step_ds,
...
...
@@ -3607,6 +4093,10 @@ class X393McntrlAdjust(object):
filter_dqso
=
2
,
filter_dqsi
=
2
,
filter_cmda
=
2
,
filter_read
=
0
,
filter_write
=
0
,
filter_rsel
=
None
,
filter_wsel
=
None
,
keep_all
=
False
,
set_table
=
True
,
quiet
=
2
):
...
...
@@ -3620,6 +4110,12 @@ class X393McntrlAdjust(object):
@param filter_dqsi for DQS input delays
@param filter_cmda for command and address output delays
if non-integer - special mode - try to keep cmda low, with setup violation to test marginal phase
@param filter_read remove phases that do not provide correct reads (data shifted by some periods/half periods)
@param filter_write remove phases that do not provide correct writes (data shifted by some periods/half periods)
@param filter_rsel filter by early/late read command (in two-clock command cycle - 'sel') Valid values: None, 0 or 1
@param filter_wsel filter by early/late write command (in two-clock command cycle - 'sel') Valid values: None, 0 or 1
@param keep_all Keep phases where some delays do not have valid values, just mark them as None
remove just items that do not have any non-None elements
@param set_table store results to the global table (used to simultaneously set all pahse-derived
...
...
@@ -3641,6 +4137,37 @@ class X393McntrlAdjust(object):
# clk_period=1000.0*timing['SDCLK_PERIOD'] # in PS
if
quiet
<
1
:
print
(
"halfDlyRange="
,
halfDlyRange
)
try
:
read_variants
=
self
.
adjustment_state
[
'read_variants'
]
except
:
read_variants
=
None
try
:
write_variants
=
self
.
adjustment_state
[
'write_variants'
]
except
:
write_variants
=
None
if
filter_read
or
(
not
filter_rsel
is
None
):
if
not
read_variants
is
None
:
filter_read
=
1
# if filter_rsel is not None
if
filter_dqsi
==
0
:
filter_dqsi
=
2
if
filter_dqi
==
0
:
filter_dqi
=
2
else
:
print
(
'Data for filter_read is not available (self.adjustment_state["read_variants"]'
)
filter_read
=
0
filter_rsel
=
None
if
filter_write
or
(
not
filter_wsel
is
None
):
if
not
write_variants
is
None
:
filter_write
=
1
# if filter_wsel is not None
if
filter_dqso
==
0
:
filter_dqso
=
2
if
filter_dqo
==
0
:
filter_dqo
=
2
else
:
print
(
'Data for filter_write is not available (self.adjustment_state["write_variants"]'
)
filter_write
=
0
filter_wsel
=
None
delays_phase
=
[]
if
filter_dqo
:
try
:
...
...
@@ -3764,6 +4291,10 @@ class X393McntrlAdjust(object):
else
:
if
None
in
dqi
:
continue
# not this branch
elif
filter_read
and
not
k
in
read_variants
:
continue
# not this branch
elif
(
not
filter_rsel
is
None
)
and
(
k
in
read_variants
)
and
(
read_variants
[
k
][
'sel'
]
!=
filter_rsel
):
continue
# not this branch
elif
(
filter_dqi
==
2
)
and
((
max
(
dqi
)
-
min
(
dqi
))
>
halfDlyRange
):
continue
# failed filter, continue to the next branch
dqi_options
[
k
]
=
dqi
...
...
@@ -3788,6 +4319,10 @@ class X393McntrlAdjust(object):
else
:
if
None
in
dqo
:
continue
# not this branch
elif
filter_write
and
not
k
in
write_variants
:
continue
# not this branch
elif
(
not
filter_wsel
is
None
)
and
(
k
in
write_variants
)
and
(
write_variants
[
k
][
'sel'
]
!=
filter_wsel
):
continue
# not this branch
elif
(
filter_dqi
==
2
)
and
((
max
(
dqo
)
-
min
(
dqo
))
>
halfDlyRange
):
continue
# failed filter, continue to the next branch
dqo_options
[
k
]
=
dqo
...
...
@@ -3849,6 +4384,9 @@ class X393McntrlAdjust(object):
break
except
:
pass
if
numBits
is
None
:
print
(
"No phase has all delays valid"
)
return
delays_phase
numLanes
=
numBits
//
8
try
:
maxErrDqsi
=
self
.
adjustment_state
[
"maxErrDqsi"
]
...
...
@@ -3879,15 +4417,21 @@ class X393McntrlAdjust(object):
print
(
"
%
s-DQ
%
di"
%
(
k
.
upper
()[
0
],
b
),
end
=
" "
)
for
lane
in
range
(
numLanes
):
print
(
"DQS
%
d0"
%
(
lane
),
end
=
" "
)
#TODO: add DQ%do
for
k
in
enl_list_out
:
for
b
in
range
(
numBits
):
print
(
"
%
s-DQ
%
do"
%
(
k
.
upper
()[
0
],
b
),
end
=
" "
)
if
not
read_variants
is
None
:
for
k
in
enl_list_in
:
print
(
"
%
s-rsel"
%
(
k
.
upper
()[
0
]),
end
=
" "
)
if
not
write_variants
is
None
:
for
k
in
enl_list_out
:
print
(
"
%
s-wsel"
%
(
k
.
upper
()[
0
]),
end
=
" "
)
for
k
in
enl_list_in
:
print
(
"
%
s-in-err"
%
(
k
.
upper
()[
0
]),
end
=
" "
)
for
k
in
enl_list_out
:
print
(
"
%
s-out-err"
%
(
k
.
upper
()[
0
]),
end
=
" "
)
print
()
print
()
#print table rows
for
phase
,
phase_data
in
enumerate
(
delays_phase
):
print
(
"
%
d"
%
(
phase
),
end
=
" "
)
...
...
@@ -3926,13 +4470,30 @@ class X393McntrlAdjust(object):
print
(
"
%
d"
%
(
phase_data
[
'dqo'
][
k
][
b
]),
end
=
" "
)
except
:
print
(
"?"
,
end
=
" "
)
if
not
read_variants
is
None
:
for
k
in
enl_list_in
:
try
:
if
not
None
in
phase_data
[
'dqi'
][
k
]:
print
(
"
%
d"
%
(
10
*
read_variants
[
k
][
'sel'
]),
end
=
" "
)
# 10* - for graph visibility
else
:
print
(
"?"
,
end
=
" "
)
except
:
print
(
"?"
,
end
=
" "
)
if
not
write_variants
is
None
:
for
k
in
enl_list_out
:
try
:
# print ('k=',k,end=" ")
# print ("phase_data['dqo']=",phase_data['dqo'])
if
not
None
in
phase_data
[
'dqo'
][
k
]:
print
(
"
%
d"
%
(
12
*
write_variants
[
k
][
'sel'
]),
end
=
" "
)
# 12* - for graph visibility
else
:
print
(
"?"
,
end
=
" "
)
except
:
print
(
"?"
,
end
=
" "
)
for
k
in
enl_list_in
:
try
:
if
not
None
in
phase_data
[
'dqsi'
]:
max_err
=
max
(
maxErrDqsi
[
k
][
dly
][
lane
]
for
lane
,
dly
in
enumerate
(
phase_data
[
'dqsi'
]))
# for dly in phase_data['dqsi']:
# err=maxErrDqsi[k][dly]
# print("%.1f"%(err),end=" ")
print
(
"
%.1
f"
%
(
max_err
),
end
=
" "
)
else
:
print
(
"X"
,
end
=
" "
)
...
...
@@ -3956,7 +4517,10 @@ class X393McntrlAdjust(object):
def
show_all_vs_phase
(
self
,
keep_all
=
False
,
load_hardcoded
=
False
):
load_hardcoded
=
False
,
filter_rw
=
False
,
filter_rsel
=
None
,
filter_wsel
=
None
):
'''
Show table (to be copied to a spreadsheet) with all delay settings for each
DDR3 memory clock phase value
...
...
@@ -3973,6 +4537,10 @@ class X393McntrlAdjust(object):
filter_dqso
=
2
,
filter_dqsi
=
2
,
filter_cmda
=
2
,
filter_read
=
(
0
,
1
)[
filter_rw
],
#
filter_write
=
(
0
,
1
)[
filter_rw
],
filter_rsel
=
filter_rsel
,
filter_wsel
=
filter_wsel
,
keep_all
=
keep_all
,
set_table
=
False
,
quiet
=
2
)
...
...
py393/x393_mcntrl_buffers.py
View file @
45d1f6b7
...
...
@@ -117,17 +117,18 @@ class X393McntrlBuffers(object):
def
write_block_incremtal
(
self
,
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)
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
<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
<start_value>
value to write to the first register (to start_word_address)
@param start_word_address
full register address in AXI space (in 32-bit words, not bytes)
@param num_words
number of 32-bit words to generate/write
@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
))
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
))
self
.
x393_mem
.
axi_write_single_w
(
start_word_address
+
i
,
start_value
+
i
)
...
...
py393/x393_mcntrl_timing.py
View file @
45d1f6b7
...
...
@@ -533,21 +533,24 @@ class X393McntrlTiming(object):
def
axi_set_dqs_dqm_patterns
(
self
,
dqs_patt
=
None
,
dqm_patt
=
None
):
dqm_patt
=
None
,
quiet
=
1
):
"""
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)
<dm_patt> DM pattern (if None - use DFLT_DQM_PATTERN (currently 0x00) should be 0 for now
@param dqs_patt DQS toggle pattern (if None - use DFLT_DQS_PATTERN (currently 0xaa)
@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
:
dqs_patt
=
vrlg
.
DFLT_DQS_PATTERN
if
dqm_patt
is
None
:
dqm_patt
=
vrlg
.
DFLT_DQM_PATTERN
patt
=
(
dqs_patt
&
0xff
)
|
((
dqm_patt
&
0xff
)
<<
8
)
if
self
.
DEBUG_MODE
>
1
:
if
quiet
<
2
:
print
(
"SET DQS+DQM PATTERNS, patt= 0x
%08
x"
%
patt
)
# 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);
def
util_test4
(
self
):
# print("vrlg.globals():")
# print(vrlg.globals())
...
...
py393/x393_pio_sequences.py
View file @
45d1f6b7
...
...
@@ -38,7 +38,7 @@ from x393_mem import X393Mem
import
x393_axi_control_status
from
x393_mcntrl_buffers
import
X393McntrlBuffers
#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
import
vrlg
# global parameters
from
time
import
sleep
...
...
@@ -527,13 +527,13 @@ class X393PIOSequences(object):
"""
Setup write block sequence at parameter defined address in the sequencer memory
@ba 3-bit memory bank address
@ra 15-bit memory row address
@ca 10-bit memory column address
@num8 - number of 8-bursts (default=64, should be >2)
@extraTgl add extra 8-burst of toggling DQS
@sel - 0 - early, 1 - late read command
@verbose print data being written (default: False)
@
param
ba 3-bit memory bank address
@
param
ra 15-bit memory row address
@
param
ca 10-bit memory column address
@
param
num8 - number of 8-bursts (default=64, should be >2)
@
param
extraTgl add extra 8-burst of toggling DQS
@
param
sel - 0 - early, 1 - late read command
@
param
verbose print data being written (default: False)
"""
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
))
...
...
@@ -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
def
read_block
(
self
,
num
,
show_rslt
,
wait_complete
=
1
):
# Wait for operation to complete
num
,
show_rslt
,
wait_complete
=
1
):
# Wait for operation to complete
"""
Read block in PS PIO mode
<num>
number of 32-bit words to read
<show_rslt> print read data
<wait_complete>
wait read pattern operation to complete (0 - may initiate multiple PS PIO operations)
returns
list of the read data
@param num
number of 32-bit words to read
@param show_rslt print buffer data read 1 - column, 16 - as 16-bit (memory words), 32 - as 32-bit (data words)
@param wait_complete
wait read pattern operation to complete (0 - may initiate multiple PS PIO operations)
@return
list of the read data
"""
self
.
schedule_ps_pio
(
# schedule software-control memory operation (may need to check FIFO status first)
...
...
@@ -1012,6 +1012,117 @@ class X393PIOSequences(object):
# temporary - for debugging:
# 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
,
wait_complete
=
1
,
# Wait for operation to complete
...
...
@@ -1160,6 +1271,7 @@ class X393PIOSequences(object):
def
task_set_up
(
self
,
dqs_pattern
=
None
,
quiet
=
1
):
"""
Initial setup of the memory controller, including:
...
...
@@ -1173,7 +1285,7 @@ class X393PIOSequences(object):
I/O delays
clock phase
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
"""
#reset memory controller
...
...
@@ -1185,7 +1297,9 @@ class X393PIOSequences(object):
# set dq /dqs tristate on/off 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.)
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
self
.
set_all_sequences
(
quiet
)
# prepare write buffer
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment