VerilogA 数字序列波形发生器
基于ColsonZhang/VerilogA-Wave-Generator库进行改进:
在此感谢原作者,提供了生成波形的思路和代码。
本版本具体改进点如下:
1.波形播放完后不再重复播放,而是停在最后一个码字
2.增加了可配置的上升时间和下降时间
使用方法:
1.将以下三个文件保存到同一文件夹,并安装python 3.6.
2.编辑main.py,在 signal_args 数组中输入序列名字,序列宽度,序列长度,和序列数据,可以同时修改模块名(module_name)
3.在当前目录下运行python main.py 得到generate.va文件
4.将该va导入到virtuoso或其他仿真环境中使用
CLK 代表时钟输入端,该veriloga模块每一个时钟周期输出一个码字,应接一个vpluse源
VDD代表电源输入 ,定义了输出波形的高电平,应接一个vdc源。
GND代表电源地,应接GND。
注意:使用时请保证CLK端的高电平标准和VDD端的高电平标准一致,均为同一电压值。
代码如下:
template.va
// $TEMPLATE_HEAD_NOTES `include "constants.vams" `include "disciplines.vams" module $TEMPLATE_MODULE_NAME(VDD, GND, CLK, $TEMPLATE_PORT_LIST); input VDD, GND, CLK ; electrical VDD, GND, CLK ; $TEMPLATE_INPUT_DECLARATION $TEMPLATE_OUTPUT_DECLARATION $TEMPLATE_SIGNAL_DECLARATION $TEMPLATE_COUNT_DECLARATION $TEMPLATE_WAVELIST_DECLARATION integer count = 0; integer clock = 0; integer flag_clk ; genvar i ; // ___ __ // /\_ \ /\ \ // ___\//\ \ ___ ___\ \ \/'\ __ __ ___ // /'___\\ \ \ / __`\ /'___\ \ , < _______ /'_ `\ /'__`\/' _ `\ // /\ \__/ \_\ \_/\ \L\ \/\ \__/\ \ \\`\ /\______\/\ \L\ \/\ __//\ \/\ \ // \ \____\/\____\ \____/\ \____\\ \_\ \_\/______/\ \____ \ \____\ \_\ \_\ // \/____/\/____/\/___/ \/____/ \/_/\/_/ \/___L\ \/____/\/_/\/_/ // /\____/ // \_/__/ // Clock-Generator analog begin @(initial_step) begin count = 0 ; clock = 0 ; flag_clk = 0 ; $TEMPLATE_SIGNAL_INITIAL $TEMPLATE_COUNT_INITIAL end @( cross( V(CLK,GND)- V(VDD,GND), +1 ) ) begin clock = 1 ; count = count + 1 ; if(count >= 100 ) count = 0 ; end @( cross( clock - 1 , +1) ) begin if(clock != 0) clock = 0 ; flag_clk = 1 ; end end // __ __ ____ // /\ \ __/\ \ /\ _`\ // \ \ \/\ \ \ \ __ __ __ __ ____ \ \ \L\_\ __ ___ // \ \ \ \ \ \ \ /'__`\ /\ \/\ \ /'__`\ /',__\ _______\ \ \L_L /'__`\/' _ `\ // \ \ \_/ \_\ \/\ \L\.\_\ \ \_/ |/\ __//\__, `\/\______\\ \ \/, \/\ __//\ \/\ \ // \ `\___x___/\ \__/.\_\\ \___/ \ \____\/\____/\/______/ \ \____/\ \____\ \_\ \_\ // '\/__//__/ \/__/\/_/ \/__/ \/____/\/___/ \/___/ \/____/\/_/\/_/ // Waves-Generator analog begin @( cross( flag_clk - 1 , +1) ) begin flag_clk = 0 ; $TEMPLATE_SIGNAL_GENERATE $TEMPLATE_COUNT_GENERATE end end // __ __ // /\ \__ /\ \__ // ___ __ __\ \ ,_\ _____ __ __\ \ ,_\ // / __`\/\ \/\ \\ \ \/ /\ '__`\/\ \/\ \\ \ \/ // /\ \L\ \ \ \_\ \\ \ \_\ \ \L\ \ \ \_\ \\ \ \_ // \ \____/\ \____/ \ \__\\ \ ,__/\ \____/ \ \__\ // \/___/ \/___/ \/__/ \ \ \/ \/___/ \/__/ // \ \_\ // \/_/ // Signal-Output analog begin $TEMPLATE_SIGNAL_OUTPUT end endmodule
main.py
import va_gen as va # input template file path template_path ='./template.va' # output file path save_path = './generate.va' # the comment in the veriloga file comment = 'This file is generated by the VA_GEN .' # the module name module_name = 'SPI_SLAVE_DATA_V2' # the expected output signals # signal-name | signal-width | waves-length | waves-value #signal_args = [ # ['cmp_res', 1, 32, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0]] # ] signal_args = [ ['DATA', 1, 8, [0,0,0,1,0,0,0,0]] ] rise_t='1n' fall_t='1n' #NOTICE: #THIS GENERATOR WILL NOT REPEATER THE WAVE if __name__ == '__main__': generator = va.VaGenerator(template_path) generator.generate_veriloga(module_name, comment, signal_args, save_path , rise_t, fall_t)
va_gen.py
# *************************************************************** # File-Name: va_gen.py # Author: Zhang Shen # Email: zhangshen@shanghaitech.edu.cn # Time: 2021/09/29 # Version: V-0.1 # Usage: Automatically generate the veriloga file used to # generating the wave according to your input. # *************************************************************** class Signal: def __init__(self, name = 'signal', width = 1, length = 1, waves = [0] ,rise_t = '1n' ,fall_t = '1n'): self.name = name self.width = width self.length = length self.waves = waves self.rise_t = rise_t self.fall_t = fall_t self.signal_name = 'signal_{}'.format(self.name) self.count_name = 'count_{}'.format(self.name) self.wave_name = "wave_{}".format(self.name) self.width_declaration = self.get_width_declaration() self.length_declaration = self.get_length_declaration() self.input_declaration = '' self.output_declaration = self.get_output_declaration() self.signal_declaration = self.get_signal_declaration() self.count_declaration = self.get_count_declaration() self.wavelist_declaration = self.get_wavelist_declaration() self.signal_initial = self.get_signal_initial() self.count_initial = self.get_count_initial() self.signal_generate = self.get_signal_generate() self.count_generate = self.get_count_generate() self.signal_output = self.get_signal_output() def get_width_declaration(self): arg_1 = '' if self.width > 1: arg_1 = '[{}:0]'.format(self.width - 1) return arg_1 def get_length_declaration(self): template = '[0:{}]' return template.format(self.length-1) def get_output_declaration(self): template = ' output {} {} ;\n electrical {} {} ;\n' arg_1 = self.width_declaration arg_2 = self.name return template.format(arg_1, arg_2, arg_1, arg_2) def get_signal_declaration(self): template = ' integer {} ;' return template.format(self.signal_name) def get_count_declaration(self): template = ' integer {} ;' return template.format(self.count_name) def get_wavelist_declaration(self): template = ' integer {} {} = {} ;' arg_1 = self.wave_name arg_2 = self.length_declaration arg_3 = '' if len(self.waves) > 0 : arg_3 = arg_3 + '{ ' for i in self.waves: arg_3 = arg_3 + ' {},'.format(i) arg_3 = arg_3 + ' }' else: print('ERROR!!! The length of the wave list = 0 !!!') return template.format(arg_1, arg_2, arg_3) def get_signal_initial(self): template = ' {} = 0 ;' return template.format(self.signal_name) def get_count_initial(self): template = ' {} = 0 ;' return template.format(self.count_name) def get_signal_generate(self): template = ' {} = {}[ {} % {} ] ;' arg_1 = self.signal_name arg_2 = self.wave_name arg_3 = self.count_name arg_4 = self.length return template.format(arg_1, arg_2, arg_3, arg_4) def get_count_generate(self): template = ' if ({} < {}) {} = {} + 1 ;' arg_1 = self.count_name arg_2 = self.length - 1 arg_3 = self.count_name arg_4 = self.count_name return template.format(arg_1, arg_2, arg_3, arg_4) def get_signal_output(self): template = ''' for(i=0; i<{}; i=i+1) begin V( {} ) <+ transition( V(VDD,GND)*(({}&(1<<i))>>i), {}, {} ) ; end ''' arg_1 = self.width if(self.width) > 1: arg_2 = "{}[i]".format(self.name) else: arg_2 = self.name arg_3 = self.signal_name arg_4 = self.rise_t arg_5 = self.fall_t return template.format(arg_1, arg_2, arg_3 , arg_4, arg_5) class MultiSignal: def __init__(self, args = []): self.signals = self.get_signals(args=args) self.port_list = self.get_port_list() self.input_declaration = '' self.output_declaration = self.get_output_declaration() self.signal_declaration = self.get_signal_declaration() self.count_declaration = self.get_count_declaration() self.wavelist_declaration = self.get_wavelist_declaration() self.signal_initial = self.get_signal_initial() self.count_initial = self.get_count_initial() self.signal_generate = self.get_signal_generate() self.count_generate = self.get_count_generate() self.signal_output = self.get_signal_output() def get_signals(self, args): thelist = [] for arg in args: the_signal = Signal( name = arg[0], width = arg[1], length = arg[2], waves = arg[3] ) thelist.append(the_signal) return thelist def get_port_list(self): result = '' for i in self.signals[:-1]: result = result + ' {},'.format(i.name) result = result + ' {}'.format(self.signals[-1].name) return result def get_output_declaration(self): result = '' for i in self.signals: result = result + i.output_declaration +'\n' return result def get_signal_declaration(self): result = '' for i in self.signals: result = result + i.signal_declaration +'\n' return result def get_count_declaration(self): result = '' for i in self.signals: result = result + i.count_declaration +'\n' return result def get_wavelist_declaration(self): result = '' for i in self.signals: result = result + i.wavelist_declaration +'\n' return result def get_signal_initial(self): result = '' for i in self.signals: result = result + i.signal_initial +'\n' return result def get_count_initial(self): result = '' for i in self.signals: result = result + i.count_initial +'\n' return result def get_signal_generate(self): result = '' for i in self.signals: result = result + i.signal_generate +'\n' return result def get_count_generate(self): result = '' for i in self.signals: result = result + i.count_generate +'\n' return result def get_signal_output(self): result = '' for i in self.signals: result = result + i.signal_output +'\n' return result class VaGenerator: def __init__(self, file_path): self.template = self.read_template(file_path=file_path) self.macro_list = [ '$TEMPLATE_HEAD_NOTES', '$TEMPLATE_MODULE_NAME', '$TEMPLATE_PORT_LIST', '$TEMPLATE_INPUT_DECLARATION', '$TEMPLATE_OUTPUT_DECLARATION', '$TEMPLATE_SIGNAL_DECLARATION', '$TEMPLATE_COUNT_DECLARATION', '$TEMPLATE_WAVELIST_DECLARATION', '$TEMPLATE_SIGNAL_INITIAL', '$TEMPLATE_COUNT_INITIAL', '$TEMPLATE_SIGNAL_GENERATE', '$TEMPLATE_COUNT_GENERATE', '$TEMPLATE_SIGNAL_OUTPUT' ] def generate_veriloga(self, module_name, comment, args, save_path, rise_t, fall_t): self.module_name = module_name self.comment = comment self.generate_signals(args=args) self.fill_template() self.save_file(file_path=save_path) self.rise_time = rise_t self.fall_time = fall_t def read_template(self, file_path='./template.va'): with open(file_path,"r") as f: str_template = f.read() return str_template def generate_signals(self, args): thesignals = MultiSignal(args=args) self.signals = [ self.comment, self.module_name, thesignals.port_list, thesignals.input_declaration , thesignals.output_declaration , thesignals.signal_declaration , thesignals.count_declaration , thesignals.wavelist_declaration , thesignals.signal_initial , thesignals.count_initial , thesignals.signal_generate , thesignals.count_generate , thesignals.signal_output ] def fill_template(self): content = self.template for i in range(len(self.macro_list)): content = content.replace( self.macro_list[i], self.signals[i] ) self.veriloga = content def save_file(self,file_path='generated.va'): with open(file_path,"w") as f: f.write(self.veriloga)