FPGA测试文件testbench模块

8 篇文章 0 订阅
5 篇文章 0 订阅

测试文件testbench:是写输入激励的。模拟实际环境,从软件角度仿真进行分析与验证。

一、测试文件的书写流程:
定义时间标尺——定义信号类型——例化.v文件——编写输入驱动

二、固定写法:
1、时间标尺的格式:`timescale 仿真时间单位/时间精度,时间单位>=时间精度

`timescale 1ns/1ps 
#100//延迟100ns,跟时间单位有关
#100.01//延迟100.01ns,若改为`timescale 1ns/1ns 则错误,因为精度还是ns无法达到小数点后面

2、信号类型的定义:原模块输入在testbench中为wire,输出在testbench中为reg。
3、几种固定的书写:

//时钟激励,这种写法可以在例化的时候修改参数大小,而不改变代码本身,减少了错误率。
parameter CYCLE = 20;		//默认50MHz的信号,则脉冲周期T=1/f=20ns
initial begin
	clk = 0;
	forever
	#(CYCLE/2)
	clk = ~clk;
end
//修改参数例化例子,其中A和B分别为原程序中参数名,2与10为在例化模块中最终参数值
modulename #(.A(2),.B(10)) modulename1(
	例化语句;
);
//时钟激励另一种书写形式
`define clock_period 20 		//在时间标尺下面预编译——宏定义
initial begin
	clk = 0;
	always #(·clock_period /2)
	clk = ~clk;
end
//复位信号
initial begin
	rst_n = 1;
	#2;
	rst_n = 0;
	#(CYCLE*RST_TIME)		//延迟RST_TIME个脉冲周期
	rst_n = 1;
end
//输入激励赋值
initial begin
	#1;		//每个输入信号赋值前需延迟1个时间单位,由D触发器决定
	din0 = 0;
	#TIME;
	din0 = 1;
end

三、仿真激励常见写法

1、一种激励方式:

initial begin
a = 0;b = 0;
#200
a = 0;b = 1;
#200
a = 1;b = 0;
#200
a = 1;b = 1;
#200
$stop;	//停止仿真
end

2、repeat造30次占空比为1:5的激励:

//在使用repeat时,需要注意前面必须加initial begin…end ,除此在任务函数的设定时需要有 task myname;begin repeat() …end endtask

initial begin

repeat(30)begin
  cin = 1'b1;
  #`clock_period;
  cin = 1'b0;
  #(`clock_period*5);
  end
end

3、随机任务函数

<1> 随机函数:$ random 这一系统函数可以产生一个有符号的32bit随机整数。一般的用法是$ random%b,其中 b>0,这样就会生成一个范围在(-b+1):(b-1)中的随机数。如果只得到正数的随机数,可采用{$ random}%b。
tip:这里的32bit随机整数指的是$random为32位大小,而非b为32位大小。

//eg1:产生一个随机的数c
c=$random;

//eg2:产生一个[min,max]区间的随机数
 reg	[31:0]	rand;
 rand = min+{$random}%(max-min+1);

<2> 任务函数
task <任务名>;
<端口及数据 类型声明语句>
<语句 1>
<语句 2>
<语句 n>
endtask
tip:task只要里面的语句是可综合的,那么task就可综合!

//eg:后面7.8要调用这里的任务函数

reg [5:0]myrand;

task press_key;				//建任务函数press_key(相当于module用于testbench的调用)
begin		
repeat(50) begin 			// 重复五十次随机时间
	myrand = {$random}%25; 		//取一次myrand为-24~24的一个随机数
	#myrand key_in = ~key_in; 	// 延迟随机数myrand后,输入激励取反
	end
end  
endtask 

initial begin
	Rst_n = 1'b0;
	key_in = 1'b1;
	#(`clk_period*10) Rst_n = 1'b1;
	#30000;
	press_key; #10000;	//调用任务函数press_key
	press_key; #10000;
	$stop;
end 

4、一种仿真写法,内部信号产生输出

`timescale 1ns/1ns
module key_model(key);

output reg key;
reg [15:0]myrand;

initial begin
	key = 1'b1;
	press_key;
	#10000;
	press_key;
	#10000;
	press_key;
	$stop;
	end

task press_key;
	begin
	// 此部分同6(上面设计)
	end
endtask

endmodule

5、一种仿真写法——内部信号产生输入输出

`timescale 1ns/1ns
module key_model(press,key);
input press;
output reg key;

reg [15:0]myrand;

initial begin
	key = 1'b1;
	end
	
always@(posedge press)
	press_key;
	
task press_key;
	begin
	// 此部分同6(上面设计)
	end
	
endtask

endmodule


6、当激励需要自动增加或者循环多次的时候,可以使用for循环在测试文件中
当要求发送的报文中报文长度随机(有上下限),报文之间间隔为随机(上下限),信号概率丢失,重复发多个报文时,使用随机函数$random和for循环来做。
在这里插入图片描述

