木曜日, 4月 08, 2010

always_combとalways@*の違い

by Manuel Cernuda

以前のVerilog HDLでは、alwaysを使って組み合わせ回路を書く場合には
Sensitivity Listに入力を全て列挙しなければならず面倒で、またバグの温床でもありました。
例えばこんな感じです。

  1. always @ ( color or a or b or c or ... ) begin  
  2.   case (color)  
  3.     RED  : x = a;  
  4.     BLUE : x = b & c;  
  5.     ....;  
  6.   endcase  
  7. end  

Verilog 2001ではalways @*がサポートされてかなりの簡潔に記述できるようになり、Sensitivity Listの記入漏れの問題は起きにくくなりました。
しかし、それでもまだ実はシミュレーション時に問題が起こる可能性があります。

  1. always @* begin  
  2.   case (color)  
  3.     RED  : x = a;  
  4.     BLUE : x = b & c;  
  5.     PINK : x = my_function(d, e, f);  
  6.     ....;  
  7.   endcase  
  8. end  
  9.   
  10. function my_function;  
  11.   input sig_a;  
  12.   input sig_b;  
  13.   input sig_c;  
  14.   begin  
  15.     my_function = sig_a | sig_b | sig_c | SIG_X;  
  16.   end  
  17. endfunction  

always @*はalways内で直接使用している信号までしかsensitiveではなく、
例えば上の例の様な記述の場合、my_function()の中で使用しているSIG_Xに変化があったとしてもalways @*の出力xは変化しません。

このような問題を解決できるのがSystemVerilogのalways_combです。

  1. always_comb begin  
  2.   case (color)  
  3.     RED  : x = a;  
  4.     BLUE : x = b & c;  
  5.     PINK : x = my_function(d, e, f);  
  6.     ....;  
  7.   endcase  
  8. end  

このようにalways @*の場合と同様に記述出来ます(functionの内部は省略)。
しかし、always_combの場合はalways @*と違い、内部に含まれるfunctionが使用している信号に対してもsensitiveになります。つまり、この場合はSIG_Xの変化にもalways_combの出力xが連動します。

その他にも、always_combではalways @*と比べて以下のような違いがあります。

・時刻0で一度always_comb内部が実行される
・always_comb内でドライブされている信号は他の場所でドライブできない
・always_comb内ではwait()やfork...joinなどのタイミングをブロックするような制御が行えない

他にもSystemVerilogではalways_latchやalways_ffなどが追加されていますが特にこのalways_combが重要ですね。

alwaysで組み合わせ回路を記述する場合は是非使うようにしましょう。

最後に、昔書いた組み合わせ回路の記事のリンクを貼っておきます。
ここではalwaysで組み合わせ回路を記述する場合の短所としてregで出力を宣言しなければならないと書きましたが、SystemVerilogでは新たにlogicが追加されたので便利になりました。
functionを使う場合は、always_combの中に入れておくとより安全でしょう。

こちらで別の例が詳細されていたのでリンクしときます。

0 件のコメント: