在此示例中,非阻塞賦值傳播到連續賦值。這可以導致任何執行範例。請詳細說明這段代碼 - 可能的錯誤,它如何被刪除和良好的編碼風格。非阻塞賦值的細節
always @(posedge clk)
dff1 <= f(x);
assign fsm_in = f(dff1);
assign fsm_out = fsm_state;
always @(fsm_in)
fsm_state <= g(fsm_in);
在此示例中,非阻塞賦值傳播到連續賦值。這可以導致任何執行範例。請詳細說明這段代碼 - 可能的錯誤,它如何被刪除和良好的編碼風格。非阻塞賦值的細節
always @(posedge clk)
dff1 <= f(x);
assign fsm_in = f(dff1);
assign fsm_out = fsm_state;
always @(fsm_in)
fsm_state <= g(fsm_in);
你的代碼是正確的,雖然我與格雷格同意,這是更好的風格的組合使用阻塞賦值處理。
您的意見:
在非常簡單的條件,調度包含5個隊列(SV有17個),但 你只是在其中的2感興趣的是:在active event queue
和 nonblocking assignment update queue
。在給定的模擬週期中, 模擬器處理活動事件隊列,然後處理非阻塞更新 隊列。一般來說,這將創建更多事件,並且模擬器以預定順序在隊列周圍循環 ,直到在此模擬時間處沒有更多事件在 處。然後模擬器繼續下一次調度事件(例如,在下一個時鐘邊沿)。
假設4事情發生了「一次」:有在fsm_state
有變化,但 在f(x)
的變化,你都分配NBA執行。至於模擬器 ,這4個語句在相同的 模擬週期中執行,但是以未定義的順序執行。 「立即」的定義是 相當複雜,但假設它們都是由於時鐘邊緣而產生的,並且在語句之間沒有順序依賴關係。該模擬器通常是 單線程的,所以它實際上將在不同 真正次執行4條語句,但它知道所有4預計在同一 模擬時間發生。
上fsm_state
和f(dff1)
的變化是update events
,並添加到 調度的active event queue
。
立即評估兩個NBA的RHS,並將LHS更新 添加到nonblocking assignment update queue
。
模擬器現在看到一個隊列上有4個事件。它首先以未定義的順序執行兩個活動的 事件,因此fsm_in
和fsm_out
將獲得其新的 值。如果沒有更多活動事件,則它將以未定義的順序執行兩個非阻塞更新,因此dff1
和fsm_state
現在將獲得 的新值。
在你的情況下,仿真週期還沒有結束,因爲 fsm_in
的變化也是一個更新事件,這觸發評估/執行always塊這是fsm_in
敏感的 。這是一個evaluation event
。模擬執行always塊,立即讀取新值 fsm_in
,並將更新fsm_state
添加到NBA分配更新 隊列中。如果沒有活動事件,則分配將被執行,並且 fsm_state
會得到它的新值。
這一直持續下去,直到在此模擬週期中沒有更多事件,並且 模擬器隨後會推進時間,如果將來安排了某些事情。
您可以從Verilog LRM的第5部分中獲得所有這些信息,但它不會使 有意義。所有的語言都在標準化後期嫁接,並且使用了在LRM其他地方沒有使用的(VHDL)術語。它還全部以與Verilog-XL的行爲相匹配的方式添加,並且專門用於記錄特定於XL的非確定性,因此不要指望 太多。直到1992年,NBAs才被添加到語言中,I 認爲。不要打擾SV LRM;還有更多的隊列,並且常見的文本已經改變,只是增加了另一層次的混亂。
Cliff Cummings在他的一篇論文(關於 非阻塞作業)中有一個簡化的描述,但請仔細閱讀。我很確定活動事件隊列的描述是不正確的(對於 NBAs的RHS評估)。如果他是對的,會造成各種問題;他大概從 得到了早期版本LRM的描述。
要做的最好的事情是在VHDL delta週期中查找任何文本。這些 很容易理解,而且它們工作,並且總是完成,並且多年來他們已經將其嵌入到Verilog中。細節是不同的,但你不需要知道任何東西比你會發現三角洲週期。
首先:最佳做法是對寄存器進行非阻塞賦值並對組合邏輯進行阻塞賦值。我建議看看這篇論文:Clifford E. Cummings的Nonblocking Assignments in Verilog Synthesis, Coding, Styles That Kill!。 § 11涵蓋組合邏輯。該論文的指導原則適用於IEEE Std 1364-1995,現在仍然完全適用; Verilog和SystemVerilog。
這就是說,給定的代碼是可行的,因爲你有一個簡單的條件。它也可能會正確合成(基於Cliff的頁面)。
如果您在較複雜的設計中使用較差的編碼風格,可能會遇到問題。例子見Cliff's paper。糟糕的編碼風格也會使其他人難以閱讀[1]。可讀的代碼是你想要給你的教授和同事的東西。一個理想的消磨工具也會標記它。最好讓自己養成編寫高質量代碼的習慣。
1:請IEEE std 1800-2012 § 34,如果你真的不希望別人讀你的代碼
我同意在組合過程中使用阻塞賦值是'最佳實踐',但這當然只是一個指導原則。您始終可以使用NBAs編碼組合邏輯,而VHDL設計人員始終可以執行此操作。當然,如果您開始使用臨時變量來保存中間值,則必須瞭解NBAs實際執行的操作以及值何時更新。在VHDL中,您使用一個變量來確保立即更新;在Verilog中,你使用阻塞賦值。 Verilog的'指導原則'存在,因爲語言指定的很差 - 如果你理解語言,你可以忽略它們。 – EML
我建議你總是使用非阻塞時鐘驅動信號和阻塞組合邏輯(如果它是RTL)。我使用過許多合成器,如果您不按照我的建議使用任務,它們會顯示錯誤。另外還有其他的線跡工具也會顯示錯誤。 我同意Greg的觀點,爲了更好的閱讀代碼,你應該遵循這個指導原則。
我從來沒有見過合成失敗,因爲它不瞭解NBAs,甚至聽說過它。這是不太可能的,因爲他們在模板識別上工作,這也意味着他們無法處理大量的VHDL代碼。 – EML
f和g是任意表達式,就像數學模型i一樣。e(x)= x 2 - x + 1; – chitranna