且看一段代码:
always @(posedge clk) begin if(count<=5*T10MS) count<=count+1‘b1; else begin count<=0; sel<={sel[4:0],sel[5]}; flag<=flag+1‘b1; if(flag>=4‘b1010) flag<=0; end end always @(flag)
begin case(flag) 4‘b0000: dig=S0; 4‘b0001: dig=S1; 4‘b0010: dig=S2; 4‘b0011: dig=S3; 4‘b0100: dig=S4; 4‘b0101: dig=S5; 4‘b0110: dig=S6; 4‘b0111: dig=S7; 4‘b1000: dig=S8; 4‘b1001: dig=S9; default: dig=8‘hff; endcase end
以上一个例子是,控制一个数码管从0到9进行显示,但是却出现了default所示的状态,也就相当于出现了一个空档。这个是不允许出现的。这个不允许出现的flag状态就是flag=10。当flag=10,不能正常译码就执行了default语句,那么数码管就熄灭了。那么这个状态时如何出现的呢?
当flag=9时,一个clk的上升沿到来时,
flag<=flag+1‘b1; if(flag>=4‘b1010) flag<=0; 由于flag<10,那么if条件语句部分并未执行,所以当上升沿结束以后,flag为10,只有当下一个clk上升沿到来的时候,flag才会清零。这样就导致了数码管会熄灭。
当代码变为如下的时(其他部分不变)
flag=flag+1‘b1; if(flag>=4‘b1010) flag=0; 结果是不会出现数码管熄灭的。因为在这里,是进行阻塞赋值的,当flag为9时,一个clk的上升沿到来,那么就出现
flag=flag+1‘b1; flag=10;紧接着执行
if(flag>=4‘b1010) flag=0; 这样在这个always模块执行完毕的时候,flag为0而不是10。
出现这样这样的结果的主要原因是对于阻塞赋值和非阻塞赋值语句不清楚的,
不要因为这里有一个判断语句就以为上下两个语句是非阻塞的。但是如果换成,非阻塞语句就不会出现这样情况,而且也容易理解,可读性强,所以还是建议用非阻塞语句,书写这样的代码。