Verilog RTL優化策略(一):推薦使用assign語法替代if-else和case語法

流星斬月發表於2021-09-15

參考

  《手把手教你設計CPU——RISC-V處理器篇》

先給出不用if-else和case的原因

  Verilog中的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 語法編寫電路。

相關文章