はじめに
RTLで、単純な条件式はif文ではなく3項演算子を使用した方がよいという話をどこかで聞いたが
なぜだかわからなかったため、調べてみました。
3項演算子の方が実機での動作に近いから、ということかなと思いました。
ifの条件式と3項演算子
if文で下記のような条件式を書くとき、
if (sel) begin
<式1>
else begin
<式2>
end
3項演算子では下記のようになると思います。
sel ? <式1> : <式2>;
しかし、両者は動作が異なります。
selにx、zが入ったとき、if文ではelse項に行きますが、
3項演算子では、<式1>, <式2>がマルチアサインされます。
実機では不定がないので0 or 1です。つまり真偽どちらになるかわかりません。
なので、必ずelse項が評価されるif文より、マルチアサインとなり場合によっては不定が伝播する3項演算子の方が実機とシミュレーションで整合性が高いと思われます。
不定が伝播していることがシミュレーションの波形上で分かり、RTLを修正することができます。
動作確認
if文
tb.sv
module tb;
bit clk = 0;
always #5 clk = ~clk;
logic sel;
logic [5:0] sig;
always_comb begin
if (sel) begin
sig = 6'b10z001;
end
else begin
sig = 6'b10z1zz;
end
end
initial begin
sel = 1'b0;
@(posedge clk);
$display("%b", sig);
sel = 1'b1;
@(posedge clk);
$display("%b", sig);
sel = 1'bz;
@(posedge clk);
$display("%b", sig);
$finish;
end
endmodule
出力
selが0, 1のときは、真偽の値がそのままsigに代入されています。
selがzのときは、else項に入りselが0のときと同じ値がsigに代入されています。
sel: 0 sig: 10z1zz
sel: 1 sig: 10z001
sel: z sig: 10z1zz
3項演算子
tb.sv
module tb;
bit clk = 0;
always #5 clk = ~clk;
logic sel;
logic [5:0] sig;
assign sig = sel ? 6'b10z001 : 6'b10z1zz;
initial begin
sel = 1'b0;
@(posedge clk);
$display("%b", sig);
sel = 1'b1;
@(posedge clk);
$display("%b", sig);
sel = 1'bz;
@(posedge clk);
$display("%b", sig);
$finish;
end
endmodule
出力
selが0, 1のときは、真偽の値がそのままsigに代入されています。
selがzのときは、
5ビット目は真偽で両方1のため1、
4ビット目は真偽で両方0のため0、
3ビット目は真偽でどちらかがzのためx
2、1、0ビット目は真偽で異なる値のためxになっています。
sel: 0 sig: 10z1zz
sel: 1 sig: 10z001
sel: z sig: 10xxxx
まとめ
3項演算子の動作について調査しました。
コメント