初めてでも使えるVHDL文法ガイド ―― 記述スタイル編
tag: 半導体 ディジタル・デザイン
技術解説 2009年7月27日
4.シミュレーション記述
4.1 シミュレーション記述の構造と記述例
● シミュレーション記述も回路記述と同じ構造
シミュレーション記述の実際の例をリスト5に示します.シミュレーション対象は,リスト2の4ビット・カウンタです.
リスト5 シミュレーション記述
シミュレーション記述は,回路記述とほぼ同様に,
- パッケージ呼び出し
- エンティティ
- アーキテクチャ
- コンフィグレーション宣言
から構成されています.
呼び出すパッケージは,回路記述に用いる標準的なもの以外に,シミュレーション記述に必要な,例えばファイル・アクセス用のパッケージを呼び出すこともあります.リスト5では,回路記述と同じものだけを呼び出しています.
シミュレーションの最上位階層には,入力や出力はありません.したがってエンティティは,ポート宣言などのない空のエンティティとなります.
● アーキテクチャ宣言部で,接続の準備
アーキテクチャの宣言部(isとbeginの間)には,
- コンポーネント宣言(検証対象のエンティティ部分)
- 定数宣言(クロックの周期などを設定)
- 内部信号宣言
があります.
コンポーネント宣言は下位ブロックを呼び出すために必要です.階層を持った回路記述でも同様でした.コンポーネント宣言の記述内容は,その階層のエンティティとほぼ同じです.
定数は,コンスタント宣言を用いて設定します.この例では,1周期を示す定数CYCLEを100nsに設定しています.
VHDLは,定数にも型があります.定数CYCLEは,時刻型の定数です.この型は以下のような単位を付けることができます.
fs, ps, ns, us, ms, sec, min, hr
これらの単位表現と,数値の間にはスペースが必要です.100nsなどと付けて記述すると文法エラーです.
呼び出す検証対象ブロックに接続される信号は,すべて信号(signal)宣言します.
● アーキテクチャ本体で,シミュレーション入力を記述
検証対象の呼び出しは,アーキテクチャ本体で行います.もし,シミュレーション・モデルなどがあれば,ここで検証対象に接続します.
回路記述では,プロセス文のセンシティビティ・リストが必要でした.組み合わせ回路では入力のすべてが,順序回路ではクロックや非同期のリセット信号などがセンシティビティ・リストに記述されていました.
クロックの記述のようにセンシティビティ・リストがなければ,「無限ループ」として動作します.リスト5では,半周期ごとにCK信号に0,1,0,1,...を印加しています.
テスト入力の簡単な記述方法に,「遅延を与えて入力を変化させる」方法があります.ここでは,プロセス文の中で入力resに順次信号を与えています.プロセス文は「無限ループ」的な動作ですが,無条件のwait文を記述することで,処理を停止することができます.
wait文には,
- wait for 時間 : 記述した時間待つ
- wait until 条件 : 条件が真になるまで待つ
- wait on 信号,信号,...: 信号に変化があるまで待つ
の三つの形式があります.
さらに,これらを組み合わせて,
wait on 信号 for 時間 :信号に変化があるかどうか時間が来るまで待つ
wait until 条件 for 時間:条件が真になるかどうか時間が来るまで待つ
などとできます.
また,
wait
と,条件を何も記述しなければ,それ以降の記述は実行されません.processの中で記述されていれば,そのプロセス文の実行は停止します.
● コンフィグレーション宣言はシミュレータに依存
コンフィグレーション宣言は,本来エンティティとアーキテクチャを結びつけるものです.しかし実際の回路記述では,複数のアーキテクチャを持つことはほとんどありません.つまり,エンティティに対して一つのアーキテクチャしか持ちません.
リスト5のシミュレーション記述でも同様ですが,シミュレータが最上位階層のコンフィグレーション宣言を必要としているため,エンティティcount_tpとアーキテクチャSIMを結びつけるコンフィグレーション宣言を記述しています.
4.2 テスト入力の作成
「シミュレーション記述を作成する」ことは,言い換えればテスト入力を作成することにほかなりません.内部信号を宣言したり,検証対象を呼び出したりすることは,シミュレーション記述作成の準備にすぎません.
以下に3種類のテスト入力作成方法を解説します.
● その1:遅延を与えて入力を変化させる
簡易的なテスト入力作成方法です.ここでは遅延の与えかたに応じて,3種類の方法を示します.
(1) 相対遅延を与える
まず相対的な遅延を与える方法です(リスト6(a)).wait forを用いて単純に「待ち」を作っています.一般的にシステム・クロックの1周期ごとに遅延させ,入力を変化させます.リスト6(a)のように1周期の時間を定数STEPにコンスタント宣言しておき,STEPごとに入力を変化させます.遅延を与えることがシミュレーションを進めることになります.
リスト6 テスト入力作成法1 ―― 遅延を与えて入力を変化
(2) 絶対遅延を与える
次の方法が絶対遅延です(リスト6(b)).この例では,res信号に,初期値'0',絶対時間100nsで'1', 200nsで'0'というように,シミュレーション開始を0nsとした絶対時間で信号が変化する時間を表現しています.信号resについては同時処理代入文で記述しています.つまり相対遅延と違って,プロセス文中ではなくアーキテクチャ内の直下で記述しています.
(3) クロック・エッジからの相対遅延
もう一つの方法がクロック・エッジからの相対遅延です(リスト6(c)).システム・クロックCLKの立ち上がりを待って,ここから10ns,25nsなどの遅延を与えています.この,
wait until CLK'event and CLK='1';
という記述は,順序回路のもう一つの記述スタイルでも紹介したように,
「CLKの立ち上がりを待つ」
という意味です.
● その2:テスト入力をファイルから読み込む
多量のテスト・パターンを一気に印加してシミュレーションを行うためには,パターン・ファイルを読み込んでテスト入力として印加する方法があります.
図10にファイルからの読み込み例を示します.ファイル・アクセス用の手続き類は専用のパッケージに格納されており,これらを呼び出す必要があります.TEXTIOと呼ばれるパッケージ類です.
![]() (a) 入力ファイル |
![]() (b) 記述例 |
図10 テスト入力作成法2 ―― ファイルからの読み込み
ここでは,入力ファイルを1行ずつ読み込んで,WEB信号とDIN信号に印加しています.
ファイル・アクセスのために,
- ファイル・アクセス用のパッケージ(std_logic_textioとtextio)の読み込み
- ファイル変数宣言(file VECTOR: TEXT is in "pat_file. txt";)
- ライン・バッファ宣言(variable V_LI: line;)
などの準備を行います.
ファイルの読み込みは,
- readlineでライン・バッファへ読み込む
- readで1信号ずつ読み込む
の手順で行います.
● その3:プロシージャを使ったテスト入力
プロシージャを用いれば,シミュレーション記述のサブルーチン化が可能です.図11(a)のようなCPUのバスをイメージした入力を与える場合,1クロックごとに印加するのではなく,バスのシーケンスそのものを記述できます.
![]() (a) 書き込みシーケンスの波形 |
![]() (b) 記述例 |
図11 テスト入力の作成法3 ―― プロシージャ(タスク)を使う
図11(b)では,アドレスとデータを引き数にした,write_regというプロシージャを宣言しています.これは図11(a)の書き込みシーケンスをそのまま一つのプロシージャで表現したものです.これにより,
write_reg(アドレス,データ);
の形式で呼び出すことができ,わかりやすく確実なテスト入力が得られます.
プロシージャの定義は,
- パッケージ
- エンティティ
- アーキテクチャの宣言部
- プロセスの宣言部
などで可能です.一般的には,パッケージ内か,アーキテクチャの宣言部で定義します.