Semiconductor_Verilog

◎Verilog

※Verilogは合成の入力として開発された言語ではないため、構文の多くは合成ツールでサポートされていない

◆文字、型、定数、コメント

_◇識別子
信号線や素子を識別するためにつける名前

①英字かアンダースコア “_” で始める
②先頭以外なら数字やドル記号 “$” も含められる
③大文字と小文字は区別される。
④予約語は使ってはならない。
⇒全ての予約語は小文字

※VHDLの制限の方がきついので、VHDLに適合させるとよい
⇒mixed設計対応のため

※先頭にバックスラッシュでエスケープされた識別子とできる
⇒ホワイト・スペース文字で識別子の区切り

_◇データ型(論理値)

0  論理0
1  論理1
x  不定値
z  ハイインピーダンス

※数値表現中の?はzと同義となる

_◇データ型(数値表現)

width’radix value

①width  データのビット幅
十進数で表記

②radix
b  バイナリ
o  オクタル
d  デシマル
h  ヘクサデシマル

③value
各基数での数値を記述する。

例)
5’b10011
12’h01F
例)
16進数 4’h0;
2進数 1’b0;

※widthを省略すると,32 ビットとして扱われる。
※radixを省略すると,10 進数として扱われる。
※valueに“_” を区切りとして入れることが可能

※16、8、2進数値では、各桁に
x
z
を含めることが可能

_◇文字列型
シミュレーション結果の表示などのために “” でくくった文字列を使用できる。
⇒文字列は1行以内

_◇bit_vector型

※std_logic_vector型との型変換
to_bitvector(S)
to_stdlogicvector(B)
⇒型変換関数は回路としては生成されない。VHDL論理上の概念

_◇boolean_vector型

_◇integer型

※std_logic_vector型との型変換
CONV_INTEGER(S)
⇒型変換関数は回路としては生成されない。VHDL論理上の概念

_◇コメント
//      行コメント
/* */    複数行コメント

_◇parameter文

モジュール内での定数定義など

◆基本構造

_◇Module
基本となるユニット
論理のある塊をまとめたもの

module <module_name> <i/o list>;
<i/o declarations>
<local variable declarations>
<module_item>

endmodule

※VHDLと異なり、インタフェースと内部動作を1つのモジュール内に定義する
※モジュールを他のモジュールから呼び出すことで階層構造を構築する
※モジュールは1ファイルに1個でも、1ファイルに複数個でもよい

// Verilog-HDL の Module の説明

// {} は必要に応じて記入することを示す。必要でない場合は記述することはいらない。
// <> はバスの情報やビット幅の定義をする場合に必要である。

{`timescale 単位 / 精度}
//例)`timescale 1ps/1ps
{`include “ファイル名”}
{`define マクロ名 値}

{parameter PARM = value;}

module モジュール名<(ポート名,{ポート名})>;
//入出力信号宣言
//ポートリストの信号の方向、ビット幅を宣言
{input <[ビット幅]> ポート名,{ポート名};}
{output <[ビット幅]> ポート名,{ポート名};}
{inout <[ビット幅]> ポート名,{ポート名};}

// オブジェクト宣言

// レジスタ
{reg <[ビット幅]> レジスタ名,{レジスタ名};}
// メモリ
{reg [ビット幅] メモリ名[アドレス幅];}
// 結線
{wire <[ビット幅]> ワイヤ名,{ワイヤ名};}   //例) parameter STEP = 100000;

// 定数
{parameter <[ビット幅]> パラメタ名 = 値;}   //例) parameter STEP = 100000;

// 整数
{integer 整数名,{整数名};}
{function/task定義}

// assign文:組み合わせ回路の記述
assign ワイヤ名 = 式;

// alwaysブロック
//<= ノンブロックキング代入
// = ブロッキング代入
{always @(信号名) begin
レジスタ名 = 式; // 手続的代入文
end}
// レジスタの標準的記述
// ノンブロッキング代入と非同期RESET
{always @( posedge ck or posedge rst) begin
if ( rst )
r <= 1’b0;
else
r <= ~r;
end}

// initialブロック
[initial begin
#000
xxx = xxx;
end]

{インスタンス文}
endmodule

_◇ポート宣言(input, output)

input 入力信号名;
output 出力信号名;

モジュール宣言の入出力ポート名で記述したものを,入力と出力に分けて宣言
⇒暗黙のうちにinput,outputはwireとして定義される

※バスの宣言例
input [MSB:LSB] バス名;

※双方向ポート宣言 inout
⇒インプリ対象によってはサポートされない
⇒通常、使うとしてもトップレベルのみ

_◇パラメータ宣言

parameter <[MSB:LSB]> 代入文;

parameter sig = 1;

モジュール内に有効な定数を定義する。
⇒回路として生成はされない。

※ポートのビット幅を可変にしたモジュールを定義するなどに利用⇒パラメータに定義する値は上位階層から書き換える。

_◇module_item
①continuous assignments
assign文による継続代入
例)
wire[7:0] result;
assign result = op1 + op2;

