Commit 6ff31a13 authored by Andrey Filippov's avatar Andrey Filippov

porting delay scan/adjustment functions from the eddr3 Python code

parent 652c47ec
......@@ -97,7 +97,7 @@
<link>
<name>vivado_logs/VivadoTimimgSummaryReportImplemented.log</name>
<type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoTimimgSummaryReportImplemented-20150311172942225.log</location>
<location>/home/andrey/git/x393/vivado_logs/VivadoTimimgSummaryReportImplemented-20150313235008423.log</location>
</link>
<link>
<name>vivado_logs/VivadoTimimgSummaryReportSynthesis.log</name>
......@@ -107,7 +107,7 @@
<link>
<name>vivado_logs/VivadoTimingReportImplemented.log</name>
<type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoTimingReportImplemented-20150311172942225.log</location>
<location>/home/andrey/git/x393/vivado_logs/VivadoTimingReportImplemented-20150314001725869.log</location>
</link>
<link>
<name>vivado_logs/VivadoTimingReportSynthesis.log</name>
......
......@@ -73,7 +73,9 @@ NUM_FINE_STEPS= 5
DLY_PHASE= 0x2c # 0x1c # mmcm fine phase shift, 1/4 tCK
*/
`ifdef TARGET_MODE
`ifdef TARGET_MODE
localparam T_RFC=50; // t_rfc=50 for tCK=2.5ns
localparam T_REFI=48; // t_refi; # 48/97 for normal, 8 - for simulation (7.8us <85C, 3.9us >85C)
`ifdef use200Mhz
localparam DLY_LANE0_DQS_WLV_IDELAY = 8'hb0; // idelay dqs
localparam DLY_LANE1_DQS_WLV_IDELAY = 8'hb0; // idelay dqs
......@@ -113,19 +115,21 @@ DLY_PHASE= 0x2c # 0x1c # mmcm fine phase shift, 1/4 tCK
`endif
localparam DLY_PHASE= 8'h1c; // mmcm fine phase shift, 1/4 tCK
`else
localparam T_RFC=50; // t_rfc=50 for tCK=2.5ns
localparam T_REFI=16; // t_refi; # 48/97 for normal, 8 - for simulation (7.8us <85C, 3.9us >85C)
`ifdef use200Mhz
localparam DLY_LANE0_DQS_WLV_IDELAY = 8'hb0; // idelay dqs
localparam DLY_LANE1_DQS_WLV_IDELAY = 8'hb0; // idelay dqs
localparam DLY_LANE0_ODELAY= 80'h4c4c4b4a494844434241; // odelay dqm, odelay ddqs, odelay dq[7:0]
localparam DLY_LANE0_ODELAY= 80'h4c784b4a494844434241; // odelay dqm, odelay ddqs, odelay dq[7:0]
localparam DLY_LANE0_IDELAY= 72'ha0636261605c5b5a59; // idelay dqs, idelay dq[7:0
localparam DLY_LANE1_ODELAY= 80'h4c4c4b4a494844434241; // odelay dqm, odelay ddqs, odelay dq[7:0]
localparam DLY_LANE1_ODELAY= 80'h4c784b4a494844434241; // odelay dqm, odelay ddqs, odelay dq[7:0]
localparam DLY_LANE1_IDELAY= 72'ha0636261605c5b5a59; // idelay dqs, idelay dq[7:0
localparam DLY_CMDA= 256'h3c3c3c3c3b3a39383434343433323130002c2c2c2b2a29282424242423222120; // odelay odt, cke, cas, ras, we, ba2,ba1,ba0, X, a14,..,a0
// alternative to set same type delays to the same value
localparam DLY_DQ_IDELAY = 'h20 ;// 'h60;
localparam DLY_DQ_ODELAY = 'ha0; // 'h48;
localparam DLY_DQS_IDELAY = 'h40; // 'ha0;
localparam DLY_DQS_ODELAY = 'h4c; //
localparam DLY_DQS_ODELAY = 'h78; //
localparam DLY_DM_ODELAY = 'ha0; // 'h48;
localparam DLY_CMDA_ODELAY ='h50; // 'h30;
`else
......
......@@ -41,6 +41,10 @@
task axi_set_dqs_odelay_nominal; //SuppressThisWarning VEditor : may be unused
begin
$display("axi_set_dqs_odelay_nominal(0x%x,0x%x) @ %t",
(DLY_LANE0_ODELAY >> (8<<3)) & 32'hff,
(DLY_LANE1_ODELAY >> (8<<3)) & 32'hff,
$time);
// axi_set_dqs_idelay(
write_contol_register(LD_DLY_LANE0_ODELAY + 8, (DLY_LANE0_ODELAY >> (8<<3)) & 32'hff);
write_contol_register(LD_DLY_LANE1_ODELAY + 8, (DLY_LANE1_ODELAY >> (8<<3)) & 32'hff);
......@@ -68,6 +72,8 @@
task axi_set_delays; // set all individual delays
integer i;
begin
$display("axi_set_delays @ %t",$time);
for (i=0;i<10;i=i+1) begin
write_contol_register(LD_DLY_LANE0_ODELAY + i, (DLY_LANE0_ODELAY >> (i<<3)) & 32'hff);
end
......
......@@ -210,7 +210,7 @@ task set_read_pattern;
end
// nop - all 3 below are the same? - just repeat?
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
data <= func_encode_skip( 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0);
data <= func_encode_skip( 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0); // was BUF WR
@(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
// nop
// skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
......
......@@ -70,7 +70,7 @@ module phy_cmd#(
// clocks, reset
input clk_in,
input rst_in,
output mclk, // global clock, half DDR3 clock, synchronizes all I/O thorough the command port
output mclk, // global clock, half DDR3 clock, synchronizes all I/O through the command port
// inteface to control I/O delays and mmcm
input [7:0] dly_data, // delay value (3 LSB - fine delay)
input [6:0] dly_addr, // select which delay to program
......
......@@ -285,6 +285,7 @@ wire sdclk; // BUFIO
// mclk - same frequency as clk_div (same dynamic phase adjust), but with BUFG to be used in other regions. Phase to be
// statically adjusted for clock boundary crossing
// Phase control included, allowing setting phase in +/- 127 steps, each 1/56 of 1/Fvco (~22ps for Fvco=800MHz)
// So shifting phase dynamically by plus/- 113 moves SDCLK by a full period (2.5ns) forward and backward (113= 0x71)
wire clk_pre, clk_div_pre, sdclk_pre, mclk_pre, clk_fb;
BUFR clk_bufr_i (.O(clk), .CE(), .CLR(), .I(clk_pre));
BUFR clk_div_bufr_i (.O(clk_div), .CE(), .CLR(), .I(clk_div_pre));
......
-v
-d TARGET_MODE=1
-f /usr/local/verilog/system_defines.vh
-f /usr/local/verilog/x393_parameters.vh /usr/local/verilog/x393_localparams.vh
......
......@@ -44,6 +44,8 @@ from argparse import RawDescriptionHelpFormatter
from import_verilog_parameters import ImportVerilogParameters
from import_verilog_parameters import VerilogParameters
from verilog_utils import hx
import x393_mem
import x393_utils
import x393_axi_control_status
......@@ -51,6 +53,7 @@ import x393_pio_sequences
import x393_mcntrl_timing
import x393_mcntrl_buffers
import x393_mcntrl_tests
import x393_mcntrl_adjust
__all__ = []
__version__ = 0.1
__date__ = '2015-03-01'
......@@ -122,11 +125,7 @@ def execTask(commandLine):
else:
result = callableTasks[funcName]['func'](callableTasks[funcName]['inst'],*funcArgs)
return result
def hx(obj):
try:
return "0x%x"%obj
except:
return str(obj)
def getFuncArgsString(name):
funcFArgs=callableTasks[name]['args']
......@@ -297,6 +296,8 @@ USAGE
x393Timing= x393_mcntrl_timing.X393McntrlTiming(verbose,args.simulated)
x393Buffers=x393_mcntrl_buffers.X393McntrlBuffers(verbose,args.simulated)
x393Tests= x393_mcntrl_tests.X393McntrlTests(verbose,args.simulated)
x393Adjust= x393_mcntrl_adjust.X393McntrlAdjust(verbose,args.simulated)
'''
print ("----------------------")
print("x393_mem.__dict__="+str(x393_mem.__dict__))
......@@ -318,6 +319,7 @@ USAGE
extractTasks(x393_mcntrl_timing.X393McntrlTiming,x393Timing)
extractTasks(x393_mcntrl_buffers.X393McntrlBuffers,x393Buffers)
extractTasks(x393_mcntrl_tests.X393McntrlTests,x393Tests)
extractTasks(x393_mcntrl_adjust.X393McntrlAdjust,x393Adjust)
#
"""
......
......@@ -31,11 +31,22 @@ __status__ = "Development"
#import sys
#import x393_mem
#MCNTRL_TEST01_CHN4_STATUS_CNTRL=0
def hx(obj):
def hx(obj,length=None):
frmt="0x%x"
if (length):
frmt="0x%0"+str(length)+"x"
s=""
try:
return "0x%x"%obj
s=frmt%obj
s1=s[0:2]
for i in range(2,len(s)):
if s[i] != '0':
break
s1+="o"
s=s1+s[len(s1):]
except:
return str(obj)
s=str(obj)
return s
'''
Simulate Verilog concatenation. Input list tuple of items, each being a pair of (value, width)
'''
......@@ -45,9 +56,9 @@ def concat(items):
width=0
for vw in reversed(items):
v=vw[0]
if vw[1]==1: # So True/False will also work, not just 0/1
if not isinstance(v,int):
if v:
v=1
v=1 # So True/False will also work, not just 0/1
else:
v=0
val |= (v & ((1 << vw[1])-1))<<width
......@@ -108,4 +119,28 @@ def getParWidth(bitRange):
else:
return wl[0]
def hexMultiple(data):
if isinstance(data,list) or isinstance(data,tuple):
rslt=[]
for item in data:
if isinstance(item,list) or isinstance(item,tuple):
subResult=[]
for subItem in item:
try:
rslt.append("0x%x"%subItem)
except:
rslt.append(str(subItem))
rslt.append(subResult)
else:
try:
rslt.append("0x%x"%item)
except:
rslt.append(str(item))
rslt=str(rslt)
else:
try:
rslt = "0x%x"%item
except:
rslt = str(item)
return rslt
\ No newline at end of file
......@@ -72,6 +72,17 @@ class X393AxiControlStatus(object):
<data> - 32-bit data to write
"""
self.x393_mem.axi_write_single_w(self.CONTROL_ADDR+reg_addr, data)
def test_read_status(self, rpt): # was read_and_wait_status
"""
Read word from the status register 0 and calculate part of the run busy
<rpt> - number of times to repeat
"""
num_busy=0
for _ in range(rpt):
num_busy+=(self.x393_mem.axi_read_addr_w(self.STATUS_ADDR + 0)>>8) & 1
ratio=(1.0* num_busy)/rpt
print (("num_busy=%d, rpt=%d, ratio=%f"%(num_busy,rpt,100*ratio))+"%")
return ratio
def read_status(self, address): # was read_and_wait_status
"""
Read word from the status register (up to 26 bits payload and 6-bit sequence number)
......@@ -140,17 +151,17 @@ class X393AxiControlStatus(object):
# for name in self.__dict__:
# print (name+": "+str(name=='MCONTR_PHY_STATUS_REG_ADDR'))
# print (self.__dict__['MCONTR_PHY_STATUS_REG_ADDR'])
print ("MCONTR_PHY_STATUS_REG_ADDR: %s"%(hx(self.read_status(self.MCONTR_PHY_STATUS_REG_ADDR))))
print ("MCONTR_TOP_STATUS_REG_ADDR: %s"%(hx(self.read_status(self.MCONTR_TOP_STATUS_REG_ADDR))))
print ("MCNTRL_PS_STATUS_REG_ADDR: %s"%(hx(self.read_status(self.MCNTRL_PS_STATUS_REG_ADDR))))
print ("MCNTRL_SCANLINE_STATUS_REG_CHN1_ADDR:%s"%(hx(self.read_status(self.MCNTRL_SCANLINE_STATUS_REG_CHN1_ADDR))))
print ("MCNTRL_SCANLINE_STATUS_REG_CHN3_ADDR:%s"%(hx(self.read_status(self.MCNTRL_SCANLINE_STATUS_REG_CHN3_ADDR))))
print ("MCNTRL_TILED_STATUS_REG_CHN2_ADDR: %s"%(hx(self.read_status(self.MCNTRL_TILED_STATUS_REG_CHN2_ADDR))))
print ("MCNTRL_TILED_STATUS_REG_CHN4_ADDR: %s"%(hx(self.read_status(self.MCNTRL_TILED_STATUS_REG_CHN4_ADDR))))
print ("MCNTRL_TEST01_STATUS_REG_CHN1_ADDR: %s"%(hx(self.read_status(self.MCNTRL_TEST01_STATUS_REG_CHN1_ADDR))))
print ("MCNTRL_TEST01_STATUS_REG_CHN2_ADDR: %s"%(hx(self.read_status(self.MCNTRL_TEST01_STATUS_REG_CHN2_ADDR))))
print ("MCNTRL_TEST01_STATUS_REG_CHN3_ADDR: %s"%(hx(self.read_status(self.MCNTRL_TEST01_STATUS_REG_CHN3_ADDR))))
print ("MCNTRL_TEST01_STATUS_REG_CHN4_ADDR: %s"%(hx(self.read_status(self.MCNTRL_TEST01_STATUS_REG_CHN4_ADDR))))
print ("MCONTR_PHY_STATUS_REG_ADDR: %s"%(hx(self.read_status(self.MCONTR_PHY_STATUS_REG_ADDR),8)))
print ("MCONTR_TOP_STATUS_REG_ADDR: %s"%(hx(self.read_status(self.MCONTR_TOP_STATUS_REG_ADDR),8)))
print ("MCNTRL_PS_STATUS_REG_ADDR: %s"%(hx(self.read_status(self.MCNTRL_PS_STATUS_REG_ADDR) ,8)))
print ("MCNTRL_SCANLINE_STATUS_REG_CHN1_ADDR:%s"%(hx(self.read_status(self.MCNTRL_SCANLINE_STATUS_REG_CHN1_ADDR),8)))
print ("MCNTRL_SCANLINE_STATUS_REG_CHN3_ADDR:%s"%(hx(self.read_status(self.MCNTRL_SCANLINE_STATUS_REG_CHN3_ADDR),8)))
print ("MCNTRL_TILED_STATUS_REG_CHN2_ADDR: %s"%(hx(self.read_status(self.MCNTRL_TILED_STATUS_REG_CHN2_ADDR),8)))
print ("MCNTRL_TILED_STATUS_REG_CHN4_ADDR: %s"%(hx(self.read_status(self.MCNTRL_TILED_STATUS_REG_CHN4_ADDR),8)))
print ("MCNTRL_TEST01_STATUS_REG_CHN1_ADDR: %s"%(hx(self.read_status(self.MCNTRL_TEST01_STATUS_REG_CHN1_ADDR),8)))
print ("MCNTRL_TEST01_STATUS_REG_CHN2_ADDR: %s"%(hx(self.read_status(self.MCNTRL_TEST01_STATUS_REG_CHN2_ADDR),8)))
print ("MCNTRL_TEST01_STATUS_REG_CHN3_ADDR: %s"%(hx(self.read_status(self.MCNTRL_TEST01_STATUS_REG_CHN3_ADDR),8)))
print ("MCNTRL_TEST01_STATUS_REG_CHN4_ADDR: %s"%(hx(self.read_status(self.MCNTRL_TEST01_STATUS_REG_CHN4_ADDR),8)))
def program_status(self,
base_addr, # input [29:0] base_addr;
......
......@@ -41,7 +41,7 @@ from x393_mcntrl_buffers import X393McntrlBuffers
#from verilog_utils import hx, concat, bits, getParWidth
from verilog_utils import concat #, getParWidth
#from x393_axi_control_status import concat, bits
#from time import sleep
from time import sleep
class X393McntrlTests(object):
DRY_MODE= True # True
DEBUG_MODE=1
......@@ -175,8 +175,8 @@ class X393McntrlTests(object):
self.x393_pio_sequences.set_mrs(1) # reset DLL
if self.verbose>0: print("SET REFRESH")
self.x393_pio_sequences.set_refresh(
50, # input [ 9:0] t_rfc; # =50 for tCK=2.5ns
16) #input [ 7:0] t_refi; # 48/97 for normal, 8 - for simulation
self.T_RFC, # input [ 9:0] t_rfc; # =50 for tCK=2.5ns
self.T_REFI) #input [ 7:0] t_refi; # 48/97 for normal, 16 - for simulation
if self.verbose>0: print("SET WRITE LEVELING")
self.x393_pio_sequences.set_write_lev(16) # write leveling, 16 times (full buffer - 128)
if self.verbose>0: print("SET READ PATTERNt")
......@@ -194,62 +194,55 @@ class X393McntrlTests(object):
0x1234, # 15'h1234, # row address
0x100 # 10'h100 # column address
)
def init_ddr3(self):
def init_ddr3(self,
wait_complete=True):
"""
Enable address/command pins, remove SDRST, enable CKE,
Setup PS PIO
Set DDR3 MR0..MR3 registers
Enable refresh
<wait_complete> Do not request a new transaction from the scheduler until previous memory transaction is finished
"""
"""
// enable output for address/commands to DDR chip
enable_cmda(1);
repeat (16) @(posedge CLK) ;
// remove reset from DDR chip
activate_sdrst(0); // was enabled at system reset
#5000; // actually 500 usec required
repeat (16) @(posedge CLK) ;
enable_cke(1);
repeat (16) @(posedge CLK) ;
// enable_memcntrl(1); // enable memory controller
enable_memcntrl_channels(16'h0003); // only channel 0 and 1 are enabled
configure_channel_priority(0,0); // lowest priority channel 0
configure_channel_priority(1,0); // lowest priority channel 1
enable_reset_ps_pio(1,0); // enable, no reset
// set MR registers in DDR3 memory, run DCI calibration (long)
wait_ps_pio_ready(DEFAULT_STATUS_MODE, 1); // wait FIFO not half full
schedule_ps_pio ( // schedule software-control memory operation (may need to check FIFO status first)
INITIALIZE_OFFSET, // input [9:0] seq_addr; // sequence start address
0, // input [1:0] page; // buffer page number
0, // input urgent; // high priority request (only for competion with other channels, wiil not pass in this FIFO)
0, // input chn; // channel buffer to use: 0 - memory read, 1 - memory write
`PS_PIO_WAIT_COMPLETE );// wait_complete; // Do not request a newe transaction from the scheduler until previous memory transaction is finished
`ifdef WAIT_MRS
wait_ps_pio_done(DEFAULT_STATUS_MODE, 1);
`else
repeat (32) @(posedge CLK) ; // what delay is needed to be sure? Add to PS_PIO?
// first refreshes will be fast (accummulated while waiting)
`endif
enable_refresh(1);
axi_set_dqs_odelay('h78); //??? dafaults - wrong?
# enable output for address/commands to DDR chip
self.x393_axi_tasks.enable_cmda(1)
# remove reset from DDR3 chip
self.x393_axi_tasks.activate_sdrst(0) # was enabled at system reset
sleep(0.1) # actually 500 usec required
self.x393_axi_tasks.enable_cke(1);
"""
self.x393_axi_tasks.enable_memcntrl_channels(0x3) # only channel 0 and 1 are enabled
self.x393_axi_tasks.configure_channel_priority(0,0) # lowest priority channel 0
self.x393_axi_tasks.configure_channel_priority(1,0) # lowest priority channel 1
self.x393_pio_sequences.enable_reset_ps_pio(1,0) # enable, no reset
# set MR registers in DDR3 memory, run DCI calibration (long)
self.x393_pio_sequences.wait_ps_pio_ready(self.DEFAULT_STATUS_MODE, 1, 2.0); # wait FIFO not half full, sync sequences, timeout 2 sec
self.x393_pio_sequences.schedule_ps_pio ( # schedule software-control memory operation (may need to check FIFO status first)
self.INITIALIZE_OFFSET, # input [9:0] seq_addr; # sequence start address
0, # input [1:0] page; # buffer page number
0, # input urgent; # high priority request (only for competion with other channels, wiil not pass in this FIFO)
0, # input chn; # channel buffer to use: 0 - memory read, 1 - memory write
wait_complete ); # wait_complete; # Do not request a newe transaction from the scheduler until previous memory transaction is finished
# Wait PS PIO sequence DOEN
self.x393_pio_sequences.wait_ps_pio_done(self.DEFAULT_STATUS_MODE, 1 , 2.0); # wait FIFO not half full, sync sequences, timeout 2 sec
self.x393_axi_tasks.enable_refresh(1)
# axi_set_dqs_odelay('h78); #??? defaults - wrong? DLY_DQS_ODELAY=0x74
def test_write_levelling(self,
wait_complete, # Wait for operation to complete
wlev_dqs_dly= 0x80,
norm_dqs_odly=0x78):
norm_dqs_odly=None):
"""
Test write levelling mode
<wait_complete> wait write levelling operation to complete (0 - may initiate multiple PS PIO operations)
<wlev_dqs_dly> DQS output delay for write levelling mode (default 0x80)
<norm_dqs_odly> DQS output delay for normal (not write levelling) mode (default 0x78)
returns list of the read data
returns a pair of ratios for getting "1" for 2 lanes
"""
numBufWords=32 # twice nrep in set_write_lev
if norm_dqs_odly is None:
norm_dqs_odly=self.DLY_DQS_ODELAY
# Set special values for DQS idelay for write leveling
self.x393_pio_sequences.wait_ps_pio_done(self.DEFAULT_STATUS_MODE,1); # not no interrupt running cycle - delays are changed immediately
self.x393_mcntrl_timing.axi_set_dqs_idelay_wlv()
......@@ -260,87 +253,70 @@ class X393McntrlTests(object):
self.x393_pio_sequences.schedule_ps_pio (# schedule software-control memory operation (may need to check FIFO status first)
self.WRITELEV_OFFSET, # input [9:0] seq_addr; # sequence start address
0, # 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 competition with other channels, will not pass in this FIFO)
0, # input chn; # channel buffer to use: 0 - memory read, 1 - memory write
wait_complete) # `PS_PIO_WAIT_COMPLETE );# wait_complete; # Do not request a newe transaction from the scheduler until previous memory transaction is finished
self.x393_pio_sequences.wait_ps_pio_done(self.DEFAULT_STATUS_MODE,1); # wait previous memory transaction finished before changing delays (effective immediately)
self.x393_mcntrl_buffers.read_block_buf_chn (0, 0, 32, 1, 1); # chn=0, page=0, number of 32-bit words=32, wait_done
self.x393_mcntrl_timing.axi_set_dqs_odelay(self.DLY_DQS_ODELAY)
self.x393_pio_sequences.schedule_ps_pio ( # schedule software-control memory operation (may need to check FIFO status first)
self.WRITELEV_OFFSET, # input [9:0] seq_addr; # sequence start address
1, # 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 chn; # channel buffer to use: 0 - memory read, 1 - memory write
wait_complete) # `PS_PIO_WAIT_COMPLETE );# wait_complete; # Do not request a newe transaction from the scheduler until previous memory transaction is finished
self.x393_pio_sequences.wait_ps_pio_done(self.DEFAULT_STATUS_MODE,1); # wait previous memory transaction finished before changing delays (effective immediately)
rslt=self.x393_mcntrl_buffers.read_block_buf_chn (0, 1, 32, 1, 1 ); # chn=0, page=1, number of 32-bit words=32, wait_done
buf=self.x393_mcntrl_buffers.read_block_buf_chn (0, 0, numBufWords, (0,1)[self.verbose>1]) # chn=0, page=0, number of 32-bit words=32, show_rslt
#calculate 1-s ratio for both lanes
rslt=[0.0,0.0]
for i in range(0,numBufWords):
rslt[i & 1]+=(buf[i] & 1) + ((buf[i] >> 8) & 1) + ((buf[i] >> 16) & 1) + ((buf[i] >> 24) & 1)
for i in range(2):
rslt[i]/=2*numBufWords
self.x393_mcntrl_timing.axi_set_dqs_idelay_nominal()
self.x393_mcntrl_timing.axi_set_dqs_odelay(norm_dqs_odly) # 'h78);
self.x393_mcntrl_timing.axi_set_wbuf_delay(self.WBUF_DLY_DFLT); #DFLT_WBUF_DELAY
return rslt
def test_read_pattern(self,
wait_complete): # Wait for operation to complete
dq_idelay=None,
dqs_idelay=None,
wait_complete=1): # Wait for operation to complete
"""
Test read pattern mode
Test read pattern mode
<dq_idelay> set DQ input delays if provided ([] - skip, single number - both lanes, 2 element list - per/lane)
<dqs_idelay> set DQS input delays if provided ([] - skip, single number - both lanes, 2 element list - per/lane)
<wait_complete> wait read pattern operation to complete (0 - may initiate multiple PS PIO operations)
returns list of the read data
"""
self.x393_pio_sequences.schedule_ps_pio ( # schedule software-control memory operation (may need to check FIFO status first)
self.READ_PATTERN_OFFSET, # input [9:0] seq_addr; # sequence start address
2, # 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 chn; # channel buffer to use: 0 - memory read, 1 - memory write
wait_complete) # `PS_PIO_WAIT_COMPLETE ) # wait_complete; # Do not request a newe transaction from the scheduler until previous memory transaction is finished
self.x393_pio_sequences.wait_ps_pio_done(self.DEFAULT_STATUS_MODE,1) # wait previous memory transaction finished before changing delays (effective immediately)
return self.x393_mcntrl_buffers.read_block_buf_chn (0, 2, 32, 1, 1 ) # chn=0, page=2, number of 32-bit words=32, wait_done
if (not dq_idelay is None) and (dq_idelay != []):
self.x393_mcntrl_timing.axi_set_dq_idelay(dq_idelay)
if (not dqs_idelay is None) and (dqs_idelay != []):
self.x393_mcntrl_timing.axi_set_dqs_idelay(dqs_idelay)
return self.x393_pio_sequences.read_pattern(
32, # num
1, # show_rslt,
wait_complete) # # Wait for operation to complete
def test_write_block(self,
wait_complete): # Wait for operation to complete
"""
Test write block in PS PIO mode
<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
self.x393_pio_sequences.schedule_ps_pio ( # schedule software-control memory operation (may need to check FIFO status first)
self.WRITE_BLOCK_OFFSET, # input [9:0] seq_addr; # sequence start address
0, # 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)
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 newe transaction from the scheduler until previous memory transaction is finished
# temporary - for debugging:
# self.x393_pio_sequences.wait_ps_pio_done(self.DEFAULT_STATUS_MODE,1) # wait previous memory transaction finished before changing delays (effective immediately)
return self.x393_pio_sequences.write_block(wait_complete) # Wait for operation to complete
def test_read_block(self,
wait_complete): # Wait for operation to complete
dq_idelay=None,
dqs_idelay=None,
wait_complete=1): # Wait for operation to complete
"""
Test read block in PS PIO mode
<dq_idelay> set DQ input delays if provided ([] - skip, single number - both lanes, 2 element list - per/lane)
<dqs_idelay> set DQS input delays if provided ([] - skip, single number - both lanes, 2 element list - per/lane)
<wait_complete> wait read block operation to complete (0 - may initiate multiple PS PIO operations)
returns list of the read data
"""
self.x393_pio_sequences.schedule_ps_pio ( # schedule software-control memory operation (may need to check FIFO status first)
self.READ_BLOCK_OFFSET, # input [9:0] seq_addr; # sequence start address
3, # 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 chn; # channel buffer to use: 0 - memory read, 1 - memory write
wait_complete) # wait_complete; # Do not request a newe transaction from the scheduler until previous memory transaction is finished
self.x393_pio_sequences.schedule_ps_pio ( # schedule software-control memory operation (may need to check FIFO status first)
self.READ_BLOCK_OFFSET, # input [9:0] seq_addr; # sequence start address
2, # 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 chn; # channel buffer to use: 0 - memory read, 1 - memory write
wait_complete) # wait_complete; # Do not request a newe transaction from the scheduler until previous memory transaction is finished
self.x393_pio_sequences.schedule_ps_pio ( # schedule software-control memory operation (may need to check FIFO status first)
self.READ_BLOCK_OFFSET, # input [9:0] seq_addr; # sequence start address
1, # 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 chn; # channel buffer to use: 0 - memory read, 1 - memory write
wait_complete) # wait_complete; # Do not request a newe transaction from the scheduler until previous memory transaction is finished
self.x393_pio_sequences.wait_ps_pio_done(self.DEFAULT_STATUS_MODE,1); # wait previous memory transaction finished before changing delays (effective immediately)
return self.x393_mcntrl_buffers.read_block_buf_chn (0, 3, 256, 1, 1 ) # chn=0, page=3, number of 32-bit words=256, wait_done
if (not dq_idelay is None) and (dq_idelay != []):
self.x393_mcntrl_timing.axi_set_dq_idelay(dq_idelay)
if (not dqs_idelay is None) and (dqs_idelay != []):
self.x393_mcntrl_timing.axi_set_dqs_idelay(dqs_idelay)
return self.x393_pio_sequences.read_block(self,
256, # num,
1, # show_rslt,
wait_complete) # Wait for operation to complete
def test_scanline_write(self, #
channel, # input [3:0] channel;
extra_pages, # input [1:0] extra_pages;
......@@ -537,7 +513,7 @@ class X393McntrlTests(object):
channel,
(ii & 3),
xfer_size <<2,
1, # chn=0, page=3, number of 32-bit words=256, wait_done
# 1, # chn=0, page=3, number of 32-bit words=256, show_rslt
show_data))
self.x393_axi_tasks.write_contol_register(test_mode_address, self.TEST01_NEXT_PAGE)
return result
......@@ -767,7 +743,7 @@ class X393McntrlTests(object):
result.append(self.x393_mcntrl_buffers.read_block_buf_chn (channel,
(ii & 3),
tile_size <<2,
1, # chn=0, page=3, number of 32-bit words=256, wait_done
# 1, # chn=0, page=3, number of 32-bit words=256, show_rslt
show_data))
self.x393_axi_tasks.write_contol_register(test_mode_address, self.TEST01_NEXT_PAGE);
# enable_memcntrl_en_dis(channel,0); # disable channel
......
......@@ -36,8 +36,8 @@ from x393_mem import X393Mem
from x393_axi_control_status import X393AxiControlStatus
#from verilog_utils import * # concat, bits
#from verilog_utils import hx, concat, bits, getParWidth
from verilog_utils import concat, getParWidth
#from x393_axi_control_status import concat, bits
from verilog_utils import concat, getParWidth,hexMultiple
#from x393_axi_control_status import concat, bits
class X393McntrlTiming(object):
DRY_MODE= True # True
DEBUG_MODE=1
......@@ -174,72 +174,141 @@ class X393McntrlTiming(object):
delay): # input [7:0] delay;
"""
Set all DQ input delays to the same value
<delay> 8-bit (5+3) delay value to use
<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
"""
if delay is None: return # Do nothing, that's OK
if isinstance(delay,int):
delay=(delay,delay)
if self.DEBUG_MODE > 1:
print("SET DQ IDELAY=0x%x"%delay)
self.axi_set_multiple_delays(self.LD_DLY_LANE0_IDELAY, 8, delay)
self.axi_set_multiple_delays(self.LD_DLY_LANE1_IDELAY, 8, delay)
print("SET DQ IDELAY="+hexMultiple(delay)) # hexMultiple
self.axi_set_multiple_delays(self.LD_DLY_LANE0_IDELAY, 8, delay[0])
self.axi_set_multiple_delays(self.LD_DLY_LANE1_IDELAY, 8, delay[1])
self.x393_axi_tasks.write_contol_register (self.DLY_SET,0);# // set all delays
def axi_set_dq_odelay(self,
delay): # input [7:0] delay;
"""
Set all DQ OUTput delays to the same value
<delay> 8-bit (5+3) delay value to use
<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
"""
if delay is None: return # Do nothing, that's OK
if isinstance(delay,int):
delay=(delay,delay)
if self.DEBUG_MODE > 1:
print("SET DQ ODELAY=0x%x"%delay)
self.axi_set_multiple_delays(self.LD_DLY_LANE0_ODELAY, 8, delay);
self.axi_set_multiple_delays(self.LD_DLY_LANE1_ODELAY, 8, delay);
print("SET DQ ODELAY="+hexMultiple(delay)) # hexMultiple
self.axi_set_multiple_delays(self.LD_DLY_LANE0_ODELAY, 8, delay[0]);
self.axi_set_multiple_delays(self.LD_DLY_LANE1_ODELAY, 8, delay[1]);
self.x393_axi_tasks.write_contol_register(self.DLY_SET,0); # set all delays
def axi_set_dqs_idelay(self,
delay): # input [7:0] delay;
"""
Set all DQs input delays to the same value
<delay> 8-bit (5+3) delay value to use
<delay> 8-bit (5+3) delay value to use or a tuple/list with a pair for (lane0, lane1)
"""
if delay is None: return # Do nothing, that's OK
if isinstance(delay,int):
delay=(delay,delay)
if self.DEBUG_MODE > 1:
print("SET DQS IDELAY=0x%x"%delay)
self.axi_set_multiple_delays(self.LD_DLY_LANE0_IDELAY + 8, 1, delay)
self.axi_set_multiple_delays(self.LD_DLY_LANE1_IDELAY + 8, 1, delay)
print("SET DQS IDELAY="+hexMultiple(delay)) # hexMultiple
self.axi_set_multiple_delays(self.LD_DLY_LANE0_IDELAY + 8, 1, delay[0])
self.axi_set_multiple_delays(self.LD_DLY_LANE1_IDELAY + 8, 1, delay[1])
self.x393_axi_tasks.write_contol_register(self.DLY_SET,0); # set all delays
def axi_set_dqs_odelay(self,
delay): # input [7:0] delay;
"""
Set all DQs OUTput delays to the same value
<delay> 8-bit (5+3) delay value to use
<delay> 8-bit (5+3) delay value to use or a tuple/list with a pair for (lane0, lane1)
"""
if delay is None: return # Do nothing, that's OK
if isinstance(delay,int):
delay=(delay,delay)
if self.DEBUG_MODE > 1:
print("SET DQS ODELAY=0x%x"%delay)
self.axi_set_multiple_delays(self.LD_DLY_LANE0_ODELAY + 8, 1, delay)
self.axi_set_multiple_delays(self.LD_DLY_LANE1_ODELAY + 8, 1, delay)
print("SET DQS ODELAY="+hexMultiple(delay)) # hexMultiple
self.axi_set_multiple_delays(self.LD_DLY_LANE0_ODELAY + 8, 1, delay[0])
self.axi_set_multiple_delays(self.LD_DLY_LANE1_ODELAY + 8, 1, delay[1])
self.x393_axi_tasks.write_contol_register(self.DLY_SET,0); # set all delays
def axi_set_dm_odelay (self,
delay): # input [7:0] delay;
"""
Set all DM output delays to the same value
<delay> 8-bit (5+3) delay value to use
<delay> 8-bit (5+3) delay value to use or a tuple/list with a pair for (lane0, lane1)
"""
if delay is None: return # Do nothing, that's OK
if isinstance(delay,int):
delay=(delay,delay)
if self.DEBUG_MODE > 1:
print("SET DQM IDELAY=0x%x"%delay)
self.axi_set_multiple_delays(self.LD_DLY_LANE0_ODELAY + 9, 1, delay)
self.axi_set_multiple_delays(self.LD_DLY_LANE1_ODELAY + 9, 1, delay)
print("SET DQM IDELAY="+hexMultiple(delay)) # hexMultiple
self.axi_set_multiple_delays(self.LD_DLY_LANE0_ODELAY + 9, 1, delay[0])
self.axi_set_multiple_delays(self.LD_DLY_LANE1_ODELAY + 9, 1, delay[1])
self.x393_axi_tasks.write_contol_register(self.DLY_SET,0) # set all delays
def axi_set_cmda_odelay(self,
delay): # input [7:0] delay;
"""
Set all command/addressoutput delays to the same value
<delay> 8-bit (5+3) delay value to use
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
List elements may be None, those values will not be overwritten
"""
if delay is None: return # Do nothing, that's OK
if isinstance(delay,int):
delay=(delay,)*32 # all address/commands
if self.DEBUG_MODE > 1:
print("SET COMMAND and ADDRESS ODELAY=0x%x"%delay)
print("SET COMMAND and ADDRESS ODELAY"+hexMultiple(delay))
self.axi_set_multiple_delays(self.LD_DLY_CMDA, 32, delay);
self.x393_axi_tasks.write_contol_register(self.DLY_SET,0) # set all delays
def axi_set_address_odelay(self,
delay): # input [7:0] delay;
"""
Set output delays for address lines only
<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
"""
if delay is None: return # Do nothing, that's OK
if isinstance(delay,int):
delay=(delay,)*self.ADDRESS_NUMBER
if self.DEBUG_MODE > 1:
print("SET ADDRESS ODELAY="+hexMultiple(delay))
self.axi_set_multiple_delays(self.LD_DLY_CMDA, 0,delay) # 32, delay); length will be determined by len(delay)
self.x393_axi_tasks.write_contol_register(self.DLY_SET,0) # set all delays
def axi_set_bank_odelay(self,
delay): # input [7:0] delay;
"""
Set output delays for bank lines only
<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
"""
bank_offset=24
if delay is None: return # Do nothing, that's OK
if isinstance(delay,int):
delay=(delay,)*3
if self.DEBUG_MODE > 1:
print("SET BANK ODELAY="+hexMultiple(delay))
self.axi_set_multiple_delays(self.LD_DLY_CMDA+bank_offset, 0,delay) # length will be determined by len(delay)
self.x393_axi_tasks.write_contol_register(self.DLY_SET,0) # set all delays
def axi_set_cmd_odelay(self,
delay): # input [7:0] delay;
"""
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
List elements may be None, those values will not be overwritten
"""
command_offset=24+3
if delay is None: return # Do nothing, that's OK
if isinstance(delay,int):
delay=(delay,)*3
if self.DEBUG_MODE > 1:
print("SET COMMAND ODELAY="+hexMultiple(delay))
self.axi_set_multiple_delays(self.LD_DLY_CMDA+command_offset, 0,delay) # length will be determined by len(delay)
self.x393_axi_tasks.write_contol_register(self.DLY_SET,0) # set all delays
def axi_set_multiple_delays(self,
reg_addr, #input [29:0] reg_addr;
......@@ -249,11 +318,17 @@ class X393McntrlTiming(object):
Set same delay to a range of I/O delay registers
<reg_addr> control register address of the first register in the range
<number> number of registers to write
<delay> 8-bit (5+3) delay value to use
"""
for i in range(0,number): # (i=0;i<number;i=i+1) begin
self.x393_axi_tasks.write_contol_register(reg_addr + i, delay) # {24'b0,delay}); // control register address
<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
"""
if delay is None: return # Do nothing, that's OK
if