.
This commit is contained in:
@@ -1,30 +0,0 @@
|
||||
`timescale 10ns/1ns
|
||||
`include "div3.v"
|
||||
|
||||
module div3_tb;
|
||||
|
||||
reg CLK;
|
||||
wire LED;
|
||||
|
||||
initial CLK=0;
|
||||
always #1 CLK=~CLK;
|
||||
|
||||
div3 dut (.clk(CLK), .r(1'b1), .q(LED));
|
||||
|
||||
//-- Begin test
|
||||
initial begin
|
||||
|
||||
//-- Set the dumpfile
|
||||
$dumpfile("div3_tb.vcd");
|
||||
|
||||
//-- Dump everything into the dumpfile
|
||||
$dumpvars(0, div3_tb);
|
||||
|
||||
//-- End after 10 time units
|
||||
# 100 $finish;
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
`timescale 10ns/1ns
|
||||
|
||||
module blinky_tb;
|
||||
|
||||
reg CLK;
|
||||
wire LED;
|
||||
|
||||
blinky dut (
|
||||
.CLK (CLK),
|
||||
.PIN_24 (PIN_24)
|
||||
);
|
||||
|
||||
initial CLK=0;
|
||||
always #1 CLK=~CLK;
|
||||
|
||||
//-- Begin test
|
||||
initial begin
|
||||
|
||||
//-- Set the dumpfile
|
||||
$dumpfile("blinky_tb.vcd");
|
||||
|
||||
//-- Dump everything into the dumpfile
|
||||
$dumpvars(0, blinky_tb);
|
||||
|
||||
//-- End after 10 time units
|
||||
# 100000 $finish;
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
23
gate/sim.v
23
gate/sim.v
@@ -1,23 +0,0 @@
|
||||
module SB_HFOSC(
|
||||
input CLKHFPU,
|
||||
input CLKHFEN,
|
||||
output CLKHF
|
||||
);
|
||||
parameter CLKHF_DIV = "0b00";
|
||||
endmodule
|
||||
|
||||
module SB_RGBA_DRV (
|
||||
input RGBLEDEN,
|
||||
input RGB0PWM,
|
||||
input RGB1PWM,
|
||||
input RGB2PWM,
|
||||
input CURREN,
|
||||
output RGB0,
|
||||
output RGB1,
|
||||
output RGB2
|
||||
);
|
||||
parameter CURRENT_MODE="0b1";
|
||||
parameter RGB0_CURRENT="0b000001";
|
||||
parameter RGB1_CURRENT="0b000001";
|
||||
parameter RGB2_CURRENT="0b000001";
|
||||
endmodule
|
||||
235
gate/tbgen.py
235
gate/tbgen.py
@@ -1,235 +0,0 @@
|
||||
#! /usr/bin/python
|
||||
|
||||
# THE BEER-WARE LICENSE" (Revision 42):
|
||||
# <xfguo@xfguo.org> wrote this file. As long as you retain this notice you
|
||||
# can do whatever you want with this stuff. If we meet some day, and you think
|
||||
# this stuff is worth it, you can buy me a beer in return Xiongfei(Alex) Guo.
|
||||
|
||||
# some minor additions by Al Williams 2018-9-11
|
||||
|
||||
'''
|
||||
Created on 2010-4-23
|
||||
|
||||
@author: Alex Guo
|
||||
'''
|
||||
|
||||
import re
|
||||
import sys
|
||||
import argparse
|
||||
|
||||
class TestbenchGenerator(object):
|
||||
'''
|
||||
verilog test bench auto generation
|
||||
'''
|
||||
|
||||
def __init__(self, vfile_name = None, ofile_name = None):
|
||||
self.vfile_name = vfile_name
|
||||
self.vfile = None
|
||||
self.ofile_name = ofile_name
|
||||
if(ofile_name == None):
|
||||
self.ofile = sys.stdout
|
||||
self.vcont = ""
|
||||
self.mod_name = ""
|
||||
self.pin_list = []
|
||||
self.clock_name = 'clk'
|
||||
self.reset_name = 'rst'
|
||||
|
||||
if vfile_name == None:
|
||||
sys.stderr.write("ERROR: You did not provide an input file name.\n")
|
||||
sys.exit(1)
|
||||
else:
|
||||
self.open()
|
||||
self.parser()
|
||||
self.open_outputfile()
|
||||
|
||||
def open(self, vfile_name = None):
|
||||
if vfile_name != None:
|
||||
self.vfile_name = vfile_name
|
||||
|
||||
try:
|
||||
self.vfile = open(self.vfile_name, 'r')
|
||||
self.vcont = self.vfile.read()
|
||||
except Exception as e:
|
||||
print("ERROR: Input file error.\n ERROR: %s" % e)
|
||||
sys.exit(1)
|
||||
|
||||
def open_outputfile(self, ofile_name = None):
|
||||
try:
|
||||
if(ofile_name == None):
|
||||
if(self.ofile_name == None):
|
||||
ofname = "tb_%s.v" % self.mod_name
|
||||
self.ofile = open(ofname, 'w')
|
||||
print("You did not specify an output file name, using '%s'." % ofname)
|
||||
else:
|
||||
self.ofile = open(self.ofile_name, 'w')
|
||||
print("Output file is '%s'." % self.ofile_name)
|
||||
else:
|
||||
self.ofile = open(ofile_name, 'w')
|
||||
print("Output file is '%s'." % ofile_name)
|
||||
except Exception as e:
|
||||
print("ERROR: Output file error. \n ERROR: %s" % e)
|
||||
sys.exit(1)
|
||||
|
||||
def clean_other(self, cont):
|
||||
## clean '// ...'
|
||||
cont = re.sub(r"//[^\n^\r]*", '\n', cont)
|
||||
## clean '/* ... */'
|
||||
cont = re.sub(r"/\*.*\*/", '', cont)
|
||||
## clean '`define ..., etc.'
|
||||
#cont = re.sub(r"[^\n^\r]+`[^\n^\r]*", '\n', cont)
|
||||
## clean tables
|
||||
cont = re.sub(r' +', ' ', cont)
|
||||
## clean '\n' * '\r'
|
||||
#cont = re.sub(r'[\n\r]+', '', cont)
|
||||
return cont
|
||||
|
||||
def parser(self):
|
||||
print("Parsing...")
|
||||
# print vf_cont
|
||||
mod_pattern = r"module[\s]+(\S*)[\s]*\([^\)]*\)[\s\S]*"
|
||||
|
||||
module_result = re.findall(mod_pattern, self.clean_other(self.vcont))
|
||||
#print module_result
|
||||
self.mod_name = module_result[0]
|
||||
|
||||
self.parser_inoutput()
|
||||
self.find_clk_rst()
|
||||
|
||||
|
||||
def parser_inoutput(self):
|
||||
pin_list = self.clean_other(self.vcont)
|
||||
|
||||
comp_pin_list_pre = []
|
||||
for i in re.findall(r'(input|output|inout)[\s]+([^;,\)]+)[\s]*[;,]', pin_list):
|
||||
comp_pin_list_pre.append((i[0], re.sub(r"^reg[\s]*", "", i[1])))
|
||||
|
||||
comp_pin_list = []
|
||||
type_name = ['reg', 'wire', 'wire', "ERROR"]
|
||||
for i in comp_pin_list_pre:
|
||||
x = re.split(r']', i[1])
|
||||
type = 0;
|
||||
if i[0] == 'input':
|
||||
type = 0
|
||||
elif i[0] == 'output':
|
||||
type = 1
|
||||
elif i[0] == 'inout':
|
||||
type = 2
|
||||
else:
|
||||
type = 3
|
||||
|
||||
if len(x) == 2:
|
||||
x[1] = re.sub('[\s]*', '', x[1])
|
||||
comp_pin_list.append((i[0], x[1], x[0] + ']', type_name[type]))
|
||||
else:
|
||||
comp_pin_list.append((i[0], x[0], '', type_name[type]))
|
||||
|
||||
self.pin_list = comp_pin_list
|
||||
# for i in self.pin_list: print i
|
||||
|
||||
def print_dut(self):
|
||||
max_len = 0
|
||||
for cpin_name in self.pin_list:
|
||||
pin_name = cpin_name[1]
|
||||
if len(pin_name) > max_len:
|
||||
max_len = len(pin_name)
|
||||
|
||||
|
||||
self.printo( "%s uut (\n" % self.mod_name )
|
||||
|
||||
align_cont = self.align_print(list(map(lambda x:("", "." + x[1], "(", x[1], '),'), self.pin_list)), 4)
|
||||
align_cont = align_cont[:-2] + "\n"
|
||||
self.printo( align_cont )
|
||||
|
||||
self.printo( ");\n" )
|
||||
|
||||
def print_wires(self):
|
||||
self.printo(self.align_print(list(map(lambda x:(x[3], x[2], x[1], ';'), self.pin_list)), 4))
|
||||
self.printo("\n")
|
||||
|
||||
def print_clock_gen(self,period,dfile,depth,resetpol):
|
||||
fsdb = " $dumpfile(\"%s\");\n $dumpvars(%d, tb_%s);\n" % (dfile, depth, self.mod_name)
|
||||
|
||||
clock_gen_text = "\nparameter PERIOD = %d; //adjust for your timescale\n\ninitial begin\n%s CLK = 1'b0;\n #(PERIOD/2);\n forever\n #(PERIOD/2) CLK = ~CLK;\nend\n" % (period, fsdb)
|
||||
self.printo(re.sub('CLK', self.clock_name, clock_gen_text))
|
||||
if self.reset_name!="":
|
||||
clock_gen_text = "\ninitial begin\n RST=1'b%d;\n #(PERIOD*2) RST=~RST;\n #PERIOD RST=~RST;\n end\n" % resetpol
|
||||
self.printo(re.sub('RST',self.reset_name, clock_gen_text))
|
||||
|
||||
def find_clk_rst(self):
|
||||
for pin in self.pin_list:
|
||||
if re.match(r'[\S]*(clk|clock)[\S]*', pin[1]):
|
||||
self.clock_name = pin[1]
|
||||
print("Clock signal detected: '%s'." % pin[1])
|
||||
break
|
||||
|
||||
for pin in self.pin_list:
|
||||
if re.match(r'rst|reset', pin[1]):
|
||||
self.reset_name = pin[1]
|
||||
print("Reset signal detected: '%s'." % pin[1])
|
||||
break
|
||||
|
||||
# Original code -- no longer used
|
||||
def print_module_head_orig(self):
|
||||
self.printo("`include \"timescale.v\"\nmodule tb_%s;\n\n" % self.mod_name)
|
||||
|
||||
def print_module_head(self,timescale):
|
||||
self.printo("`timescale %s //Adjust to suit\n\nmodule tb_%s;\n\n" % (timescale,self.mod_name))
|
||||
|
||||
def print_module_end(self,iname):
|
||||
if iname is None:
|
||||
iname='user.tb_%s.v' % self.mod_name
|
||||
self.printo("`include \"%s\"\nendmodule\n" % iname)
|
||||
|
||||
def printo(self, cont):
|
||||
self.ofile.write(cont)
|
||||
|
||||
def close(self):
|
||||
if self.vfile != None:
|
||||
self.vfile.close()
|
||||
print("Output complete.\n\n")
|
||||
|
||||
def align_print(self, content, indent):
|
||||
""" Align pretty print."""
|
||||
|
||||
row_len = len(content)
|
||||
col_len = len(content[0])
|
||||
align_cont = [""] * row_len
|
||||
for i in range(col_len):
|
||||
col = list(map(lambda x:x[i], content))
|
||||
max_len = max(list(map(len, col)))
|
||||
for i in range(row_len):
|
||||
l = len(col[i])
|
||||
align_cont[i] += "%s%s" % (col[i], (indent + max_len - l) * ' ')
|
||||
|
||||
# remove space in line end
|
||||
align_cont = list(map(lambda s:re.sub('[ ]*$', '', s), align_cont))
|
||||
return "\n".join(align_cont) + "\n"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print('''***************** tbgen - Auto generate a testbench. *****************
|
||||
Author: Xiongfei(Alex) Guo <xfguo@credosemi.com>
|
||||
License: Beerware
|
||||
''')
|
||||
ofile_name = None
|
||||
|
||||
aparse = argparse.ArgumentParser(description='Automatically generate Verilog testbench')
|
||||
aparse.add_argument('input_file', help='input Verilog file')
|
||||
aparse.add_argument('output_file', help='output Verilog testbench', nargs='?', default=None)
|
||||
aparse.add_argument('-p','--period', type=int, help='set period in clock ticks (default=10)', default=10)
|
||||
aparse.add_argument('-t','--timescale',help='set timescale (default=1ns/10ps)', default='1ns/10ps')
|
||||
aparse.add_argument('-d','--dumpfile',help='set dumpfile (default=tb_output.vcd)', default='tb_output.vcd')
|
||||
aparse.add_argument('-l','--level', type=int, help='set dump depth level (usually 0,1, or 2; default=2)', default=2)
|
||||
aparse.add_argument('-r','--resetneg', help='set reset to negative (default positive)', action='store_const', const=1, default=0)
|
||||
aparse.add_argument('-i','--include', help='sets user include file name (default=user.tb_<name>.v)', default=None)
|
||||
args = aparse.parse_args()
|
||||
|
||||
tbg = TestbenchGenerator(args.input_file, args.output_file)
|
||||
|
||||
|
||||
tbg.print_module_head(args.timescale)
|
||||
tbg.print_wires()
|
||||
tbg.print_dut()
|
||||
tbg.print_clock_gen(args.period,args.dumpfile,args.level,args.resetneg)
|
||||
tbg.print_module_end(args.include)
|
||||
tbg.close()
|
||||
Reference in New Issue
Block a user