②structual instances
下位の階層のモジュールのインスタンス呼び出し。
例)
fulladd f1 (cin0, a0, b0, sum0, cout0);

③behavioral instances
initialもしくはalways文によるインスタンス。階層インスタンスとビヘイビュアインスタンスのすべては並行に実行される
initial  最初に一度だけ実行される。
always  継続的(無限ループ)に実行される。

_◇モジュールのインスタンス化

モジュール名 [パラメータ割り当て] インスタンス名(ポート接続)

※ポート順接続
順序のみで接続する

※ポート名接続
.ポート名(信号名)
の形式で接続する
⇒出力ポートに接続できるのはネット型(wire)の信号のみ

※パラメータ割り当て
#(値, …)
モジュール内のparameter宣言した定数に対して、上書きできる
⇒パラメタライズ設計用

例)
adder adder1(A, B, Q)
⇒ポート順接続
ff ff4( .CK(clk), .D(din), .Q(dout));
⇒ポート名接続

※ポートリストに与えるのは式なので、信号でなく直接値を書いてもよい。

◇ブロック

※順序ブロック
beginキーワードで始まり、endキーワードで終わる
その中は順番に実行される。
各ブロックは並列に実行される。
⇒論理合成の対象となる

※順序ブロック内にローカルなレジスタやパラメータを宣言する場合には、ブロック名を指定する

begin <:ブロック名>
パラメータ宣言
内部データタイプ宣言
手続き文
end

※並行ブロック
forkキーワードで始まり、joinキーワードで終わる
⇒論理合成の対象とならない

◇プロセス(alwaysとinitial)

※プロセス(always とintialブロック)
それぞれは独立し、ハードウエアにおける並行的な動作を表す
⇒別々のalways, initialブロックは並列に動く
initial文。。。1回だけ実行
⇒通常、テストベンチの記述に使用
always文。。。何度でも繰り返し実行
⇒通常順序回路を記述するために使用

内部からドライブされる信号はreg型であること
他はwire型
⇒キーワードregには、論理合成の結果としてFFが割り当てられるとは限らない

※initial
例)
initial begin
A = 0;

※always
always節は、
⇒括弧内の信号に指定条件の変化があったときに実行される。
⇒一種の無限ループであり、@は実行の条件(変化があれば待ちが解除されてalways内部が実行される)
⇒posedgeは信号が0から1に変化した場合
⇒negedgeは信号が1から0に変化した場合
⇒or は括弧内の信号のどれか1つでも変化した場合を指定する。

例)
always @(posedge SIG1)
begin

※always @*
常に実行する組み合わせ回路などを記述できる。
⇒全ての信号変化で評価されるので実回路動作との整合性が高い
⇒しかし、SIM時間がかかる

※非同期Reset付き
always @(posedge reset)
begin
if (reset)~
で非同期RESETが合成される。resetのエッジだけでリセットされるわけでなく、RESET期間中RESETされる

※歴史的知識
HDL設計の初期には順序回路の合成はできず、明示的にFFセルを記述していたので、alwaysは論理設計の対象外だった。

_◇alwaysによる組み合わせ回路の記述

通常 alwaysは順序回路の記述に用いるが

①always文の@以下のイベント式に、全ての入力を列挙
②出力はreg宣言されていること
③always文の中に出力に対する代入文を記述

ことにより、組み合わせ回路を生成させることができる
⇒組み合わせ回路を記述したつもりでも、値を保持するような記述があればラッチが生成される
⇒入力値が同じでも出力値が異なる回路は組み合わせ回路ではなく、ラッチが生成される

※alwaysでの組み合わせ回路の利点
①記述量が若干すくない。余分な識別子や呼び出しが不要。
②assignでfunctionを呼び出すよりもイベント発生回数が少ない

※alwaysによる組み合わせ回路の場合
ブロッキング代入 = では記述の順序の問題があり
ノンブロッキング代入 <= の方が良い
しかし、内部で信号を参照すると<=の場合、一拍おくれるので、思った動作をしなくなるので注意

