verilog coding过程中,经常需要调用其他module,业内俗称“例化”(instance)。
根据module的信号列表一行行的敲代码确实不是个事,本文提供一套python脚本,可以一键式完成例化工作,从而提高效率;
- Python 代码(python2.7)
新建名字为inst文件,输入如下code:
#!/usr/bin/python
import sys
import re
#global parameter max length
maxlen=0
maxbw =0
#global match mode
comment_pt=r'^\s*\/\/'
cmatch =re.compile(comment_pt)
module_pt =r'module\s+(\w+)'
mmatch =re.compile(module_pt)
parameter_pt=r'parameter\s*(\w+)\s*=.*'
pmatch =re.compile(parameter_pt)
signal_pt =r'(output|input|inout)\s*(wire|reg|\s)\s*(\[.*?:.*?\]|\s)\s*(\w+)\s*[,; \n]'
smatch =re.compile(signal_pt)
end_pt = r'^\s*endmodule'
ematch = re.compile(end_pt)
#caculate the max length
def calc_maxlen(rtlfile):
global maxlen
global maxbw
global pmatch
global smatch
test=open(rtlfile)
while True:
line=test.readline()
if not line:
break
if pmatch.findall(line):
p_tmp=pmatch.findall(line)[0]
if len(p_tmp)>maxlen:
maxlen=len(p_tmp)
if smatch.findall(line):
s_tmp=smatch.findall(line)[0]
if len(s_tmp[3])>maxlen:
maxlen=len(s_tmp[3])
if len(s_tmp[2].replace('/t',''))>maxbw:
maxbw=len(s_tmp[2].replace('/t',''))
def igen(rtlfile):
global maxlen
global maxbw
global cmatch
global mmatch
global pmatch
global smatch
global ematch
params=[]
sigs =[]
start =0
end =0
md_name=''
ins_name='U_'+md_name
file=rtlfile
test=open(file)
while True:
line=test.readline()
if not line:
break
comment_mc=cmatch.match(line)
module_mc =mmatch.match(line)
end_mc =ematch.match(line)
if comment_mc:
pass
elif module_mc:
md_name=module_mc.group(1)
start=1
elif end==1:
start=0
break
if pmatch.findall(line) and start==1:
p_tmp=pmatch.findall(line)[0]
params.append(p_tmp)
if smatch.findall(line) and start==1:
s_tmp=smatch.findall(line)[0]
sigs.append(s_tmp)
if end_mc:
end=1
test.close
ins_name='U_'+md_name.upper()
#print head
head_fmt0='/'*2+'-'*58
head_fmt1='/'*2+'-'*4+' INSTANCE OF '+md_name
print head_fmt0
print head_fmt1
print head_fmt0
#print output wire
for sig in sigs:
#if sig[3][:3]=='clk' or sig[3][:3]=='rst':
# new_sig3=sig[3]
#elif sig[3][-2:]=='_i' or sig[3][-2:]=='_o':
# new_sig3=sig[3][:-2]+'_s'
#else:
# new_sig3=sig[3]
new_sig3=sig[3]
if sig[0]=='output' or sig[0]=='inout':
print "wire"+" "*4+\
"%-*s "%(maxbw,sig[2].replace('/t',''))+\
" "*4+\
"%-*s;"%(maxlen,new_sig3)
#print module name
if len(params)==0:
print "%-s %-s("%(md_name,ins_name)
else:
print "%-s #("%md_name
#print instance of parameter
if len(params)==0:
pass
else:
for param in params:
if params[len(params)-1]==param:
sp_param=")"
else:
sp_param=","
print " .%-*s (%-*s )%s"%\
(maxlen,param,maxlen,param,sp_param)
#print instance name
if len(params)==0:
pass
else:
print ins_name+' ('
#print input and output signals
for sig in sigs:
if sigs[len(sigs)-1]==sig:
sp_sig=' '
else:
sp_sig=','
if sigs[0]=='inout':
dirtag='io'
else :
dirtag=sig[0][0]
#if sig[3][:3]=='clk' or sig[3][:3]=='rst':
# new_sig3=sig[3]
#elif sig[3][-2:]=='_i' or sig[3][-2:]=='_o':
# new_sig3=sig[3][:-2]+'_s'
#else:
# new_sig3=sig[3]
new_sig3=sig[3]
print " .%-*s (%-*s )%s //%s,%-*s"%\
(maxlen,sig[3],\
maxlen,new_sig3,\
sp_sig ,\
dirtag,maxbw ,\
sig[2].replace('/t',''))
#print end
print ");"
print ""
#run the program
if len(sys.argv)<2:
print "ERROR USEAGE"
else:
for aidx in range(1,len(sys.argv)):
calc_maxlen(sys.argv[aidx])
for aidx in range(1,len(sys.argv)):
igen(sys.argv[aidx])
整体思路是打开verilog module file,一般一个module一个file,这在许多公司都是规范;然后提取parameter/input/output 信号名称,位宽等信息,然后再在当前file打印;
- 调用方法
将inst放入/home/bin下,并确保/home/bin加入到path中。
在gvim coding过程中,在需要插入instance的位置输入如下命令即可;
:!r inst xxxx.v
3.存在的问题
- 默认连线名称与信号接口名称一致,如不一致,利用其它工具删除,并重新连接;
- 很好的支持verilog2001,对verilog1998效果没有2001好;
<end and enjoy yourself>
网友评论