路科验证的个人空间 https://blog.eetop.cn/1561828 [收藏] [复制] [分享] [RSS]

空间首页 动态 记录 日志 相册 主题 分享 留言板 个人资料

日志

SV的环境构建篇之五:测试的始终

已有 2653 次阅读| 2016-12-4 22:20 |个人分类:验证系统思想|系统分类:芯片设计

在上一节《程序和模块》中我们提到了各个设计自身可以作为一个大的线程,内部又包含多个并行的线程,而模块之间即线程的通信主要依靠信号的变化。可以想象,对于一个设计,如果在仿真开始没有任何的激励,譬如时钟和复位信号,那么仿真并未开始,也可以认为已经结束,因为对于设计内部并没有产生任何新的事件,也不会由这些事件进一步触发组合逻辑和时序逻辑。

那么,如果我们在仿真开始后提供时钟和复位信号,这对于验证而言是必要的步骤,但是它本身不会对设计的功能产生实质的功能影响。从设计的角度来看,复位信号只是为了让设计进入确定的状态,而时钟信号是如同血管的供血功能一般保证设计可以正常地“跳动”。

在Verilog的测试方式中,即便我们只给设计提供复位和时钟信号,整个仿真也会一直持续下去,并不会主动结束。即使DUT的输入激励已经执行完毕,仿真也会一直进行下去,这就需要通过Verilog系统函数主动结束仿真。

结束方式之一:系统函数
在Verilog测试中,需要通过Verilog提供的系统函数来结束仿真。下面的例子即在仿真500ns时通过系统函数$finish结束了仿真,而用户也看可以考虑使用$stop来暂停仿真。这两者的区别在于$finish会使得仿真退出,将控制权交回给操作系统,仿真无法再次继续;$stop会使得仿真暂停,用户还有机会让仿真继续运行。

module tb;
bit clk;

initial begin
forever #5ns clk <= !clk;
end

counter dut(clk);

initial begin
#500ns;
$finish();
end
endmodule

执行结果:


结束方式之二:program隐式结束
在SV推出program将验证部分与设计部分进行有效隔离以后,SV也会将每一个program块作为一个独立的测试,如果testbench中只有一个program,则会在执行完该program中最后一个initial后自动结束仿真。如果testbench中有多个program,那么需要等待所有program中最后一个initial才能结束仿真。

program pgm1;
initial begin: proc1
#100ns;
$display("@%0t p1.proc1 finished", $time);
end

initial begin: proc2
#400ns;
$display("@%0t p1.proc2 finished", $time);
end
endprogram

program pgm2;
initial begin: proc1
#200ns;
$display("@%0t p2.proc1 finished", $time);
end

initial begin: proc2
#300ns;
$display("@%0t p2.proc2 finished", $time);
end
endprogram


module tb;
bit clk;

initial begin
forever #5ns clk <= !clk;
end

counter dut(clk);
pgm1 p1();
pgm2 p2();

endmodule

执行结果:
# @100 p1.proc1 finished
# @200 p2.proc1 finished
# @300 p2.proc2 finished
# @400 p1.proc2 finished

从上面这个例子可以看到, 仿真会在p1.proc2最后执行完毕后自动结束。


结束方式之三:program显式结束
从上面的第二种结束方式来看,要求仿真自动结束的前提是所有program的initial块都应该在一定时间内完成,而实际上有的program内的initial语句块会一直运行下去,这就使得仿真无法等到所有的program均执行完毕,也就无法自动结束。这时候,我们可以在目标program内置入系统函数$exit来要求该program强行结束,待该program结束之后,仿真器仍然会等待其它program执行完毕后再结束仿真。

program pgm1;
initial begin: proc1
#100ns;
$display("@%0t p1.proc1 finished", $time);
end

initial begin: proc2
#200ns;
$display("@%0t p1.proc2 finished", $time);
end
endprogram

program pgm2;
initial begin: proc1
#700ns;
$display("@%0t p2.proc1 finished", $time);
$exit();
end

initial begin: proc2
forever begin
#300ns;
$display("@%0t p2.proc2 loop", $time);
end
end
endprogram


module tb;
bit clk;

initial begin
forever #5ns clk <= !clk;
end

counter dut(clk);
pgm1 p1();
pgm2 p2();

endmodule

执行结果:
# @100 p1.proc1 finished
# @200 p1.proc2 finished
# @300 p2.proc2 loop
# @600 p2.proc2 loop
# @700 p2.proc1 finished

从上面的例子可以看到p2由于有forever loop proc2,本身无法正常结束,所以仿真是无法自动结束的。这时,我们可以在p2内的proc1(任何一个initial块)置入一个系统函数$exit()。该系统函数的作用是可以强制结束它所在的program,这使得在proc1在700ns结束之后p2就结束了,而仿真器仍然会 统览其它的program2:p1,发现所有的program均执行完毕,于是就自动结束仿真了。

通过上面三种在SV中结束仿真的方式,我们可以更便利地控制仿真的结束,也能在更深的层次掌握仿真结束的机制。


至此,我们本篇《SV环境构建篇》就介绍完毕了,通过本篇的学习,读者可以在开始搭建“测试房子”之前懂得如何与设计做恰当的连接、模块的例化、验证与设计部分的隔离和结束测试的方式

我们下一篇《SV组件实现篇》将对之前做模块验证的几位验证者做一线跟拍,看看他们是如何实现它们的验证组件和环境的

谢谢你对路科验证的关注,也欢迎你分享和转发真正的技术价值,你的支持是我们保持前行的动力。

点赞

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 注册

  • 关注TA
  • 加好友
  • 联系TA
  • 0

    周排名
  • 0

    月排名
  • 0

    总排名
  • 0

    关注
  • 254

    粉丝
  • 25

    好友
  • 33

    获赞
  • 45

    评论
  • 访问数
关闭

站长推荐 上一条 /1 下一条

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-5-13 03:00 , Processed in 0.019821 second(s), 12 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
返回顶部