※alwaysによる組み合わせ回路の場合、各alwaysひとつに代入される信号は1つという記述にするのが安全

※組み合わせ回路の場合でも reg への代入は <= を使う

_◇alwaysによる順序回路の記述

①ラッチの記述
module latch( D, G, Q );
input D, G;
output Q;
reg Q;

always @( D or G ) begin
if ( G==1’b1 )
Q <= D;
end

endmodule

②ロード、イネーブル付きカウンタ
module counter4( CK, LD, EN, D, Q);
input CK, LD, EN;
input [3:0] D;
output [3:0] Q;
reg [3:0] Q;

always @(posedge CK) begin
if ( LD==1’b1)
Q <= D;
else if ( EN==1’b1 )
Q <= Q + 4’h1;
end

endmodule

③4ビットシフトレジスタ
module shift4 (CK SI, EN, Q);
input CK, SI, EN;
output [3:0] Q;
reg [3:0] Q;

always @(posedge CK) begin
if ( EN==1’b1 )
Q <= { Q, SI };
end

endmodule

④非同期リセットつきDFF

module f_async_res(D, RESB, CK, Q);
input D, RESB, CK;
output Q;
reg Q;

always @(posedge DK or negedge RESB)
begin
if ( RESB==1’b0 ) //(~RESB)
Q <= 1’b0;
else
Q <= D;
end

endmodule

⇒通常は非同期リセットを使用する。

_◇function

※論理式1行で記述できないような組み合わせ回路を記述するのに用いる
例)
デコーダ
ROM
⇒if ~ else や caseのような制御構造を使って組み合わせ回路を記述する。

※シミュレーション時間0で実行され値を戻す
※function内部ではブロッキング代入 = を使う
※ノン・ブロッキング代入 <= を使っても文法上は記述できるが、
シミュレーション上は次のタイミングで反映する
しかし論理合成は組み合わせ回路
となり、回路とシミュレーションの結果がずれてしまう。

※assignやalwaysの中で呼び出す
⇒組み合わせ回路であれば、assign文でfunctionを呼び出す
例)
assign dout = dec( din );

function <戻り幅> ファンクション名
入力宣言
内部データ宣言
手続き文
endfunction

※暗黙の内にファンクション名のレジスタ扱いの信号名が戻り値の代入のために生成される
⇒ レジスタ扱いのため <= で代入することもできるが、シミュレーション時の挙動が一拍遅れる問題がおきるので = で代入する

例)
function [3:0] dec
input [1:0] din;
case (din)
0: dec = 4’b0001;

default: dec = 4’bx;
endcase
endfunction

※function内では遅延の定義はできない

※注意点
①引数や戻り値のビット幅が呼び出し側と一致しなくても文法エラーにはならない

②module内で定義した信号は一種のグローバルであり、引数を介さず参照できてしまう。
⇒文法上は許されているが、評価が正しく行われない
assign文の右辺(functionの引数)の変化がないとき、該当信号が変化してもfunctionは評価されないため。
⇒入力はすべて引数宣言する
⇒出力は戻り値で返す

③function内で中間変数を用いる時はreg型を用いる

_◇functionによる組み合わせ回路の記述

functionは、組み合わせ回路の記述に適する
⇒論理合成ツールで、functionは組み合わせ回路として処理されるので、caseの記述漏れがあってもラッチは生成されない。

_◇task
ゼロまたは1つ以上の入力、出力、入出力パラメータの値の受け渡しができ、内部にタイミング制御文も記述できる
⇒通常、テストの記述などに使う

task タスク名
入出力宣言
内部データ宣言
手続き文
endtask

※遅延 #~の定義、イベント@~も記述できる

例)
task ff_write;
input [3:0] data;
begin
D = data;
#(STEP/2) CK = 1;
#(STEP/2) CK = 0;
end
endtask

※taskの呼び出し

task名;

task名(式,…);
例)
ff_write ( 4’h0 );

◇disable

disable ブロック名またはタスク名

名前つきのブロックの活性化を消去し、実行をそのブロックの次に移す

_◇if
順序ブロックの中で使用される
条件式によって分岐する

if (条件式)

else if (条件式)

else

_◇case
順番に分岐を評価し、一致すれば対応する文が実行される。

case (式)
分岐式1: 文;

<default 文;>
endcase

※組み合わせの判定は { } で1つのデータにまとめて行うと
case文に適する

