SystemVerilogにおけるlogicとregに関するまとめ
SystemVerilogでのlogicとregに関するまとめ
よくある解釈
Verilogではassign文ではwire、always文ではregと使い分ける必要があったが、SystemVerilogではlogicという型が増設されて、どちらも同じlogicを使えるようになった。
という説明がされることが多いです。RTLを記述するためにはこれでも問題はないですが、厳密には少し異なるところがあります。Behavor modelなどを記述する場合はもう少し正確なところを知っておく必要が出てきます。
Verilogの仕様
Verilogでは大きく分けてデータ型には、「ネット(Nets)」と「変数(Variables)」の2つに分類され、それぞれ異なる振る舞いと代入方法を持ちます。
Net型にはwire, tri, wor, wand, trireg, supply0, supply1があり、
Variable型にはreg, time, integer, real ,realtimeがあります。
Variableは値を保持する型であり、手続き型代入(Procedural Assignment)で代入を行うことができます。Procedural Assignmentにはblocking assigment(=),non-blocking assignment(<=)があります。
wireは値を伝搬させる型であり、continuous assignmentで伝搬させる値を指定することができます。
// variableの宣言
integer variable_integer;
reg variable_reg;
initial begin
// blocking assignmentによるvariableへの代入
variable_integer = 0;
variable_reg = 1'b0;
end
// netの宣言
wire net_wire;
// continous assignによるnetへの代入
assign net_wire = variable_or_net;
また、varibleとnetでは宣言時代入の意味が全く異なります。
variableでは時間0での初期値の代入、netへの宣言時代入はcontinous assignmentになります。
// 宣言時代入の意味の違い
reg variable_reg = 1'b0; //初期値の指定
wire net_wire = variable_or_net; // continuous assignment
SystemVerilogの仕様
SystemVerilogでも同じようにVariablesとNetsが存在します。
Variablesは下記のように数多くの型が存在し、大幅に拡張されています。
variable
- 4値(4-state)型
- logic (ユーザー定義サイズ、0, 1, X, Zの4値)
- reg (ユーザー定義サイズ、0, 1, X, Zの4値)
- integer (32ビット符号付き整数、0, 1, X, Zの4値)
- time (64ビット符号なし整数、0, 1, X, Zの4値)
- 2値(2-state)型
- bit (ユーザー定義サイズ、0, 1の2値)
- byte (8ビット符号付き整数、0, 1の2値)
- shortint (16ビット符号付き整数、0, 1の2値)
- int (32ビット符号付き整数、0, 1の2値)
- longint (64ビット符号付き整数、0, 1の2値)
- 非整数型
- real (浮動小数点数)
- shortreal (短精度浮動小数点数)
- 複合型・その他
- struct
- union
- enum (列挙型)
- string
- chandle (C言語ポインタへのハンドル)
- virtual interface
- class (クラスハンドル)
- event (イベントオブジェクト)
Net型は下記に拡張されています。
net
- supply0
- supply1
- tri
- triand
- trior
- trireg
- tri0
- tri1
- uwire
- wire
- wand
- wor
ここで、まずVerilogからの大きな変更点として、Systemverilogではvariableに対してcontinous assignを行うことができます。すなわち
reg variable_reg;
assign variable_reg = variable_or_net;
int variable_int;
assign variable_int = variable_or_net;
という表記が可能です。
logic型にしたから、logicに対するcontinuous assignmentができるようになったということではなく、variableすべてに対してcontinous assignmentができるようになった、というのが本当の変更点です。
(ただしdriverが1つの場合に限ります。2つ以上のdriverがある場合にはdrive strengthによるレベル解決を行う仕様がありますが、これはnetでしか使用できません。)
では、logic型とは何かというと、実はreg型と全く同じ機能を持つ型となっています。continuous assignmentにvariableが使えるようになった結果、regという名称が誤解を生みやすい不適切な名前となったために新たな名称の型が作られた。ということになります。
また、netがさらにデータ型を持つよう拡張されています。データ型を省略した場合はlogic型になります。
wire implicit_wire_logic; //これはwire logic implicit_wire_logic;と同じ
wire logic wire_logic;
wire integer wire_integer;
wire reg wire_reg;
これは、wire型で伝搬する値に使えるデータ型を指定するものです。4値型のデータ型が指定可能です。
ただし、reg型は禁止となっています。(IEEE Std 1800-2017 6.7.1)
wire reg wire_reg; // これは禁止されている
多分紛らわしすぎるから禁止されていると思われます。この場合はwire logicを使う必要があります。
wire型に型指定を追加することで、user定義型を持つwireを作ったりすることもできます。
continous assignにvariableが使えるようになったため、netの存在意義はnetでしかできない機能を実現するためと、verilogとの互換性のためにあると思われます。netでしかできない機能は複数driverでの駆動、strength解決や、triregによりchargeの処理、inoutポートの処理が含まれます。
varibleとnetでは宣言時代入の意味はverilogとほぼ同等で、variableでは変数の初期化、netへの宣言時代入はcontinous assignmentになります。
すなわち
logic variable_logic = 1'b0;
は初期化であり、continous assignmentではありません。
また、SystemVerilogでは初期化は時間0より前で行われるため、Verilogとは若干意味が変わっています。
まとめ
SystemVerilogではvariable型に対するcontinous assignが可能になった。logicはregと同等のデータ型である。ただし、wireに対するデータ型指定としてはregは使用禁止であり、代わりにlogicが使える。
Discussion