| |
程序语句如下:
always @(posedge RST or posedge CLK)
if(RST)
begin
addra <=0;
flag <=0;
end
else
begin
addra <= addra +1'b1;
if(addra==1)
flag<=1;
end
意思就是说addra在RST为0时开始从0增长,长到1时flag非阻塞赋值为1.仿真结果如下:
过程解析:addra从0变到1的时钟上长沿时刻,检测addra的值,addra的值为0,因为是非阻塞赋值,左式还没来得及更新。等到addra从1变到2的clk上升沿时刻,检测addra的值,此时addra的值为1,并非2,同样也是因为左式没有更新,此时才符合flag赋1的条件,也就是在这个时间步,flag非阻塞赋值为1,该时间步刚刚结束flag立即更新为1.图中第三行为flag,第四行为addra的值变化。
若将addra的值由非阻塞赋值改为阻塞赋值,那么addra 值是立即更新的,即在addra由0变为1的时钟沿时刻即能检测出addra的值是1的,于是flag立即变为1.当然对于flag而言,阻塞赋值与非阻塞赋值是一样的,但会对以flag为判断标志的其它信号造成影响。仿真结果如下图:
其实以上说法有失准确,addra阻塞赋值时,addra由0变为1的时钟沿时刻能检测出addra的值是1实属巧合,因为“检测”这一动作也是在时钟沿时刻进行的,属于非阻塞赋值左式更新之前的活跃事件,而活跃事件(阻塞赋值,非阻塞赋值右式计算,连续赋值等)的进行是随机的,本次实验时,“检测”恰好在addra的阻塞赋值之后。通过实验,或将assign flag1= addra(连续赋值),flag在flag1由1变到2的时钟沿时刻才变为1的,这恰恰说明了“检测”发生在该连续赋值语句的前面,检测时还末经过连续赋值,下一次检测时才检测出来。
这里也加深一下对连续赋值的认识:一个线网型变量一旦被连续赋值语句赋值之后,赋值语句右端赋值表达式的值将持续对被赋值变量产生连续驱动。只要右端表达式任一个操作数的值发生变化,就会立即触发对被赋值变量的更新操作。这种更新不像过程赋值那样只发生在时钟沿时刻,它除了发生在时钟沿时刻,还发生在其它任一时刻。