※分岐式で通りえる分岐を列挙した後、default文で不定値を代入してもよい(機能的にdefaultはとおらなくても)
⇒明示することにより、論理合成時に余計なLatchを作らず、かつ、コンパクトな回路になる可能性がある

_◇for

例)
for(i=0; i<256; i=1+1)
mem[i]=8’h0;

_◇while

例)
i=0;
while (i<256) begin
mem[i]=8’h0;
i=i+1;
end

_◇repeat

固定回数ループ

例)
repeat (式) ステートメント

_◇forever

無限ループ

例)
initial begin
CK=0;
forever #(STEP/2) CK = ~CK;
end

_◇wait

wait (式) ステートメント
式が偽(0)なら待つ、真ならステートメントを実行する

◆信号、レジスタ

_◇変数 reg, wire, integer, real, event ,time

①reg
reg [レンジ] レジスタ変数;
レジスタ。値を保持する。デフォルトのビット幅1。1,0,x,zの4値をとる。
例)
reg FLAG;  //1ビットのレジスタ
reg [3:0] cnt;  //4ビットのレジスタ
reg [7:0] mem [0:255];  //256バイトのレジスタ配列

※合成するとレジスタになる筈だが、必ずしもそうではない
⇒always文で、組合せ回路を作るときなどは、regで宣言した信号がレジスタにならないことがある
※integer, time, realなどの型はレジスタ型の一族
※代入できる場所(手続き的代入)
initial, always, function, taskの中
⇒一度値が代入されると次に別の値が代入されるまで保持される

②wire
wire [レンジ] [遅延] 信号名;
ワイア(ネット型)。値を保持しない。デフォルトのビット幅1。1,0,x,zの4値をとる。

※主として配線となる筈だが、必ずしもそうではない
※tri, wor, trior, wand, triandなどはネット型の一族
※代入できる場所
assign文、force文, モジュール呼び出しの出力ポート
⇒シミュレーション中は常に接続先の信号の値に依存する

③integer
抽象型。32ビット符号付整数。

④real

⑤event
イベントは値を持たない信号。
イベント信号の起動は -> を使う
参照は @(~)のイベント式の中で行う

例)
event trigger, t2;
@trigger #5 ->t2;

⑥time
抽象型。64ビット符号無し整数。

※論理合成の対象になるのは、regとwireである。

⑦realtime
実数表記での時間

_◇wire(ネット)
組合せ回路で用いる信号線などの定義。

wire 信号名;
wire [MSB:LSB] バス名;

※wireへの代入は,assign 文でのみ可能。
⇒必ず = で

ネットタイプ <[MSB:LSB]> <電荷ストレングス> <遅延> ネット名

※ネットタイプ
wire
wand    ワイヤAND
wor      ワイヤOR
tri      トライステート
triand    ワイヤAND,トライステート
trior    ワイヤOR、トライステート
tri1    プルアップ
tri0    プルダウン
trireg    キャパシタ付き
supply0    電源
supply1    電源

※電荷ストレングス
small
medium
large

_◇reg(レジスタ)
順序回路で用いるフリップ・フロップ(FF)やラッチなどを宣言する。しかし、reg 宣言すれば必ずFFに論理合成されるというわけではない

reg 信号名;
reg [MSB:LSB] レジスタ名;

※regへの代入は,always 文,initial 文,task,function の中で可能。

※いずれの変数も,式の右辺や引数として参照できる。

_◇信号強度

強度レベル
7    supply0, supply1
6    strong0, strong1
5    pull0, pull1
4    large0, large1
3    weak0, weak1
2    medium0, medium1
1    small0, small1
0    highz0, highz1

_◇配列
ROM, RAM, PLAなどのモデル化

reg[MSB:LSB]配列名[アドレスL:アドレスH]

例)
reg[15:0]mem[0:255]

例)
reg [7:0]mem[0:1024];
⇒8ビット幅1Kのメモリ


reg [3:0] cnt;
reg [7:0] mem [0:255];
と定義した場合
cnt[3]  cntのMSBにあたる1ビット
mem[0]  メモリの0番地の8ビット

_◇演算子

※真偽
真:1
偽:0
//(Cとは異なる!)

※VHDLと異なり演算子に暗黙の優先順位がある

①算術
+

*
/
⇒整数割り算、小数点以下切捨て

②関係
>
>=
<
<=
⇒比較結果の論理値はビット値として代入可能。xやzが含まれると結果も不定となる

③論理
!    論理反転。ワイヤの論理反転はこれ
&&
||
⇒論理式は左から右へ評価、真偽が確定した時点で評価は止まる
⇒結果が分らない場合は不定x
⇒1ビットでも1があれば真。オール0で偽

