Verilog

出典: フリー百科事典『ウィキペディア(Wikipedia)』
移動先: 案内検索

テンプレート:Infobox プログラミング言語 Verilog(ヴェリログ)は、デジタル回路の設計用の論理シミュレータであり、そこで使用するハードウェア記述言語でもある。両者を区別する場合、言語の方を「Verilog HDL」と呼ぶ場合もある。 言語の開発にあたっては、ソフトウェア開発者にも受け入れられるようにプログラム言語C言語Pascalの要素を取り入れたものとなっている。IEEE 1364-2005として標準化している。後継言語はSystemVerilog

概要

CPU 上で動くプログラミング言語との相違点として、文(ステートメント)の実行は並列実行を基本とし、逐次実行も記述できる。これは、並列動作する電子回路を記述する言語だからである。また、Verilogモデルは実際のハードウェアの構成に近いモジュールの階層を構成できる。モジュールではまず、入力/出力端子、必要に応じて双方向端子を宣言する。次に、配線を示すwire、記憶素子を示すregとサブモジュールのリストなどを定義する。さらに、続いてその動作を規定するステートメントやステートメントをグループにしたブロック群を定義する。ブロックはbeginキーワードで始まり、endキーワードで終わる範囲で定義し、ブロック内はステートメントが並列に実行される。逐次実行したい場合は、ブロッキング代入を使うか、クロックのタイミングを待つ書き方をする。各ブロックは並列に実行される。

Verilog 言語には、論理合成を適用して実際の回路に変換可能な記述(設計機能)とそうではない部分(検証機能)がある。検証機能はテストやデバッグ時にシミュレータ上で実行する際に使われる。設計中のモジュールが全て合成可能なステートメントだけで記述している場合、適切なソフトウェアを用いて半導体チップの回路、さらにレイアウトデータまで変換することができる。

「Verilog-HDL」という表記が用いられることがあるが、正しくは「Verilog」と「HDL」との間にハイフンが入らない「Verilog HDL」である。

歴史

始まり

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

標準化

同種のハードウェア記述言語であるVHDLの台頭に対し、ケイデンスはVerilogの規格を公開し標準化する道をとった。すなわちケイデンスはOVI(Open Verilog International)という組織へ版権の一部を移譲した。その後VerilogをIEEEに提出しIEEE 1364-1995[1]として規格化し、Verilog-1995と呼ぶ。なおOVIはその後Accelleraという組織になっている。

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

Verilog 2001

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

Superlog/System Verilog

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

Verilog-AMS

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

Verilog 2005

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

文法(抜粋)

キーワード

module(入出力端子リスト) .. endmodule
この範囲が一つの回路モジュールとなる。
begin .. end
汎用のブロック範囲。
initial
モジュールの中で一回だけ実行されるブロック
always @(イベント式)
イベント式にあるイベントが発生するたびに実行されるブロック
if (条件式) else ..
条件判断文
for(変数定義;条件式;変移)
繰り返し処理
while(条件式)
繰り返し処理
input、output
入力端子、出力端子の定義。モジュールの最初に記述。
reg、wire
内部配線がレジスタ(値を記憶)か単なる配線かの指定。
=
always 内ではブロッキング代入(逐次実行。詳細は後述する)
<=
always 内のノンブロッキング代入(詳細は後述する)
assign
継続的代入。電気回路の配線接続に相当。
function
assign 用の関数定義
task
always 用の関数定義
and、or、xor(exor)、nand、nor(exnor)、xnor、not
基本ゲート
//、/* .. */
コメント。実行には影響しない。

オペレータ(演算子)

+、-、*、/
加減乗除(算術演算)
%
除算の余り(剰余演算)
~、&、|、^、~^(^~)
not、and、or、xor、xnor(ビット演算)
&&、||、!
and、or、not(論理演算)
!=、==、!==、===
等号演算(前者2つが論理等号演算、後者2つがケース等号演算)
{}
連節演算
?:
条件演算

上記のようにbegin、end、functionなどはPascalの文法を、オペレータや条件、繰り返し処理はC言語の文法を流用している。

モジュールの構成

Verilogの最小単位はモジュールである。以下に、カウンタ回路の例で説明する。

モジュールはキーワード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 とintialブロックのこと)内部からドライブする信号はreg型である必要があり、他はwire型である。キーワードregが必ずしもハードウェアであるレジスタを意味するものではない(論理合成の結果、FFを割り当てるとは限らない)。

次にその中のalways節を説明する。always節は、括弧内の信号を指定した条件に変化があったときに実行する。posedgeは信号が0から1に変化した場合を指定する。or は括弧内の信号のどれか1つでも変化した場合を指定する。上記のように reset に合わせて reg型を初期化するのが基本的なデザインパターンである。

always節中の"<="オペレータはCPU上で動く通常の手続き型言語と異なりハードウェア記述言語の特徴の一つであり、「ノン・ブロッキング代入」というものである。シミュレーション実行時に並列に評価する。下記の例の場合、cが変化すると、aとbへの代入を同時に行う(aとbの値を交換する)。これは実際のフリップフロップの動作に近いものである。

    reg a, b;
    wire c; 

    always @(c)
      begin
        a <= b;
        b <= a;
      end

もう一つの代入文である"="はブロッキング代入といい、手続き型言語のように逐次実行する。下記の例の場合、bかeが変化すると、aに代入された後、bに対する代入を行う。

    reg a, b, c, d;
    wire e; 

    always @(b or e)
      begin
        a = b & e;
        b = a | b;
        #5 c = b;
        d = #6 c ^ e;
      end

なお、#は時間経過を示し、シミュレーション時に使う。この場合、単位時間5経過の後、cにbを代入する。またc^eは一時変数に記録し、単位時間6経過後にdに代入する。時間は秒など実時間の指定も出来る。

主要ソフトウェア

シミュレータ

論理合成

  • Design Compiler シノプシス社
  • Encounter RTL Compiler ケイデンス社

lint チェックツール

  • SpyGlass アトレンタ社

関連項目

参照

  1. 1364-1995 IEEE Standard Hardware Description Language Based on the Verilog(R) Hardware Description Language
  2. 1364-2001 IEEE Standard Verilog Hardware Description Language
  3. 1364-2005 IEEE Standard for Verilog Hardware Description Language
テンプレート:Link GA