在CSDN上有两篇文章介绍生成顶层测试文件
https://blog.csdn.net/qq_16923717/article/details/77746503
Python初体验之简单TestBench自动生成+Verilog模块信号提取
https://blog.csdn.net/weixin_45342712/article/details/99632229
利用python自动生成verilog模块例化模板
参考上面操作,进行了部分优化,代码行中有注释的自动跳过,信号名自动增加自定义的前缀。
- test_gen.py 调用模块
import module_gen_def
#parameter
NAME = 'top'
out_file=open('%s.v'% NAME,'w')
out_file.truncate(0) #clear file
out_file.write("//generate from test_gen.py \n\n")
#out_file=open('%s.v' % NAME, 'a')
module_gen_def.extract_ports('fir_hdl.v','0',out_file)
module_gen_def.extract_ports('fir.v','0',out_file)
module_gen_def.extract_ports('fir.v','1',out_file)
module_gen_def.extract_ports('fir.v','2',out_file)
module_gen_def.extract_ports('fir.v','',out_file)
module_gen_def.extract_apb_slave_ports('ctim.v','apb1','ctim0','1',out_file)
- module_gen_def.py定义了两个函数。产生两种风格的代码 ,一个针对子模块,一个针对APB Slave device.
import re
regex_module = re.compile('(module)(\s+)(\w+)')
regex_ports = re.compile('''
(\/\/+)? #0 comment
(\s+)? #1 space
(input|output) #2
(\s+)? #3
(wire|reg\s+)? #4
(\[\w+\:0\]\s+)? #5
(\w+) #6
''',re.VERBOSE)
regex_wires = re.compile('''
(\/\/+)?
(\s+)?
(output)
(\s+)?
(wire|reg\s+)?
(\[\w+\:0\]\s+)?
(\w+)
''',re.VERBOSE)
#regex compile
def extract_ports(in_file,u,fo):
with open(in_file,'r') as fi:
comment = fi.read()
#regex match module name
module_name = regex_module.search(comment)
#regex match ports name
groups_wires = regex_wires.findall(comment)
groups_ports = regex_ports.findall(comment)
#print (groups_ports)
for i in range(len(groups_wires)):
if("//" in groups_wires[i][0]):
continue
else:
fo.write("wire %-12s%s_%s;\n" % (groups_wires[i][5],groups_wires[i][6],u))
if module_name is not None:
fo.write('%s \tu%s_%s\n(\n' %(module_name.group(3),u,module_name.group(3)))
num = len(groups_ports)
for i in range(num):
if(('output' in groups_ports[i][2])&(u!='')):
temp=groups_ports[i][6]+'_'+u
else:
temp=groups_ports[i][6]
if i == num-1:
fo.write("\t\t.%-20s(%-20s)\n" % (groups_ports[i][6],temp))
else:
#print(groups_ports[i][0])
if("//" in groups_ports[i][0]):
#fo.write("\t//.%-18s(%-20s),\n" % (groups_ports[i][6],groups_ports[i][6]))
continue
else:
fo.write("\t\t.%-20s(%-20s),\n" % (groups_ports[i][6],temp))
fo.write(');\n')
#################### apb slave top level extract ######################################
def extract_apb_slave_ports(in_file,apbx,inst,u,fo): # apbx =apbx inst=module name
with open(in_file,'r') as fi:
comment = fi.read()
#regex match module name
module_name = regex_module.search(comment)
groups_wires = regex_wires.findall(comment)
groups_ports = regex_ports.findall(comment)
for i in range(len(groups_wires)):
if("//" in groups_wires[i][0]):
continue
else:
fo.write("wire %-12s%s_%s;\n" % (groups_wires[i][5],inst,groups_wires[i][6])) # module name_signal name
fo.write('\n\n')
if module_name is not None:
fo.write('%s \tu%s_%s\n(\n' %(module_name.group(3),u,inst))
num = len(groups_ports)
re_apb_signals = 'paddr|penable|pwrite|pstrb|pwdata'
for i in range(num):
re_match = re.match(re_apb_signals,groups_ports[i][6])
if re_match is not None:
temp = apbx + '_' + groups_ports[i][6]
else:
temp = inst + '_' + groups_ports[i][6]
if i == num-1:
fo.write("\t\t.%-20s(%-20s)\n" % (groups_ports[i][6],temp))
else:
#print(groups_ports[i][0])
if("//" in groups_ports[i][0]):
#fo.write("\t//.%-18s(%-20s),\n" % (groups_ports[i][6],groups_ports[i][6]))
continue
else:
fo.write("\t\t.%-20s(%-20s),\n" % (groups_ports[i][6],temp))
fo.write(');\n')
- 源文件
//fir.v
module fir (
fir_in_TDATA,
fir_out_TDATA,
ap_clk,
ap_rst_n,
fir_in_TVALID,
fir_in_TREADY,
fir_out_TVALID,
//fir_out_TREADY
);
input [31:0] fir_in_TDATA;
output[31:0] fir_out_TDATA;
input ap_clk;
input ap_rst_n;
// input fir_in_TVALID;
output fir_in_TREADY;
output fir_out_TVALID;
input fir_out_TREADY;
//fir_hdl.v
module fir_hdl(
input clk,
input [31:0] fir_in,xxx,yyyy,zzzz,
output [31:0] fir_out
);
//ctim.v
module ctim(
//apb if
input[9:0] paddr ,
input penable ,
input pwrite ,
input[3:0] pstrb ,
input[15:0] pwdata ,
input pclk ,
input prstn ,
input psel ,
output[31:0] prdata ,
output pready ,
output pslverr ,
input etr ,
input tradcin ,
input dbg_act0 ,
input dbg_act1 ,
input dbg_act2 ,
input ch1ai ,
input ch2ai ,
input ch1bi ,
input ch2bi ,
input itr ,
output tro ,
output reg tim_ov ,
output intr ,
output tradco ,
output ch0ao ,
output ch1ao ,
output ch2ao ,
output ch0bo ,
output ch1bo ,
output ch2bo
);
- 产生的文件
//generate from test_gen.py
wire [31:0] fir_out_0;
fir_hdl u0_fir_hdl
(
.clk (clk ),
.fir_in (fir_in ),
.fir_out (fir_out_0 )
);
wire [31:0] fir_out_TDATA_0;
wire fir_out_TVALID_0;
fir u0_fir
(
.fir_in_TDATA (fir_in_TDATA ),
.fir_out_TDATA (fir_out_TDATA_0 ),
.ap_clk (ap_clk ),
.ap_rst_n (ap_rst_n ),
.fir_out_TVALID (fir_out_TVALID_0 ),
.fir_out_TREADY (fir_out_TREADY )
);
wire [31:0] fir_out_TDATA_1;
wire fir_out_TVALID_1;
fir u1_fir
(
.fir_in_TDATA (fir_in_TDATA ),
.fir_out_TDATA (fir_out_TDATA_1 ),
.ap_clk (ap_clk ),
.ap_rst_n (ap_rst_n ),
.fir_out_TVALID (fir_out_TVALID_1 ),
.fir_out_TREADY (fir_out_TREADY )
);
wire [31:0] fir_out_TDATA_2;
wire fir_out_TVALID_2;
fir u2_fir
(
.fir_in_TDATA (fir_in_TDATA ),
.fir_out_TDATA (fir_out_TDATA_2 ),
.ap_clk (ap_clk ),
.ap_rst_n (ap_rst_n ),
.fir_out_TVALID (fir_out_TVALID_2 ),
.fir_out_TREADY (fir_out_TREADY )
);
wire [31:0] fir_out_TDATA_;
wire fir_out_TVALID_;
fir u_fir
(
.fir_in_TDATA (fir_in_TDATA ),
.fir_out_TDATA (fir_out_TDATA ),
.ap_clk (ap_clk ),
.ap_rst_n (ap_rst_n ),
.fir_out_TVALID (fir_out_TVALID ),
.fir_out_TREADY (fir_out_TREADY )
);
wire [31:0] ctim0_prdata;
wire ctim0_pready;
wire ctim0_pslverr;
wire ctim0_tro;
wire ctim0_tim_ov;
wire ctim0_intr;
wire ctim0_tradco;
wire ctim0_ch0ao;
wire ctim0_ch1ao;
wire ctim0_ch2ao;
wire ctim0_ch0bo;
wire ctim0_ch1bo;
wire ctim0_ch2bo;
ctim u1_ctim0
(
.paddr (apb1_paddr ),
.penable (apb1_penable ),
.pwrite (apb1_pwrite ),
.pstrb (apb1_pstrb ),
.pwdata (apb1_pwdata ),
.pclk (ctim0_pclk ),
.prstn (ctim0_prstn ),
.psel (ctim0_psel ),
.prdata (ctim0_prdata ),
.pready (ctim0_pready ),
.pslverr (ctim0_pslverr ),
.etr (ctim0_etr ),
.tradcin (ctim0_tradcin ),
.dbg_act0 (ctim0_dbg_act0 ),
.dbg_act1 (ctim0_dbg_act1 ),
.dbg_act2 (ctim0_dbg_act2 ),
.ch1ai (ctim0_ch1ai ),
.ch2ai (ctim0_ch2ai ),
.ch1bi (ctim0_ch1bi ),
.ch2bi (ctim0_ch2bi ),
.itr (ctim0_itr ),
.tro (ctim0_tro ),
.tim_ov (ctim0_tim_ov ),
.intr (ctim0_intr ),
.tradco (ctim0_tradco ),
.ch0ao (ctim0_ch0ao ),
.ch1ao (ctim0_ch1ao ),
.ch2ao (ctim0_ch2ao ),
.ch0bo (ctim0_ch0bo ),
.ch1bo (ctim0_ch1bo ),
.ch2bo (ctim0_ch2bo )
);