④論理比較
==
!=
⇒論理比較結果の論理値はビット値として代入可能。xやzが含まれると結果も不定となる

⑤条件
?:
式1?式2:式3

⑥連結
{ }
※連接演算
信号を{}でくくることにより、まとまりとして扱って代入できる。

⑦モジュロ
%

⑧ケース比較
===
!==
⇒x,zも独立した値としてビット毎に比較

⑨ビット演算  バス信号に対して適用可能
~  ビット反転
&  ビットAND
|  ビットOR
^  ビットEXOR

⑩シフト
<<
>>
⇒空いたビットには0が詰められる

※bit_vector型、boolean_vector型とinteger型によるシフトの演算子
sll    shift left logical
srl    shift right logical
sla    shift left arithmetic
sra    shift right arithmetic
rol    rotate left logical
ror    rotate right logical

⑪リダクション演算
2項のビット演算子と同じ演算子記号を単一のオペランドに適用することで、そのオペランドの全ビットにビット演算を適用し、1ビットの値としたものを得ることができる

_◇継続代入(assign)
Continuous Assignment
ベクタまたはスカラ・ネットに対して継続的に値をドライブする
⇒右辺に含まれる信号の値が変化⇒自動評価、左辺へ代入
⇒遅延値が指定されている場合は指定時間だけ代入が遅延される

※wireで定義された信号への代入は =

assign <遅延> 代入文;
assign <信号強度> <遅延> <ネット型信号名>=<式>;

例)
assign #1 C = A + B;

※reg型に対する assign文も存在するが論理合成対象外

_◇手続き的代入
値をレジスタに代入する
⇒式が評価されるとレジスタに代入され、次回の代入まで値を保持する
reg で定義されたレジスタへの代入

※ノンブロッキング代入  ”<=”オペレータ
右辺の評価が完了しても、同時刻での他の代入文の評価が完了するまで代入されない
⇒ハードウェア記述言語の特徴の一つ

<左辺値> <= [タイミング制御] 式;

例)値のスワップ
reg a, b;
wire c;

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

⇒always文内でのreg型への代入は 通常 <=

⇒複数箇所で代入してはいけない
同一regへの代入は1つのalways内で
重ねて代入するようなパスを作らない
条件選択の木の末端で代入する

※ブロッキング代入  ”=”
手続き型言語のように逐次実行される。

<左辺値> = [タイミング制御] 式;

※左辺値として
レジスタ変数
レジスタ変数[式]
レジスタ変数[式1:式2]
連接
をとることができる

例)連接
{{16{bus[15]}},bus}
⇒16ビットから32ビットへの符号拡張

⇒シミュレーション記述の initial内やtask内では
順次処理の = で代入してよい

※ブロッキング代入とノン・ブロッキング代入を混在させると不具合を起こす

_◇force, release

force 代入文
内部信号への強制代入

release 信号
強制代入の解除

◆プリミティブ・ゲート

ゲートタイプ [信号強度] [遅延] ゲート名(信号,…);
⇒入力本数の制限はない
⇒並びの最初が出力で以降が入力
⇒トライステートの場合は
(出力信号, 入力信号, トライステート制御信号)

⇒信号強度や遅延を負荷することができるが論理合成の対象外となる
⇒スイッチレベルも論理合成対象外

※信号強度のデフォルトはstrong
⇒信号が衝突している場合、シミュレータは信号強度が大きい方の値を使う

例)
nand (weak0, weak1) #(5:10:15) N1(o2, i0, i1);

_◇ゲート
and
nand
nor
or
xor
xnor
buf
not

_◇トライステート
bufif0
bufif1
notif0
notif1

_◇スイッチ
⇒スイッチレベルは、シミュレーション可能だが、論理合成の対象外
nmos
pmos
rnmos
rpmos
rcmos
tran
tranif0
tranif1
rtran
rtranif0
rtranif1

_◇プルアップ、プルダウン
pullup
pulldown

_◇ゲート記述の例

レベルセンスのDラッチの記述

module latch( G, D, Q );
input G, D;
output Q;
wire D1;
bufif1( D1, D, G );
buf(Q, D1);
bufif0( D1, Q, G );
endmodule

※エッジセンスのDFFの記述

module flipflop( CK, D, Q );
input CK, D;
output Q;
wire L1Q, CKB;
not ( CKB, CK );
latch L1 ( CKB, D, L1Q ),
L2 ( CK, L1Q, Q );
endmodule

