大数据最全【Verilog HDL】FPGA-testbench基础知识(2),2024年最新快速上手

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以戳这里获取

//------<testbench文件的基本结构>------

//`timescale 仿真单位/仿真精度
`timescale xx/xx

//仿真文件模块名
module xx_tb;
	
	//定义声明信号或变量
	...
	...
	
	//例化设计模块
	...
	...
	
	//使用always语句产生激励波形
	...
	...
	
	//使用initial产生激励波形
	initial begin
		...
		...
		...
		$stop;
	
	end

endmodule


🎈举个例子详细说明一下:
目前已经编写好了一个led闪烁的模块,我们需要对该模块进行测试,以确保模块设计的正确性,模块代码如下:

led_flash.v:

//------<模块代码>------
module led\_flash(
	input 		Clk;
	input 		Rst_n;
	output reg	led
);
	
	//定义led状态
	parameter led_on  = 1'b0;
	parameter led_off = 1'b1; 
	
	//定义计数器寄存器
	reg [24:0]cnt;
	
	//定义计数器参数
	parameter cnt_max = 24'd24_999_999;
	parameter cnt_min = 24'd0;
	parameter cnt_add = 1'b1;
	
	//计数器
	always@(posedge Clk or negedge Rst_n)begin
		if(!Rst_n)
			cnt <= cnt_min;
		else if(cnt == cnt_max)
			cnt <= cnt_min;
		else
			cnt <= cnt + cnt_add;
	end
	
	//led
	always@(posedge Clk or negedge Rst_n)begin
		if(!Rst_n)
			led <= led_off;
		else if(cnt == cnt_max)
			led <= ~led;
		else
			led <= led;
	end

endmodule


接下来根据上述模块编写测试激励文件。

3.1 声明仿真的单位和精度

`timescale时间刻度指令用来说明模块工作的时间单位时间精度,基本语句如下:

`timescale 时间单位/时间精度

时间单位和时间精度可以以秒、毫秒、纳秒、皮秒或飞秒作为度量,具体数值可以选择1、10或100,如:

`timescale 10ns/1ns

该语句定义了当前模块中的仿真时间单位是10ns,仿真精度是1ns,语法上要求时间精度必须小于等于时间单位,即前面的数值要大于等于后面的数值。

测试模块中经常使用 #号 延迟来生成信号,例如:

`timescale 10ns/1ns
...
initial
	begin
		A = 0;B = 0;//初始值
		#4 A = 1;//4时间单位后,即40ns
		#5 B = 1;//5时间单位后,即50ns
		#6 A = 0;//6时间单位后,即60nd
		#7 $stop;//7时间单位后,即70ns
	end

又如:

`timescale 1ns/1ns

当代码中出现#10时,代表的意思是延时10ns,由于仿真的精度为1ns,所以最低的延时精度只能到1ns,如果想要延时10.001ns,则需要更改仿真的精度(1ns=1000ps),代码如下:

`timescale 1ns/1ps
#10.001 rst_n = 0;

为了测试上述led闪烁模块,定义如下时间单位和时间精度:

`timescale 1ns/1ns

3.2 宏定义

宏定义采用 `define 来进行指定,把某个指定的标识符用来代表一个字符串,整个标识符在整个文件中都表示所指代的字符串,语法如下:

`define 标识符 字符串  //注意句末无分号

对于上述led闪烁模块,需要产生一个时钟信号给它,为了方便进行全文的修改,我们对时钟信号的周期进行宏定义

`define clock_period 20

如果不想让宏定义生效,可以使用 `undef 指令取消前面定义的宏:

`define WIDTH 16

`undef WIDTH  //此条语句之后,WIDTH失效

reg [`WIDTH-1:0] data;  //报错,因为宏定义已经取消

3.3 定义测试模块名

定义模块名的关键字为module,同时测试模块以endmodule结束,代码如下:

module led_flash_tb;
	...
	...
	...
endmodule


模块名的命名方式一般在被测模块名后面加上 _tb,或者在被测模块名前面加上tb_,表示为哪个模块提供激励测试文件,通常激励文件不需要定义输入和输出端口。代码中定义的常量有时需要频繁的修改,为了方便修改,可以把常量定义成参数的形式,定义参数的关键字为 parameter

3.4 声明信号

在testbench中,信号常用的类型为reg类型wire类型reg类型表示激励信号,wire类型表示输出信号。

定义led闪烁测试模块中的输入和输出信号:

//时钟信号和复位信号均需要输入给待测模块
reg Clk;
reg Rst_n;

//led信号为待测模块的输出信号
wire led;

3.5 模块实例化

例化的设计模块是指被测模块,例化被测模块的目的是把被测模块和激励模块实例化起来,并且把被测模块的端口与激励模块的端口进行相应的连接,使得激励可以输入到被测模块。

如果被测模块是由多个模块组成的,激励模块中只需要例化多个模块的顶层模块。

将led闪烁模块实例化:

led_flash led\_flash0(
		.Clk(Clk);
		.Rst\_n(Rst_n);
		.led(led)
);

在实例化模块中,左侧带“.” 的信号为 led 模块定义的端口信号,右侧括号内的信号为激励模块中定义的信号,其信号名可以和被测模块中的信号名一致,也可以不一致,命名一致的好处是便于理解激励模块和被测模块信号之间的对应关系

3.6 使用initial或always产生激励信号

产生时钟激励信号:

initial Clk = 1;
always#(`clock_period/2) Clk = ~Clk;

