概述
以16位乘法器为例,输入有a、b、sign,分别为乘数,被乘数以及符号选择,输出c为运算结果。sign=1计算有符号乘法,sign=0计算无符号乘法,模块名称为MUTI_16X16。
仿真环境基本结构
运行perl脚本,可生成testbench.v、run.f 、testcase.v(激励文件)以及Makefile。
simenv.pl脚本内容
对于一个模块来说,我们只需要定义模块的module 名称、输入信号、输出信号以及相关的地址参数,若有地址,可以WIDTH(n)形式定义n为具体地址,若没有地址可不写,即@addr_array数组为空。
#! /user/bin/perl
use strict;
#---------------------------------------------------------
# variable define
#---------------------------------------------------------
#--------------------
# Module Name
#--------------------
my $top_name = "MUTI_16X16";
#--------------------
# Input Collection
#--------------------
my @in_array = qw(
[15:0]a
[15:0]b
sign
);
#--------------------
# Output Collection
#--------------------
my @out_array = qw(
[31:0]c
);
#--------------------
# Addr Collection
#--------------------
my @addr_array = qw(
);
#---------------------------------------------------------
#*********************************************************
# generate testbench.v files
#*********************************************************
#---------------------------------------------------------
my $outf0 = "testbench.v";
if (-e $outf0){
system("rm -rf $outf0");
}
open (OUTFILE0, ">>$outf0");
print OUTFILE0 "
//----------------------------------
//signals_type declare
//----------------------------------
`timescale 1ns / 1ns
module test;
\n";
#------------------------
#input declare
#------------------------
open (OUTFILE0, ">>$outf0");
foreach my $tbins (@in_array) {
my $tbins_new = join " " , "reg" ,$tbins;
print OUTFILE0 " $tbins_new;\n";
}
#--------------------
#newline
#--------------------
open (OUTFILE0, ">>$outf0");
print OUTFILE0 "\n";
#------------------------
#output declare
#------------------------
open (OUTFILE0, ">>$outf0");
foreach my $tbouts (@out_array) {
my $tbouts_new = join " " , "wire" ,$tbouts;
print OUTFILE0 " $tbouts_new;\n";
}
#--------------------
#print head
#--------------------
open (OUTFILE0, ">>$outf0");
print OUTFILE0 "
//----------------------------------
//module instance
//----------------------------------
$top_name\n";
#--------------------
#print addr
#--------------------
open (OUTFILE0, ">>$outf0");
if(@addr_array > 1){
foreach my $addr_one (@addr_array){
if($addr_one eq @addr_array[0]){
print OUTFILE0 "#(\n .$addr_one,\n";
}
elsif($addr_one eq @addr_array[-1]){
print OUTFILE0 " .$addr_one\n)\ntop(\n";
}
else{
print OUTFILE0 " .$addr_one,\n";
}
}
}
elsif(@addr_array eq 1){
print OUTFILE0 "#(\n .@addr_array[0]\n)\ntop(\n";
}
else{
print OUTFILE0 "top(\n";
}
#------------------------
#input instance
#------------------------
open (OUTFILE0, ">>$outf0");
foreach my $modins (@in_array) {
if($modins =~ /[[0-9:0-9]][a-zA-Z0-9]/){
my @tempin = split "]" ,$modins;
print OUTFILE0 " .$tempin[-1]($tempin[-1]),\n";
}
else{
print OUTFILE0 " .$modins($modins),\n";
}
}
#--------------------
#newline
#--------------------
open (OUTFILE0, ">>$outf0");
print OUTFILE0 "\n";
#------------------------
#output instance
#------------------------
open (OUTFILE0, ">>$outf0");
foreach my $modouts (@out_array) {
if($modouts eq @out_array[-1]){
if($modouts =~ /[[0-9:0-9]][a-zA-Z0-9]/){
my @tempout = split "]" ,$modouts;
print OUTFILE0 " .$tempout[-1]($tempout[-1])\n);\n";
}
else{
print OUTFILE0 " .$modouts($modouts)\n);\n";
}
}
else{
if($modouts =~ /[[0-9:0-9]][a-zA-Z0-9]/){
my @tempout = split "]" ,$modouts;
print OUTFILE0 " .$tempout[-1]($tempout[-1]),\n";
}
else{
print OUTFILE0 " .$modouts($modouts),\n";
}
}
}
#------------------------
#print stil & waves
#------------------------
open (OUTFILE0, ">>$outf0");
print OUTFILE0 "
//------------------------------------
//testcase.v
//------------------------------------
`include \"./testcase.v\"
//------------------------------------
//waves
//------------------------------------
initial
begin
\$fsdbDumpfile(\"waves.fsdb\");
\$fsdbDumpvars;
\$fsdbDumpflush;
end
endmodule
\n";
close OUTFILE0;
#---------------------------------------------------------
#*********************************************************
# generate testcase.v files
#*********************************************************
#---------------------------------------------------------
my $outf1 = "testcase.v";
if (-e $outf1){
system("rm -rf $outf1");
}
open (OUTFILE1, ">>$outf1");
print OUTFILE1 "
//----------------------------------
//initial input_signals
//----------------------------------
initial
begin\n";
#------------------------
#initial
#------------------------
open (OUTFILE1, ">>$outf1");
foreach my $testcins (@in_array) {
if($testcins eq @in_array[-1]){
if($testcins =~ /[[0-9:0-9]][a-zA-Z0-9]/){
my @testcase = split "]" ,$testcins;
print OUTFILE1 " $testcase[-1] = 'd0;\n
\#1_000_000;
\$finish;
end";
}
else{
print OUTFILE1 " $testcins = 'd0;\n
\#1_000_000;
\$finish;
end";
}
}
else{
if($testcins =~ /[[0-9:0-9]][a-zA-Z0-9]/){
my @testcase = split "]" ,$testcins;
print OUTFILE1 " $testcase[-1] = 'd0;\n";
}
else{
print OUTFILE1 " $testcins = 'd0;\n";
}
}
}
\n";
close OUTFILE1;
#---------------------------------------------------------
#*********************************************************
# generate run.f files
#*********************************************************
#---------------------------------------------------------
my $outf2 = "run.f";
if (-e $outf2){
system("rm -rf $outf2");
}
open (OUTFILE2, ">>$outf2");
print OUTFILE2 "
//----------------------------------
//add testbench.v
//----------------------------------
./testbench.v\n";
my @verfiles = glob("../src/*");
print OUTFILE2 "
//----------------------------------
//add .v files
//----------------------------------\n";
foreach my $cds (@verfiles) {
print OUTFILE2 "$cds\n";
}
close OUTFILE2;
#---------------------------------------------------------
#*********************************************************
# generate Makefile
#*********************************************************
#---------------------------------------------------------
my $outf3 = "Makefile";
if (-e $outf3){
system("rm -rf $outf3");
}
open (OUTFILE3, ">>$outf3");
print OUTFILE3 "
#--------------------------------------------
#NC
#--------------------------------------------
one:clean
ncverilog +access+rwc +nc64bit -f run.f -l ncverilog.log
-rm -rf *.history *novas*
#--------------------------------------------
#verdi
#--------------------------------------------
verdi:
verdi -f run.f -nologo -ssf waves.fsdb &
clean:
-rm -rf *.log *.fsdb verdiLog *novas*
\n";
close OUTFILE3;