Verilog

Verilog（ヴェリログ）は、IEEE 1364として標準化されているハードウェア記述言語（Hardware Description Language; HDL）である。最も重要な用途は、デジタル回路をレジスタ転送レベルで設計・検証することである。また、アナログ回路や混合信号回路（英語版）の検証や、遺伝子回路（英語版）の設計にも使用されている。 もともとVerilogは電子回路シミュレーションを行うシミュレータであり、それに使用する言語であった。文法は、プログラミング言語のC言語やPascalに似ている。 後継言語はSystemVerilogで、Verilogの機能的な上位互換である。System Verilogの規格と統合して、「IEEE/IEC 62530:2011 SystemVerilog - Unified Hardware Design, Specification, and Verification Language」と呼ばれる標準になっている。 Verilogのようなハードウェア記述言語は、ソフトウェアプログラミング言語に似ている。これは、信号の伝達時間や信号強度を記述するコードから作られているからである。Verilogには、ブロッキング代入とノン・ブロッキング代入という2種類の代入演算子（英語版）がある。ノン・ブロッキング代入文のおかげで、設計者はステートマシンの更新を一時変数（英語版）を宣言せずに書くことができるようになった。これらの概念はVerilog言語のセマンティックの一部となっているため、設計者は大規模な回路の記述を比較的にコンパクトで簡潔な形式ですばやく書くことができる。Verilogが開発された当初（1984年）、回路設計者はグラフィカルな回路図入力（英語版）ソフトウェアや、ドキュメントと電子回路シミュレータのためだけに書かれた特殊なソフトウェアを使っていたため、複雑な回路を簡潔に記述できるVerilogは、極めて大きな生産性の向上をもたらした。 Verilogの設計者は、言語の構文を、工学分野のソフトウェア開発で当時すでに広く普及していたC言語と似たものにしたいと考えた。そのため、C言語のように、Verilogの識別子は ケース・センシティブであり、基本的なプリプロセッサーを持っている（ただし、ANSI C/C++のものほどは洗練されていない）。制御フローのキーワード（if/else、for、while、caseなど）はC言語と同一であり、演算子の優先順位もC言語と互換性がある。構文の違いとしては、変数宣言にビット幅が必要であることや、手続きブロックの宣言の相違（カーリー・ブレイス{}の代わりにbegin/endを使用する）があり、その他多数の細かな違いがある。Verilogは変数に固定サイズを与えなければならないが、C言語の場合はサイズは変数の「型」から推定される（たとえば、integer型は8ビットであると）。 Verilogのコードはモジュールの階層（英語版）から構成する。モジュールは設計の階層をカプセル化し、他のモジュールとは、宣言された入力、出力、必要に応じて双方向ポートを使用して通信する。モジュールの内部では、net/変数の宣言（wire、reg、integerなど）、並行または逐次のステートメントブロック、他のモジュールのインスタンス（サブ階層）などの、あらゆる組み合わせが記述できる。逐次的な文は、begin/endブロック内に配置し、ブロック内では逐次的に実行される。しかし、ブロック自体は並列に実行されるため、この特徴によりVerilogはデータフロー言語となっている。 次に、配線を示すwire、記憶素子を示すregとサブモジュールのリストなどを定義する。さらに、続いてその動作を規定するステートメントやステートメントをグループにしたブロック群を定義する。ブロックはbeginキーワードで始まり、endキーワードで終わる範囲で定義し、ブロック内はステートメントが並列に実行される。逐次実行したい場合は、ブロッキング代入を使うか、クロックのタイミングを待つ書き方をする。各ブロックは並列に実行される。Verilogの'wire'の概念は信号の値 (4状態："1、0、floating、undefined") と信号の強度（強い、弱いなど）からなる。このシステムのおかげで、共有信号線の抽象的なモデリングが可能になり、複数のソースで共通の回路網を駆動することが可能になった。wireが複数のドライバーを持つ時、wireの（読み取り可能な）値はソースドライバーの関数と強度で解決される。 Verilog言語の文のサブセットは、合成可能である。RTL（register-transfer level; レジスタ転送レベル）として知られる合成可能なコーディングスタイルを使用して書かれたVerilogのモジュールは、合成ソフトウェアを使用することで物理的に実装することができる。合成ソフトウェアは、アルゴリズムを用いて、（抽象的な）Verilogのソースをネットリストに変換する。ネットリスト（英語版）とは、特定のFPGAやVLSI技術で利用可能な基本ゲート（AND、OR、NOT、フリップフロップなど）のみからなるソースコードと論理的に等価な記述である。さらにネットリストに修正を加えることで、究極的には（ASICのフォトマスクのセットやFPGAのビットストリームなどの）電子回路製造の設計図を生成することが可能である。 「Verilog-HDL」という表記が用いることがあるが、IEEEなどの文書では「Verilog」と「HDL」との間にハイフンが入らない「Verilog HDL」のように表記されている。 Verilogは、ゲートウェイ・デザイン・オートメーション（英語版）社のフィル・ムーアビーが、ハードウェア・モデリング言語とそのためのシミュレータとして1984年頃開発した。その後、同社は1990年にケイデンス・デザイン・システムズが買収した。ケイデンスは、現在も大元のゲートウェイVerilogおよびVerilog-XL論理シミュレータの版権を持っている。 同種のハードウェア記述言語であるVHDLの台頭に対し、ケイデンスはVerilogの規格を公開し標準化する道をとり、OVI（Open Verilog International）と呼ばれる組織へ版権の一部を移譲した。OVI LRM2.0に準拠したVerilogシミュレータとしてSimucad社が開発したSILOS IIIは、1993年には日本で発売されていた。それと前後した1993年6月には、IEEE1364として標準化が開始された。その後、Verilogの規格がIEEEに提出され、IEEE 1364-1995として標準化された。この標準は、Verilog-1995と呼ばれる。なお、OVIはその後Accelleraという組織になっている。 標準化にともない、ケイデンス社以外の会社やフリーソフトのVerilogシミュレータが登場するようになった。 オリジナルのVerilog標準に対する不満を解消するために、Verilog-95に対する拡張がなされた。この拡張はVerilog 2001といいIEEE 1364-2001になった。VHDLにあったgenerate文に対応し、大規模設計が容易になった。 やがてOpenVeraやVerisityのE言語のようなハイ・レベルの検証言語が登場する。このことはその種の機能を盛り込んだVerilog、すなわちコデザイン・オートメーション社によるSuperlogの開発を促すこととなった。コデザイン・オートメーション社は、シノプシスによってその後買収された。SuperlogとVeraの基本部分はAccelleraに寄贈され、次のIEEE標準としてSystemVerilogとVerilogとに分かれた。 言語の最新のバージョンは、アナログ素子および回路の機能記述を行うための言語であるVerilog-Aを包含し、さらにアナログ／デジタルのミックス・シグナル・モデルへの対応もなされており、Verilog-AMSという。 IEEE 1364-2005 として規格化。その際、上位互換の SystemVerilog IEEE 1800-2005 も作った。 IEEE/IEC 62530-2011 - SystemVerilog – Unified Hardware Design, Specification, and Verification Language として、Verilog HDLとSystem Verilogの文書を一本化した。 簡単な2フリップフロップの例を以下に示す。 module toplevel(clock,reset); input clock; input reset; reg flop1; reg flop2; always @ (posedge reset or posedge clock) if (reset) begin flop1 <= 0; flop2 <= 1; end else begin flop1 <= flop2; flop2 <= flop1; end endmodule Verilogにおける"<="演算子は、普通の手続き型言語とは異なる、ハードウェア記述言語としてのもう1つの側面である。この演算子は「ノンブロッキング」代入文として知られ、alwaysブロックが実行されるまでアクションは登録されない。つまり、代入文を書いた順序は無関係であり、必ず同じ結果が生じる。そのため、flop1とflop2はクロックごとに値がスワップされることになる。 もう1つの代入演算子である"="は、ブロッキング代入文と呼ばれる。"="による代入が行われると、代入先の値は即座に更新される。もし上の例で"<="の代わりにブロッキング演算子の"="を使用したとすると、flop1とflop2の値はスワップされず、手続き型プログラミング言語のように、コンパイラはflop1の値をflop2の値にセットするのだと解釈する（その結果、flop2とflop1の値にセットするという冗長な論理は無視されることになる）。 モジュールはキーワードmoduleで始まる。その後のDiv20xが名前を示し、続く括弧内は端子リストである。6個の端子があり、それぞれの端子の入出力方向はモジュール中のポート宣言（inputとoutput）で指定される。最後のendmoduleでモジュールの終了である。モジュール内には、パラメータ宣言、ポート宣言、レジスタ宣言、イベント宣言、ネット宣言、ステートメントなどを記述する。 // // 表題 イネーブル付20段カウンター // module Div20x ( // ポート宣言（外部から本モジュールへの接続を定義する） input clock, // クロック input reset, // リセット（正論理, ハイアクティブ） input cet, // カウンターとTC出力のイネーブル input cep, // カウンターのみのイネーブル output reg [size - 1:0] count, // 束線を示す。この場合5bit幅 // alwaysまたはinitialブロックでドライブする信号は // reg型でなければならない output tc); // 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 @ (posedge clock or posedge reset) begin if (reset) begin // 非同期リセット count <= count_zero; end else begin if (cet || cep) begin // イネーブル if (count == length - 1) begin count <= count_zero; end else begin count <= count + count_one; end end end end // assign文。tcの値は実行中、継続的に値が与る assign tc = (cet && (count == length - 1)); endmodule ポート宣言やレジスタ宣言での[a:b]のような形式は、束線（多くはバス）を示す。例えば[3:0]であれば配線が4本あることになる。always節は、括弧内の信号を指定した条件に変化があったときに実行される。posedgeは信号が0から1に変化した場合を指定する。orは括弧内の信号のどれか1つでも変化した場合を指定する。上記のように、resetに合わせてreg型を初期化するのが基本的なデザインパターンである。 ディレイの例は以下の通りである。 ... reg a, b, c, d; wire e; ... always @(b or e) begin a = b & e; b = a | b; #5 c = b; d = #6 c