初めてでも使えるVerilog HDL文法ガイド ―― 文法ガイド編
tag: 半導体 ディジタル・デザイン
技術解説 2009年7月13日
2.モジュール構造
module <モジュール名> ( <ポート宣言> );
<パラメータ宣言>
<変数宣言>
<イベント宣言>
<ネット宣言>
<プリミティブ・ゲート接続>
<下位モジュール接続>
<generateブロック>
<alwaysブロック>
<initialブロック>
<function定義>
<task定義>
<継続的代入>
endmodule
注:モジュール構成要素(モジュール内の各要素)の記述順は任意.ただし,信号名やパラメータなどの識別子は,使用する前に宣言が必要.
3.モジュール構成要素
● ポート宣言
- input [<ネット型>] [signed] [<レンジ>] <信号名>, <信号名>, ...
- output [<ネット型>またはreg] [signed] [<レンジ>] <信号名>, <信号名>, ...
- inout [<ネット型>] [signed] [<レンジ>] <信号名>, <信号名>, ...
● レンジ
[<定数式>:<定数式>]
注:[MSB:LSB]となる.レンジを省略すると1ビット.
ここの[ ]は省略可能を意味するのではなく,[ ]そのものを意味する.
《記述例》
module BLOCK (
input wire CK, RST, LD,
output reg [3:0] Q,
inout wire [15:0] DBUS );
注:ポート宣言をかっこの外で行うスタイルもある.
module <モジュール名> ( ポート名, ポート名, ... );
<ポート宣言>;
《記述例》
module BLOCK ( CK, RST, LD, Q, DBUS );
input CK, RST, LD;
output [3:0] Q;
inout [15:0] DBUS;
reg [3:0] Q;
● パラメータ宣言
- parameter [signed] [<レンジ>] <パラメータ名> = <定数式>, <パラメータ名> = <定数式>, ... ;
- parameter integer <パラメータ名> = <定数式>, <パラメータ名> = <定数式>, ... ;
《記述例》
parameter STEP=1000;
parameter [1:0] HALT=2'b00, INIT=2'b01, ADRINC=2'b10, RAMWRT=2'b11;
parameter integer MINUS = -1234;
● 変数宣言
<変数型> [signed] [<レンジ>] <変数名リスト>;
● 変数型
表2 変数型
● 変数名リスト
<信号名> [<次元> <次元> ... ], <信号名> [<次元> <次元> ... ], ...
● 次元
[<定数式>:<定数式>]
《記述例》
reg FLAG, Q; // 1ビット変数
reg [3:0] CNT; // 4ビット変数
reg [7:0] ARRAY [0:255][0:15]; // 8ビットの要素が256×16個ある2次元配列
● イベント宣言
event <イベント名リスト>;
● イベント名リスト
<イベント名> [<次元> <次元> ... ], <イベント名> [<次元> <次元> ... ], ...
注:イベントは値を持たない信号.したがって,代入ではなく「起動」できる.イベント信号の起動には -> を使い, 参照は @( ~ ) のイベント式の中で行う.
《記述例》
event EVENT_SIG1, EVENT_SIG2;
● ネット宣言
<ネット型> [signed] [<レンジ>] [<遅延>] <ネット名リスト>;
● ネット型
表3 ネット型
● ネット名リスト
<信号名> [<次元> <次元> ... ], <信号名> [<次元> <次元> ... ], ...
● 遅延
- #<定数式>
- #( <min_typ_max定数式> )
- #( <min_typ_max定数式>, <min_typ_max定数式> )
注:プリミティブ・ゲート接続用.
(立ち上がり,立ち下がり)の遅延を設定.
- #( <min_typ_max定数式>, <min_typ_max定数式>, <min_typ_max定数式> )
注:プリミティブ・ゲート(3ステート・タイプ)接続用.
(立ち上がり, 立ち下がり, ターン・オフ)の遅延を設定.
● min_typ_max定数式
<定数式>:<定数式>:<定数式>
注:min:typ:maxの遅延量を設定.どの値を使用するかは,シミュレーション時に設定する.
《記述例》
wire X, Y, Z; // 1ビットのネット
wire [3:0] Q; // 3ビットのネット
wire [7:0] #(10:15:20) DBUS; //遅延付きの8ビット・バス
● プリミティブ・ゲート接続
<ゲート・タイプ> [<信号強度>] [<遅延>] [<ゲート名>] (<信号名>, <信号名>, ... );
● ゲート・タイプ
表4 ゲート・タイプ
● 信号強度
- ( <強度0>, <強度1> )
- ( <強度1>, <強度0> )
表5 信号強度
《記述例》
nand (weak0, weak1) #(5:10:15) N1 (OUT2, IN0, IN1); // NANDゲート
● 下位モジュール接続
<モジュール名> [<パラメータ割り当て>] <インスタンス名> (<ポート・リスト>) ;
注:モジュール名と,インスタンス名を同じにしても文法上OK.
● パラメータ割り当て
- #( <式>, <式>, ... )
- #( .<パラメータ名>(<式>), .<パラメータ名>(<式>), ... )
注:モジュール内のparameter宣言した定数に対し,呼び出し時に上書き設定できる.HDLライブラリ作成に有用.
● ポート・リスト
- <信号名>, <信号名>, <信号名>, ...
- .<定義側ポート名> ( <信号名> ), .<定義側ポート名> ( <信号名> ), ...
注:ポート・リストの<信号名>は,正確には<式>.したがって定数でも論理式でも記述できる.
《記述例》
ADDER ADDER( A, B, Q );
FF #(4) FF4( .CK(CLK), .D(DIN), .Q(DOUT) );
SUBCIRCUIT S1( ADDR[15:12], FLAG & BUSY, 1'b1 );
● generateブロック
generate
<genvar宣言>
<パラメータ宣言>
<変数宣言>
<イベント宣言>
<ネット宣言>
<プリミティブ・ゲート接続>
<下位モジュール接続>
<if文>
<case文>
<for文>
begin ~ end
<alwaysブロック>
<initialブロック>
<function定義>
<task定義>
<継続的代入>
endgenerate
注:ここでのfor文には,begin: <ブロック名> ~ endを付加する.
● genvar宣言
genvar <変数名>, <変数名>, ...;
● alwaysブロック
always <ステートメント>
《記述例》
always @( posedge CK ) // 順序回路
Q <= D;
always @( A, B, C ) // 組み合わせ回路
Y <= A & B & C;
always begin // クロックの記述
CK = 1; #(STEP/2);
CK = 0; #(STEP/2);
end
● initialブロック
initial <ステートメント>
《記述例》
initial begin // テスト入力
CK = 0;
#STEP RST = 1;
#STEP RST = 0;
#(STEP*20) $finish;
end
● function定義
function [automatic] [signed] [<レンジまたは型>]
<ファンクション名>(<ファンクション・ポート宣言>);
<タスク・ファンクション内宣言>
<ステートメント>
endfunction
注:automaticを付加すると再帰呼び出しが可能となる.
● レンジまたは型
- <レンジ>
- <タスク・ポート型>
● タスク・ポート型
- integer
- real
- realtime
- time
● ファンクション・ポート宣言
- input [reg] [signed] [<レンジ>] <ポート名>, <ポート名>, ...
- input [<タスク・ポート型>] <ポート名>, <ポート名>, ...
● タスク・ファンクション内宣言
- <パラメータ宣言>
- <変数宣言>
- <イベント宣言>
《記述例》
// 2 to 4 デコーダ
function [3:0] dec (input [1:0] din);
case ( din )
0: dec = 4'b0001;
1: dec = 4'b0010;
2: dec = 4'b0100;
3: dec = 4'b1000;
default:
dec = 4'bx;
endcase
endfunction
● task定義
task [automatic] <タスク名> (<タスク・ポート宣言>);
<タスク・ファンクション内宣言>
<ステートメント>
endtask
● タスク・ポート宣言
- input [reg] [signed] [<レンジ>] <ポート名>, <ポート名>, ...
- input [<タスク・ポート型>] <ポート名>, <ポート名>, ...
- output [reg] [signed] [<レンジ>] <ポート名>, <ポート名>, ...
- output [<タスク・ポート型>] <ポート名>, <ポート名>, ...
- inout [reg] [signed] [<レンジ>] <ポート名>, <ポート名>, ...
- inout [<タスク・ポート型>] <ポート名>, <ポート名>, ...
注:task内では 遅延(#~, @~)を記述できるが,function内では不可.
《記述例》
task FF_write( input [3:0] data );
begin
D = data;
#(STEP/2) CK = 1;
#(STEP/2) CK = 0;
end
endtask
● 継続的代入
- assign [<信号強度>] [<遅延>] <ネット型信号名> = <式>, <ネット型信号名> = <式>, ... ;
- <ネット型> [<信号強度>] [signed] [<レンジ>] [<遅延>] <ネット型信号名> = <式>, ... ;
《記述例》
assign #(5:10:15) sum = a + b;
wire (pull1, pull0) [15:0] tribus = reg_A[15:0] + reg_B[15:0]; // 信号強度付き信号への代入