verilog チュートリアル
Verilogを使い始める
サーチ…
備考
Verilogは、ビヘイビアレベルまたはレジスタ転送レベルでデジタル回路を設計、シミュレート、検証するために使用されるハードウェア記述言語(HDL)です。 「伝統的な」プログラミング言語と区別する理由から注目すべき点は次のとおりです。
- 割当てには、それぞれ独自の用途とセマンティクスを持つ2種類の割当て、ブロッキングとノンブロッキングがあります。
- 変数は、1ビット幅または明示的な幅として宣言する必要があります。
- デザインは階層的で、目的の動作を持つモジュールをインスタンス化することができます。
- シミュレーション(通常は合成ではない)では、
wire
変数は0,1、浮動(z
)、および未定義(x
)の4つの状態のいずれかになります。
バージョン
バージョン | 発売日 |
---|---|
Verilog IEEE-1364-1995 | 1995-01-01 |
Verilog IEEE-1364-2001 | 2001年9月28日 |
Verilog IEEE-1364.1-2002 | 2002-12-18 |
Verilog IEEE-1364-2005 | 2006-04-07 |
SystemVerilog IEEE-1800-2009 | 2009-12-11 |
SystemVerilog IEEE-1800-2012 | 2013-02-21 |
インストールまたはセットアップ
Verilogのセットアップやインストールの詳細な手順は、多くのVerilogツールがあるため、使用するツールによって異なります。
前書き
Verilogは、電子システムをモデル化するために使用されるハードウェア記述言語(HDL)です。最も一般的には、抽象化のレジスタ転送レベル(RTL)での電子システムを記述します。また、アナログ回路と混合信号回路の検証にも使用されます。その構造と主な原則(後述)は、電子システムを記述し、首尾よく実装するように設計されています。
- 剛性
電子回路は固定構造を持つ物理的実体であり、Verilogはそれに適合しています。モジュール(モジュール)、ポート(入力/出力/入出力)、接続(ワイヤ)、ブロック(@常に)、レジスタ(reg)はすべてコンパイル時に固定されます。エンティティと相互接続の数は動的に変化しません。チップ構造(合成用)を表す最上位には常に常に「モジュール」があり、検証用にシステムレベルには「モジュール」があります。 - 平行
物理チップ内の固有の同時操作は、常に(ほとんどのcommmon)、初期およびfork / joinブロックによって言語で模倣されます。
module top();
reg r1,r2,r3,r4; // 1-bit registers
initial
begin
r1 <= 0 ;
end
initial
begin
fork
r2 <= 0 ;
r3 <= 0 ;
join
end
always @(r4)
r4 <= 0 ;
endmodule
上記のステートメントはすべて、同じ時間単位内で並行して実行されます。
タイミングと同期
Verilogは、回路の時間的性質を記述するためのさまざまな構成をサポートしています。回路のタイミングと遅延は、Verilogで、たとえば#delay構造で実装できます。同様に、Verilogは、同期回路と非同期回路、およびフロップ、ラッチ、コンビナトリアルロジックなどのコンポーネント(さまざまなコンストラクト、たとえば「常に」ブロックを使用)にも対応しています。 1組のブロックは、共通クロック信号を介して同期させることもできるし、特定の組の入力に基づいてブロックをトリガすることもできる。#10 ; // delay for 10 time units always @(posedge clk ) // synchronous always @(sig1 or sig2 ) // combinatorial logic @(posedge event1) // wait for post edge transition of event1 wait (signal == 1) // wait for signal to be 1
不確実性
Verilogは電子回路に内在する不確実性のいくつかをサポートしています。 「X」は、回路の未知の状態を表すために使用される。 「Z」は、回路の非駆動状態を表すために使用される。reg1 = 1'bx; reg2 = 1'bz;
抽象化
Verilogは異なる抽象レベルでの設計をサポートしています。デザインの最高レベルの抽象化レベルはResister transfer Level(RTL)で、次はゲートレベルとセルレベルの下限(User Define Primitives)で、RTL抽象化が最も一般的です。 Verilogは、検証のために主に使用される設計の構造的実現に関係なく、抽象化の動作レベルもサポートしています。
// Example of a D flip flop at RTL abstraction
module dff (
clk , // Clock Input
reset , // Reset input
d , // Data Input
q // Q output
);
//-----------Input Ports---------------
input d, clk, reset ;
//-----------Output Ports---------------
output q;
reg q;
always @ ( posedge clk)
if (~reset) begin
q <= 1'b0;
end else begin
q <= d;
end
endmodule
// And gate model based at Gate level abstraction
module and(input x,input y,output o);
wire w;
// Two instantiations of the module NAND
nand U1(w,x, y);
nand U2(o, w, w);
endmodule
// Gate modeled at Cell-level Abstraction
primitive udp_and(
a, // declare three ports
b,
c
);
output a; // Outputs
input b,c; // Inputs
// UDP function code here
// A = B & C;
table
// B C : A
1 1 : 1;
0 1 : 0;
1 0 : 0;
0 0 : 0;
endtable
endprimitive
Verilogの主な使用例は3つあります。コードの構造とその解釈を決定し、使用されるツールセットを決定します。 3つのアプリケーションはすべて、Verilogデザインの実装を成功させるために必要です。
- 物理設計/バックエンド
ここでは、Verilogは論理設計を実装する相互接続ゲートのマトリックスとして設計を主に見るために使用されます。 RTL /ロジック/デザインは、合成 - >配置 - >クロックツリー構築 - >ルーティング - > DRC - > LVS - >テープアウトまでのさまざまなステップを経ます。正確なステップおよびシーケンスは、実装の正確な性質に基づいて異なります。 - シミュレーション
このユースケースでは、主要な目的は、仕様に従って設計を検証するためのテストベクトルを生成することです。このユースケースで記述されたコードは、合成可能である必要はなく、検証領域内にとどまります。ここのコードはfor / while / doループなどの一般的なソフトウェア構造によく似ています。 - 設計
設計には一般的に抽象化のRTLレベルで回路の仕様を実装することが含まれます。検証のためにVerilogコードが与えられ、物理的な実装のために完全に検証されたコードが与えられます。このコードは、Verilogの合成可能な構造体のみを使用して記述されています。特定のRTLコーディングスタイルは、シミュレーションと合成の不一致を引き起こす可能性があり、それらを避けるために注意が必要です。
主な実装フローは2つあります。また、Verilogコードの記述方法や実装方法にも影響します。特定のスタイルのコーディングと特定の構造は、一方のフローで他方のフローより適しています。
- ASICフロー(特定用途向け集積回路)
- FPGAフロー(フィールドプログラマブルゲートアレイ) - FPGAとCPLDを含む
こんにちは世界
この例では、icarus verilogコンパイラを使用しています。
ステップ1:hello.vというファイルを作成する
module myModule();
initial
begin
$display("Hello World!"); // This will display a message
$finish ; // This causes the simulation to end. Without, it would go on..and on.
end
endmodule
ステップ2. icarusを使用して.vファイルをコンパイルします。
>iverilog -o hello.vvp hello.v
-oスイッチは、出力オブジェクトファイルに名前を割り当てます。このスイッチがなければ、出力ファイルはa.outと呼ばれます。 hello.vは、コンパイルされるソースファイルを示します。エラーがない限り、このソースコードをコンパイルすると実際に出力はありません。
ステップ3.このHello World Verilogプログラムをシミュレートする準備が整いました。これを行うには、次のように呼び出します。
>vvp hello.vvp
Hello World!
>
Mac OSX Sierra用イカルスVerilogコンパイラのインストール
- App StoreからXcodeをインストールします。
- Xcodeデベロッパーツールをインストールする
> xcode-select --install
これは、 gcc
やmake
などの基本的なコマンドラインツールを提供します
- Macポートをインストールする
https://www.macports.org/install.php
OSX Sierraインストールパッケージは、Macプラットフォーム上に追加のソフトウェアパッケージをインストールしてアップグレードするオープンソースの方法を提供します。マックのためにyum
かapt-get
を考えてみてください。
- Macポートを使ってイカルスをインストールする
> sudo port install iverilog
- コマンドラインからインストールを確認する
$ iverilog
iverilog: no source files.
Usage: iverilog [-ESvV] [-B base] [-c cmdfile|-f cmdfile]
[-g1995|-g2001|-g2005] [-g<feature>]
[-D macro[=defn]] [-I includedir] [-M depfile] [-m module]
[-N file] [-o filename] [-p flag=value]
[-s topmodule] [-t target] [-T min|typ|max]
[-W class] [-y dir] [-Y suf] source_file(s)
See the man page for details.
$
これで、Mac上の最初のVerilogファイルをコンパイルしてシミュレートする準備が整いました。
Mac OS X Sierraでシミュレーションデータをグラフィカルに表示するためにGTKWaveをインストールする
GTKWaveは、いくつかのグラフィカルデータストレージ標準をサポートするフル機能のグラフィカル表示パッケージですが、 vvp
が出力するフォーマットであるVCDもサポートしています。だから、GTKWaveを拾うには、いくつかのオプションがあります
- http://gtkwave.sourceforge.net/gtkwave.zipに移動してダウンロードしてください 。通常、このバージョンは最新のものです。
- MacPorts( https://www.macports.org/ )をインストールしている場合は、単に
sudo port install gtkwave
実行してください 。これはおそらく依存関係にインストールすることを望みます。このメソッドは、通常、古いバージョンを取得することに注意してください。 MacPortsをインストールしていない場合は、このページでこれを行うためのインストール設定例があります。はい!この方法はソースからGTKWaveを "ビルド"するので、xcode開発ツールをすべて必要とします。
インストールが完了すると、Pythonのバージョンを選択するよう求められることがあります。私はすでに2.7.10をインストールしているので、新しいものを決して選択したことはありません。
この時点で、 gtkwave
コマンドラインからgtkwaveを起動することができます。起動すると、XQuartをインストールまたは更新するように求められることがあります。そうする。私の場合、XQuarts 2.7.11がインストールされています。
注:私は実際にXQuartを正しく取得するためにリブートする必要がありました。そしてgtkwave
もう一度タイプしてアプリケーションが起動します。
次の例では、2つの独立したファイル、つまりテストするテストベンチとモジュールを作成し、gtkwaveを使用してデザインを表示します。
Icarus VerilogとGTKWavesを使用して、デザインをグラフィカルにシミュレーションおよび表示する
この例では、IcarusとGTKWaveを使用しています。 OSx上のこれらのツールのインストール手順は、このページの他の場所で提供されています。
モジュール設計から始めましょう。このモジュールは7セグメント表示のBCDです。私は簡単に壊れやすいものを与えるために鈍的な方法でデザインをコーディングしました。そして、私たちはいつかグラフィカルに固定することができます。したがって、クロック、リセット、BCD値を表す4データ入力、7セグメント表示を表す7ビット出力があります。 bcd_to_7seg.vというファイルを作成し、ソースをその中に置きます。
module bcd_to_7seg (
input clk,
input reset,
input [3:0] bcd,
output [6:0] seven_seg_display
);
parameter TP = 1;
reg seg_a;
reg seg_b;
reg seg_c;
reg seg_d;
reg seg_e;
reg seg_f;
reg seg_g;
always @ (posedge clk or posedge reset)
begin
if (reset)
begin
seg_a <= #TP 1'b0;
seg_b <= #TP 1'b0;
seg_c <= #TP 1'b0;
seg_d <= #TP 1'b0;
seg_e <= #TP 1'b0;
seg_f <= #TP 1'b0;
seg_g <= #TP 1'b0;
end
else
begin
seg_a <= #TP ~(bcd == 4'h1 || bcd == 4'h4);
seg_b <= #TP bcd < 4'h5 || bcd > 6;
seg_c <= #TP bcd != 2;
seg_d <= #TP bcd == 0 || bcd[3:1] == 3'b001 || bcd == 5 || bcd == 6 || bcd == 8;
seg_e <= #TP bcd == 0 || bcd == 2 || bcd == 6 || bcd == 8;
seg_f <= #TP bcd == 0 || bcd == 4 || bcd == 5 || bcd == 6 || bcd > 7;
seg_g <= #TP (bcd > 1 && bcd < 7) || (bcd > 7);
end
end
assign seven_seg_display = {seg_g,seg_f,seg_e,seg_d,seg_c,seg_b,seg_a};
endmodule
次に、このモジュールが正しく動作しているかどうかを確認するテストが必要です。テストベンチのcase文は、私の意見では実際に読みやすく、それが何をするのかがより明確です。しかし、私は同じケースの文章をデザインとテストに入れないようにしました。それは悪い習慣です。むしろ、2つの独立した設計が互いを検証するために使用されている。
以下のコードを使用すると、 $dumpfile("testbench.vcd");
dumpfile $dumpfile("testbench.vcd");
2行が表示され$dumpfile("testbench.vcd");
と$dumpvars(0,testbench);
。これらの行は、デザインのグラフィック解析を実行するために使用されるVCD出力ファイルを作成するものです。それらを残しておくと、VCDファイルが生成されません。 testbench.vというファイルを作成し、ソースをその中に置きます。
`timescale 1ns/100ps
module testbench;
reg clk;
reg reset;
reg [31:0] ii;
reg [31:0] error_count;
reg [3:0] bcd;
wire [6:0] seven_seg_display;
parameter TP = 1;
parameter CLK_HALF_PERIOD = 5;
// assign clk = #CLK_HALF_PERIOD ~clk; // Create a clock with a period of ten ns
initial
begin
clk = 0;
#5;
forever clk = #( CLK_HALF_PERIOD ) ~clk;
end
initial
begin
$dumpfile("testbench.vcd");
$dumpvars(0,testbench);
// clk = #CLK_HALF_PERIOD ~clk;
$display("%0t, Reseting system", $time);
error_count = 0;
bcd = 4'h0;
reset = #TP 1'b1;
repeat (30) @ (posedge clk);
reset = #TP 1'b0;
repeat (30) @ (posedge clk);
$display("%0t, Begin BCD test", $time); // This displays a message
for (ii = 0; ii < 10; ii = ii + 1)
begin
repeat (1) @ (posedge clk);
bcd = ii[3:0];
repeat (1) @ (posedge clk);
if (seven_seg_display !== seven_seg_prediction(bcd))
begin
$display("%0t, ERROR: For BCD %d, module output 0b%07b does not match prediction logic value of 0b%07b.",$time,bcd, seven_seg_display,seven_seg_prediction(bcd));
error_count = error_count + 1;
end
end
$display("%0t, Test Complete with %d errors", $time, error_count);
$display("%0t, Test %s", $time, ~|error_count ? "pass." : "fail.");
$finish ; // This causes the simulation to end.
end
parameter SEG_A = 7'b0000001;
parameter SEG_B = 7'b0000010;
parameter SEG_C = 7'b0000100;
parameter SEG_D = 7'b0001000;
parameter SEG_E = 7'b0010000;
parameter SEG_F = 7'b0100000;
parameter SEG_G = 7'b1000000;
function [6:0] seven_seg_prediction;
input [3:0] bcd_in;
// +--- A ---+
// | |
// F B
// | |
// +--- G ---+
// | |
// E C
// | |
// +--- D ---+
begin
case (bcd_in)
4'h0: seven_seg_prediction = SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F;
4'h1: seven_seg_prediction = SEG_B | SEG_C;
4'h2: seven_seg_prediction = SEG_A | SEG_B | SEG_G | SEG_E | SEG_D;
4'h3: seven_seg_prediction = SEG_A | SEG_B | SEG_G | SEG_C | SEG_D;
4'h4: seven_seg_prediction = SEG_F | SEG_G | SEG_B | SEG_C;
4'h5: seven_seg_prediction = SEG_A | SEG_F | SEG_G | SEG_C | SEG_D;
4'h6: seven_seg_prediction = SEG_A | SEG_F | SEG_G | SEG_E | SEG_C | SEG_D;
4'h7: seven_seg_prediction = SEG_A | SEG_B | SEG_C;
4'h8: seven_seg_prediction = SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G;
4'h9: seven_seg_prediction = SEG_A | SEG_F | SEG_G | SEG_B | SEG_C;
default: seven_seg_prediction = 7'h0;
endcase
end
endfunction
bcd_to_7seg u0_bcd_to_7seg (
.clk (clk),
.reset (reset),
.bcd (bcd),
.seven_seg_display (seven_seg_display)
);
endmodule
testbench.vとbcd_to_7seg.vという2つのファイルがあるので、私たちはコンパイルして、Icarusを使って詳細に調べる必要があります。これをする:
$ iverilog -o testbench.vvp testbench.v bcd_to_7seg.v
次はシミュレートする必要があります
$ vvp testbench.vvp
LXT2 info: dumpfile testbench.vcd opened for output.
0, Reseting system
6000, Begin BCD test
8000, Test Complete with 0 errors
8000, Test pass.
この時点で、ファイルが実際にテストされていることを確認したい場合は、bcd_2_7seg.vファイルに移動してロジックの一部を移動し、最初の2つの手順を繰り返します。
例として、 seg_c <= #TP bcd != 2;
という行を変更しseg_c <= #TP bcd != 2;
seg_c <= #TP bcd != 4;
。再コンパイルしてシミュレートすると、次のことが行われます。
$ iverilog -o testbench.vvp testbench.v bcd_to_7seg.v
$ vvp testbench.vvp
LXT2 info: dumpfile testbench.vcd opened for output.
0, Reseting system
6000, Begin BCD test
6600, ERROR: For BCD 2, module output 0b1011111 does not match prediction logic value of 0b1011011.
7000, ERROR: For BCD 4, module output 0b1100010 does not match prediction logic value of 0b1100110.
8000, Test Complete with 2 errors
8000, Test fail.
$
これで、GTKWaveを使ってシミュレーションを見ることができます。コマンドラインから次のコマンドを実行します。
gtkwave testbench.vcd &
GTKWaveウィンドウが表示されたら、左上のボックスにモジュール名testbenchが表示されます。クリックして。これにより、そのファイルに関連するサブモジュール、タスク、および機能が明らかになります。ワイヤーとレジスタは、左下のボックスにも表示されます。
次に、clk、bcd、error_count、seven_seg_displayを波形ウィンドウの横の信号ボックスにドラッグします。信号がプロットされます。 Error_countは、どの特定のBCD入力が間違ったseven_seg_display出力を生成したかを示します。
Verilogのバグをグラフィカルにトラブルシューティングする準備が整いました。