2016-12-21 40 views
0

2個問題系統verilog 2012中關於always_comb中的非阻塞的參考指南?和延遲斷言屬性標記?

    系統的Verilog 2012參考指南中
  1. 存在要在always_comb編碼時序邏輯的參考,這是可能的,因爲存在用於一個always_comb塊沒有時鐘參考 - 可以在這裏看到 - > [順序邏輯中總是梳]

enter image description here

  • 同時使用系統的Verilog斷言中的Synopsys威爾第,是有可能的是,綠色箭頭(指示斷言屬性坐isfied)稍後解僱一半或一次時鐘週期,財產被滿足
  • 感謝後:d

    +0

    歡迎來到StackOverflow。下一次,爲了清楚起見,請不要在同一篇帖子中提出兩個問題。 –

    +0

    大聲笑,當然我的壞 – TheSprintingEngineer

    回答

    3

    關於質詢1.非阻塞賦值並不一定意味着順序行爲。阻塞/非阻塞賦值是一個仿真結構。我們來看一個小例子來更好地理解它:

    module some_gate(
        input logic a, 
        input logic b, 
        output logic c, 
        output logic d 
    ); 
    
        // c is 'a or b' 
        // d is 'a and c' 
    endmodule 
    

    我們有兩個輸入信號和兩個輸出信號。我們想要模擬複合門。

    在古典風格的Verilog,我們這樣寫:

    always @(a or b) begin 
        c = a || b; 
        d = a && c; 
    end 
    

    這意味着,無論何時ab變化,計算的cd值。因爲我們對c使用了阻塞賦值,所以我們在此計算的值被「傳播」到d的計算。這實際上意味着我們鏈接了d所描述的邏輯,以便遵循c的邏輯。

    我們可以使用一個小的測試平臺測試:

    module test; 
        logic a, b, c, d; 
    
        some_gate dut(.*); 
    
        always @(a or b or c or d) 
        $display("[%0d] a = %b, b = %b, c = %b, d = %b", $time(), a, b, c, d); 
    
        initial begin 
        #1 a = 1; 
        #1 b = 1; 
        #1 a = 0; 
    
        #1 $finish(); 
        end 
    endmodule 
    

    如果我們模仿這個,我們會得到:

    [1] a = 1, b = x, c = x, d = x 
    [1] a = 1, b = x, c = 1, d = 1 
    [2] a = 1, b = 1, c = 1, d = 1 
    [3] a = 0, b = 1, c = 1, d = 1 
    [3] a = 0, b = 1, c = 1, d = 0 
    

    這是因爲顯示過程的每一個變化觸發一次變量。 a已從x更改爲1,但c尚未更新。然後cd在同一時間步驟中得到更新。稍後,我們更改b,但這不會在cd上觸發任何更改。然後,我們再次在同一時間段更改a,並更新d

    需要指定靈敏度列表有點多餘,因爲如果我們知道我們想要組合邏輯,那麼只要賦值右側的內容發生變化,我們就應該重新觸發該過程。這是always_comb的用途。

    使用always_comb,由剛剛擺脫敏感列表中我們可以重新寫我們的代碼:

    always_comb begin 
        c = a || b; 
        d = a && c; 
    end 
    

    運行這段代碼將導致相同的打印:

    [1] a = 1, b = x, c = x, d = x 
    [1] a = 1, b = x, c = 1, d = 1 
    [2] a = 1, b = 1, c = 1, d = 1 
    [3] a = 0, b = 1, c = 1, d = 1 
    [3] a = 0, b = 1, c = 1, d = 0 
    

    現在到了有趣的部分。我們可以模擬使用always_comb和非阻塞賦值完全相同的電路:

    always_comb begin 
        c <= a || b; 
        d <= a && c; 
    end 
    

    運行這段代碼,雖然會產生稍有不同的打印:

    [1] a = 1, b = x, c = x, d = x 
    [1] a = 1, b = x, c = 1, d = x 
    [1] a = 1, b = x, c = 1, d = 1 
    [2] a = 1, b = 1, c = 1, d = 1 
    [3] a = 0, b = 1, c = 1, d = 1 
    [3] a = 0, b = 1, c = 1, d = 0 
    

    注意的是,在第一次的步驟,我們有3打印,而不是一個。讓我們仔細看看這裏發生了什麼。首先,我們更改a,但cd尚未更新。其次,c得到更新,但d保持不變。這是因爲c上的非阻塞賦值導致d「看到」c的「舊」值。第三,cc正式更新之後,該工具在d上安排更新,我們將看到第一個時間步的最後一個打印。其餘部分與之前的情況相同。

    請記住,從前面的段落可以看出always_comb只要分配右側的內容發生變化就會重新觸發。這裏的技巧是,這always_comb實際上表現爲:

    always @(a or b or c) begin 
        c <= a || b; 
        d <= a && c; 
    end 
    

    這是不規範的Verilog,但仍模型相同的邏輯。請注意,c已被明確添加到靈敏度列表中。如果我們省略這個,那麼我們會描述一個閂鎖。這種風格是不鼓勵的,因爲它很容易出錯(即忘記將中間邏輯節點添加到靈敏度列表中)。

    這裏的關鍵問題是阻塞或非阻塞賦值不描述順序邏輯或組合邏輯。它是控制從代碼推斷出什麼邏輯電路的整個上下文(即確定何時執行的敏感性列表)。

    完整的示例代碼可以在EDAPlayground

    關於問題2.這是工具特定的,這不是論壇。你應該在供應商的網站上提問。

    +0

    謝謝都鐸王朝,這幫助了很多! :D – TheSprintingEngineer

    +0

    在我看到它之前,我在新的EDA Playground Community標籤中看到了這個例子!感謝您發佈它。 –