Verilog

Verilogは、IEEE 1364として標準化されているハードウェア記述言語である。最も重要な用途は、デジタル回路をレジスタ転送レベルで設計・検証することである。また、アナログ回路や混合信号回路の検証や、遺伝子回路の設計にも使用されている。

もともとVerilogは電子回路シミュレーションを行うシミュレータであり、それに使用する言語であった。文法は、プログラミング言語のC言語やPascalに似ている。

後継言語はSystemVerilogで、Verilogの機能的な上位互換である。System Verilogの規格と統合して、「IEEE/IEC 62530:2011 SystemVerilog - Unified Hardware Design, Specification, and Verification Language」と呼ばれる標準になっている。

1. 概要
-----

Verilogのようなハードウェア記述言語は、ソフトウェアプログラミング言語に似ている。これは、信号の伝達時間や信号強度を記述するコードから作られているからである。Verilogには、ブロッキング代入とノン・ブロッキング代入という2種類の代入演算子がある。ノン・ブロッキング代入文のおかげで、設計者はステートマシンの更新を一時変数を宣言せずに書くことができるようになった。これらの概念はVerilog言語のセマンティックの一部となっているため、設計者は大規模な回路の記述を比較的にコンパクトで簡潔な形式ですばやく書くことができる。Verilogが開発された当初、回路設計者はグラフィカルな回路図入力ソフトウェアや、ドキュメントと電子回路シミュレータのためだけに書かれた特殊なソフトウェアを使っていたため、複雑な回路を簡潔に記述できるVerilogは、極めて大きな生産性の向上をもたらした。

Verilogの設計者は、言語の構文を、工学分野のソフトウェア開発で当時すでに広く普及していたC言語と似たものにしたいと考えた。そのため、C言語のように、Verilogの識別子は ケース・センシティブであり、基本的なプリプロセッサーを持っている。制御フローのキーワードはC言語と同一であり、演算子の優先順位もC言語と互換性がある。構文の違いとしては、変数宣言にビット幅が必要であることや、手続きブロックの宣言の相違があり、その他多数の細かな違いがある。Verilogは変数に固定サイズを与えなければならないが、C言語の場合はサイズは変数の「型」から推定される。

Verilogのコードはモジュールの階層から構成する。モジュールは設計の階層をカプセル化し、他のモジュールとは、宣言された入力、出力、必要に応じて双方向ポートを使用して通信する。モジュールの内部では、net/変数の宣言、並行または逐次のステートメントブロック、他のモジュールのインスタンスなどの、あらゆる組み合わせが記述できる。逐次的な文は、begin/endブロック内に配置し、ブロック内では逐次的に実行される。しかし、ブロック自体は並列に実行されるため、この特徴によりVerilogはデータフロー言語となっている。

次に、配線を示すwire、記憶素子を示すregとサブモジュールのリストなどを定義する。さらに、続いてその動作を規定するステートメントやステートメントをグループにしたブロック群を定義する。ブロックはbeginキーワードで始まり、endキーワードで終わる範囲で定義し、ブロック内はステートメントが並列に実行される。逐次実行したい場合は、ブロッキング代入を使うか、クロックのタイミングを待つ書き方をする。各ブロックは並列に実行される。Verilogの'wire'の概念は信号の値  と信号の強度からなる。このシステムのおかげで、共有信号線の抽象的なモデリングが可能になり、複数のソースで共通の回路網を駆動することが可能になった。wireが複数のドライバーを持つ時、wireの値はソースドライバーの関数と強度で解決される。

Verilog言語の文のサブセットは、合成可能である。RTLとして知られる合成可能なコーディングスタイルを使用して書かれたVerilogのモジュールは、合成ソフトウェアを使用することで物理的に実装することができる。合成ソフトウェアは、アルゴリズムを用いて、Verilogのソースをネットリストに変換する。ネットリストとは、特定のFPGAやVLSI技術で利用可能な基本ゲートのみからなるソースコードと論理的に等価な記述である。さらにネットリストに修正を加えることで、究極的には電子回路製造の設計図を生成することが可能である。

「Verilog-HDL」という表記が用いることがあるが、IEEEなどの文書では「Verilog」と「HDL」との間にハイフンが入らない「Verilog HDL」のように表記されている。

2. 歴史
-----

2.1. 始まり
--------

Verilogは、ゲートウェイ・デザイン・オートメーション社のフィル・ムーアビーが、ハードウェア・モデリング言語とそのためのシミュレータとして1984年頃開発した。その後、同社は1990年にケイデンス・デザイン・システムズが買収した。ケイデンスは、現在も大元のゲートウェイVerilogおよびVerilog-XL論理シミュレータの版権を持っている。

2.2. 標準化
--------

同種のハードウェア記述言語であるVHDLの台頭に対し、ケイデンスはVerilogの規格を公開し標準化する道をとり、OVIと呼ばれる組織へ版権の一部を移譲した。OVI LRM2.0に準拠したVerilogシミュレータとしてSimucad社が開発したSILOS IIIは、1993年には日本で発売されていたインターフェース 1993年12月号。それと前後した1993年6月には、IEEE1364として標準化が開始されたインターフェース 1993年12月号。その後、Verilogの規格がIEEEに提出され、IEEE 1364-1995として標準化された。この標準は、Verilog-1995と呼ばれる。なお、OVIはその後Accelleraという組織になっている。

標準化にともない、ケイデンス社以外の会社やフリーソフトのVerilogシミュレータが登場するようになった。

