2015-09-25 1300 views
0

之間的行爲差​​異我剛剛發現,當涉及function時,總是@(*)無法按預期工作。always_comb和always @(*)

請參閱下面的簡單示例代碼。

http://www.edaplayground.com/x/J7M

module test; 
    reg a, b, c; 

    function reg my_func(); 
    if (b==0) begin 
     $display("DEBUG 0 @%0t", $time); 
     return a; 
    end 
    else if (b==1) begin 
     $display("DEBUG 1 @%0t", $time); 
     return ~a; 
    end 
    else begin 
     $display("DEBUG 2 @%0t", $time); 
     return 0; 
    end 
    endfunction 

    always @(*) begin 
    //always_comb begin 
    c = my_func(); 
    end 

    initial begin 
    a = 0; #10; 
    a = 1; #10; 
    a=0; 
    end 
endmodule 

嘗試在模擬always @(*)always_comb之間切換。如果我使用always @(*),則不會顯示任何內容。但是,如果使用always_comb,它會顯示預期的結果如下:

DEBUG 2 @0 
DEBUG 2 @0 
DEBUG 2 @10 
DEBUG 2 @20 

上面的代碼只是簡單的組合邏輯。 爲什麼always @(*)always_comb顯示不同的結果?這只是模擬問題嗎?進一步的實驗我注意到它可能與在always塊內使用function有關。

+0

IEEE Std 1800-2012,第9.2.2.2節組合邏輯always_comb過程 – toolic

回答

3

總是@(*)塊對所有變量值的變化很敏感,通過始終阻止讀取,或者我們可以說哪些位於always塊的右側。

在你的例子中,在always塊內沒有使用任何變量,所以這總是@(*)塊在這裏不起作用。

按SV LRM,

always_comb是一個函數, 而永遠的內容中的變化很敏感@ *是更改爲 函數的參數只有敏感。

即,無論何時函數中的變量會改變,always_comb都會觸發,但在您的情況下,只有在函數中傳遞參數時,纔會觸發@(*)。

因此,無論您可以使用,

always @(*) begin 
    c = my_func(b); 
    end 

,或者您可以使用,

always_comb begin 
    c = my_func(); 
    end 

我已經修改了你的代碼。請在下面的鏈接中找到它。

http://www.edaplayground.com/x/JiS

1

always @(*)用的Verilog IEEE 1364-2001標準和取代了的SystemVerilog IEEE 2000至05年標準加入由always_comb。應該不再使用always @(*),因爲它不能在所有情況下正確模擬硬件。除了您注意到的功能差異之外,它不能正確處理常量邏輯。

parameter C = 0; 
reg A,B; 
always @(*) A = B && C; 

A仍然是未知的,直到有上B的變化。而使用always_comb將立即將A設置爲0,因爲在時間0的執行得到保證。