木曜日, 4月 08, 2010

always_combとalways@*の違い

by Manuel Cernuda

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

always @ ( color or a or b or c or ... ) begin
  case (color)
    RED  : x = a;
    BLUE : x = b & c;
    ....;
  endcase
end

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

always @* begin
  case (color)
    RED  : x = a;
    BLUE : x = b & c;
    PINK : x = my_function(d, e, f);
    ....;
  endcase
end

function my_function;
  input sig_a;
  input sig_b;
  input sig_c;
  begin
    my_function = sig_a | sig_b | sig_c | SIG_X;
  end
endfunction

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

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

always_comb begin
  case (color)
    RED  : x = a;
    BLUE : x = b & c;
    PINK : x = my_function(d, e, f);
    ....;
  endcase
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 件のコメント: