《SystemVerilog验证测试平台编写指南》学习笔记——连接设计和测试平台(二)

一、接口的驱动和采样

测试平台需要驱动和采样设计的信号,主要是通过带有时钟块的接口做到的。异步信号通过接口时没有任何延时,比如rst,而时钟块中的信号将得到同步。

1、接口同步

可以使用Verilog的@和wait来同步测试平台中的信号

信号同步

program automatic test(bus.if.TB bus);
	initial begin
		@bus.cb;		//在时钟块的有效时钟沿继续
		repeat (3) @bus.cb;		//等待三个有效时钟沿
		@bus.cb.grant;		//在任何边沿继续
		@(postedge bus.cb.grant);		//上升沿继续
		@(negegde bus.cb.grant);		//下降沿继续
		wait(bus.cb.grant == 1);		//等待表达式被执行,如果已经是真,不做任何延时
		@(postedge bus.cb.grant or negedge bus.rst)		//等待几个信号
	end
endprogram

2、接口信号采样

模块中同步接口的采样和驱动

'timescale 1ns/1ns
program test(arb_if.TEST arbif);
	initial begin
		$monitor("@%0t: grant=%h", $time, arbif.cb.grant);
		# 50ns $display("End of test");
endprogram

module arb(arb_if.DUT arbif);
	initial begin
		# 7 arbif.grant = 1; 	//@7ns;
		# 10 arbif.grant = 2; 	//@17ns;
		# 8 arbif.grant = 3; 	//@25ns;
	end
endmodule

波形如下:
在这里插入图片描述
波形表明,arbif.cb.grant在时钟边沿到来之前获得数值,在5ns时获取的值时之前的X值,所以5ns~15ns显示的值为X,在15ns时获取的值时15ns到来之前的值1,所以15ns ~ 25ns显示的值为1,以此类推。
arb模块在一个时钟周期的中间产生grant信号的值1和2,然后在时钟沿产生值3。

3、接口信号驱动

使用带有时钟块接口的测试平台