※遅延・信号強度を付加したゲート呼び出し
nand (pull0, pull1) #(5:10:15) na2(out2, in0, in1);

◆イベント

タイミングをコントロールする
各ステートメントの直前に記述できる

_◇遅延制御 #
#は時間経過を示す。

#定数式

#(min_typ_max定数式)

例)initialブロック
initial begin
A=0
#10 B = 1;
#20 A = 1;

※min_typ_max定数式
min:typ:max
で遅延を記述

例)
#(10:15:20)

立ち上がり、立下り
#(10:15:20, 10:15:20)
⇒プリミティブ・ゲート記述用

立ち上がり、立下り、トライステートターンオフ
#(10:15:20, 10:15:20, 10:15:20)
⇒プリミティブ・ゲート記述用

_◇イベント制御
①#expression
指定された時間の間プロセスの実行をサスペンドする。
//例
#STEP  a = 4’h5;  b = 4’ha;

②@event-expression
指定されたイベントが起こるまで実行をサスペンド。
※イベントの指定方法
a) variable <or variable>
変数が変化するまで待つ
b) posedge one-bit-variable
変数が0,x,zから1になった場合
c) negedge one-bit-variable
変数が1,x,zから0になった場合
d) event-variable
イベントがイベントされた場合

③wait (expression)
レベルセンシティブなイベント制御。偽の間は実行がサスペンドされる。

※指定した時刻までてシミュレーションを停止させるための定石
initial #70 $stop;

④イベントのトリガ
-> イベント名
(event宣言されたイベント名に対して行う)
例)
event e1;

->e1;

※タイミングコントロール拡張としてのrepeat
repeat <式> @信号
repeat <式> @(イベント式)

◆テストベンチ

シミュレーション用の記述
論理合成の対象としないので、Verilog HDLの構文を全て利用できる。

_◇テストベンチの構造

①Mudule宣言
②テスト用信号の宣言
③被テストモジュールのインスタンシェイション
④スティミュラス

※追加機能
仮想ディスプレイ
エラー検出機能など

_◇テストベンチ記述の注意点

①入出力は無し
②呼び出し回路の入力は regで定義
③呼び出し回路の出力は wireで定義
④アンダーテスト回路を呼び出し
⑤クロック生成
例)
parameter CLK_PERIOD = 10;

initial begin
forever clk = #(CLK_PERIOD / 2) ~clk;
end

または

always #(CLK_PERIOD/2) clk = ~clk;

⇒clkの初期値は別なinitialの中で与える。

⑥必要なtaskの定義

⑦initial begin~endにテストベクタ定義
⇒複数あっても良い

※遅延絶対値での記述
例)
initial begin
sig = 1;

#100 sig = 0;

end

※遅延相対値(カウンタ値による)
例)
always @(posedge clock)
count <= count + 1;

count値に応じた印加
end

※スティミュラスは関係のあるもの毎に分割した方が見通しが良くなる

※塊で繰り返されるスティミュリは taskでサブルーチン化
後のinitialで呼び出す。

※不要なデータまでI/Oさせると速度が遅くなる

※シミュレーション記述の場合、regへの代入を = でおこなってよい

_◇システムタスク:表示
monitor/dumpfile/dumpvarsなど

①$monitor
//例 通常initial文の中で実行する
$monitor( $stime, ” a=%h b=%h q=%h”,a,b,q);
⇒信号に変化があれば表示
⇒%t記述子 時間フォーマット
⇒$timeformatシステムタスクでフォーマット変更可能

②$dumpfile
波形ファイルの名前を指定
//例 通常initial文の中で実行する
//GTK wave
$dumpfile(“adder_4.vcd”);
$dumpvars(0, adder);

③$dumpvars
波形ファイルに出力するタイミングとモジュール名を指定
//例 通常initial文の中で実行する
//GTK wave
$dumpfile(“adder_4.vcd”);
$dumpvars(0, adder);

④$write
$write(“xxxx\n”);
⇒何もしなければ改行なし

⑤$display(“xxxx”);
⇒改行する

⑥$strobe(P1,…)
全イベント処理後に表示

_◇システムタスク:実行制御
①$stop
一時停止

②$finish
終了

_◇システムタスク:関数
①$stime

②$time

③$random

_◇システムタスク:タイミングチェック
①$setup

②$hold

③$width

_◇システムタスク:メモリ読み書き
①$readmemh( “fname”, memname, beginAdr, endAdr);

②$readmemb( “fname”, memname, beginAdr, endAdr);

