3803703 ランダム
 HOME | DIARY | PROFILE 【フォローする】 【ログイン】

CPUを作ろう ~計算機教材とマイコンと電子工作~

Verilog超入門

1. モジュールの基本構造
Verilog はモジュールを基本単位として記述します.
(1)モジュール宣言
1行目がモジュールの宣言です.モジュールは,moduleではじまり,続くgandがモジュール名です.入出力信号(ポート・リスト)はモジュール名の後に()で囲んで,列挙します.文の終わりにはセミコロン(;)をつけます.モジュールの最後はendmoduleで終わります.

module gand( a,b,c);        ・・・1行目
input a,b;        ・・・2行目
output c;         ・・・3行目
assign c = a & b;     ・・・4行目
endmodule        ・・・5行目

(2) ポート宣言
2行目と3行目は,入出力信号(ポート)の宣言です.入力信号はinput,出力信号はoutputに続けて信号名を記述して宣言します.信号が複数個あれば,コンマ(,)で続けて記述できます.このほか,双方向のポートはinoutとして宣言できます.

(3) assign文による回路記述
assign文は組み合わせ論理回路の記述に用います.4行目のように,assign文を用いて入出力の関係を記述することができます.&はAND演算子で,この文は入力信号aとbのANDをcに出力することを意味します.

2. 多ビットの取り扱い
多ビットの信号も宣言することができます.例えば,8ビットの双方向データバス(d_bus)は次のように宣言できます.

inout [7:0] d_bus;

 ここで[7:0]がビット幅を定義したものです.
多ビットの信号間の接続は信号の並び順に接続されます.多ビットの信号の一部を使うこともできます.例えばb[3:0]で定義された4ビットの最下位ビットに1ビットのc信号を接続するには,

assign b[0]=c;

と書けます.また,a[7:0]で8ビットの信号を定義し,次のように書けば,a[7:0]の上位4ビットだけがb[3:0]に接続されます.

assign  a[7:4]=b[3:0];

複数の信号間の接続や多ビット信号との接続を行うこともできます.信号を中カッコ{}で囲み,コンマで区切って信号名を並べて書くことができるので,例えばa,b,sumとも8ビットで定義されていて,aとbの足し算結果をsumに,桁上がりを1ビットのキャリー信号cへ代入するには,

assign {c, sum}=a+b;

と記述できます.

3. 論理値・定数
Verilog では,”0”,”1”,”x”(不定,ドントケア),”z”(ハイインピーダンス,絶縁のこと)の4通りの論理値を扱うことができます.
定数は,10進数,2 進数,8 進数,16 進数で以下のように表現できます.

<ビット幅>’<基数><数値>

ビット幅は10進数で書き,省略すると32ビットとして扱われます.基数は,次のように何進数かを表す記号です.

b:2進数, o:8進数, d:10進数, h:16進数  (大文字のB,O,D,Hでも可)

4. データ型
 信号や変数は型宣言する必要があります.Verilogではネット型とレジスタ型の2種類があり,次のように宣言します.

wire bus; ・・・1ビットのbusをネット型で宣言
reg [3:0] count; ・・・4ビットのcountをレジスタ型で宣言

5. 演算子
Verilogでは表4.4に示す演算子を用いることができます.算術演算子,ビット演算子,リダクション演算子,論理演算子,関係演算子,シフト演算子,連接演算子,条件演算子が用意されています.
算術演算子には,加算(+),減算(-),乗算(*),割算(/),剰余演算(割算の余り,演算子は%)があります.
条件演算子(? :)は,条件式を評価し,真か偽かでそれらに対応する結果を返す3項演算子で次のように記述します.

assign out = (sel==1)? a: b;  ・・・ (条件式)? 真の場合: 偽の場合

6. 組み合わせ論理回路
複雑な回路の記述を容易にするためにfucntion文があります.
function文は文字通り関数を定義するもので,引数と戻り値があり,関数の機能を記述します.複数の引数を持つ場合は,function文内で定義された順番どおりに引数が渡されます.

function  [戻り値のビット幅の定義] 関数名;
input [引数のビット幅の定義] 引数名1;
input [引数のビット幅の定義] 引数名2;
begin
関数の機能の記述;
関数名=戻り値;
end
endfunction

funciton文と,後に述べるalways文中では,以下の条件判断文が使えます.

a) if 文
If文は次の構造をとり,条件式を評価し,真であるか偽であるかによって異なる動作を記述できます.
if (条件式) ステートメント
if (条件式) ステートメント else ステートメント

b) case 文
case文は次の構造をとり,最後はendcaseで括ります.caseに続く式の値を評価した後,その値と対応した分岐式の動作を行います.対応する分岐式がない場合には,defaultに書かれた動作を行います.


case (式)
分岐式1: ステートメント1
分岐式2: ステートメント2



default: ステートメント3
endcase

