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
Expand all
Show 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
,
...
...
@@ -895,6 +898,55 @@ class X393LMA(object):
compare_prim_steps
,
scale_w
,
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
This diff is collapsed.
Click to expand it.
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
))
...
...
@@ -979,10 +979,10 @@ class X393PIOSequences(object):
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