5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[SystemVerilog] SystemVerilogで拡張されたビット操作機能(論理合成用)

Last updated at Posted at 2019-10-14

SystemVerilogではVerilogに対してビット操作の機能が拡張されています。ここでは論理合成にも使える機能を見ていきましょう。
筆者は頻繁に使うわけではないですが、うまくはまるとコードが非常に簡潔に書けることがあります。

Streaming Operator

最初にStreaming Operatorです。LRMによるとbit streamはUnpack/Pack変換を主用途としているようなのですが、これはシミュレーション用の機能です。おまけ的な機能として(おまけにしては便利すぎる機能なのですが)ビットの順番を変換する機能があり、こちらは論理合成でサポートされています。
Stream Operatorには<<と>>の2種類があるのですが、RTL記述に役立つのは<<のみです。
以下の例のように使用し、<<nのnビット毎に位置を逆に並び替えます。

program top();
  initial begin
    logic [7:0] v0 = 8'b0011_1101; // 8'h3d
    logic [7:0] v1, v2;

    v1 = {<<1{v0}}; // Bit reverse (8'b1011_1100)
    v2 = {<<4{v0}}; // 4 Bit chunk reverse (8'b1101_0011 or 8'hd3)

    $display("%08b", v1);
    $display("%08b", v2);
  end
endprogram

ベクタのビット選択

Verilog/Systemverilogではベクタから複数ビットを選択するのに変数が使用できないため、以下のようなコードはコンパイルエラーとなります。

module u1(output logic [3:0] vout,
          input logic [7:0] vin,
          input logic [2:0] sel // Assuming ranges 0 to 4
         );
  assign vout = vin[sel + 3 : sel]; // Verilog/SystemVerilog do not support!!
endmodule

同等の機能を実現するには以下のようにコードを書き直す必要があります。ちょっと面倒ですね。

module u1(output logic [3:0] vout,
         input logic [7:0] vin,
         input logic [2:0] sel // Assuming ranging 0 to 4
         );
  always_comb begin
    for (int i = 0; i < 4; i++) begin
      vout[i] = vin[sel + i];
    end
  end
endmodule

SystemVerilogでは以下のように簡潔に書くことができます。n+:mで、ベクタのnビット目からmビット幅を表します。同様にn-:mでnビット目からマイナス方向にmビット幅を表します。
nには変数を使えますがmは定数でなければなりません。

module u1(output logic [3:0] vout,
          input logic [7:0] vin,
          input logic [2:0] sel // Assuming ranging 0 to 4
         );
  assign vout = vin[sel +: 4]; // i.e. vout[3:0] = vin[sel + 3 : sel]
endmodule

上記は代入式の右辺に使用していますが、左辺にも使用できます。

module u1(output logic [7:0] vout,
          input logic [3:0] vin,
          input logic [2:0] sel // Assuming ranging 0 to 4
         );
  always_comb begin
    vout = 0;
    vout[sel +: 4] = vin; // i.e. vout[sel + 3 : sel] = vin[3:0]
  end
endmodule

複合技

上記の2つを利用して、さらに複雑なビット操作ができます。以下は32bit x 4set=128bit長のデータを受け取り、
32bit毎にエンディアンを変換して出力するモジュールの例です。

module EndianConverter(output logic[127:0] vout,
                       input logic[127:0] vin);
  localparam BIT_CHUNK = 32;
  always_comb begin
    for (int i = 0; i < 127; i += BIT_CHUNK) begin
      vout[i +: BIT_CHUNK] = {<<8{vin[i +: BIT_CHUNK]}};
    end
  end
endmodule

上記モジュールのテストプログラムです。

module top;
  logic [127:0] vin;
  logic [127:0] vout;

  EndianConverter u1(.vout(vout), .vin(vin));

  initial begin
    vin = 128'h01234567_89abcdef_01020304_05060708;
    #1ns;
    $display("VIN:  %032h", vin);
    $display("VOUT: %032h", vout); // 67452301_efcdab89_04030201_08070605
    $display("");
    vin = 128'h090a0b0c_0d0e0f00_11121314_15161718;
    #1ns;
    $display("VIN:  %032h", vin);
    $display("VOUT: %032h", vout); // 0c0b0a09_000f0e0d_14131211_18171615
  end
endmodule

参考文献

"11.4.14 Streaming operators (pack/unpack)". 1800-2017 - IEEE Standard for SystemVerilog--Unified Hardware Design, Specification, and Verification Language. pp. 274-278.
"11.5.1 Vector bit-select and part-select addressing". 1800-2017 - IEEE Standard for SystemVerilog--Unified Hardware Design, Specification, and Verification Language. pp. 279-281.

5
3
0

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
5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?