对于稍微复杂的Verilog设计,如果不进行仿真,99.999999%的手子都会出错

testbench 结构划分

一般结构包括:

  • 信号声明
  • 复位
  • 时钟
  • 激励
  • 模块例化
  • 自校验
  • 停止仿真 基本结构包括:
  • 信号声明
  • 激励
  • 模块例化

testbench 仿真举例

module data_consolidation
	(
	input clk,
	input rstn,
	input [1:0] din,
	input din_en,
	output [7:0] dout,
	output dout_en
	);
	reg [7:0] data_r;
	reg [1:0] state_cnt;
	always @(posedge clk or negedge rstn) begin
		if(!rstn) begin
			state_cnt <='b0;
			data_r <= 'b0;
		end
		else if(din_en)begin
			state_cnt <= state_cnt+1'b1;
			data_r <= {data_r[5:0],din};
		end
		else begin
			state_cnt <= 'b0;
		end
		
	end
	assign dout = data_r;
	reg dout_en_r;
	always @(posedge clk or negedge rstn) begin
		if(!rstn)begin
			dout_en_r<='b0;
		end
		else if(state_cnt == 2'd3&din_en) begin
			dout_en_r <= 1'b1;
		end
		else begin
			dout_en_r <= 1'b0;
		end
	end
	assign dout_en = dout_en_r;
endmodule

对应的testbench描述

`timescale 1ns/1ns

//信号声明
module test;
	reg clk;
	reg rstn;
	reg [1:0] din;
	reg din_en;
	wire [7:0] dout;
	wire dout_en;
	
	//时钟生成
	real CYCLE_200MHz= 5;
	always begin
		clk = 0; #(CYCLE_200MHz/2);
		clk = 1; #(CYCLE_200MHz/2);
	end
	
	//复位生成
	initial begin
		rstn = 1'b0;
		#8 rstn = 1'b1;
	end
	
	//motivation
	int fd_rd;
	reg [7:0] data_in_temp;
	reg [15:0] read_temp;
	initial begin
		din_en = 1'b0;
		din = 'b0;
		open_file("../tb/data_in.dat","r",fd_rd);
		wait (rstn);
		#CYCLE_200MHz;
		
		//read data from file
		while(!$Feof(fa_rd)) begin
			@(negedge clk);
			$fread(read_temp,fd_rd);
			din = read_temp[9:8];
			data_in_temp={data_in_temp[5:0],din};
			din_en=1'b1;
		end
		
		//stop data
		@(posedge clk);
		#2 din_en = 1'b0;
	end
	
	//open task
	task open_file;
		input string file_dir_name;
		input string rw;
		output int fd;
		
		fd = $open(file_dir_name,rw);
		if(!fd)begin
			$display("---iii---Failed to open files:%s",file_dir_name);
		end
		else begin
			$display("---iii---%s has been opened successfully.",file_dir_name)
		end
		
	endtask
	
	//模块例化
	data_consolidation u_data_process
	(
	.clk (clk),
	.rstn (rstn),
	.din (din),
	.din_en (din_en),
	.dout (dout),
	.dout_en (dout_en)
	);
	
	//自校验(不必要)
	reg [7:0] err_cnt;
	int fd_wr;
	initial begin
		err_cnt = 'b0;
		open_file("../tb/data_out.bat","w",fd_wr);
		forever begin
			@(negedge clk);
			if(dout_en)begin
				$fdisplay(fd_wr,"%h",dout);
			end
		end
	end
	always @(posedge clk) begin
		#1;
		if(dout_cnt) begin
			if(data_in_temp!=dout)begin
				err_cnt=err_cnt+1'b1;
			end
		end
	end
	
	//simulation finish
	always begin
		#100;
		if($time >= 1000000) begin
			if(!err_cnt) begin
				$display("---------------");
				$display("Data process is OK!!!");
				$display("---------------");
			end
			else begin
				$display("---------------");
				$display("Error occurs in data process!!!");
				$display("---------------");
			end
		end
	end
endmodule