Perl语言学习(4)- generate_testbench

generate_testbench

  • Perl源代码
  • 运行结果
    • Example1
    • Example2

Perl源代码

#!/user/bin/perl -w
use strict;
use POSIX;

my $cur_time = strftime("%m/%d/%Y",localtime());
my $file_name;
my $outfile_name;
my $module_name;
my $tb_module_name;
my $author_name = "Sniper";
my $tab = " "x4;
my @input;
my @output;
my @signal;
my @parameter;

$file_name = $ARGV[0] if(@ARGV == 1);
&help_message() if(@ARGV != 1);

open(LOG,"<",$file_name) or die "Can not open $file_name for reading!\n";

while (defined(my $line = ))
{
	chomp $line;
	next if ($line =~ /\A\s*\z/);
	$line =~ s/\A\s*|\s*\z//g;
	
	#module name
	if($line =~ /\Amodule\s*([a-zA-Z0-9_]+)/)
	{
		$module_name = $1;
		$tb_module_name = "tb_" . $module_name;
	}
	
	#parameter
	if($line =~ /parameter\s*([a-zA-Z0-9_]+)\s*=\s*(\d+)/)
	{
		push (@parameter, "parameter $1 = $2");
	}
	
	#io port
	if($line =~ /\Ainput\s*([a-zA-Z0-9_]+)/)
	{
		push (@input, "input $1");
		push (@signal, "input $1");
	}
	elsif($line =~ /\Ainput\s*\[([a-zA-Z0-9_-]+):(\d+)\]\s*([a-zA-Z0-9_]+)/)
	{
		push (@input, "input [$1:$2] $3");
		push (@signal, "input [$1:$2] $3");
	}
	
	elsif($line =~ /\Aoutput\s*reg\s*([a-zA-Z0-9_]+)/)
	{
		push (@output, "output $1");
		push (@signal, "output $1");
	}
	elsif($line =~ /\Aoutput\s*reg\s*\[([a-zA-Z0-9_-]+):(\d+)\]\s*([a-zA-Z0-9_]+)/)
	{
		push (@output, "output [$1:$2] $3");
		push (@signal, "output [$1:$2] $3");
	}

	elsif($line =~ /\Aoutput\s*([a-zA-Z0-9_]+)/)
	{
		push (@output, "output $1");
		push (@signal, "output $1");
	}
	elsif($line =~ /\Aoutput\s*\[([a-zA-Z0-9_-]+):(\d+)\]\s*([a-zA-Z0-9_]+)/)
	{
		push (@output, "output [$1:$2] $3");
		push (@signal, "output [$1:$2] $3");
	}
	
}

close (LOG);

print "DUT module name: " . $module_name . "\n";
foreach (@parameter) {print $_ . "\n";}
foreach (@input)		 {print $_ . "\n";}
foreach (@output)		 {print $_ . "\n";}


my $str = "";
$str .= "`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: $cur_time
// Author Name: $author_name
// Module Name: $tb_module_name
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////";
$str .= "

module $tb_module_name;

";

