參考
《手把手教你設計CPU——RISC-V處理器篇》
先給出不用if-else和case的原因
- 不能傳播不定態X;
- 會產生優先順序的選擇電路而非並行選擇電路,從而不利於時序和麵積;
情況一:if-else不能傳播不定態
Verilog 的if-else 不能傳播不定態,以如下程式碼片段為例。假設 a 的值為X不定態,按照Verilog語法會將其等效於 a == 0,從而讓 out 輸出值等於in2 最終沒有將X不定態傳播出去。這種情況可能會在模擬階段掩蓋某些致命的 bug,造成晶片功能錯誤:
if(a) out = in1; else out = in2;
而使用功能等效的 assign 語法,如下所示,假設 a 的值為X不定態,按照 Verilog 語法,則會將X不定態傳播出去,從而讓out 輸出值也等於X。通過X不定態的傳播,可以在模擬階段將 bug徹底暴露出來
assign out = a ? inl : in2;
雖然現在有的 EDA 工具提供專有選項(例如 Synopsys VCS 提供 xprop 選項)可以將 Verilog 原始語法中定 義的"不傳播不定態"的情形強行傳播出來,但是一方面不是所有的 EDA 工具均支援此功能;另一方面在操作中此選項也時常被忽視,從而造成疏漏。
情況二:case不能傳播不定態
Verilog 的 case 語法也不能傳播不定態,與情況一中的if-else 同理。而使用等效的 assign 語法即可規避此缺陷。
情況三:if-else語法被綜合成優先順序選擇電路
verilog 的 if-else 語法會被綜合成為優先順序選擇的電路,面積和時序均不夠優化,如下所示∶
if (sel1) out = in1[3:0]; else if (sel2) out = in2[3:0]; else if (sel3) out = in3[3:0]; else out = 4'b0;
如果此處確實是希望生成一種優先順序選擇的邏輯,則推薦使用 assign 語法等效地編寫成如下形式,以規避 X 不定態傳播的問題∶
assign out = sel1 ? in1[3:0]: sel2 ? in2[3:0]: sel3 ? in3[3:0]: 4' b0;
而如果此處本來是希望生成一種並行選擇的邏輯,則推薦使用 assign 語法明確地使用"與"-"或"邏輯,編寫如下∶
assign out = ({4{sel1}} & in1[3:0]) | ({4{sel2}} & in2[3:0]) | ({4{sel3}} & in3[3:0]);
使用明確的 assign 語法編寫的"與"-"或"邏輯一定能夠保證綜合生成並行選擇的電路
情況四:case語法被綜合成優先順序選擇電路
與情況三同理,verilog 的 case 語法也會被綜合成為優先順序選擇的電路,面積和時序均不夠優化。有的EDA綜合工具可以提供指引註釋(例如 synopsys parallel case 和 full case)來使得綜合工具能夠綜合出並行選擇邏輯,但是這樣可能會造成前後模擬不一致的嚴重問題,從而產生重大的bug。因此,在實際的工程開發中∶
● 應該明令禁止使用 EDA 綜合工具提供的指引註釋(例如 synopsys parallel case 和 full case)。
● 應該使用情況三推薦的等效 assign 語法編寫電路。