Commit fad107cb authored by Andrey Filippov's avatar Andrey Filippov

implemented help for task based on functions documentation

parent e6868ded
...@@ -35,7 +35,9 @@ __status__ = "Development" ...@@ -35,7 +35,9 @@ __status__ = "Development"
''' '''
import sys import sys
import os import os
import inspect
import re
#import os.path
from argparse import ArgumentParser from argparse import ArgumentParser
#import argparse #import argparse
from argparse import RawDescriptionHelpFormatter from argparse import RawDescriptionHelpFormatter
...@@ -78,8 +80,12 @@ class CLIError(Exception): ...@@ -78,8 +80,12 @@ class CLIError(Exception):
def extractTasks(obj,inst): def extractTasks(obj,inst):
for name in obj.__dict__: for name in obj.__dict__:
if hasattr((obj.__dict__[name]), '__call__') and not (name[0]=='_'): if hasattr((obj.__dict__[name]), '__call__') and not (name[0]=='_'):
# print (name+" -->"+str(obj.__dict__[name]))
# print (obj.__dict__[name].func_code)
# print ("COMMENTS:"+str(inspect.getcomments(obj.__dict__[name])))
# print ("DOCS:"+str(inspect.getdoc(obj.__dict__[name])))
func_args=obj.__dict__[name].func_code.co_varnames[1:obj.__dict__[name].func_code.co_argcount] func_args=obj.__dict__[name].func_code.co_varnames[1:obj.__dict__[name].func_code.co_argcount]
callableTasks[name]={'func':obj.__dict__[name],'args':func_args,'inst':inst} callableTasks[name]={'func':obj.__dict__[name],'args':func_args,'inst':inst,'docs':inspect.getdoc(obj.__dict__[name])}
def execTask(commandLine): def execTask(commandLine):
# result=None # result=None
cmdList=commandLine #.split() cmdList=commandLine #.split()
...@@ -118,6 +124,17 @@ def hx(obj): ...@@ -118,6 +124,17 @@ def hx(obj):
return "0x%x"%obj return "0x%x"%obj
except: except:
return str(obj) return str(obj)
def getFuncArgsString(name):
funcFArgs=callableTasks[name]['args']
sFuncArgs=""
if funcFArgs:
sFuncArgs+='<'+str(funcFArgs[0])+'>'
for a in funcFArgs[1:]:
sFuncArgs+=' <'+str(a)+'>'
return sFuncArgs
def main(argv=None): # IGNORE:C0111 def main(argv=None): # IGNORE:C0111
'''Command line options.''' '''Command line options.'''
...@@ -163,9 +180,14 @@ USAGE ...@@ -163,9 +180,14 @@ USAGE
parser.add_argument("-p", "--parameter", dest="parameters", action="append", default=[], help="Define parameter(s) as name=value" , nargs='*' ) parser.add_argument("-p", "--parameter", dest="parameters", action="append", default=[], help="Define parameter(s) as name=value" , nargs='*' )
parser.add_argument("-c", "--command", dest="commands", action="append", default=[], help="execute command" , nargs='*') parser.add_argument("-c", "--command", dest="commands", action="append", default=[], help="execute command" , nargs='*')
parser.add_argument("-i", "--interactive", dest="interactive", action="store_true", help="enter interactive mode [default: %(default)s]") parser.add_argument("-i", "--interactive", dest="interactive", action="store_true", help="enter interactive mode [default: %(default)s]")
parser.add_argument("-s", "--simulated", dest="simulated", action="store_true", help="Simulated mode (no real hardware I/O) [default: %(default)s]")
# Process arguments # Process arguments
args = parser.parse_args() args = parser.parse_args()
if not args.simulated:
if not os.path.isfile("/dev/xdevcfg"):
args.simulated=True
print("Program is forced to run in SIMULATED mode as '/dev/xdevcfg' does not exist (not a camera)")
#print("--- defines=%s"% str(args.defines)) #print("--- defines=%s"% str(args.defines))
#print("--- paths=%s"% str(args.paths)) #print("--- paths=%s"% str(args.paths))
#print("--- parameters=%s"% str(args.parameters)) #print("--- parameters=%s"% str(args.parameters))
...@@ -259,12 +281,12 @@ USAGE ...@@ -259,12 +281,12 @@ USAGE
if verbose > 3: print("vpars1.VERBOSE__TYPE="+str(vpars1.VERBOSE__TYPE)) if verbose > 3: print("vpars1.VERBOSE__TYPE="+str(vpars1.VERBOSE__TYPE))
if verbose > 3: print("vpars1.VERBOSE__RAW="+str(vpars1.VERBOSE__RAW)) if verbose > 3: print("vpars1.VERBOSE__RAW="+str(vpars1.VERBOSE__RAW))
x393mem= x393_mem.X393Mem(verbose,True) #add dry run parameter x393mem= x393_mem.X393Mem(verbose,args.simulated) #add dry run parameter
x393tasks= x393_axi_control_status.X393AxiControlStatus(verbose,True) x393tasks= x393_axi_control_status.X393AxiControlStatus(verbose,args.simulated)
x393Pio= x393_pio_sequences.X393PIOSequences(verbose,True) x393Pio= x393_pio_sequences.X393PIOSequences(verbose,args.simulated)
x393Timing= x393_mcntrl_timing.X393McntrlTiming(verbose,True) x393Timing= x393_mcntrl_timing.X393McntrlTiming(verbose,args.simulated)
x393Buffers=x393_mcntrl_buffers.X393McntrlBuffers(verbose,True) x393Buffers=x393_mcntrl_buffers.X393McntrlBuffers(verbose,args.simulated)
x393Tests= x393_mcntrl_tests.X393McntrlTests(verbose,True) x393Tests= x393_mcntrl_tests.X393McntrlTests(verbose,args.simulated)
''' '''
print ("----------------------") print ("----------------------")
print("x393_mem.__dict__="+str(x393_mem.__dict__)) print("x393_mem.__dict__="+str(x393_mem.__dict__))
...@@ -315,23 +337,40 @@ USAGE ...@@ -315,23 +337,40 @@ USAGE
if (args.interactive): if (args.interactive):
line ="" line =""
while True: while True:
line=raw_input('x393--> ').strip() line=raw_input('x393%s--> '%('','(simulated)')[args.simulated]).strip()
if not line: if not line:
print ('Use "quit" to exit, "help" - for help') print ('Use "quit" to exit, "help" - for help')
elif line == 'quit': elif (line == 'quit') or (line == 'exit'):
break break
elif line== 'help' : elif line== 'help' :
print ("\nAvailable tasks:") print ("\nAvailable tasks:")
for name,val in sorted(callableTasks.items()): for name,val in sorted(callableTasks.items()):
# funcFArgs=callableTasks[name]['args'] sFuncArgs=getFuncArgsString(name)
funcFArgs=val['args']
sFuncArgs=""
if funcFArgs:
sFuncArgs+='<'+str(funcFArgs[0])+'>'
for a in funcFArgs[1:]:
sFuncArgs+=' <'+str(a)+'>'
print ("Usage: %s %s"%(name,sFuncArgs)) print ("Usage: %s %s"%(name,sFuncArgs))
print ('\n"parameters" and "defines" list known defined parameters and macros') print ('\n"parameters" and "defines" list known defined parameters and macros')
elif (len(line) > len("help")) and (line[:len("help")]=='help'):
helpFilter=line[len('help'):].strip()
try:
re.match(helpFilter,"")
except:
print("Invalid search expression: %s"%helpFilter)
helpFilter=None
if helpFilter:
print
for name,val in sorted(callableTasks.items()):
# if re.findall(helpFilter,name):
if re.match(helpFilter,name):
print('=== %s ==='%name)
sFuncArgs=getFuncArgsString(name)
# print ("Usage: %s %s"%(name,sFuncArgs))
docs=callableTasks[name]['docs']
if docs:
docsl=docs.split("\n")
for l in docsl:
#print (' %s'%l)
print ('%s'%l)
#print(docs)
print (" Usage: %s %s\n"%(name,sFuncArgs))
elif line == 'parameters': elif line == 'parameters':
parameters=ivp.getParameters() parameters=ivp.getParameters()
for par,val in sorted(parameters.items()): for par,val in sorted(parameters.items()):
......
...@@ -65,8 +65,17 @@ class X393AxiControlStatus(object): ...@@ -65,8 +65,17 @@ class X393AxiControlStatus(object):
''' '''
def write_contol_register(self, reg_addr, data): def write_contol_register(self, reg_addr, data):
"""
Write 32-bit word to the control register
<addr> - register address relative to the control register address space
<data> - 32-bit data to write
"""
self.x393_mem.axi_write_single_w(self.CONTROL_ADDR+reg_addr, data) self.x393_mem.axi_write_single_w(self.CONTROL_ADDR+reg_addr, data)
def read_and_wait_status(self, address): def read_and_wait_status(self, address):
"""
Read word from the status register (up to 26 bits payload and 6-bit sequence number)
<addr> - status register address (currently 0..255)
"""
return self.x393_mem.axi_read_addr_w(self.STATUS_ADDR + address ) return self.x393_mem.axi_read_addr_w(self.STATUS_ADDR + address )
def wait_status_condition(self, def wait_status_condition(self,
...@@ -77,6 +86,20 @@ class X393AxiControlStatus(object): ...@@ -77,6 +86,20 @@ class X393AxiControlStatus(object):
mask, # input [25:0] mask; // which bits to compare mask, # input [25:0] mask; // which bits to compare
invert_match, # input invert_match; // 0 - wait until match to pattern (all bits), 1 - wait until no match (any of bits differ) invert_match, # input invert_match; // 0 - wait until match to pattern (all bits), 1 - wait until no match (any of bits differ)
wait_seq): # input wait_seq; // Wait for the correct sequence number, False assume correct wait_seq): # input wait_seq; // Wait for the correct sequence number, False assume correct
"""
Poll specified status register until some condition is matched
<status_address> - status register address (currently 0..255)
<status_control_address> - control register address (to control status generation)
<status_mode> - status generation mode:
0: disable status generation,
1: single status request,
2: auto status, keep specified seq number,
4: auto, inc sequence number
<pattern> - 26-bit pattern to match
<mask> - 26-bit mask to enable pattern matching (0-s - ignore)
<invert_match> - invert match (wait until matching condition becomes false)
<wait_seq>- wait for the correct sequence number, if False - assume always correct
"""
match=False match=False
while not match: while not match:
data=self.read_and_wait_status(status_address) data=self.read_and_wait_status(status_address)
...@@ -92,6 +115,9 @@ class X393AxiControlStatus(object): ...@@ -92,6 +115,9 @@ class X393AxiControlStatus(object):
if self.DRY_MODE: break if self.DRY_MODE: break
def read_all_status(self): def read_all_status(self):
"""
Read and print contents of all defined status registers
"""
# print (self.__dict__) # print (self.__dict__)
# for name in self.__dict__: # for name in self.__dict__:
# print (name+": "+str(name=='MCONTR_PHY_STATUS_REG_ADDR')) # print (name+": "+str(name=='MCONTR_PHY_STATUS_REG_ADDR'))
...@@ -113,19 +139,33 @@ class X393AxiControlStatus(object): ...@@ -113,19 +139,33 @@ class X393AxiControlStatus(object):
reg_addr, # input [7:0] reg_addr; reg_addr, # input [7:0] reg_addr;
mode, # input [1:0] mode; mode, # input [1:0] mode;
seq_number): # input [5:0] seq_number; seq_number): # input [5:0] seq_number;
''' """
// mode bits: Poll specified status register until some condition is matched
// 0 disable status generation, <base_addr> - base control address of the selected module
// 1 single status request, <reg_addr> - status control register relative to the module address space
// 2 - auto status, keep specified seq number, <mode> - status generation mode:
// 3 - auto, inc sequence number 0: disable status generation,
''' 1: single status request,
2: auto status, keep specified seq number,
4: auto, inc sequence number
<seq_number> - 6-bit sequence number of the status message to be sent
"""
self.write_contol_register(base_addr + reg_addr, ((mode & 3)<< 6) | (seq_number * 0x3f)) self.write_contol_register(base_addr + reg_addr, ((mode & 3)<< 6) | (seq_number * 0x3f))
def program_status_all( self, def program_status_all( self,
mode, # input [1:0] mode; mode, # input [1:0] mode;
seq_num): # input [5:0] seq_num; seq_num): # input [5:0] seq_num;
"""
Set status generation mode for all defined modules
<mode> - status generation mode:
0: disable status generation,
1: single status request,
2: auto status, keep specified seq number,
4: auto, inc sequence number
<seq_number> - 6-bit sequence number of the status message to be sent
"""
self.program_status (self.MCONTR_PHY_16BIT_ADDR, self.MCONTR_PHY_STATUS_CNTRL, mode,seq_num)# //MCONTR_PHY_STATUS_REG_ADDR= 'h0, self.program_status (self.MCONTR_PHY_16BIT_ADDR, self.MCONTR_PHY_STATUS_CNTRL, mode,seq_num)# //MCONTR_PHY_STATUS_REG_ADDR= 'h0,
self.program_status (self.MCONTR_TOP_16BIT_ADDR, self.MCONTR_TOP_16BIT_STATUS_CNTRL, mode,seq_num)# //MCONTR_TOP_STATUS_REG_ADDR= 'h1, self.program_status (self.MCONTR_TOP_16BIT_ADDR, self.MCONTR_TOP_16BIT_STATUS_CNTRL, mode,seq_num)# //MCONTR_TOP_STATUS_REG_ADDR= 'h1,
self.program_status (self.MCNTRL_PS_ADDR, self.MCNTRL_PS_STATUS_CNTRL, mode,seq_num)# //MCNTRL_PS_STATUS_REG_ADDR= 'h2, self.program_status (self.MCNTRL_PS_ADDR, self.MCNTRL_PS_STATUS_CNTRL, mode,seq_num)# //MCNTRL_PS_STATUS_REG_ADDR= 'h2,
...@@ -140,32 +180,61 @@ class X393AxiControlStatus(object): ...@@ -140,32 +180,61 @@ class X393AxiControlStatus(object):
def enable_cmda(self, def enable_cmda(self,
en): # input en; en): # input en;
"""
Enable (disable) address, bank and command lines to the DDR3 memory
<en> - 1 - enable, 0 - disable
"""
self.write_contol_register(self.MCONTR_PHY_0BIT_ADDR + self.MCONTR_PHY_0BIT_CMDA_EN + en, 0); self.write_contol_register(self.MCONTR_PHY_0BIT_ADDR + self.MCONTR_PHY_0BIT_CMDA_EN + en, 0);
def enable_cke(self, def enable_cke(self,
en): # input en; en): # input en;
"""
Enable (disable) CKE - clock enable to DDR3 memory
<en> - 1 - enable, 0 - disable
"""
self.write_contol_register(self.MCONTR_PHY_0BIT_ADDR + self.MCONTR_PHY_0BIT_CKE_EN + en, 0); self.write_contol_register(self.MCONTR_PHY_0BIT_ADDR + self.MCONTR_PHY_0BIT_CKE_EN + en, 0);
def activate_sdrst(self, def activate_sdrst(self,
en): # input en; en): # input en;
"""
Activate SDRST (reset) to DDR3 memory
<en> - 1 - activate (low), 0 - deactivate (high)
"""
self.write_contol_register(self.MCONTR_PHY_0BIT_ADDR + self.MCONTR_PHY_0BIT_SDRST_ACT + en, 0); self.write_contol_register(self.MCONTR_PHY_0BIT_ADDR + self.MCONTR_PHY_0BIT_SDRST_ACT + en, 0);
def enable_refresh(self, def enable_refresh(self,
en): # input en; en): # input en;
"""
Enable (disable) refresh of the DDR3 memory
<en> - 1 - enable, 0 - disable
"""
self.write_contol_register(self.MCONTR_TOP_0BIT_ADDR + self.MCONTR_TOP_0BIT_REFRESH_EN + en, 0); self.write_contol_register(self.MCONTR_TOP_0BIT_ADDR + self.MCONTR_TOP_0BIT_REFRESH_EN + en, 0);
def enable_memcntrl(self, def enable_memcntrl(self,
en): # input en; en): # input en;
"""
Enable memory controller module
<en> - 1 - enable, 0 - disable
"""
self.write_contol_register(self.MCONTR_TOP_0BIT_ADDR + self.MCONTR_TOP_0BIT_MCONTR_EN + en, 0); self.write_contol_register(self.MCONTR_TOP_0BIT_ADDR + self.MCONTR_TOP_0BIT_MCONTR_EN + en, 0);
def enable_memcntrl_channels(self, def enable_memcntrl_channels(self,
chnen): # input [15:0] chnen; // bit-per-channel, 1 - enable; chnen): # input [15:0] chnen; // bit-per-channel, 1 - enable;
"""
Enable memory controller channels (all at once control)
<chnen> - 16-bit control word with per-channel enable bits (bit0 - chn0, ... bit15 - chn15)
"""
self.enabled_channels = chnen; # currently enabled memory channels self.enabled_channels = chnen; # currently enabled memory channels
self.write_contol_register(self.MCONTR_TOP_16BIT_ADDR + self.MCONTR_TOP_16BIT_CHN_EN, self.enabled_channels & 0xffff) # {16'b0,chnen}); self.write_contol_register(self.MCONTR_TOP_16BIT_ADDR + self.MCONTR_TOP_16BIT_CHN_EN, self.enabled_channels & 0xffff) # {16'b0,chnen});
def enable_memcntrl_en_dis(self, def enable_memcntrl_en_dis(self,
chn, # input [3:0] chn; chn, # input [3:0] chn;
en):# input en; en):# input en;
"""
Enable memory controller channels (one at a time)
<chn> - 4-bit channel select
<en> - 1 - enable, 0 - disable of the selected channel
"""
if en: if en:
self.enabled_channels = self.enabled_channels | (1<<chn); self.enabled_channels = self.enabled_channels | (1<<chn);
else: else:
...@@ -175,5 +244,10 @@ class X393AxiControlStatus(object): ...@@ -175,5 +244,10 @@ class X393AxiControlStatus(object):
def configure_channel_priority(self, def configure_channel_priority(self,
chn, # input [ 3:0] chn; chn, # input [ 3:0] chn;
priority): #input [15:0] priority; // (higher is more important) priority): #input [15:0] priority; // (higher is more important)
"""
Configure channel priority
<chn> - 4-bit channel select
<priority> - 16-bit priority value (higher value means more important)
"""
self.write_contol_register(self.MCONTR_ARBIT_ADDR + chn, priority & 0xffff)# {16'b0,priority}); self.write_contol_register(self.MCONTR_ARBIT_ADDR + chn, priority & 0xffff)# {16'b0,priority});
...@@ -61,7 +61,16 @@ class X393McntrlBuffers(object): ...@@ -61,7 +61,16 @@ class X393McntrlBuffers(object):
num_bursts, # input [NUM_XFER_BITS:0] num_bursts; // number of 8-bursts to write (will be rounded up to multiple of 16) num_bursts, # input [NUM_XFER_BITS:0] num_bursts; // number of 8-bursts to write (will be rounded up to multiple of 16)
startX, # input integer startX; startX, # input integer startX;
startY): #input integer startY; startY): #input integer startY;
print("====== write_block_scanline_chn:%d page: %x X=0x%x Y=0x%x num=%dt"%(chn, page, startX, startY,num_bursts)) """
Fill buffer with the generated data in scanline mode
<chn> 4-bit channel number (0,1,2,3,4 are valid) to use
<page> 2-bit page number in the buffer to write to
<num_bursts> number of 8-word (16 bytes) bursts to write
<startX> horizontal shift of the left of the data line to write, in bytes
<startY> line number to encode in the data
"""
if self.DEBUG_MODE > 1:
print("====== write_block_scanline_chn:%d page: %x X=0x%x Y=0x%x num=%dt"%(chn, page, startX, startY,num_bursts))
if chn == 0: start_addr=self.MCONTR_BUF0_WR_ADDR + (page << 8) if chn == 0: start_addr=self.MCONTR_BUF0_WR_ADDR + (page << 8)
elif chn == 1: start_addr=self.MCONTR_BUF1_WR_ADDR + (page << 8) elif chn == 1: start_addr=self.MCONTR_BUF1_WR_ADDR + (page << 8)
elif chn == 2: start_addr=self.MCONTR_BUF2_WR_ADDR + (page << 8) elif chn == 2: start_addr=self.MCONTR_BUF2_WR_ADDR + (page << 8)
...@@ -76,6 +85,11 @@ class X393McntrlBuffers(object): ...@@ -76,6 +85,11 @@ class X393McntrlBuffers(object):
def write_block_buf(self, def write_block_buf(self,
start_word_address, # input [29:0] start_word_address; start_word_address, # input [29:0] start_word_address;
num_words_or_data_list): # input integer num_words; # number of words to write (will be rounded up to multiple of 16) num_words_or_data_list): # input integer num_words; # number of words to write (will be rounded up to multiple of 16)
"""
Fill buffer the pattern data
<start_word_address> full register address in AXI space (in 32-bit words, not bytes)
<num_words_or_data_list> number of 32-bit words to generate/write or a list with integer data
"""
if isinstance (num_words_or_data_list,int): if isinstance (num_words_or_data_list,int):
data=[] data=[]
for i in range(num_words_or_data_list): for i in range(num_words_or_data_list):
...@@ -94,6 +108,12 @@ class X393McntrlBuffers(object): ...@@ -94,6 +108,12 @@ class X393McntrlBuffers(object):
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;
"""
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)
"""
if self.verbose>0: if self.verbose>0:
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):
...@@ -105,6 +125,12 @@ class X393McntrlBuffers(object): ...@@ -105,6 +125,12 @@ class X393McntrlBuffers(object):
chn, # input integer chn; # buffer channel chn, # input integer chn; # buffer channel
page, # input [1:0] page; page, # input [1:0] page;
num_words_or_data_list): # input integer num_words; # number of words to write (will be rounded up to multiple of 16) num_words_or_data_list): # input integer num_words; # number of words to write (will be rounded up to multiple of 16)
"""
Fill specified buffer with the pattern data
<chn> 4-bit buffer channel (0..4) to write data to
<page> 2-bit buffer page to write to
<num_words_or_data_list> number of 32-bit words to generate/write or a list with integer data
"""
start_addr=-1 start_addr=-1
if chn==0:start_addr=self.MCONTR_BUF0_WR_ADDR + (page << 8) if chn==0:start_addr=self.MCONTR_BUF0_WR_ADDR + (page << 8)
elif chn==1:start_addr=self.MCONTR_BUF1_WR_ADDR + (page << 8) elif chn==1:start_addr=self.MCONTR_BUF1_WR_ADDR + (page << 8)
...@@ -120,6 +146,13 @@ class X393McntrlBuffers(object): ...@@ -120,6 +146,13 @@ class X393McntrlBuffers(object):
start_word_address, # input [29:0] start_word_address; start_word_address, # input [29:0] start_word_address;
num_read, # input integer num_read; # number of words to read (will be rounded up to multiple of 16) num_read, # input integer num_read; # number of words to read (will be rounded up to multiple of 16)
show_rslt=True): show_rslt=True):
"""
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_read> number of 32-bit words to read
<show_rslt> print buffer data read
"""
if self.verbose>0: if self.verbose>0:
print("**** read_block_buf, start_word_address=0x%x, num_read=0x%x "%(start_word_address,num_read)) print("**** read_block_buf, start_word_address=0x%x, num_read=0x%x "%(start_word_address,num_read))
result=[] result=[]
...@@ -135,6 +168,13 @@ class X393McntrlBuffers(object): ...@@ -135,6 +168,13 @@ class X393McntrlBuffers(object):
page, #input [1:0] page; page, #input [1:0] page;
num_read, #input integer num_read; # number of words to read (will be rounded up to multiple of 16) num_read, #input integer num_read; # number of words to read (will be rounded up to multiple of 16)
show_rslt=True): show_rslt=True):
"""
Fill buffer the incremental data (each next register is written with previous register data + 1
<chn> 4-bit buffer channel (0..4) to read from
<page> 2-bit buffer page to read from
<num_read> number of 32-bit words to read
<show_rslt> print buffer data read
"""
start_addr=-1 start_addr=-1
if chn==0: start_addr=self.MCONTR_BUF0_RD_ADDR + (page << 8) if chn==0: start_addr=self.MCONTR_BUF0_RD_ADDR + (page << 8)
elif chn==1: start_addr=self.MCONTR_BUF1_RD_ADDR + (page << 8) elif chn==1: start_addr=self.MCONTR_BUF1_RD_ADDR + (page << 8)
......
...@@ -72,7 +72,18 @@ class X393McntrlTests(object): ...@@ -72,7 +72,18 @@ class X393McntrlTests(object):
write_mem, # input write_mem; # write to memory mode (0 - read from memory) write_mem, # input write_mem; # write to memory mode (0 - read from memory)
enable, # input enable; # enable requests from this channel ( 0 will let current to finish, but not raise want/need) enable, # input enable; # enable requests from this channel ( 0 will let current to finish, but not raise want/need)
chn_reset): # input chn_reset; # immediately reset all the internal circuitry chn_reset): # input chn_reset; # immediately reset all the internal circuitry
return concat (# func_encode_mode_tiled={ """
Combines arguments to create a 7-bit encoded data for tiled mode memory R/W
<byte32> use 32-byte wide columns (0 - use 16-byte ones)
<keep_open>, do not close page between accesses (for 8 or less rows only)
<extra_pages>, 2-bit number of extra pages that need to stay (not to be overwritten) in the buffer
This argument can be used for read access with horizontal overlapping tiles
<write_mem>, write to memory mode (0 - read from memory)
<enable>, enable requests from this channel ( 0 will let current to finish, but not raise want/need)
<chn_reset>): immediately reset all the internal circuitry
"""
return concat (
((0,1)[byte32], 1), # byte32, ((0,1)[byte32], 1), # byte32,
((0,1)[keep_open],1), # keep_open, ((0,1)[keep_open],1), # keep_open,
(extra_pages, 2), # extra_pages, (extra_pages, 2), # extra_pages,
...@@ -86,13 +97,33 @@ class X393McntrlTests(object): ...@@ -86,13 +97,33 @@ class X393McntrlTests(object):
write_mem, # input write_mem; # write to memory mode (0 - read from memory) write_mem, # input write_mem; # write to memory mode (0 - read from memory)
enable, # input enable; # enable requests from this channel ( 0 will let current to finish, but not raise want/need) enable, # input enable; # enable requests from this channel ( 0 will let current to finish, but not raise want/need)
chn_reset): # input chn_reset; # immediately reset all the internal circuitry chn_reset): # input chn_reset; # immediately reset all the internal circuitry
return concat (# func_encode_mode_tiled={ """
Combines arguments to create a 5-bit encoded data for scanline mode memory R/W
<extra_pages>, 2-bit number of extra pages that need to stay (not to be overwritten) in the buffer
This argument can be used for read access with horizontal overlapping tiles
<write_mem>, write to memory mode (0 - read from memory)
<enable>, enable requests from this channel ( 0 will let current to finish, but not raise want/need)
<chn_reset>): immediately reset all the internal circuitry
"""
return concat (
(extra_pages, 2), # extra_pages, (extra_pages, 2), # extra_pages,
((0,1)[write_mem],1), # write_mem, ((0,1)[write_mem],1), # write_mem,
((0,1)[enable], 1), #enable, ((0,1)[enable], 1), #enable,
((1,0)[chn_reset],1)) # ~chn_reset}; ((1,0)[chn_reset],1)) # ~chn_reset};
def task_set_up(self, def task_set_up(self,
set_per_pin_delays): set_per_pin_delays):
"""
Initial setup of the memory controller, including:
tristate patterns
DQS/DQM patterns
all sequences
channel 0 buffer data
I/O delays
clock phase
<set_per_pin_delays> - 1 - set individual (per-pin) I/O delays, 0 - use common for the whole class
"""
# 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.)
...@@ -117,6 +148,9 @@ class X393McntrlTests(object): ...@@ -117,6 +148,9 @@ class X393McntrlTests(object):
self.x393_mcntrl_timing.axi_set_phase(self.DLY_PHASE); self.x393_mcntrl_timing.axi_set_phase(self.DLY_PHASE);
def set_all_sequences(self): def set_all_sequences(self):
"""
Set all sequences: MRS, REFRESH, WRITE LEVELLING, READ PATTERN, WRITE BLOCK, READ BLOCK
"""
if self.verbose>0: print("SET MRS") if self.verbose>0: print("SET MRS")
self.x393_pio_sequences.set_mrs(1) # reset DLL self.x393_pio_sequences.set_mrs(1) # reset DLL
if self.verbose>0: print("SET REFRESH") if self.verbose>0: print("SET REFRESH")
...@@ -145,6 +179,13 @@ class X393McntrlTests(object): ...@@ -145,6 +179,13 @@ class X393McntrlTests(object):
wait_complete, # Wait for operation to complete wait_complete, # Wait for operation to complete
wlev_dqs_dly= 0x80, wlev_dqs_dly= 0x80,
norm_dqs_odly=0x78): norm_dqs_odly=0x78):
"""
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
"""
# Set special values for DQS idelay for write leveling # 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_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() self.x393_mcntrl_timing.axi_set_dqs_idelay_wlv()
...@@ -155,7 +196,7 @@ class X393McntrlTests(object): ...@@ -155,7 +196,7 @@ class X393McntrlTests(object):
self.x393_pio_sequences.schedule_ps_pio (# schedule software-control memory operation (may need to check FIFO status first) 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 self.WRITELEV_OFFSET, # input [9:0] seq_addr; # sequence start address
0, # input [1:0] page; # buffer page number 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 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 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 wait_complete) # `PS_PIO_WAIT_COMPLETE );# wait_complete; # Do not request a newe transaction from the scheduler until previous memory transaction is finished
...@@ -165,7 +206,7 @@ class X393McntrlTests(object): ...@@ -165,7 +206,7 @@ class X393McntrlTests(object):
self.x393_pio_sequences.schedule_ps_pio ( # schedule software-control memory operation (may need to check FIFO status first) 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 self.WRITELEV_OFFSET, # input [9:0] seq_addr; # sequence start address
1, # input [1:0] page; # buffer page number 1, # 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 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 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 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_pio_sequences.wait_ps_pio_done(self.DEFAULT_STATUS_MODE,1); # wait previous memory transaction finished before changing delays (effective immediately)
...@@ -177,11 +218,16 @@ class X393McntrlTests(object): ...@@ -177,11 +218,16 @@ class X393McntrlTests(object):
def test_read_pattern(self, def test_read_pattern(self,
wait_complete): # Wait for operation to complete wait_complete): # Wait for operation to complete
"""
Test read pattern mode
<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.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 self.READ_PATTERN_OFFSET, # input [9:0] seq_addr; # sequence start address
2, # input [1:0] page; # buffer page number 2, # 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 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 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 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_pio_sequences.wait_ps_pio_done(self.DEFAULT_STATUS_MODE,1) # wait previous memory transaction finished before changing delays (effective immediately)
...@@ -189,12 +235,15 @@ class X393McntrlTests(object): ...@@ -189,12 +235,15 @@ class X393McntrlTests(object):
def test_write_block(self, def test_write_block(self,
wait_complete): # Wait for operation to complete 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 # 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.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 self.WRITE_BLOCK_OFFSET, # input [9:0] seq_addr; # sequence start address
0, # input [1:0] page; # buffer page number 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 urgent; # high priority request (only for competion with other channels, will not pass in this FIFO)
1, # input chn; # channel buffer to use: 0 - memory read, 1 - memory write 1, # input chn; # channel buffer to use: 0 - memory read, 1 - memory write
wait_complete) # `PS_PIO_WAIT_COMPLETE )# wait_complete; # Do not request a newe transaction from the scheduler until previous memory transaction is finished 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: # temporary - for debugging:
...@@ -202,22 +251,27 @@ class X393McntrlTests(object): ...@@ -202,22 +251,27 @@ class X393McntrlTests(object):
def test_read_block(self, def test_read_block(self,
wait_complete): # Wait for operation to complete wait_complete): # Wait for operation to complete
"""
Test read block in PS PIO mode
<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.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 self.READ_BLOCK_OFFSET, # input [9:0] seq_addr; # sequence start address
3, # input [1:0] page; # buffer page number 3, # 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 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 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_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.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 self.READ_BLOCK_OFFSET, # input [9:0] seq_addr; # sequence start address
2, # input [1:0] page; # buffer page number 2, # 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 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 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_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.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 self.READ_BLOCK_OFFSET, # input [9:0] seq_addr; # sequence start address
1, # input [1:0] page; # buffer page number 1, # 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 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 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_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_pio_sequences.wait_ps_pio_done(self.DEFAULT_STATUS_MODE,1); # wait previous memory transaction finished before changing delays (effective immediately)
...@@ -231,6 +285,16 @@ class X393McntrlTests(object): ...@@ -231,6 +285,16 @@ class X393McntrlTests(object):
window_height, # input [15:0] window_height; window_height, # input [15:0] window_height;
window_left, # input [15:0] window_left; window_left, # input [15:0] window_left;
window_top): # input [15:0] window_top; window_top): # input [15:0] window_top;
"""
Test scanline write (frame size/row increment is set in parameters)
<channel> channel number to use. Valid values: 1, 3
<extra_pages> 2-bit number of extra pages that need to stay (not to be overwritten) in the buffer
<wait_done> for operation finished
<window_width> 13-bit window width in 8-bursts (16 bytes)
<window_height> 16 bit window height
<window_left>, 13-bit window left margin in 8-bursts (16 bytes)
<window_top> 16-bit window top margin
"""
# integer startx,starty; # temporary - because of the vdt bug with integer ports # integer startx,starty; # temporary - because of the vdt bug with integer ports
# pages_per_row= (window_width>>NUM_XFER_BITS)+((window_width[NUM_XFER_BITS-1:0]==0)?0:1); # pages_per_row= (window_width>>NUM_XFER_BITS)+((window_width[NUM_XFER_BITS-1:0]==0)?0:1);
pages_per_row= (window_width>>self.NUM_XFER_BITS)+(0,1)[(window_width & ((1<<self.NUM_XFER_BITS))-1)==0] # (window_width>>NUM_XFER_BITS)+((window_width[NUM_XFER_BITS-1:0]==0)?0:1); pages_per_row= (window_width>>self.NUM_XFER_BITS)+(0,1)[(window_width & ((1<<self.NUM_XFER_BITS))-1)==0] # (window_width>>NUM_XFER_BITS)+((window_width[NUM_XFER_BITS-1:0]==0)?0:1);
...@@ -336,6 +400,18 @@ class X393McntrlTests(object): ...@@ -336,6 +400,18 @@ class X393McntrlTests(object):
window_height, # input [15:0] window_height; window_height, # input [15:0] window_height;
window_left, # input [15:0] window_left; window_left, # input [15:0] window_left;
window_top): # input [15:0] window_top; window_top): # input [15:0] window_top;
"""
Test scanline read (frame size/row increment is set in parameters)
<channel> channel number to use. Valid values: 1, 3
<extra_pages> 2-bit number of extra pages that need to stay (not to be overwritten) in the buffer
<show_data> print read data
<window_width> 13-bit window width in 8-bursts (16 bytes)
<window_height> 16 bit window height
<window_left>, 13-bit window left margin in 8-bursts (16 bytes)
<window_top> 16-bit window top margin
Returns read data as list
"""
result=[] # will be a 2-d array result=[] # will be a 2-d array
# pages_per_row= (window_width>>NUM_XFER_BITS)+((window_width[NUM_XFER_BITS-1:0]==0)?0:1); # pages_per_row= (window_width>>NUM_XFER_BITS)+((window_width[NUM_XFER_BITS-1:0]==0)?0:1);
...@@ -415,6 +491,22 @@ class X393McntrlTests(object): ...@@ -415,6 +491,22 @@ class X393McntrlTests(object):
tile_width, # input [ 7:0] tile_width; tile_width, # input [ 7:0] tile_width;
tile_height, # input [ 7:0] tile_height; tile_height, # input [ 7:0] tile_height;
tile_vstep): # input [ 7:0] tile_vstep; tile_vstep): # input [ 7:0] tile_vstep;
"""
Test tiled mode write (frame size/row increment is set in parameters)
<channel> channel number to use. Valid values: 2, 4
<byte32> use 32-byte wide columns (0 - use 16-byte ones)
<keep_open>, do not close page between accesses (for 8 or less rows only)
<extra_pages> 2-bit number of extra pages that need to stay (not to be overwritten) in the buffer
<wait_done> wait for operation finished
<window_width> 13-bit window width in 8-bursts (16 bytes)
<window_height> 16 bit window height
<window_left>, 13-bit window left margin in 8-bursts (16 bytes)
<window_top> 16-bit window top margin
<tile_width> 6-bit tile width in 8-bursts (16 bytes) (0 -> 64)
<tile_height> 6-bit tile_height (0->64)
<tile_vstep> 6-bit tile vertical step (0->64) to control tole vertical overlap
"""
# tiles_per_row= (window_width/tile_width)+ ((window_width % tile_width==0)?0:1); # tiles_per_row= (window_width/tile_width)+ ((window_width % tile_width==0)?0:1);
tiles_per_row= (window_width/tile_width)+ (0,1)[(window_width % tile_width)==0] tiles_per_row= (window_width/tile_width)+ (0,1)[(window_width % tile_width)==0]
tile_rows_per_window= ((window_height-1)/tile_vstep) + 1 tile_rows_per_window= ((window_height-1)/tile_vstep) + 1
...@@ -525,6 +617,22 @@ class X393McntrlTests(object): ...@@ -525,6 +617,22 @@ class X393McntrlTests(object):
tile_width, # input [ 7:0] tile_width; tile_width, # input [ 7:0] tile_width;
tile_height, # input [ 7:0] tile_height; tile_height, # input [ 7:0] tile_height;
tile_vstep): # input [ 7:0] tile_vstep; tile_vstep): # input [ 7:0] tile_vstep;
"""
Test tiled mode write (frame size/row increment is set in parameters)
<channel> channel number to use. Valid values: 2, 4
<byte32> use 32-byte wide columns (0 - use 16-byte ones)
<keep_open>, do not close page between accesses (for 8 or less rows only)
<extra_pages> 2-bit number of extra pages that need to stay (not to be overwritten) in the buffer
<show_data> print read data
<window_width> 13-bit window width in 8-bursts (16 bytes)
<window_height> 16 bit window height
<window_left>, 13-bit window left margin in 8-bursts (16 bytes)
<window_top> 16-bit window top margin
<tile_width> 6-bit tile width in 8-bursts (16 bytes) (0 -> 64)
<tile_height> 6-bit tile_height (0->64)
<tile_vstep> 6-bit tile vertical step (0->64) to control tole vertical overlap
Returns read data as a list
"""
result=[] # will be a 2-d array result=[] # will be a 2-d array
# tiles_per_row= (window_width/tile_width)+ ((window_width % tile_width==0)?0:1); # tiles_per_row= (window_width/tile_width)+ ((window_width % tile_width==0)?0:1);
tiles_per_row= (window_width/tile_width)+ (0,1)[(window_width % tile_width)==0] tiles_per_row= (window_width/tile_width)+ (0,1)[(window_width % tile_width)==0]
......
...@@ -52,6 +52,9 @@ class X393McntrlTiming(object): ...@@ -52,6 +52,9 @@ class X393McntrlTiming(object):
self.x393_axi_tasks=X393AxiControlStatus(debug_mode,dry_mode) self.x393_axi_tasks=X393AxiControlStatus(debug_mode,dry_mode)
self.__dict__.update(VerilogParameters.__dict__["_VerilogParameters__shared_state"]) # Add verilog parameters to the class namespace self.__dict__.update(VerilogParameters.__dict__["_VerilogParameters__shared_state"]) # Add verilog parameters to the class namespace
def get_target_phase(self): def get_target_phase(self):
"""
Returns previously set clock phase value
"""
return self.target_phase return self.target_phase
def axi_set_same_delays(self, # def axi_set_same_delays(self, #
dq_idelay, # input [7:0] dq_idelay; dq_idelay, # input [7:0] dq_idelay;
...@@ -60,7 +63,20 @@ class X393McntrlTiming(object): ...@@ -60,7 +63,20 @@ class X393McntrlTiming(object):
dqs_odelay, # input [7:0] dqs_odelay; dqs_odelay, # input [7:0] dqs_odelay;
dm_odelay, # input [7:0] dm_odelay; dm_odelay, # input [7:0] dm_odelay;
cmda_odelay): # input [7:0] cmda_odelay; cmda_odelay): # input [7:0] cmda_odelay;
print("SET DELAYS(0x%x,0x%x,0x%x,0x%x,0x%x,0x%x)"%(dq_idelay,dq_odelay,dqs_idelay,dqs_odelay,dm_odelay,cmda_odelay)) """
Set I/O delays for the DDR3 memory, same delay for all signals in the same class
Each delay value is 8-bit, 5 MSB program in equal steps (=360/32 degrees each),
and 3 LSB (valid values are 0..4) add additional non-calibrated 10ps delay
<dq_idelay> input delay for DQ lines
<dq_odelay> output delay for DQ lines
<dqs_idelay> input delay for DQS lines
<dqs_odelay> output delay for DQS lines
<dm_odelay> input delay for DM lines
<cmda_odelay> output delay for DM lines
"""
if self.DEBUG_MODE > 1:
print("SET DELAYS(0x%x,0x%x,0x%x,0x%x,0x%x,0x%x)"%(dq_idelay,dq_odelay,dqs_idelay,dqs_odelay,dm_odelay,cmda_odelay))
self.axi_set_dq_idelay(dq_idelay) self.axi_set_dq_idelay(dq_idelay)
self.axi_set_dq_odelay(dq_odelay) self.axi_set_dq_odelay(dq_odelay)
self.axi_set_dqs_idelay(dqs_idelay) self.axi_set_dqs_idelay(dqs_idelay)
...@@ -69,21 +85,34 @@ class X393McntrlTiming(object): ...@@ -69,21 +85,34 @@ class X393McntrlTiming(object):
self.axi_set_cmda_odelay(cmda_odelay) self.axi_set_cmda_odelay(cmda_odelay)
def axi_set_dqs_odelay_nominal(self): def axi_set_dqs_odelay_nominal(self):
"""
Set DQS output delays to nominal values (parameter-defined)
"""
self.x393_axi_tasks.write_contol_register(self.LD_DLY_LANE0_ODELAY + 8, (self.DLY_LANE0_ODELAY >> (8<<3)) & 0xff) # 32'hff); self.x393_axi_tasks.write_contol_register(self.LD_DLY_LANE0_ODELAY + 8, (self.DLY_LANE0_ODELAY >> (8<<3)) & 0xff) # 32'hff);
self.x393_axi_tasks.write_contol_register(self.LD_DLY_LANE1_ODELAY + 8, (self.DLY_LANE1_ODELAY >> (8<<3)) & 0xff) # 32'hff); self.x393_axi_tasks.write_contol_register(self.LD_DLY_LANE1_ODELAY + 8, (self.DLY_LANE1_ODELAY >> (8<<3)) & 0xff) # 32'hff);
self.x393_axi_tasks.write_contol_register(self.DLY_SET,0); self.x393_axi_tasks.write_contol_register(self.DLY_SET,0);
def axi_set_dqs_idelay_nominal(self): def axi_set_dqs_idelay_nominal(self):
"""
Set DQS input delays to nominal values (parameter-defined)
"""
self.x393_axi_tasks.write_contol_register(self.LD_DLY_LANE0_IDELAY + 8, (self.DLY_LANE0_IDELAY >> (8<<3)) & 0xff) # 32'hff); self.x393_axi_tasks.write_contol_register(self.LD_DLY_LANE0_IDELAY + 8, (self.DLY_LANE0_IDELAY >> (8<<3)) & 0xff) # 32'hff);
self.x393_axi_tasks.write_contol_register(self.LD_DLY_LANE1_IDELAY + 8, (self.DLY_LANE1_IDELAY >> (8<<3)) & 0xff) # 32'hff); self.x393_axi_tasks.write_contol_register(self.LD_DLY_LANE1_IDELAY + 8, (self.DLY_LANE1_IDELAY >> (8<<3)) & 0xff) # 32'hff);
self.x393_axi_tasks.write_contol_register(self.DLY_SET,0); self.x393_axi_tasks.write_contol_register(self.DLY_SET,0);
def axi_set_dqs_idelay_wlv(self): def axi_set_dqs_idelay_wlv(self):
"""
Set DQS input delays to values defined for the write levelling mode (parameter-defined)
"""
self.x393_axi_tasks.write_contol_register(self.LD_DLY_LANE0_IDELAY + 8, self.DLY_LANE0_DQS_WLV_IDELAY) self.x393_axi_tasks.write_contol_register(self.LD_DLY_LANE0_IDELAY + 8, self.DLY_LANE0_DQS_WLV_IDELAY)
self.x393_axi_tasks.write_contol_register(self.LD_DLY_LANE1_IDELAY + 8, self.DLY_LANE1_DQS_WLV_IDELAY) self.x393_axi_tasks.write_contol_register(self.LD_DLY_LANE1_IDELAY + 8, self.DLY_LANE1_DQS_WLV_IDELAY)
self.x393_axi_tasks.write_contol_register(self.DLY_SET,0) self.x393_axi_tasks.write_contol_register(self.DLY_SET,0)
def axi_set_delays(self): # set all individual delays def axi_set_delays(self): # set all individual delays
"""
Set all DDR3 I/O delays to individual parameter-defined values
"""
for i in range(0,10): # (i=0;i<10;i=i+1) begin for i in range(0,10): # (i=0;i<10;i=i+1) begin
self.x393_axi_tasks.write_contol_register(self.LD_DLY_LANE0_ODELAY + i, (self.DLY_LANE0_ODELAY >> (i<<3)) & 0xff) # 32'hff); self.x393_axi_tasks.write_contol_register(self.LD_DLY_LANE0_ODELAY + i, (self.DLY_LANE0_ODELAY >> (i<<3)) & 0xff) # 32'hff);
for i in range(0,9): # (i=0;i<9;i=i+1) begin for i in range(0,9): # (i=0;i<9;i=i+1) begin
...@@ -98,42 +127,72 @@ class X393McntrlTiming(object): ...@@ -98,42 +127,72 @@ class X393McntrlTiming(object):
def axi_set_dq_idelay(self, # sets same delay to all dq idelay def axi_set_dq_idelay(self, # sets same delay to all dq idelay
delay): # input [7:0] delay; delay): # input [7:0] delay;
print("SET DQ IDELAY=0x%x"%delay) """
Set all DQ input delays to the same value
<delay> 8-bit (5+3) delay value to use
"""
if self.DEBUG_MODE > 1:
print("SET DQ IDELAY=0x%x"%delay)
self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE0_IDELAY, 8, delay) self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE0_IDELAY, 8, delay)
self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE1_IDELAY, 8, delay) self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE1_IDELAY, 8, delay)
self.x393_axi_tasks.write_contol_register (self.DLY_SET,0);# // set all delays self.x393_axi_tasks.write_contol_register (self.DLY_SET,0);# // set all delays
def axi_set_dq_odelay(self, def axi_set_dq_odelay(self,
delay): # input [7:0] delay; delay): # input [7:0] delay;
print("SET DQ ODELAY=0x%x"%delay) """
Set all DQ OUTput delays to the same value
<delay> 8-bit (5+3) delay value to use
"""
if self.DEBUG_MODE > 1:
print("SET DQ ODELAY=0x%x"%delay)
self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE0_ODELAY, 8, delay); self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE0_ODELAY, 8, delay);
self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE1_ODELAY, 8, delay); self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE1_ODELAY, 8, delay);
self.x393_axi_tasks.write_contol_register(self.DLY_SET,0); # set all delays self.x393_axi_tasks.write_contol_register(self.DLY_SET,0); # set all delays
def axi_set_dqs_idelay(self, def axi_set_dqs_idelay(self,
delay): # input [7:0] delay; delay): # input [7:0] delay;
print("SET DQS IDELAY=0x%x"%delay) """
Set all DQs input delays to the same value
<delay> 8-bit (5+3) delay value to use
"""
if self.DEBUG_MODE > 1:
print("SET DQS IDELAY=0x%x"%delay)
self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE0_IDELAY + 8, 1, delay) self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE0_IDELAY + 8, 1, delay)
self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE1_IDELAY + 8, 1, delay) self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE1_IDELAY + 8, 1, delay)
self.x393_axi_tasks.write_contol_register(self.DLY_SET,0); # set all delays self.x393_axi_tasks.write_contol_register(self.DLY_SET,0); # set all delays
def axi_set_dqs_odelay(self, def axi_set_dqs_odelay(self,
delay): # input [7:0] delay; delay): # input [7:0] delay;
print("SET DQS ODELAY=0x%x"%delay) """
Set all DQs OUTput delays to the same value
<delay> 8-bit (5+3) delay value to use
"""
if self.DEBUG_MODE > 1:
print("SET DQS ODELAY=0x%x"%delay)
self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE0_ODELAY + 8, 1, delay) self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE0_ODELAY + 8, 1, delay)
self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE1_ODELAY + 8, 1, delay) self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE1_ODELAY + 8, 1, delay)
self.x393_axi_tasks.write_contol_register(self.DLY_SET,0); # set all delays self.x393_axi_tasks.write_contol_register(self.DLY_SET,0); # set all delays
def axi_set_dm_odelay (self, def axi_set_dm_odelay (self,
delay): # input [7:0] delay; delay): # input [7:0] delay;
print("SET DQM IDELAY=0x%x"%delay) """
Set all DM output delays to the same value
<delay> 8-bit (5+3) delay value to use
"""
if self.DEBUG_MODE > 1:
print("SET DQM IDELAY=0x%x"%delay)
self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE0_ODELAY + 9, 1, delay) self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE0_ODELAY + 9, 1, delay)
self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE1_ODELAY + 9, 1, delay) self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_LANE1_ODELAY + 9, 1, delay)
self.x393_axi_tasks.write_contol_register(self.DLY_SET,0) # set all delays self.x393_axi_tasks.write_contol_register(self.DLY_SET,0) # set all delays
def axi_set_cmda_odelay(self, def axi_set_cmda_odelay(self,
delay): # input [7:0] delay; delay): # input [7:0] delay;
print("SET COMMAND and ADDRESS ODELAY=0x%x"%delay) """
Set all command/addressoutput delays to the same value
<delay> 8-bit (5+3) delay value to use
"""
if self.DEBUG_MODE > 1:
print("SET COMMAND and ADDRESS ODELAY=0x%x"%delay)
self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_CMDA, 32, delay); self.x393_axi_tasks.axi_set_multiple_delays(self.LD_DLY_CMDA, 32, delay);
self.x393_axi_tasks.write_contol_register(self.DLY_SET,0) # set all delays self.x393_axi_tasks.write_contol_register(self.DLY_SET,0) # set all delays
...@@ -141,17 +200,32 @@ class X393McntrlTiming(object): ...@@ -141,17 +200,32 @@ class X393McntrlTiming(object):
reg_addr, #input [29:0] reg_addr; reg_addr, #input [29:0] reg_addr;
number, # input integer number; number, # input integer number;
delay): # input [7:0] delay; delay): # input [7:0] delay;
"""
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 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 regiter address self.x393_axi_tasks.write_contol_register(reg_addr + i, delay) # {24'b0,delay}); // control register address
def axi_set_phase(self, def axi_set_phase(self,
phase): # input [PHASE_WIDTH-1:0] phase; phase): # input [PHASE_WIDTH-1:0] phase;
print("SET CLOCK PHASE=0x%x"%phase) """
Set clock phase
<phase> 8-bit clock phase value
"""
if self.DEBUG_MODE > 1:
print("SET CLOCK PHASE=0x%x"%phase)
self.x393_axi_tasks.write_contol_register(self.LD_DLY_PHASE, phase & ((1<<self.PHASE_WIDTH)-1)) # {{(32-PHASE_WIDTH){1'b0}},phase}); // control regiter address self.x393_axi_tasks.write_contol_register(self.LD_DLY_PHASE, phase & ((1<<self.PHASE_WIDTH)-1)) # {{(32-PHASE_WIDTH){1'b0}},phase}); // control regiter address
self.x393_axi_tasks.write_contol_register(self.DLY_SET,0) self.x393_axi_tasks.write_contol_register(self.DLY_SET,0)
self.target_phase = phase self.target_phase = phase
def wait_phase_shifter_ready(self): def wait_phase_shifter_ready(self):
"""
Wait until clock phase shifter is ready
"""
data=self.x393_axi_tasks.read_and_wait_status(self.MCONTR_PHY_STATUS_REG_ADDR) data=self.x393_axi_tasks.read_and_wait_status(self.MCONTR_PHY_STATUS_REG_ADDR)
while (((data & self.STATUS_PSHIFTER_RDY_MASK) == 0) or (((data ^ self.target_phase) & 0xff) != 0)): while (((data & self.STATUS_PSHIFTER_RDY_MASK) == 0) or (((data ^ self.target_phase) & 0xff) != 0)):
data=self.x393_axi_tasks.read_and_wait_status(self.MCONTR_PHY_STATUS_REG_ADDR) data=self.x393_axi_tasks.read_and_wait_status(self.MCONTR_PHY_STATUS_REG_ADDR)
...@@ -159,10 +233,18 @@ class X393McntrlTiming(object): ...@@ -159,10 +233,18 @@ class X393McntrlTiming(object):
def axi_set_wbuf_delay(self, def axi_set_wbuf_delay(self,
delay): # input [3:0] delay; delay): # input [3:0] delay;
print("SET WBUF DELAY=0x%x"%delay) """
Set write to buffer latency
<delay> 4-bit write to buffer signal delay (in mclk clock cycles)
"""
if self.DEBUG_MODE > 1:
print("SET WBUF DELAY=0x%x"%delay)
self.x393_axi_tasks.write_contol_register(self.MCONTR_PHY_16BIT_ADDR+self.MCONTR_PHY_16BIT_WBUF_DELAY, delay & 0xf) # {28'h0, delay}); self.x393_axi_tasks.write_contol_register(self.MCONTR_PHY_16BIT_ADDR+self.MCONTR_PHY_16BIT_WBUF_DELAY, delay & 0xf) # {28'h0, delay});
#set dq /dqs tristate on/off patterns #set dq /dqs tristate on/off patterns
def axi_set_tristate_patterns(self): def axi_set_tristate_patterns(self):
"""
Set sequencer patterns for the tristate ON/OFF (defined by parameters)
"""
# may fail if some of the parameters used have undefined width # may fail if some of the parameters used have undefined width
delays=concat((0,16), # {16'h0, delays=concat((0,16), # {16'h0,
(self.DQSTRI_LAST, getParWidth(self.DQSTRI_LAST__TYPE)), # DQSTRI_LAST, (self.DQSTRI_LAST, getParWidth(self.DQSTRI_LAST__TYPE)), # DQSTRI_LAST,
...@@ -170,10 +252,15 @@ class X393McntrlTiming(object): ...@@ -170,10 +252,15 @@ class X393McntrlTiming(object):
(self.DQTRI_LAST, getParWidth(self.DQTRI_LAST_FIRST__TYPE)), # DQTRI_LAST, (self.DQTRI_LAST, getParWidth(self.DQTRI_LAST_FIRST__TYPE)), # DQTRI_LAST,
(self.DQTRI_FIRST, getParWidth(self.DQTRI_FIRST__TYPE)) # DQTRI_FIRST}); (self.DQTRI_FIRST, getParWidth(self.DQTRI_FIRST__TYPE)) # DQTRI_FIRST});
) )
print("SET TRISTATE PATTERNS, combined delays=0x%x"%delays) if self.DEBUG_MODE > 1:
print("SET TRISTATE PATTERNS, combined delays=0x%x"%delays)
self.x393_axi_tasks.write_contol_register(self.MCONTR_PHY_16BIT_ADDR +self.MCONTR_PHY_16BIT_PATTERNS_TRI, delays) # DQSTRI_LAST, DQSTRI_FIRST, DQTRI_LAST, DQTRI_FIRST}); self.x393_axi_tasks.write_contol_register(self.MCONTR_PHY_16BIT_ADDR +self.MCONTR_PHY_16BIT_PATTERNS_TRI, delays) # DQSTRI_LAST, DQSTRI_FIRST, DQTRI_LAST, DQTRI_FIRST});
def axi_set_dqs_dqm_patterns(self): def axi_set_dqs_dqm_patterns(self):
print("SET DQS+DQM PATTERNS") """
Set sequencer patterns for the DQ lines ON/OFF (defined by parameters)
"""
if self.DEBUG_MODE > 1:
print("SET DQS+DQM 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_axi_tasks.write_contol_register(self.MCONTR_PHY_16BIT_ADDR + self.MCONTR_PHY_16BIT_PATTERNS, 0x55) # 32'h0055); self.x393_axi_tasks.write_contol_register(self.MCONTR_PHY_16BIT_ADDR + self.MCONTR_PHY_16BIT_PATTERNS, 0x55) # 32'h0055);
...@@ -45,8 +45,12 @@ class X393Mem(object): ...@@ -45,8 +45,12 @@ class X393Mem(object):
def __init__(self, debug_mode=1,dry_mode=True): def __init__(self, debug_mode=1,dry_mode=True):
self.DEBUG_MODE=debug_mode self.DEBUG_MODE=debug_mode
self.DRY_MODE=dry_mode self.DRY_MODE=dry_mode
def write_mem (self,addr, data): def write_mem (self,addr, data):
"""
Write 32-bit word to physical memory
<addr> - physical byte address
<data> - 32-bit data to write
"""
if self.DRY_MODE: if self.DRY_MODE:
print ("write_mem(0x%x,0x%x)"%(addr,data)) print ("write_mem(0x%x,0x%x)"%(addr,data))
return return
...@@ -73,6 +77,10 @@ class X393Mem(object): ...@@ -73,6 +77,10 @@ class X393Mem(object):
''' '''
def read_mem (self,addr): def read_mem (self,addr):
'''
Read 32-bit word from physical memory
<addr> - physical byte address
'''
if self.DRY_MODE: if self.DRY_MODE:
print ("read_mem(0x%x)"%(addr)) print ("read_mem(0x%x)"%(addr))
return return
...@@ -89,93 +97,36 @@ class X393Mem(object): ...@@ -89,93 +97,36 @@ class X393Mem(object):
return d return d
# mm.close() #probably not needed with "with" # mm.close() #probably not needed with "with"
''' '''
Read/write slave AXI using byte addresses relative to the AXI memory reagion Read/write slave AXI using byte addresses relative to the AXI memory region
''' '''
def axi_write_single(self,addr,data): def axi_write_single(self,addr,data):
"""
Write 32-bit word to the slave AXI address range
<addr> - physical byte address relative to the slave AXI memory region
<data> - 32-bit data to write
"""
self.write_mem(self.AXI_SLAVE0_BASE+addr,data) self.write_mem(self.AXI_SLAVE0_BASE+addr,data)
def axi_read_addr(self,addr): def axi_read_addr(self,addr):
"""
Read 32-bit word from the slave AXI address range
<addr> - physical byte address relative to slave AXI AXI memory region
"""
return self.read_mem(self.AXI_SLAVE0_BASE+addr) return self.read_mem(self.AXI_SLAVE0_BASE+addr)
''' '''
Read/write slave AXI using 32-bit word addresses (same as in Verilog code) Read/write slave AXI using 32-bit word addresses (same as in Verilog code)
''' '''
def axi_write_single_w(self,addr,data): def axi_write_single_w(self,addr,data):
"""
Write 32-bit word to the slave AXI address range, using 32-word address
<addr> - 32-bit word (register) address relative to the slave AXI memory region
<data> - 32-bit data to write
"""
self.axi_write_single(addr<<2,data) self.axi_write_single(addr<<2,data)
def axi_read_addr_w(self,addr): def axi_read_addr_w(self,addr):
"""
Read 32-bit word from the slave AXI address range, using 32-word address
<addr> - 32-bit word (register) address relative to the slave AXI memory region
"""
return self.axi_read_addr(addr<<2) return self.axi_read_addr(addr<<2)
'''
task axi_write_addr_data;
input [11:0] id;
input [31:0] addr;
input [31:0] data;
input [ 3:0] len;
input [ 1:0] burst;
input data_en; // if 0 - do not send data, only address
input [ 3:0] wstrb;
input last;
reg data_sent;
// wire data_sent_d;
// assign #(.1) data_sent_d= data_sent;
begin
wait (!CLK && AW_READY);
AWID_IN_r <= id;
AWADDR_IN_r <= addr;
AWLEN_IN_r <= len;
AWSIZE_IN_r <= 3'b010;
AWBURST_IN_r <= burst;
AW_SET_CMD_r <= 1'b1;
if (data_en && W_READY) begin
WID_IN_r <= id;
WDATA_IN_r <= data;
WSTRB_IN_r <= wstrb;
WLAST_IN_r <= last;
W_SET_CMD_r <= 1'b1;
data_sent <= 1'b1;
end else begin
data_sent <= 1'b0;
end
DEBUG1 <=1'b1;
wait (CLK);
DEBUG1 <=1'b0;
AWID_IN_r <= 'hz;
AWADDR_IN_r <= 'hz;
AWLEN_IN_r <= 'hz;
AWSIZE_IN_r <= 'hz;
AWBURST_IN_r <= 'hz;
AW_SET_CMD_r <= 1'b0;
DEBUG2 <=1'b1;
if (data_sent) begin
WID_IN_r <= 'hz;
WDATA_IN_r <= 'hz;
WSTRB_IN_r <= 'hz;
WLAST_IN_r <= 'hz;
W_SET_CMD_r <= 1'b0;
end
// Now sent data if it was not sent simultaneously with the address
if (data_en && !data_sent) begin
DEBUG3 <=1'b1;
wait (!CLK && W_READY);
DEBUG3 <=1'b0;
WID_IN_r <= id;
WDATA_IN_r <= data;
WSTRB_IN_r <= wstrb;
WLAST_IN_r <= last;
W_SET_CMD_r <= 1'b1;
wait (CLK);
DEBUG3 <=1'bx;
WID_IN_r <= 'hz;
WDATA_IN_r <= 'hz;
WSTRB_IN_r <= 'hz;
WLAST_IN_r <= 'hz;
W_SET_CMD_r <= 1'b0;
end
DEBUG2 <=1'b0;
#0.1;
data_sent <= 1'b0;
#0.1;
end
endtask
'''
\ No newline at end of file
...@@ -70,6 +70,15 @@ class X393PIOSequences(object): ...@@ -70,6 +70,15 @@ class X393PIOSequences(object):
urgent, # input urgent; // high priority request (only for competion wityh other channels, wiil not pass in this FIFO) urgent, # input urgent; // high priority request (only for competion wityh other channels, wiil not pass in this FIFO)
chn, # input chn; // channel buffer to use: 0 - memory read, 1 - memory write chn, # input chn; // channel buffer to use: 0 - memory read, 1 - memory write
wait_complete): # input wait_complete; // Do not request a newe transaction from the scheduler until previous memory transaction is finished wait_complete): # input wait_complete; // Do not request a newe transaction from the scheduler until previous memory transaction is finished
"""
Schedule PS PIO memory transaction
<seq_addr> 10-bit sequence start address
<page> buffer page address to use (0..3)
<urgent> high priority request (only for competition with other channels,
will not pass other commands in this module FIFO)
<chn> sub-channel to use: 0 - memory read, 1 - memory write
<wait_complete> Do not request a new transaction from the scheduler until previous memory transaction is finished
"""
self.write_contol_register(self.MCNTRL_PS_ADDR + self.MCNTRL_PS_CMD, self.write_contol_register(self.MCNTRL_PS_ADDR + self.MCNTRL_PS_CMD,
# {17'b0, # {17'b0,
((0,1)[wait_complete]<<14) | ((0,1)[wait_complete]<<14) |
...@@ -81,6 +90,12 @@ class X393PIOSequences(object): ...@@ -81,6 +90,12 @@ class X393PIOSequences(object):
def wait_ps_pio_ready(self, #; // wait PS PIO module can accept comamnds (fifo half empty) def wait_ps_pio_ready(self, #; // wait PS PIO module can accept comamnds (fifo half empty)
mode, # input [1:0] mode; mode, # input [1:0] mode;
sync_seq): # input sync_seq; // synchronize sequences sync_seq): # input sync_seq; // synchronize sequences
"""
Wait until PS PIO module can accept comamnds (fifo half empty)
<mode> status mode (0..3) - see 'help program_status'
<synq_seq> status sequence number - see 'help program_status'
"""
self.x393_axi_tasks.wait_status_condition ( self.x393_axi_tasks.wait_status_condition (
self.MCNTRL_PS_STATUS_REG_ADDR, self.MCNTRL_PS_STATUS_REG_ADDR,
self.MCNTRL_PS_ADDR + self.MCNTRL_PS_STATUS_CNTRL, self.MCNTRL_PS_ADDR + self.MCNTRL_PS_STATUS_CNTRL,
...@@ -93,6 +108,11 @@ class X393PIOSequences(object): ...@@ -93,6 +108,11 @@ class X393PIOSequences(object):
def wait_ps_pio_done(self, # // wait PS PIO module has no pending/running memory transaction def wait_ps_pio_done(self, # // wait PS PIO module has no pending/running memory transaction
mode, # input [1:0] mode; mode, # input [1:0] mode;
sync_seq): # input sync_seq; // synchronize sequences sync_seq): # input sync_seq; // synchronize sequences
"""
Wait PS PIO module has no pending/running memory transaction
<mode> status mode (0..3) - see 'help program_status'
<synq_seq> status sequence number - see 'help program_status'
"""
self.x393_axi_tasks.wait_status_condition ( self.x393_axi_tasks.wait_status_condition (
self.MCNTRL_PS_STATUS_REG_ADDR, self.MCNTRL_PS_STATUS_REG_ADDR,
self.MCNTRL_PS_ADDR + self.MCNTRL_PS_STATUS_CNTRL, self.MCNTRL_PS_ADDR + self.MCNTRL_PS_STATUS_CNTRL,
...@@ -119,6 +139,23 @@ class X393PIOSequences(object): ...@@ -119,6 +139,23 @@ class X393PIOSequences(object):
buf_rd, # input buf_rd; // connect to external buffer (but only if not paused) buf_rd, # input buf_rd; // connect to external buffer (but only if not paused)
nop, # input nop; // add NOP after the current command, keep other data nop, # input nop; // add NOP after the current command, keep other data
buf_rst): # input buf_rst; // connect to external buffer (but only if not paused) buf_rst): # input buf_rst; // connect to external buffer (but only if not paused)
"""
Encode data into memory controller sequencer word
<addr> 15-bit row/column adderss
<bank> 3-bit bank address
<rcw> 3-bit combined {RAS,CAS,WE}, positive logic
<odt_en> enable ODT
<cke> disable CKE
<sel> first(0)/second(1) half-cycle, other half-cycle will be NOP (cke+odt applicable to both)
<dq_en> enable (turn tristate off) DQ lines (internal timing sequencer for 0->1 and 1->0)
<dqs_en> enable (turn tristate off) DQS lines (internal timing sequencer for 0->1 and 1->0)
<dqs_toggle> enable toggle DQS lines according to the pattern
<dci> DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
<buf_wr> generate external buffer write/address increment
<buf_rd> generate external buffer read/address increment
<nop> add NOP after the current command, keep other data
<buf_rst> reset external buffer page address to 0, increment page number
"""
return ( return (
((addr & 0x7fff) << 17) | # addr[14:0], // 15-bit row/column adderss ((addr & 0x7fff) << 17) | # addr[14:0], // 15-bit row/column adderss
((bank & 0x7) << 14) | # bank [2:0], // bank ((bank & 0x7) << 14) | # bank [2:0], // bank
...@@ -149,7 +186,23 @@ class X393PIOSequences(object): ...@@ -149,7 +186,23 @@ class X393PIOSequences(object):
dci, # input dci; // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0) dci, # input dci; // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
buf_wr, # input buf_wr; // connect to external buffer (but only if not paused) buf_wr, # input buf_wr; // connect to external buffer (but only if not paused)
buf_rd, # input buf_rd; // connect to external buffer (but only if not paused) buf_rd, # input buf_rd; // connect to external buffer (but only if not paused)
buf_rst): #input buf_rst; // connect to external buffer (but only if not paused) buf_rst): #input buf_rst; // connect to external buffer (but only if not paused)
"""
Encode skip cycles command into memory controller sequencer word. NOP will be present on RCW(RAS/CAS/WE) lines
<skip> 10-bit number of cycles to skip minus 1
<done> 10-bit number of cycles to skip minus 1
<bank> 3-bit bank address
<odt_en> enable ODT
<cke> disable CKE
<sel> first(0)/second(1) half-cycle, other half-cycle will be NOP (cke+odt applicable to both)
<dq_en> enable (turn tristate off) DQ lines (internal timing sequencer for 0->1 and 1->0)
<dqs_en> enable (turn tristate off) DQS lines (internal timing sequencer for 0->1 and 1->0)
<dqs_toggle> enable toggle DQS lines according to the pattern
<dci> DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
<buf_wr> generate external buffer write/address increment
<buf_rd> generate external buffer read/address increment
<buf_rst> reset external buffer page address to 0, increment page number
"""
return self.func_encode_cmd ( return self.func_encode_cmd (
((0,1)[done] << self.CMD_PAUSE_BITS) | # {{14-CMD_DONE_BIT{1'b0}}, done, ((0,1)[done] << self.CMD_PAUSE_BITS) | # {{14-CMD_DONE_BIT{1'b0}}, done,
(skip & ((1 << self.CMD_PAUSE_BITS)-1)), # skip[CMD_PAUSE_BITS-1:0]}, // 15-bit row/column address (skip & ((1 << self.CMD_PAUSE_BITS)-1)), # skip[CMD_PAUSE_BITS-1:0]}, // 15-bit row/column address
...@@ -197,6 +250,39 @@ class X393PIOSequences(object): ...@@ -197,6 +250,39 @@ class X393PIOSequences(object):
# 2'b01 - 4 or 8 on-the-fly by A12 # 2'b01 - 4 or 8 on-the-fly by A12
# 2'b10 - fixed BL4 (chop) # 2'b10 - fixed BL4 (chop)
# 2'b11 - reserved # 2'b11 - reserved
"""
Encode DDR3 MR0 register data
<pd> precharge power down 0 - dll off (slow exit), 1 - dll on (fast exit)
<wr> write recovery:
000: 16
001: 5
010: 6
011: 7
100: 8
101: 10
110: 12
111: 14
<dll_rst> 1 - dll reset (self clearing bit)
<cl> CAS latency (>=15ns):
0000: reserved
0010: 5
0100: 6
0110: 7
1000: 8
1010: 9
1100: 10
1110: 11
0001: 12
0011: 13
0101: 14
<bt> read burst type: 0 sequential (nibble), 1 - interleaved
<bl> burst length:
00 - fixed BL8
01 - 4 or 8 on-the-fly by A12
10 - fixed BL4 (chop)
11 - reserved
"""
return concat(( return concat((
(0,3), # 3'b0, (0,3), # 3'b0,
(0,self.ADDRESS_NUMBER-13), # {ADDRESS_NUMBER-13{1'b0}}, (0,self.ADDRESS_NUMBER-13), # {ADDRESS_NUMBER-13{1'b0}},
...@@ -231,6 +317,30 @@ class X393PIOSequences(object): ...@@ -231,6 +317,30 @@ class X393PIOSequences(object):
# 2'b10 - AL=CL-2 # 2'b10 - AL=CL-2
# 2'b11 - reserved # 2'b11 - reserved
dll): #input dll; # 0 - DLL enabled (normal), 1 - DLL disabled dll): #input dll; # 0 - DLL enabled (normal), 1 - DLL disabled
"""
Encode DDR3 MR1 register data
<qoff> output enable: 0 - DQ, DQS operate in normal mode, 1 - DQ, DQS are disabled
<tdqs> termination data strobe (for x8 devices) 0 - disabled, 1 - enabled
<rtt> on-die termination resistance:
000 - disabled
001 - RZQ/4 (60 Ohm)
010 - RZQ/2 (120 Ohm)
011 - RZQ/6 (40 Ohm)
100 - RZQ/12(20 Ohm)
101 - RZQ/8 (30 Ohm)
11x - reserved
<wlev> write leveling mode
<ods> output drive strength:
00 - RZQ/6 - 40 Ohm
01 - RZQ/7 - 34 Ohm
1x - reserved
<al> additive latency:
00 - disabled (AL=0)
01 - AL=CL-1;
10 - AL=CL-2
11 - reserved
<dll> 0 - DLL enabled (normal), 1 - DLL disabled
"""
return concat (( # ddr3_mr1 = { return concat (( # ddr3_mr1 = {
(1,3), # 3'h1, (1,3), # 3'h1,
(0, self.ADDRESS_NUMBER-13), # {ADDRESS_NUMBER-13{1'b0}}, (0, self.ADDRESS_NUMBER-13), # {ADDRESS_NUMBER-13{1'b0}},
...@@ -263,6 +373,24 @@ class X393PIOSequences(object): ...@@ -263,6 +373,24 @@ class X393PIOSequences(object):
# 3'b100 9CK (1.071ns <= tCK < 1.25ns) # 3'b100 9CK (1.071ns <= tCK < 1.25ns)
# 3'b101 10CK (0.938ns <= tCK < 1.071ns) # 3'b101 10CK (0.938ns <= tCK < 1.071ns)
# 3'b11x reserved # 3'b11x reserved
"""
Encode DDR3 MR2 register data
<rtt_wr> Dynamic ODT :
00 - disabled
01 - RZQ/4 = 60 Ohm
10 - RZQ/2 = 120 Ohm
11 - reserved
<srt> Self-refresh temperature 0 - normal (0-85C), 1 - extended (<=95C)
<asr> Auto self-refresh 0 - disabled (manual), 1 - enabled (auto)
<cwl> CAS write latency:
000 5CK ( tCK >= 2.5ns)
001 6CK (1.875ns <= tCK < 2.5ns)
010 7CK (1.5ns <= tCK < 1.875ns)
011 8CK (1.25ns <= tCK < 1.5ns)
100 9CK (1.071ns <= tCK < 1.25ns)
101 10CK (0.938ns <= tCK < 1.071ns)
11x reserved
"""
return concat (( return concat ((
(2,3), # 3'h2, (2,3), # 3'h2,
(0, self.ADDRESS_NUMBER-11), # {ADDRESS_NUMBER-11{1'b0}}, (0, self.ADDRESS_NUMBER-11), # {ADDRESS_NUMBER-11{1'b0}},
...@@ -278,6 +406,13 @@ class X393PIOSequences(object): ...@@ -278,6 +406,13 @@ class X393PIOSequences(object):
mpr_rf): # input [1:0] mpr_rf; # MPR read function: mpr_rf): # input [1:0] mpr_rf; # MPR read function:
# 2'b00: predefined pattern 0101... # 2'b00: predefined pattern 0101...
# 2'b1x, 2'bx1 - reserved # 2'b1x, 2'bx1 - reserved
"""
Encode DDR3 MR3 register data
<mpr> MPR mode: 0 - normal, 1 - dataflow from MPR
<mpr_rf> MPR read function:
00: predefined pattern 0101...
1x, 2'bx1 - reserved
"""
return concat(( return concat((
(3,3), # 3'h3, (3,3), # 3'h3,
(0,self.ADDRESS_NUMBER), # {ADDRESS_NUMBER-3{1'b0}}, (0,self.ADDRESS_NUMBER), # {ADDRESS_NUMBER-3{1'b0}},
...@@ -290,6 +425,12 @@ class X393PIOSequences(object): ...@@ -290,6 +425,12 @@ class X393PIOSequences(object):
def enable_reset_ps_pio(self, #; // control reset and enable of the PS PIO channel; def enable_reset_ps_pio(self, #; // control reset and enable of the PS PIO channel;
en, # input en; en, # input en;
rst): #input rst; rst): #input rst;
"""
Enable/disable and reset PS PIO channel
<en> 1 - enable, 0 - disable (only influences request for arbitration, started transactions will finish if disabled)
<rst> 1 - reset active, 0 - reset off
"""
self.write_contol_register(self.MCNTRL_PS_ADDR + self.MCNTRL_PS_EN_RST, self.write_contol_register(self.MCNTRL_PS_ADDR + self.MCNTRL_PS_EN_RST,
((0,1)[en]<<1) | #{30'b0,en, ((0,1)[en]<<1) | #{30'b0,en,
(1,0)[rst]) #~rst}); (1,0)[rst]) #~rst});
...@@ -299,6 +440,12 @@ class X393PIOSequences(object): ...@@ -299,6 +440,12 @@ class X393PIOSequences(object):
ba, # input [ 2:0] ba; ba, # input [ 2:0] ba;
ra, # input [14:0] ra; ra, # input [14:0] ra;
ca): #input [ 9:0] ca; ca): #input [ 9:0] ca;
"""
Setup read 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
"""
cmd_addr = self.MCONTR_CMD_WR_ADDR + self.READ_BLOCK_OFFSET cmd_addr = self.MCONTR_CMD_WR_ADDR + self.READ_BLOCK_OFFSET
# activate # activate
# addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST # addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
...@@ -363,6 +510,13 @@ class X393PIOSequences(object): ...@@ -363,6 +510,13 @@ class X393PIOSequences(object):
ba, # input[2:0]ba; ba, # input[2:0]ba;
ra, # input[14:0]ra; ra, # input[14:0]ra;
ca): # input[9:0]ca; ca): # input[9:0]ca;
"""
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
"""
cmd_addr = self.MCONTR_CMD_WR_ADDR + self.WRITE_BLOCK_OFFSET cmd_addr = self.MCONTR_CMD_WR_ADDR + self.WRITE_BLOCK_OFFSET
# activate # activate
# addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST # addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
...@@ -445,6 +599,11 @@ class X393PIOSequences(object): ...@@ -445,6 +599,11 @@ class X393PIOSequences(object):
# Set MR3, read nrep*8 words, save to buffer (port0). No ACTIVATE/PRECHARGE are needed/allowed # Set MR3, read nrep*8 words, save to buffer (port0). No ACTIVATE/PRECHARGE are needed/allowed
def set_read_pattern (self, def set_read_pattern (self,
nrep): # input integer nrep; nrep): # input integer nrep;
"""
Setup read pattern sequence at parameter defined address in the sequencer memory
<nrep> number of times pattern burst is read
"""
cmd_addr = self.MCONTR_CMD_WR_ADDR + self.READ_PATTERN_OFFSET cmd_addr = self.MCONTR_CMD_WR_ADDR + self.READ_PATTERN_OFFSET
mr3_norm = self.func_ddr3_mr3( mr3_norm = self.func_ddr3_mr3(
0, # 1'h0, // mpr; // MPR mode: 0 - normal, 1 - dataflow from MPR 0, # 1'h0, // mpr; // MPR mode: 0 - normal, 1 - dataflow from MPR
...@@ -526,6 +685,10 @@ class X393PIOSequences(object): ...@@ -526,6 +685,10 @@ class X393PIOSequences(object):
def set_write_lev(self, def set_write_lev(self,
nrep): #input[CMD_PAUSE_BITS-1:0]nrep; nrep): #input[CMD_PAUSE_BITS-1:0]nrep;
"""
Setup write levelling sequence at parameter defined address in the sequencer memory
<nrep> number of times write levelling burst is repeated
"""
dqs_low_rpt = 8 dqs_low_rpt = 8
nrep_minus_1 = nrep - 1; nrep_minus_1 = nrep - 1;
mr1_norm = self.func_ddr3_mr1( mr1_norm = self.func_ddr3_mr1(
...@@ -593,6 +756,13 @@ class X393PIOSequences(object): ...@@ -593,6 +756,13 @@ class X393PIOSequences(object):
t_rfc, # input[9:0]t_rfc; # =50 for tCK=2.5ns t_rfc, # input[9:0]t_rfc; # =50 for tCK=2.5ns
t_refi, # input[7:0]t_refi; # 48/97 for normal, 8 - for simulation t_refi, # input[7:0]t_refi; # 48/97 for normal, 8 - for simulation
en_refresh=0): en_refresh=0):
"""
Setup refresh sequence at parameter defined address in the sequencer memory
<t_rfc> tRFC =50 for tCK=2.5ns
<t_refi> tREFI 48/97 for hardware, 8 - for simulation
<en_refresh> enable refresh immediately
"""
cmd_addr = self.MCONTR_CMD_WR_ADDR + self.REFRESH_OFFSET cmd_addr = self.MCONTR_CMD_WR_ADDR + self.REFRESH_OFFSET
# addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST # addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
data=self.func_encode_cmd( 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) data=self.func_encode_cmd( 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
...@@ -618,6 +788,10 @@ class X393PIOSequences(object): ...@@ -618,6 +788,10 @@ class X393PIOSequences(object):
def set_mrs(self, # will also calibrate ZQ def set_mrs(self, # will also calibrate ZQ
reset_dll): # input reset_dll; reset_dll): # input reset_dll;
"""
Setup sequence (at paramter-defined adderss) to write MR0, MR1, MR2 and MR3 mode registers of DDR3 memory
<reset_dll> reset memory DLL when running this sequence
"""
mr0 = self.func_ddr3_mr0( mr0 = self.func_ddr3_mr0(
0, # 1'h0, # pd; # precharge power down 0 - dll off (slow exit), 1 - dll on (fast exit) 0, # 1'h0, # pd; # precharge power down 0 - dll off (slow exit), 1 - dll on (fast exit)
2, # 3'h2, # [2:0] wr; # write recovery (encode ceil(tWR/tCK)) # 3'b010: 6 2, # 3'h2, # [2:0] wr; # write recovery (encode ceil(tWR/tCK)) # 3'b010: 6
......
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