if (defined($parameter[0]))
{
	$str .= "//parameter\n";
	foreach (0..$#parameter)
	{
		my $change = $parameter[$_];
		$str .= $change . ";\n";
	}
	$str .= "\n\n";
}


$str .= "//input\n";

foreach (@input)
{
	my $change = $_;
	$change =~ s/\Ainput/reg/;
	$str .= $change .";\n";
}

$str .= "\n\n";


$str .= "//output\n";

foreach (@output)
{
	my $change = $_;
	$change =~ s/\Aoutput/wire/;
	$str .= $change . ";\n";
}


$str .= "


initial
begin
";

foreach (@input)
{
	my $change = $_;
	if($change =~ /\Ainput\s*([a-zA-Z0-9_]+)/)
	{
		$change = "${tab}$1 = 0;\n";
	}
	elsif($change =~ /\Ainput\s*\[([a-zA-Z0-9_-]+):(\d+)\]\s*([a-zA-Z0-9_]+)/)
	{
		$change = "${tab}". $3 ."[". $1 .":". $2 ."] = 0;\n";
	}
	$str .= $change;
}


$str .= "
	#100;




end

//clock
//always #5 clk = ~clk;



//DUT
$module_name ";

if (defined($parameter[0]))
{
	$str .= "\n#(\n";
	foreach (0..$#parameter)
	{
		my $change = $parameter[$_];
		if($change =~ /\s+([a-zA-Z0-9_]+)\s*=/)
		{
			$change = "${tab}.$1($1),\n" if ($_ != $#parameter);
			$change = "${tab}.$1($1)\n"  if ($_ == $#parameter);
		}
		$str .= $change;
	}
	$str .= ")\n";
}


$str .= "DUT\n(\n";


foreach (0..$#signal)
{
	my $change = $signal[$_];
	if($change =~ /\s+([a-zA-Z0-9_]+)\z/)
	{
		$change = "${tab}.$1($1),\n" if ($_ != $#signal);
		$change = "${tab}.$1($1)\n"  if ($_ == $#signal);
	}
	$str .= $change;
}


$str .=");

initial
begin
  \$dumpfile(\"curve.vcd\");
  \$dumpvars(0,DUT);
end


endmodule

";



$outfile_name = $tb_module_name . ".v";

open(OUT,">",$outfile_name) or die "Can not open $outfile_name for writting!\n";

print OUT $str;
close (OUT);
print "\nThe file $outfile_name has been generated!\n\n";


sub help_message
{
	print "\n\n" . "-"x60 . "\n";
	print "THe $0 script used to generate a module testbench.\n\n";
	print "Usage:   perl $0 module_file_name\n\n";

	print "Example: perl $0 top.v\n";
	print "-"x60 . "\n\n";
	exit;
}

运行结果

perl generate_testbench file_name.v

Example1

待处理的module:

module AsyncFIFO
#(
	parameter DATA_WIDTH = 8,
	parameter DATA_DEPTH = 256,
	parameter ADDR_WIDTH = 8
)
(
	input FIFO_rst_n,

	input Write_clk,
	input Write_enable,
	input [DATA_WIDTH-1:0] Write_data,

	input Read_clk,
	input Read_enable,
	output reg Read_valid,
	output reg [DATA_WIDTH-1:0] Read_data,

	output Empty_flag,
	output Full_flag
);

处理结果:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 08/12/2020
// Author Name: Sniper
// Module Name: tb_AsyncFIFO
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////

module tb_AsyncFIFO;

//parameter
parameter DATA_WIDTH = 8;
parameter DATA_DEPTH = 256;
parameter ADDR_WIDTH = 8;


//input
reg FIFO_rst_n;
reg Write_clk;
reg Write_enable;
reg [DATA_WIDTH-1:0] Write_data;
reg Read_clk;
reg Read_enable;


//output
wire Read_valid;
wire [DATA_WIDTH-1:0] Read_data;
wire Empty_flag;
wire Full_flag;



initial
begin
    FIFO_rst_n = 0;
    Write_clk = 0;
    Write_enable = 0;
    Write_data[DATA_WIDTH-1:0] = 0;
    Read_clk = 0;
    Read_enable = 0;

	#100;




end

//clock
//always #5 clk = ~clk;



//DUT
AsyncFIFO 
#(
    .DATA_WIDTH(DATA_WIDTH),
    .DATA_DEPTH(DATA_DEPTH),
    .ADDR_WIDTH(ADDR_WIDTH)
)
DUT
(
    .FIFO_rst_n(FIFO_rst_n),
    .Write_clk(Write_clk),
    .Write_enable(Write_enable),
    .Write_data(Write_data),
    .Read_clk(Read_clk),
    .Read_enable(Read_enable),
    .Read_valid(Read_valid),
    .Read_data(Read_data),
    .Empty_flag(Empty_flag),
    .Full_flag(Full_flag)
);

initial
begin
  $dumpfile("curve.vcd");
  $dumpvars(0,DUT);
end


endmodule

Example2

待处理的module:

module pulse_synchronizer(
    input clk0,
    input clk1,
    input rst_n,

    input select,
    output DFF0_in,
    output DFF1_in,
    output reg [2:0] DFF0_out,
    output reg [2:0] DFF1_out,
    output clk_out0,
    output clk_out1,
    output clk_out
);

处理结果:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 08/12/2020
// Author Name: Sniper
// Module Name: tb_pulse_synchronizer
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////

module tb_pulse_synchronizer;

//input
reg clk0;
reg clk1;
reg rst_n;
reg select;


//output
wire DFF0_in;
wire DFF1_in;
wire [2:0] DFF0_out;
wire [2:0] DFF1_out;
wire clk_out0;
wire clk_out1;
wire clk_out;



initial
begin
    clk0 = 0;
    clk1 = 0;
    rst_n = 0;
    select = 0;

	#100;




end

//clock
//always #5 clk = ~clk;



//DUT
pulse_synchronizer DUT
(
    .clk0(clk0),
    .clk1(clk1),
    .rst_n(rst_n),
    .select(select),
    .DFF0_in(DFF0_in),
    .DFF1_in(DFF1_in),
    .DFF0_out(DFF0_out),
    .DFF1_out(DFF1_out),
    .clk_out0(clk_out0),
    .clk_out1(clk_out1),
    .clk_out(clk_out)
);

initial
begin
  $dumpfile("curve.vcd");
  $dumpvars(0,DUT);
end


endmodule

你可能感兴趣的:(Perl脚本,perl)