③$writememh( “fname”, memname, beginAdr, endAdr);

④$writememb( “fname”, memname, beginAdr, endAdr);

_◇システムタスク:ファイル出力
①$fopen( “fname”); //mcdを戻す

②$fclose( mcd );

③$fdisplay( mcd, P1,…);

④$fwrite( mcd, P1,…);

⑤$fmonitor( mcd, P1,…);

⑥$fstrobe( mcd, P1,…);

◆コンパイラ指示子

Verilog HDLの文法体系の外側にある

バッククウォート ` で始める

_◇define
テキストマクロ置換

`define マクロ名 テキスト

文末に;なし。
インクルードされるヘッダファイル内などでの定義用

_◇timescale

`timescale 時間単位/時間精度

遅延値の時間単位と精度
値は1, 10, 100
単位はs, ms, us, ps, fs

_◇include

`include “ファイル名”

_◇ifdef

`ifdef マクロ名

`else

`endif

◆TIPS

_◇トライステート
pull up … tri1
pull dwon … tri0

※双方向の信号制御では 必要なところでHi-Zを使えば済む

_◇ビット幅が異なる代入

①代入先のビット幅が狭ければ上位が欠落
②代入先のビット幅が広ければ上位に0を補う

※このルールにより、functionの戻り値や引数のビット幅が不整合でも、コンパイルが通ってしまう。

◆サンプル

_◇テストベンチ例

// led_toggle.v Test Bench
`timescale 1ns/1ps

module led_toggle_tp;
  reg  SW1_I;
  reg  CLK_I;
  reg  SW2_I;
  reg  SW3_I;
  reg  SW4_I;
  reg  GPIN;
  reg  RxD;
  wire  LED1_O;
  wire  LED2_O;
  wire  LED3_O;
  wire  LED4_O;
  wire  [4:1] DP_OEN;
  wire  [8:1] DP_O;
  wire  [15:0] GPIO;
  wire  TxD;

// clock setting
parameter STEP = 100000;  // 1STEP=100ns
// target circuit
led_toggle  led_tog(
  SW1_I,
  LED1_O,
  CLK_I,
  SW2_I,
  SW3_I,
  SW4_I,
  LED2_O,
  LED3_O,
  LED4_O,
  DP_OEN,
  DP_O,
  GPIN,
  GPIO,
  TxD,
  RxD
  );

// test pattern
initial begin
  SW1_I = 0;
  CLK_I = 0;
  SW2_I = 0;
  SW3_I = 0;
  SW4_I = 0;
  GPIN = 0;
  RxD = 0;
  #STEP  SW1_I = 1;
  #STEP  SW1_I = 0;
  #STEP  CLK_I = 1;
  #STEP  CLK_I = 0;
  #STEP  CLK_I = 1;
  #STEP  CLK_I = 0;
  #STEP  CLK_I = 1;
  #STEP  CLK_I = 0;
  #STEP  CLK_I = 1;
  #STEP  CLK_I = 0;
  #STEP  $finish;
end

initial begin
  $monitor( $stime, " SW1=%b CLK=%b LED1=%b",SW1_I, CLK_I, LED1_O);
//GTK wave
  $dumpfile("led_toggle.vcd");
  $dumpvars(0, led_tog);
end

endmodule

_◇LEDトグル

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    19:53:18 11/21/2007 
// Design Name: 
// Module Name:    led_toggle 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module led_toggle(
  SW1_I,
  LED1_O,
  CLK_I,
  SW2_I,
  SW3_I,
  SW4_I,
  LED2_O,
  LED3_O,
  LED4_O,
  DP_OEN,
  DP_O,
  GPIN,
  GPIO,
  TxD,
  RxD
);
  input  SW1_I;
  input  CLK_I;
  output  LED1_O;
  reg  led_status;
  
//FF
always @(posedge CLK_I or posedge SW1_I)
begin
  if (SW1_I)
  led_status <= 0;
  else
  led_status <= !led_status;
end
  assign  LED1_O = !led_status;
//
  input  SW2_I;
  input SW3_I;
  input SW4_I;
  output LED2_O;
  output LED3_O;
  output LED4_O;
  output [4:1] DP_OEN;
  output [8:1] DP_O;
  input  GPIN;
  output [15:0] GPIO;
  output TxD;
  input RxD;
  
  assign LED2_O = !SW2_I;
  assign LED3_O = !SW3_I;
  assign LED4_O = !SW4_I;
  assign DP_OEN = { !SW4_I, !SW3_I, !SW2_I, !SW1_I };
  assign DP_O = {8{GPIN}};
  assign GPIO = {15{CLK_I}};
  assign TxD = RxD;

