2014-07-23 76 views
0

爲什麼下面的代碼不是自觸發的?帶自觸發的clk發生器中的Verilog阻塞/非阻塞賦值

module osc1 (clk); 
output clk; 
reg clk; 
initial #10 clk = 0; 
always @(clk) #10 clk = ~clk; 

always 
begin 
$monitor("%0d clk=%0d\n",$time,clk); 
#100 $finish; 
end 
endmodule 

輸出:

# 0 clk=x 
# 10 clk=0 
# 20 clk=1 

時使用非阻塞分配它正常工作
always @(clk) #10 clk <= ~clk;

輸出:

# 0 clk=x 
# 10 clk=0 
# 20 clk=1 
# 30 clk=0 
# 40 clk=1 
# 50 clk=0 
# 60 clk=1 
# 70 clk=0 
# 80 clk=1 
# 90 clk=0 

預先感謝。

回答

1

它與Verilog調度程序有關。

@將等待新事件,它會忽略任何過去的事件。在同一時間步驟內,執行順序很重要。

clk = ~clk是一個阻塞分配,意味着clk之前將被更新調度下@clk事件將被錯過。

clk <= ~clk是非阻塞分配,意味着clk調度下@之後將被更新clk事件將被感知。


自觸發塊在實踐中並不常見。 always塊不需要有靈敏度列表。它們應該在塊內至少有一個可達時間阻塞延遲(例如@(_list_),#(_timeunit_));否則會出現零時間無限循環,並且仿真會掛起。

時鐘發生器通常植入類似於:

reg clk; 
initial begin 
    #10 clk = 0; 
    forever #10 clk = ~clk; 
end 

或者

reg clk; 
always #10 clk = (clk===1'b0);