program automatic test(arb_if.TEST arbif);

	initial begin
		arbif.cb.request <= 2'b01;		//在时钟块中使用modport的时候,任何同步接口信号都必须加上接口名和时钟块名的前缀
		$display("@%0t: Drove req = 01", $time);
		repeat(2) @arbif.cb;
		if(arbif.cb.grant != 2'b01)
			$display("@%0t: al: grant != 2'b01", $time);
	end
endprogram : test  

4、通过时钟块驱动接口信号

在时钟块中应当使用同步驱动,即“<=”操作符来驱动信号。信号在赋值后并不会立即改变——别忘了测试平台在Reactive区域执行而设计的代码在Active区域执行。如果在时钟沿之间产生一个request信号,那么该变化知道下一个时钟沿才会传递给设计。因此驱动总是同步的。
如果测试平台在时钟的有效沿驱动同步接口信号,其值会立即传递到设计中,这是因为时钟块的默认输出延时是# 0。

驱动一个同步接口

program test(arb_if.TEST arbif);
	initial begin
		# 7 arbif.cb.request <= 3; 	//@7ns;
		# 10 arbif.cb.request <= 2; 	//@17ns;
		# 8 arbif.cb.request <= 1; 	//@25ns;
		# 15 finish;
	end;
endprogram

module arb(arb_if.DUT arbif);
	initial
		$monitor("@%0t: req=%h", $time, arbif.request);

波形图如下:在这里插入图片描述
这里注意看波形中在一个周期中即5 ~ 15ns中,第7ns时TEST产生的值3,在下一个周期也就是15ns~25ns时被DUT捕获输出。但是为什么TEST在17ns产生的值2没有被DUT捕获输出呢?那是因为之前说的**如果测试平台在时钟的有效沿驱动同步接口信号,其值会立即传递到设计中,这是因为时钟块的默认输出延时是# 0。**也就是说TEST在17ns时产生的值2不会立即传递给设计,会在下一个时钟沿传递给设计。但是DUT在25ns时准备捕获TEST的值时,TEST又在25ns上升沿驱动同步信号让值变为了1,此时值会立即传递到设计中,相当于值2被值1“覆盖”了,所以DUT捕获到了值1没有捕获到值2。

异步地驱动时钟块信号会导致数值丢失,应该使用时钟延时前缀以保证在时钟UA沿驱动信号。

# # 2 arbif.cb.request <= 0;		//等待两个时钟周期然后赋值,只能在时钟块里作为驱动信号的前缀来使用,因为它需要知道使用哪个时钟来做延时
# # 3;		//非法,必须跟赋值语句同时使用

5、接口中的双向信号

在程序中对线网(net)赋值的时候,SystemVerilog实际上将值写到了一个驱动该线网的临时变量中。所有驱动器输出的值经过判决后,程序可以直接通过连线读取该值。

程序和接口中的双向信号

interface master_if(input bit clk);
	wire[7:0] data;		//双向信号
	clocking cb @(postedge clk);
		inout data;
	endclocking
	
	modport TEST(clocking cb);
endinterface

program test (master_if mif);
	initial begin
		mif.cb.data <= 'z;		//三态总线
		@mif.cb;
		$displayh(mif.cb.data);		//从总线读取
		mif.cb.data <= 7'h5a;		//驱动总线
		@mif.cb;
		mif.cb.data <= 'z;		//释放总线
	end
endprogram		

6、为什么在程序中不允许使用always块

program中可以使用initial块但是不允许使用always块。因为SystemVerilog程序比由许多并行执行的块构成的Verilog更加接近C程序,它拥有一个(或者多个)程序入口。在一个设计中,一个always块可能从仿真的开始就会在每一个时钟的上升沿触发执行,但是一个测试平台的执行过程是经过初始化、驱动、响应设计行为等步骤后结束仿真的。在这里一个连续执行的always模块不能正常工作。但是可以使用initial forever来替代always块。

7、时钟发生器

时钟发生器应当定义成一个模块,不应该把时钟发生器放在程序块里。功能验证关心的是在正确的时钟周期内提供正确的值,而不是纳秒级的延时和时钟的相对偏移。

模块中的时钟发生器

module clock_generator(output bit clk);
	initial
		always # 5 clk = ~clk;		//在时间0之后生成时钟沿
endmodule

二、将这些模块都连接起来

编译器不会成功编译任何一个在端口列表中含有接口的模块或程序块。

含有接口的模块

//没有接口声明,该模块不会被正确编译,必须完成接口的连接工作
module uses_an_interface(arb_ifc.DUT ifc);
	initial ifc.grant = 0;
endmodule

连接DUT和接口的顶层模块

module top;
	bit clk;
	always # 10 clk = !clk;
	arb_ifc ifc(clk);		//带有时钟块的接口
	uses_an_interface ul(ifc);		//必须这样定义才能被编译
endmodule

三、顶层作用域

编译单元,它是一起编译的源文件的一个组合。任何module,macromodule,interface,program,package或者primitive边界之外的作用域被称为编译单元作用域,也称为$unit

仲裁器设计的顶层作用域

'timescale 1ns/1ns
parameter int TIMEOUT = 1000000;
const string time_out_msg = "ERROR: Time Out!";

module top;
	test t1();
endmodule

program automatic test;
	...
	initial begin
		# TIMEOUT;
		$display("%s", time_out_msg);
		$finish;
	end
endprogram

实例名$root允许从顶层作用域开始明确地引用系统中的成员名。可以指定绝对路径或者相对路径来明确地引用跨模块的变量。

四、程序——模块交互

程序块可以读写模块中的所有信号,但是模块却看不到程序块。程序可以调用模块中的例程来执行不同的动作,这个例程可以改变信号的值,也称为后门。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值