LoginSignup
12
11

More than 3 years have passed since last update.

出木杉君演算子 inside

Last updated at Posted at 2020-12-05

出木杉君演算子 inside

石谷 @PEZY Computing です。SystemVerilog Advent Calendar 2020 と言うことで、inside 演算子の紹介をしたいと思います。

inside 演算子とは

inside 演算子は SystemVerilog で導入された演算子です。LRM 上は Set membership operator として説明されています。
出木杉君と言っても過言ではないぐ便利な演算子で、以下の3つの機能を有しています。

  • 複数個の比較値との比較
  • 範囲の比較
  • ワイルドカード比較

では、サンプルコードとともに、これらの機能を紹介していきます。
なお、サンプルコードは GitHub 上のリポジトリに置いてあります。

複数個の比較値との比較

「比較値が複数あり、どれかに一致するか」を調べる場合、従来の Verilog では、

is_matched = (v == 0) || (v == 1) || (v == 2);

のように書く必要があります。inside 演算子を使うと、これらを纏めることができて、

is_matched = v inside {0, 1, 2};

のように書くことができます。また、{} の中に配列を指定することもできて、

int valid_values[3] = '{0, 1, 2};
is_matched = v inside {valid_values};

と書くこともできます。

  • 注意
    • Synopsys 社の Design Compiler は、上記の比較要素を配列に詰める方法をサポートしていないようです。

以下のサンプルコードを Vivado 合成すると、

module sample_1 (
  input   var [1:0] i_d,
  input   var [1:0] i_a,
  input   var [1:0] i_b,
  input   var [1:0] i_c,
  output  var       o_matched
);
  always_comb begin
    o_matched = i_d inside {i_a, i_b, i_c};
  end
endmodule

以下のようになります。想像通り、3個の == の出力の OR になりました。

sample_1

範囲の比較

inside 演算子は出木杉君なので、範囲の比較もすることができます。
min <= v <= max のような比較を行う場合、Verilog では、

in_range = (v >= 4) && (v <= 7);

のように書く必要があります。inside 演算子では {} の中に [min:max] のように値域を指定することができて、

in_range = v inside {[4:7]};

のように書くことができます。[min:max]min/max は定数だけではなく、変数 (信号) を指定することもできて、

int min = 4;
int max = 7;
in_range = v inside {[min:max]};

と書くこともできます。
また、$: の左側に置くと inside の左辺値の最小値、右側に置くと最大値を表します。以下のような場合は、

bit [2:0] a;
range_0_to_3 = a inside {[$:3]};
range_4_to_7 = a inside {[4:$]};

a inside {[0:3]} および a inside {[4:7]} と等価になります。

範囲比較の場合も合成してみましょう。以下のサンプルコードを合成してみると、

module sample_2 (
  input   var [1:0] i_d,
  input   var [1:0] i_min,
  input   var [1:0] i_max,
  output  var [3:0] o_in_range
);
  always_comb begin
    o_in_range[0] = i_d inside {[i_min:i_max]};
    o_in_range[1] = i_d inside {[    $:i_max]};
    o_in_range[2] = i_d inside {[i_min:    $]};
    o_in_range[3] = i_d inside {[    $:    $]};
  end
endmodule

案の定な結果になります。

sample_2

ワイルドカード比較

{} の中の値の ?/x/z は don't care として扱われ、ワイルドカードとして振舞います。有能ですね。
例えば、以下のような場合、

bit [3:0] v;
bit       is_matched;
is_matched = v inside {4'b1?0?};

v4'b1000/4'b1001/4'b1100/4'b1101 の場合に、is_matched1 になります。それ以外では、0 です。

では、さっそく Vivado に食わせてみましょう。

module samaple_3 (
  input   var [3:0] i_d,
  output  var       o_matched
);
  always_comb begin
    o_matched = i_d inside {4'b1?0?};
  end
endmodule

ワルドカードを使った場合も合成可能で、以下のような結果になりました。
なるほど、マスクをかけてから、比較するのですか。

sample_3

補足

SystemVerilog では、右辺値にワイルドカードを取れる演算子として ==?!=? (Wildcard equality operators) が追加されています。inside 演算子における整数値の比較は ==? を使って行われています。

合わせ技

上述の3つを、1つの {} の中に入れることもできます。超絶便利ですね。
合わせ技の場合も合成可能です。

module sample_4 (
  input   var [3:0] i_d,
  input   var [3:0] i_a,
  input   var [3:0] i_b,
  input   var [3:0] i_min,
  input   var [3:0] i_max,
  output  var       o_result
);
  always_comb begin
    o_result  = i_d inside {i_a, i_b, [i_min:i_max], 4'b11??};
  end
endmodule

それぞれの結果の OR が最終結果になります。予想通りですね。

sample_4

注意事項

inside 演算の結果を否定 (!) する場合は注意が必要ですつ。
inside 演算子は、論理否定演算子より結合度が低いので、

result = !v inside {0, 1};

のように書くと、

result = (!v) inside {0, 1};

のようになり、v! を適用した結果に inside 演算子が適用されてしまいます。
なので、このような場合は、() で囲ってあげましょう。

result = !(v inside {0, 1});

最後に

inside 演算子がいかに出木杉君かをご理解いただけたかと思います。論理合成可能な演算子なので、どんどん使っていきましょう。
(ただし Quartus ユーザーは除く。)

宣伝

YAML とか Excel で記述したレジスタマップから、RTL 等を自動生成するツール (RgGen) を作っています。
面倒な CSR のコーディングをせずに済むので、手前味噌ですが、便利なツールです。
生成された RTL は、ダメっ子 Quartus でも合成できることを確認しています。
よかったら、使ってみてください。

Qiita にも紹介記事を載せてあります。

UVM で記述した AMBA AXI/APB の VIP (モドキ) も公開しています。
こちらも、よければ、見てみてください。

SystenVerilog で記述した Network On Chip (NoC) も公開しています。
Design Compiler および Vivado でエラボレーションできるところまでは確認しています。
RTL 中で SystemVerilog をどこまで使えるのかの参考になると思います。
(ただし Quartus は知らない。)
UVM を使った検証環境も同梱しているので、UVM を使った検証環境の参考にもなると思います。

12
11
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
11