7. 順序回路
順序回路とは,ある時点での出力がその時の入力とそれまでの経緯に依存するものです.そのため順序回路の構成には記憶素子(レジスタ)が必要となります.順序回路の代表的な例としては,カウンタやコントローラなどがあります.
 順序回路の記述には,always文を用います.always文は次のように記述し,イベントの発生によってステートメントを実行します.

always @ (イベント式) ステートメント

簡単な順序回路として, D-FF(フリップフロップ)の記述例をリスト4.7に示します.

module dff( reset_x, ck, d, q );        ・・・1行目
input reset_x, ck, d;         ・・・2行目
output q;         ・・・3行目
reg q;       ・・・4行目
always @( negedge reset_x or posedge ck ) begin ・・・5行目
if (!reset_x) q<=1’b0; ・・・6行目
else q<=d; ・・・7行目
end ・・・8行目
endmodule        ・・・9行目

モジュールdffはリセット信号(reset_x),クロック信号(ck),入力信号(d),出力信号(q)を持っています. リセット信号は負論理として用いるので,これを明示するため信号名の最後に_x(_nと書かれる場合もある)をつけて定義しています.qは値を保持できる記憶素子として4行目でレジスタ宣言されています.
5行目のalways文中のイベント式(negedge reset or posedge ck)はreset信号の立ち下り,またはck信号の立ち上がりを検出し,ステートメントを実行します. always文のステートメントはbegin~endで囲んだ複文が使え,if文やcase文を用いれば複雑な動作を記述することができます.
6行目では,resetが0のときqに0を代入し,D-FFをリセットします.resetが1でckの立ち上がりのとき,7行目でqにdが代入されます.
クロックでのレジスタへの代入には,記述の順番に代入が実行されるブロッキング代入(=による代入)と,記述の順番によらず代入が並列処理的に実行されるノン・ブロッキング代入(<=による代入)の2種類があります.

8. モジュールの階層化
Verilogでも階層的なプロジェクトを作成することができます.

module test(a,b,c,d,x,y,z);       ・・・1行目
input a,b,c,d;       ・・・2行目
output x,y,z;       ・・・3行目
gand gandv(a,b,x);       ・・・4行目
gor gorv(c,d,y);       ・・・5行目
assign z= x & y;       ・・・6行目
endmodule ・・・6行目

testモジュールは,a,b,c,dの4本の入力,x,y,zの3本の出力をもつ回路です.testモジュールは先に定義されたgandとgorを下位モジュールとして呼び出してgandv,gorvの2つの回路を生成し,それらを結線しています.gandvはa,bの入力の論理積をxに出力し,gorvはc,dの入力の論理和をyに出力しています.zはzとyの論理積としています.下位モジュールの呼び出しは例えば次のように行います.

gand  gandv (a,b,x);
下位モジュール名 インスタンス名 (ポート・リスト)

ポートの接続には,名前による接続もあります.下位モジュール内で定義されたポート名と上位モジュールのネット名との関係を明示することでポート・リストの順番に無関係に接続を表すことができます.リスト4.3の5行目を名前による接続で書き直すと次のようになります.

gor  gorv (.a(c), .b(d), .c(y));
      .下位ポート名(上位ネット名)

9. シミュレーション記述
Verilogにはシミュレーション用のテスト信号の入力とシミュレーション結果の出力形式を記述できます.リスト4.8はリスト4.1のgandモジュールのシミュレーション記述例です.
1行目では時間の基本単位を設定しています.2行目ではシミュレーションに使う閉じたモジュール(入出力を持たないモジュール)を宣言します.3行目でシミュレーション対象のgand回路に対する入力信号をレジスタ宣言しています.4行目は出力観測するためのc信号をネット宣言しています.5行目はシミュレーション対象のgand回路の呼び出しです.6行目は,シミュレーションの開始,7行目は信号a,bの初期値を与えています.8~10行目の#10は,10単位時間の経過を表しています.単位時間経過後の信号a,bの値を記述しています.11行目はシミュレーションの終了です.出力形式は13行目で記述され,経過時間と信号a,b,cを出力させます.

‘timescale 1 ns / 1 ns ・・・1行目
module gand_tp;  ・・・2行目
reg a,b; ・・・3行目
wire c; ・・・4行目

gand gand(a,b,c); ・・・5行目

initial begin ・・・6行目
a= 1’b0; b=1’b0; ・・・7行目
#10 a= 1’b0; b=1’b1; ・・・8行目
#10 a= 1’b1; b=1’b0; ・・・9行目
#10 a= 1’b1; b=1’b1; ・・・10行目
#10 $finish; ・・・11行目
end ・・・12行目

initial $monitor ( $time, “a=%b b=%b c=%b ”, a, b, c ); ・・・13行目
endmodule ・・・14行目


© Rakuten Group, Inc.