产生led闪烁测试模块的其余激励信号:

initial begin
	Rst_n = 0;
	#200
	
	Rst_n = 1;
	#(`clock_period\*200)
	
	$stop;
end

3.7 完整的testbench代码

led_flash_tb.v:

//------<测试代码>------
`timescale 1ns/1ns
`define clock_period 20

module led_flash_tb;

	reg Clk;
	reg Rst_n;
	
	wire led;
	
	led_flash led\_flash0(
		.Clk(Clk);
		.Rst\_n(Rst_n);
		.led(led)
	);

	initial Clk = 1;
	always#(`clock_period/2) Clk = ~Clk;
	
	initial begin
		Rst_n = 0;
		#200
		
		Rst_n = 1;
		#(`clock_period\*200)
		
		$stop;
	end

endmodule


四、补充语法

repeat循环和forever循环语句只适用于testbench的编写。

4.1 repeat循环

repeat循环的功能是把循环体语句执行某些次数,基本格式:

repeat(次数)
begin
	循环体语句
end

该语句的基本使用案例链接:【FPGA零基础学习之旅#7】BCD计数器设计

测试代码:

`timescale 1ns/1ns
`define clock_period 20

module BCD_Counter_tb;
	
	reg Clk;
	reg Rst_n;
	reg Cin;
	
	wire Cout;
	wire [3:0]q;
	
	BCD_Counter BCD\_Counter0(
		.Clk(Clk),		//系统时钟信号
		.Rst\_n(Rst_n),	//系统复位信号
		.Cin(Cin),		//进位输入信号
		.Cout(Cout),		//进位输出信号
		.q(q)			//计数器值
	);
	
	initial Clk = 1;
	always#(`clock_period/2) Clk = ~Clk;
	
	initial begin
		Rst_n = 1'b0;
		Cin = 1'b0;
		#(`clock_period\*20);
		
		Rst_n = 1;
		#(`clock_period\*20);
		
		repeat(30)begin
			Cin = 1'b1;
			#(`clock_period\*1);
			Cin = 1'b0;
			#(`clock_period\*5);
		end
		
		#(`clock_period\*20);
		$stop;
	end
	
endmodule


其中,该部分代码表示执行循环体中的语句30次,且循环体的语句表示生成一个占空比为1:5的脉冲信号:

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

脉冲信号是一种离散信号,形状多种多样,与普通模拟信号(如正弦波)相比,波形之间在Y轴不连续(波形与波形之间有明显的间隔),但具有一定的周期性是它的特点。最常见的脉冲波是矩形波(也就是方波)。脉冲信号可以用来表示信息,也可以用来作为载波,比如脉冲调制中的脉冲编码调制(PCM)、脉冲宽度调制(PWM)等等,还可以作为各种数字电路、高性能芯片的时钟信号。

4.2 forever循环

forever循环表示永远循环,直到仿真结束为止,相当于判断条件永远为真。forever循环语句中需要添加时序控制,否则就会陷入死循环。

可以用forever循环语句来编写文章【FPGA零基础学习之旅#9】状态机基础知识Hello例程的testbench:

reg [7:0]ASCII;

Hello Hello0(
	 .Clk(Clk),
	 .Rst\_n(Rst_n),
	 .data(ASCII),
	 .led(led)
);

initial begin
Rst_n = 0;
ASCII = 0;
#(`clock_period\*20);
Rst_n = 1;
#(`clock_period\*20 + 1);

forever begin
	ASCII = "I";
	#(`clock_period);
	ASCII = "A";
	#(`clock_period);
	ASCII = "M";
	#(`clock_period);
	ASCII = "X";
	#(`clock_period);
	ASCII = "i";
	#(`clock_period);
	ASCII = "a";
	#(`clock_period);
	ASCII = "o"; 
	#(`clock_period);
	ASCII = "M";
	#(`clock_period);
	ASCII = "e";
	#(`clock_period);
	ASCII = "i";
	#(`clock_period);


![img](https://img-blog.csdnimg.cn/img_convert/fa327ffabafd89327bd1a8838029479f.png)
![img](https://img-blog.csdnimg.cn/img_convert/ced5cb01306ba64ebe8be9c1aa855c0a.png)
![img](https://img-blog.csdnimg.cn/img_convert/b5a77f844c0174eb98afc34168845d88.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**

II = "a";
	#(`clock_period);
	ASCII = "o"; 
	#(`clock_period);
	ASCII = "M";
	#(`clock_period);
	ASCII = "e";
	#(`clock_period);
	ASCII = "i";
	#(`clock_period);


[外链图片转存中...(img-eLoCKtXN-1715754547219)]
[外链图片转存中...(img-sL9nV6Oy-1715754547219)]
[外链图片转存中...(img-dQ9LnOMc-1715754547219)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值