2.3. Verilog 2001
-----------------

オリジナルのVerilog標準に対する不満を解消するために、Verilog-95に対する拡張がなされた。この拡張はVerilog 2001といいIEEE 1364-2001になった。VHDLにあったgenerate文に対応し、大規模設計が容易になった。

2.4. Superlog/System Verilog
----------------------------

やがてOpenVeraやVerisityのE言語のようなハイ・レベルの検証言語が登場する。このことはその種の機能を盛り込んだVerilog、すなわちコデザイン・オートメーション社によるSuperlogの開発を促すこととなった。コデザイン・オートメーション社は、シノプシスによってその後買収された。SuperlogとVeraの基本部分はAccelleraに寄贈され、次のIEEE標準としてSystemVerilogとVerilogとに分かれた。

2.5. Verilog-AMS
----------------

言語の最新のバージョンは、アナログ素子および回路の機能記述を行うための言語であるVerilog-Aを包含し、さらにアナログ／デジタルのミックス・シグナル・モデルへの対応もなされており、Verilog-AMSという。

2.6. Verilog 2005
-----------------

IEEE 1364-2005 として規格化。その際、上位互換の SystemVerilog IEEE 1800-2005 も作った。

2.7. System Verilog 2011
------------------------

IEEE/IEC 62530-2011 - SystemVerilog – Unified Hardware Design, Specification, and Verification Language として、Verilog HDLとSystem Verilogの文書を一本化した。

3. 例
----

簡単な2フリップフロップの例を以下に示す。 module toplevel; input clock; input reset;

reg flop1; reg flop2;

always @  if  begin flop1 <= 0; flop2 <= 1; end else begin flop1 <= flop2; flop2 <= flop1; end endmodule<WtXmlEndTag />Verilogにおける"="演算子は、普通の手続き型言語とは異なる、ハードウェア記述言語としてのもう1つの側面である。この演算子は「ノンブロッキング」代入文として知られ、alwaysブロックが実行されるまでアクションは登録されない。つまり、代入文を書いた順序は無関係であり、必ず同じ結果が生じる。そのため、flop1とflop2はクロックごとに値がスワップされることになる。

もう1つの代入演算子である"="は、ブロッキング代入文と呼ばれる。"="による代入が行われると、代入先の値は即座に更新される。もし上の例で"="の代わりにブロッキング演算子の"="を使用したとすると、flop1とflop2の値はスワップされず、手続き型プログラミング言語のように、コンパイラはflop1の値をflop2の値にセットするのだと解釈する。

モジュールはキーワードmoduleで始まる。その後のDiv20xが名前を示し、続く括弧内は端子リストである。6個の端子があり、それぞれの端子の入出力方向はモジュール中のポート宣言で指定される。最後のendmoduleでモジュールの終了である。モジュール内には、パラメータ宣言、ポート宣言、レジスタ宣言、イベント宣言、ネット宣言、ステートメントなどを記述する。

// // 表題 イネーブル付20段カウンター // module Div20x ; // regと明記していない、他の信号はwire型。 // ポート宣言したwire型信号のネット宣言は省略可能であり、省略することも多い。

// パラメータ宣言 parameter length = 20; // カウント段数 parameter count_zero = 5'b00000; // 5bit幅,2進数の0を表す parameter count_one = 5'b00001; // 5bit幅,2進数の1を表す parameter size = 5; // bit幅,基数の指定を省略すると32bit,10進数になる。

// always文。resetやclock信号の変化に同期し並列に実行される always @  begin if  begin // 非同期リセット count <= count_zero; end else begin if  begin // イネーブル if  begin count <= count_zero; end else begin count <= count + count_one; end end end end

// assign文。tcの値は実行中、継続的に値が与る assign tc = ); endmodule<WtXmlEndTag />

ポート宣言やレジスタ宣言での[a:b]のような形式は、束線を示す。例えば[3:0]であれば配線が4本あることになる。always節は、括弧内の信号を指定した条件に変化があったときに実行される。posedgeは信号が0から1に変化した場合を指定する。orは括弧内の信号のどれか1つでも変化した場合を指定する。上記のように、resetに合わせてreg型を初期化するのが基本的なデザインパターンである。

ディレイの例は以下の通りである。 ... reg a, b, c, d; wire e; ... always @ begin a = b & e; b = a | b;

5 c = b;d = #6 c ^ e; end<WtXmlEndTag />上記のalways節は、もう1つの使い方を示している。たとえば、上の例では、リストに含まれる要素が変化したタイミングでいつでもalways節が実行される。いずれかの変数が変化すると、即座に新しい値がaに代入される。ブロッキング代入文を使用しているため、bにはその代入後に新しい値が代入される。5単位時間のディレイの後、cにbの値が代入されると同時に、c ^ eの値が計算され、見えない保管場所に一時的に保存される。6単位時間後、保管されていた値がdに代入される。

プロセス内で操作される信号は、reg型を持つ必要がある。また、プロセスの外で操作される信号はwire型を持たなければならない。この時使われるregという名前は、必ずしもハードウェアのレジスタを意味するわけではない。

4. 定数の定義
--------

Verilogにおける定数の定義では、追加のビット幅パラメータがサポートされている。基本的な構文は次のとおりである。

'

例:

12'h123 — 16進数の123
20'd44 — 10進数44 (20ビットを使用。未使用桁への0の付加は自動で行われる）