endmodule

_◇シフトレジスタ

module ShiftRegister (
    XRST ,
    CLK ,
    OUT
) ;
    input                  XRST ;
    input                  CLK ;
    output                 OUT ;

    parameter              BitWidth = 1000 ;

    integer                i ;
    reg    [BitWidth-1: 0] Out_Reg ;

    always @(negedge XRST or posedge CLK) begin
      if(XRST == 1'b0) begin
        for(i = 0; i < BitWidth; i = i + 1) begin
          if(i % 2 == 0) begin
            Out_Reg[i] <= 1'b0 ;
          end else begin
            Out_Reg[i] <= 1'b1;
          end
        end
      end else begin
        Out_Reg <= {Out_Reg[BitWidth-2: 0], ~Out_Reg[0]} ;
      end
    end

    assign OUT = Out_Reg[BitWidth-1] ;

endmodule

※上記のテストベンチ (BY Shinichiro Kobayashi)

Test bench仕様:
RTL ShiftRegisterのXRST端子に対して、Parameter ResetTimeで規定された時間Lowを印加する。
RTL ShiftRegisterにCLK端子対して、Simulation開始時にはLowを印加し、XRST端子がHighとなってからParameter HalfPeriodで規定された時間経過後に、その値の反転値を印加し、これをSimulation終了まで繰り返す。

RTL ShiftRegisterのOUT端子とその出力期待値の比較を行うための、Strobe信号を生成する。Strobe信号は、Simulation開始より、Parameter StrobeTimeで規定された時間経過後に有効となり、その後Parameter StrobeWidthで規定された時間経過後に無効となる。
OUT端子の実出力値と出力期待値とは、このStrobe信号の有効区間のみ比較を行い、それ以外では直前の値を保持するものとする。

RTL ShiftRegisterのOUT端子に想定される出力期待値を生成する。

`timescale 1ps/1ps

module Simulation ;

    reg          n_XRST ;
    reg          n_CLK ;
    wire         n_OUT ;

    reg          n_Strobe;
    reg          n_Expected_OUT ;
    reg          n_Compared_OUT ;

    integer      i ;

    parameter    MaximumCycle =    1000 ;
    parameter    HalfPeriod   =   15000 ;
    parameter    ResetTime    =   15000 ;
    parameter    StrobeTime   =   25500 ;
    parameter    StrobeWidth  =    1000 ;

    // Simulation control
    always @(posedge n_CLK) begin
      i = i + 1 ;
      if(i >= MaximumCycle) begin
        $finish ;
      end
    end

    // Generate FSDB file to debug by Verdi
    initial begin
      $fsdbDumpfile("ShiftRegistor.fsdb") ;
      $fsdbDumpvars ;
      $display("Simulation ended at %t.", $time) ;
    end

    // Define XRST wave form
    initial begin
      n_XRST = 1'b0 ;
      n_XRST = #(ResetTime) 1'b1 ;
    end

    // Define CLK wave form
    initial begin
      n_CLK = 1'b0 ;
      wait(n_XRST == 1'b1) ;
      forever #(HalfPeriod) n_CLK = ~n_CLK ;
    end

    // Generate expected output for OUT output at ShiftRegister module
    initial begin
      i = 0 ;
      n_Expected_OUT = 1'b1 ;
    end

    always @(posedge n_CLK) begin
      n_Expected_OUT = ~n_Expected_OUT ;
    end

    // Compare between expected and actual OUT output of ShiftRegister module
    // n_Compared_OUT becomes Low when both are matched, otherwise becomes High.
    always @(n_Strobe) begin
      if(n_Strobe == 1'b1) begin
        n_Compared_OUT = n_OUT == n_Expected_OUT ? 1'b0 : 1'b1 ;
      end
      $display("%b at %t", n_Compared_OUT, $time) ;
    end

    // Instanciation from RTL part of ShiftRegister
    ShiftRegister I_0 (.XRST(n_XRST), .CLK(n_CLK), .OUT(n_OUT) );

    // Generate internal strobe signel
    initial begin
      n_Strobe = 1'b0 ;
      forever begin
        n_Strobe = #(StrobeTime) 1'b1 ;
        n_Strobe = #(StrobeWidth) 1'b0 ;
        #(HalfPeriod * 2 - StrobeTime - StrobeWidth) ;
      end
    end

endmodule