/*要求:
	1、报文长度在1~128字节随机
	2、报文间隔0~3随机
	3、报文只发送1
	4、一共发送100个报文
	5、sop与eop有1/8概率丢失,din_err有1/32概率为1(即错误报文)
*/			
	reg		[31:0]		len_rand;
	reg		[3:0]		sop_rand;
	reg		[3:0]		eop_rand;
	reg		[5:0]		err_rand;
	reg		[3:0]		delay_rand;

			for(i=0;i<100;i=i+1)begin
			
				len_rand 	= MIN + {$random} % (MAX - MIN + 1);
				sop_rand 	= {$random} % 8;
				eop_rand 	= {$random} % 8;
				err_rand 	= {$random} % 32;
				delay_rand 	= {$random} % 4;
				
				for(j=0;j<len_rand;j=j+1)begin
				
					din 			= 1;
					din_sop			= (j == 0 && sop_rand != 1)?1:0;
					din_eop			= (j == len_rand-1 && eop_rand != 1)?1:0;
					din_vld			= 1;
					din_err			= (j == len_rand-1 && err_rand != 1)?1:0;
					#CYCLE;
				end
				din 			=  0;
				din_sop			=  0;
				din_eop			=  0;
				din_vld			=  0;
				din_err			=  0;
				#(CYCLE*delay_rand);
			end	
		end

完整的报文测试代码
tip:注意随机函数$ random的位置,重点理解每出现一次就会随机产生一个数。

7、一个串行输入的8bit数据
要点1:当我们输入英文字符的时候,一个字符代表8bit数据。
那么我们输入一串字符的时候,如 str = woshishei 那么定义[8*9-1:0](每个字符8bit,共9个,若中间有空格,感叹号等,也按照8bit算)

要点2:在仿真文件testbench中,语法比较随意,生成激励常用initial语句,但是也可以用组合逻辑和时序逻辑生成。

//在测试文件testbench中写入串行输入数据
	wire		[143:0]		data_temp;
	reg		[143:0]		reg_temp;
	assign	data_temp = "lssjlwjyhgggqsqqqa";		//有18个英文字符,8*18=144
	always @ (posedge clk or negedge rst_n)begin
		if(!rst_n)begin
			reg_temp <= 0;
		end
		else if(din_vld)begin
			reg_temp <= {reg_temp [135:0],reg_temp [143:136]}; 		//向左移位寄存器,位数多的向哪个方向移就是什么方向的移位寄存。
		end
		else begin
			reg_temp <= data_temp ;
		end
	end
	assign din = reg_temp[143:136];		//最后把高位的8bit数据传给输入激励din

8、仿真文件的并转串
下面的例子中task函数可不用,只是为了引出9,用了task

	//16位并行数据转换为串行数据
		input [15:0]	vdata;
		reg	[4:0] cnt;
		begin
			cnt = 0;
			wait(condition);	//等待某个条件到来,不到来时则停滞在此
			while(cnt<16)begin
				@(negedge clk) dout = vdata[15-cnt];
				cnt = cnt + 1;
			end
		end

9、仿真测试文件造rom

`define sin_data_file "./document_name.txt"		
`timescale 1ns/1ps	//把PC上txt格式的文件document_name给测试文件的sin_data_file
.............
	reg		[11:0]	memory	[4095:0];	//存储空间,4096(address)个12位的数据
	reg		[11:0]	address;	//存储地址
	
	initial $readmemh(`sin_data_file,memory); //readmemh 中的h(16进制)可以用b(2进制)替换
	
	initial begin
		address = 0;
		forever begin
			for(address=0;address<4095;address=address+1)begin	//从地址0取到地址4095
				@(posedge clk);		//等待clk上升沿到来,上升沿不到就停滞在这
					memory[address];
			end
		end
	end

tip! 1:把8中的程序封装成task dout文件,引:9中用dout(memory[address])代替memory[address]可直接得到rom中并转串的数据
2:仿真文件中,用@(posedge/negedge signal)可表沿触发
用wait(signal)可表信号电平触发
用信号 module.signal 可表示在某个例化模块中的某个信号(这个信号不用接端口即可表达)
用$display(“打印的数据=%0h”,signal),在仿真界面打印signal的值。

  • 2
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FPGAtestbench是用于对使用硬件描述语言(HDL)设计的电路进行仿真验证的。它的主要目的是测试设计电路的功能和性能是否与预期的目标相符。编写testbench可以帮助开发者更好地理解和验证设计电路的行为。而且在FPGA行业,具备编写testbench的能力是非常重要的,因为大部分公司都会让你来编写testbench测试文件。 一个基本的testbench通常包含三个部分:信号定义、模块接口和功能代码。信号定义部分用于定义输入输出信号的类型和大小,这些信号需要使用register类型来存储输入的数据。模块接口部分定义了需要测试模块的输入输出接口。功能代码部分则包含了对测试模块进行功能验证的代码。 编写testbench时,需要遵循规范化的设计和苛刻的结构。testbench编写规范可以参考Modelsim仿真步骤的相关文档。 总结起来,FPGAtestbench是对设计电路进行仿真验证的重要工具,它需要包含信号定义、模块接口和功能代码三个部分,并且需要遵循规范化的设计和苛刻的结构。掌握编写testbench的能力对于在FPGA行业的发展非常重要。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [【FPGA自学总结】Testbench测试代码推荐编写规范](https://blog.csdn.net/zhaogoudan/article/details/111933722)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值