一、VCS的Verilog仿真事件队列
1.1 仿真队列介绍
数字仿真工具VCS是如何处理我们叫给他们的代码,如下图所示:
第一步:将所有initial和always块和连续赋值语句读进去,将这些语句按照固定的顺应放到一个队列中。
第二步:首先执行没有延迟的语句,比如变量的初始化语句。
第三步:当这些没有延迟的语句和initial语句全部执行完,VCS工具就会将时间记为0,就是current time。
第四步:进入active region区,在这个区间首先执行User Defined Primitive(用户自定义语言),比如说与门、或门、非门;$dispaly语句;没有延迟的assign语句;阻塞赋值的全部;非阻塞赋值只将右边的表达式的值计算出来,没有完成对左边的赋值。
第五步:进入inactive region区,相当于没有#0的语句,该区域的语句执行相对晚点,这个区域主要执行#0延迟语句的。
第六步:进入 Nonblocking assign region区,该区域完成对非阻塞赋值左边的赋值。
第七步:进入monitor区,该区域主要执行monitor函数,比如说监测a的值,当a的值变化,monitor才会监测到。用monitor和display监测非阻塞赋值,monitor监测的赋值后的值,display展示的是赋值前的值。
第八步:进入future区,执行一些其他的语句。
1.2 举例说明
`timescale 1ns/100ps
`define CASS1
module sim_event;
reg clk,a,z,zin;
always@(posedge clk)
begin
a=1'b1;
#0 a=1'b0;
end
`ifdef CASS1
always@(a) #0 z=zin;
always@(a) zin=a;
`else
always@(a) #0 z=zin;
always@(a) zin=a;
`endif
initial begin
#50 clk=1'bz;
#50 clk=1'b0;
#50 clk=1'b1;
#50 $finish;
end
initial begin
$vcdpluson();
end
endmodule
在linux系统输入 vcs +v2k sim_event.v -debug_all (+v2k:表示支持verilog2001)
编译之后产生simv文件
然后输入 ./simv -gui & (./simv:在当前执行simv文件 -gui:gui界面 &:后台执行)
1.3 波形
VCS仿真的结果:
其中斜线表示未知值,线条在中间是高阻态,clk先是未知值,接着是高阻态,然后是低电平,最后变成高电平。
使用VCS编译最后的结果a,z,zin分别是0,1,1。
modelsim仿真的结果:
使用modelsim编译最后的结果a,z,zin分别是0,0,0。
同一段代码交给不同厂家仿真器跑出的结果可能是不同的。
同一段代码交给同一个厂家不同版本的仿真器跑出的结果也可能是不同的。
1.4 testbeach一些规范用语
时序逻辑采用非阻塞赋值,<=
敏感列表要完整, 建议使用 always( * )
不要在always语句块中使用#0