Line 17... |
Line 17... |
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
import string, math
|
import string, math, re
|
|
|
def log2 (num):
|
def log2 (num):
|
return math.ceil (math.log (num) / math.log (2))
|
return math.ceil (math.log (num) / math.log (2))
|
|
|
|
# function that tries to interpret a number in Verilog notation
|
|
def number (str):
|
|
try:
|
|
robj = re.compile ("(\d+)'([dhb])([\da-fA-F]+)")
|
|
mobj = robj.match (str)
|
|
if (mobj):
|
|
if mobj.group(2) == 'h': radix = 16
|
|
elif mobj.group(2) == 'b': radix = 2
|
|
else: radix = 10
|
|
|
|
return int (mobj.group(3), radix)
|
|
else:
|
|
return int(str)
|
|
except ValueError:
|
|
print "ERROR: number conversion of %s failed" % str
|
|
return 0
|
|
|
def comb_block (statements):
|
def comb_block (statements):
|
result = 'always @*\n'
|
result = 'always @*\n'
|
result += ' begin\n'
|
result += ' begin\n'
|
for s in statements:
|
for s in statements:
|
result += ' ' + s + '\n'
|
result += ' ' + s + '\n'
|
Line 94... |
Line 111... |
self.nets.append (net('reg','doe'))
|
self.nets.append (net('reg','doe'))
|
|
|
# create a hook for post-processing to be done after all data has been
|
# create a hook for post-processing to be done after all data has been
|
# added to the object.
|
# added to the object.
|
def post (self):
|
def post (self):
|
|
if (self.interrupts):
|
self.int_ports()
|
self.int_ports()
|
|
|
# create port for interrupt pin, as well as port for data output enable
|
# create port for interrupt pin, as well as port for data output enable
|
# when interrupt is asserted.
|
# when interrupt is asserted.
|
# This block should be called after all register data has been read.
|
# This block should be called after all register data has been read.
|
def int_ports (self):
|
def int_ports (self):
|
self.ports.append (port ('output','int_n'))
|
self.ports.append (port ('output','int_n'))
|
self.nets.append (net ('reg','int_n'))
|
self.nets.append (net ('reg','int_n'))
|
|
self.nets.append (net ('reg','int_vec',self.data_size))
|
|
|
def int_logic (self):
|
def int_logic (self):
|
statements = []
|
statements = []
|
int_nets = []
|
int_nets = []
|
for r in self.registers:
|
for r in self.registers:
|
Line 118... |
Line 137... |
statements = ["block_select = (addr[%d:%d] == %d) & !%s;" % (self.addr_size-1,self.local_width,self.base_addr >> self.local_width, self.req_pin)]
|
statements = ["block_select = (addr[%d:%d] == %d) & !%s;" % (self.addr_size-1,self.local_width,self.base_addr >> self.local_width, self.req_pin)]
|
|
|
# create read and write selects for each register
|
# create read and write selects for each register
|
for r in self.registers:
|
for r in self.registers:
|
slogic = "block_select & (addr[%d:%d] == %d) & !rd_n" % (self.local_width-1,0,r.offset)
|
slogic = "block_select & (addr[%d:%d] == %d) & !rd_n" % (self.local_width-1,0,r.offset)
|
if r.interrupt:
|
#if r.interrupt:
|
slogic = "%s_int | (%s)" % (r.name, slogic)
|
# slogic = "%s_int | (%s)" % (r.name, slogic)
|
s = "%s_rd_sel = %s;" % (r.name,slogic)
|
s = "%s_rd_sel = %s;" % (r.name,slogic)
|
statements.append (s)
|
statements.append (s)
|
if r.write_cap():
|
if r.write_cap():
|
s = "%s_wr_sel = block_select & (addr[%d:%d] == %d) & !wr_n;" % (r.name,self.local_width-1,0,r.offset)
|
s = "%s_wr_sel = block_select & (addr[%d:%d] == %d) & !wr_n;" % (r.name,self.local_width-1,0,r.offset)
|
statements.append (s)
|
statements.append (s)
|
Line 136... |
Line 155... |
rd_sel_list = []
|
rd_sel_list = []
|
# Old code for simple tri-state interface
|
# Old code for simple tri-state interface
|
#for r in self.registers:
|
#for r in self.registers:
|
# s += "assign rd_data = (%s_rd_sel) ? %s : %d'bz;\n" % (r.name, r.name, self.data_size)
|
# s += "assign rd_data = (%s_rd_sel) ? %s : %d'bz;\n" % (r.name, r.name, self.data_size)
|
|
|
|
# create interrupt address mux
|
|
if (self.interrupts):
|
|
sments.append ("case (1'b1)")
|
|
for r in self.registers:
|
|
if r.interrupt:
|
|
sments.append (" %s_int : int_vec = %d;" % (r.name, r.int_value))
|
|
sments.append (" default : int_vec = %d'bx;" % self.data_size)
|
|
sments.append ("endcase")
|
|
|
|
# create data-output mux
|
sments.append ("case (1'b1)")
|
sments.append ("case (1'b1)")
|
for r in self.registers:
|
for r in self.registers:
|
sments.append (" %s_rd_sel : rd_data = %s;" % (r.name, r.name))
|
sments.append (" %s_rd_sel : rd_data = %s;" % (r.name, r.name))
|
rd_sel_list.append (r.name + "_rd_sel")
|
rd_sel_list.append (r.name + "_rd_sel")
|
sments.append (" default : rd_data = %d'bx;" % self.data_size)
|
if (self.interrupts):
|
|
sments.append (" default : rd_data = int_vec;")
|
|
else: sments.append (" default : rd_data = %d'bx;" % self.data_size)
|
sments.append ("endcase")
|
sments.append ("endcase")
|
|
|
sments.append ("doe = %s;" % string.join (rd_sel_list, ' | '))
|
sments.append ("doe = %s;" % string.join (rd_sel_list, ' | '))
|
|
|
return comb_block (sments)
|
return comb_block (sments)
|
Line 183... |
Line 214... |
self.add (status_reg (params['name'],params['width']))
|
self.add (status_reg (params['name'],params['width']))
|
elif (type == 'config'):
|
elif (type == 'config'):
|
self.add (config_reg (params['name'],params['width'],params['default']))
|
self.add (config_reg (params['name'],params['width'],params['default']))
|
elif (type == 'int_fixed'):
|
elif (type == 'int_fixed'):
|
r2 = config_reg (params['name'] + "_msk",params['width'],params['default'])
|
r2 = config_reg (params['name'] + "_msk",params['width'],params['default'])
|
r1 = int_fixed_reg (params['name'],r2,params['width'])
|
r1 = int_fixed_reg (params['name'],r2,number(params['int_value']),params['width'])
|
self.add (r1)
|
self.add (r1)
|
self.add (r2)
|
self.add (r2)
|
self.interrupts += 1
|
self.interrupts += 1
|
elif (type == 'soft_set'):
|
elif (type == 'soft_set'):
|
self.add (soft_set_reg(params['name'],params['width'],params['default']))
|
self.add (soft_set_reg(params['name'],params['width'],params['default']))
|
elif (type == 'read_stb'):
|
elif (type == 'read_stb'):
|
self.add (read_stb_reg (params['name'],params['width']))
|
self.add (read_stb_reg (params['name'],params['width']))
|
elif (type == 'write_stb'):
|
elif (type == 'write_stb'):
|
self.add (config_reg (params['name'],params['width'],params['default']))
|
self.add (write_stb_reg (params['name'],params['width'],params['default']))
|
else:
|
else:
|
print "Unknown register type",type
|
print "Unknown register type",type
|
|
|
def add (self, reg):
|
def add (self, reg):
|
self.registers.append (reg)
|
self.registers.append (reg)
|
Line 264... |
Line 295... |
|
|
def write_cap (self):
|
def write_cap (self):
|
return 1
|
return 1
|
|
|
class int_fixed_reg (basic_register):
|
class int_fixed_reg (basic_register):
|
def __init__ (self, name, mask_reg, width=0):
|
def __init__ (self, name, mask_reg, int_value, width=0):
|
basic_register.__init__(self, name, width)
|
basic_register.__init__(self, name, width)
|
self.mask_reg = mask_reg
|
self.mask_reg = mask_reg
|
self.interrupt = 1
|
self.interrupt = 1
|
|
self.int_value = int_value
|
|
|
def verilog_body (self):
|
def verilog_body (self):
|
statements = ["if (reset) %s <= %d;" % (self.name, 0),
|
statements = ["if (reset) %s <= %d;" % (self.name, 0),
|
"else %s <= (%s_set | %s) & ~( {%d{%s}} & %s);" %
|
"else %s <= (%s_set | %s) & ~( {%d{%s}} & %s);" %
|
(self.name, self.name, self.name, self.width, self.name + '_wr_sel', 'wr_data'),
|
(self.name, self.name, self.name, self.width, self.name + '_wr_sel', 'wr_data'),
|
Line 323... |
Line 355... |
|
|
def verilog_body (self):
|
def verilog_body (self):
|
statements = ["if (reset) %s <= %d;" % (self.name, self.default),
|
statements = ["if (reset) %s <= %d;" % (self.name, self.default),
|
"else if (%s_wr_sel) %s <= %s;" % (self.name, self.name, 'wr_data'),
|
"else if (%s_wr_sel) %s <= %s;" % (self.name, self.name, 'wr_data'),
|
"if (reset) %s_stb <= 0;" % (self.name),
|
"if (reset) %s_stb <= 0;" % (self.name),
|
"else if (%s_wr_sel) %s_stb <= 1;" % (self.name),
|
"else if (%s_wr_sel) %s_stb <= 1;" % (self.name, self.name),
|
"else %s_stb <= 0;" % (self.name)
|
"else %s_stb <= 0;" % (self.name)
|
]
|
]
|
return seq_block ('clk', statements)
|
return seq_block ('clk', statements)
|
|
|
def io (self):
|
def io (self):
|