Always_comb

allways_combは、その動作が常に組み合わせ回路のを意図していることを表す。

従来のalwaysで組み合わせ回路を表現する時との違いは以下の通り。

    • センシティビティーリストが無い

    • 常に組み合わせ回路の動作をし、ラッチやFFの動作にならないことをシミュレータ/コンパイラに知らせる

特に、面倒なセンシティビティーリストを書かなく良いのはうれしい(同様なことはVerilog2001のalways @(*)でも実現できるが)。

always_combは、既存のalwaysとの違いは上記の通りなので、記述方法に迷うことはないだろう。

ところで、本機能への対応は、シミュレータや合成ツールでかなりばらついているので注意が必要だ。

以下の例を見てみよう。コメントアウトされた不完全なifにより、組み合わせ回路としては不適切な記述となっている。

module test();

reg [1:0] sel;

wire [7:0] out;

initial begin

sel = 2'b11;

do begin

sel = sel + 1;

#10 $display("sel = %2b, out = %x", sel, out);

end while (sel != 2'b11);

$finish();

end

duv duvIns(.out(out), .sel(sel));

endmodule // test

module duv(

output reg [7:0] out,

input [1:0] sel);

always_comb begin

if (sel == 2'b00) out = 8'h55;

else if (sel == 2'b01) out = 8'haa;

else if (sel == 2'b10) out = 8'hff;

// else out = 8'h00;

end

endmodule // duv

ModelSim上ではラッチの動作をし、エラーメッセージ等も表示されない。

# 6.5e

# vsim -do {run -all; quit} -c test

# Loading sv_std.std

# Loading work.test

# Loading work.duv

# run -all

# sel = 00, out = 55

# sel = 01, out = aa

# sel = 10, out = ff

# sel = 11, out = ff

一方、Quartus IIでは、合成時に以下のようなエラーが表示される。

Error (10166): SystemVerilog RTL Coding error at test.sv(23): always_comb construct does not infer purely combinational logic

次に、先ほどのalways_combを以下のように書き換えてみよう。今度は、全ての条件を網羅しているので、エラーは出ないはずだ。

always_comb begin

if (sel == 2'b00) out = 8'h55;

else if (sel == 2'b01) out = 8'haa;

else if (sel == 2'b10) out = 8'hff;

else if (sel == 2'b11) out = 8'h00;

end

ModelSimでは、期待通りの動作をする。

# 6.5e

# vsim -do {run -all; quit} -c test2

# Loading sv_std.std

# Loading work.test2

# Loading work.duv

# run -all

# sel = 00, out = 55

# sel = 01, out = aa

# sel = 10, out = ff

# sel = 11, out = 00

ところがQuartus IIでは、この記述でも同じようにエラーを出力する。おそらく、selにxやzが代入されている時の条件が網羅されていないせいなのだろうが、合成には無関係なので、ここは組み合わせ回路を合成してほしいところだ。事実そのように動作する合成ツールも存在する。

この他にも、最初の記述例でWarningを出すもののラッチを生成する合成ツールや、同様にWarningを出すのみで、ラッチの動作を行うシミュレータ等、ツール毎に対応が分かれているのが現状のようだ。

将来これらの動作に一貫性がとられることを期待するが、当面のところ、一番安全側に振って、以下のような対応をお勧めする。

    • always_combを使ったからといって、ラッチが生成されないことを期待しない。常に合成後のレポートでラッチがないことを確認する

    • always_comb内でifを使う場合はelse ifではなく、elseで終わらせる。同様にcaseにもdefaultを必ず指定する