说到verilog的阻塞与非阻塞赋值,不得不说的就是verilog的事件表,如下:
阻塞赋值,属于活跃事件,计算完RHS(Right Hand Side)立即更新左值。期间同一块内其他语句不能执行,即阻塞其他语句执行。
而非阻塞右值计算属于活跃事件,非阻塞左值更新属于非活跃事件,即计算完RHS,不能立即更新左值,而要等所有活跃事件完成,才能完成左值更新,出事件队列。
然后说说$display与$strobe
显示任务($display)在执行到该语句时立即执行显示
选通任务($strobe)要推迟到事件列表当前时阶结束时进行。
$strobe:
当该时刻的所有事件处理完后,在这个时间步的结尾打印一行格式化的文本,
规则
这些系统任务的变量的语法几乎和$display 任务一样
但是$strobe 被调用时,在该块中所有活动都完成了,$strobe 才打印文本,这包括所有阻塞性和非阻塞性赋值的作用
提示
在写仿真结果时请尽量使用$strobe 少用$display 或$write
举例
initial
begin
x = 1'b0;
$display("x1=%d",x);
$strobe("x2=%d",x);
x = 1'b1;
end
最后显示 x1=0;x2=1;
(1)
(若无延时,计算完所有RHS,同步更新到RLS,加了延时,
并且此时延时在最前边,表示计算右值与赋值都被延时)
#50延时,clk上升沿,
#100延时,RHS_a ->a
#50 RHS_b -> b
#50 RHS_c ,$display, RHS_c -> c;
打印结果:
波形结果:
(2)
(此时延时,指的是输入与输出间的延时)
#50延时,clk上升沿RHS_a,RHS_b,RHS_c, $display
#50延时,RHS_b->b,RHS_c->c
#50延时,(另一个clk上升沿)$display RHS_a->a
打印结果:
波形结果:
(3)
#50延时,clk上升沿
#100延时,RHS_a->a
#50延时,RHS_b->b
#50延时,RHS_c->c,$display
打印结果:
波形结果:
(4)
#50 lk上升沿
RHS_a#100延时RHS_a->a
RHS_b#50延时RHS_b->b
RHS_c#50延时RHS_c->c,$display
打印结果:
波形结果:
因此,将begin-end改为fork-join,系统运行结果如下;
(1)
打印结果:
波形结果:
(2)
打印结果:
波形结果:
(3)
打印结果:
波形结果:
(4)
打印结果:
波形结果:
其实$display的执行时间与仿真器有关,硬件上,$display的运行时间与并行的程序的相对时间是不确定的,而仿真器则设置了固定的开始时间。