TEXTIO を使用してテストベンチで読み込まれたスティミュラス ファイル
ファイルから信号値を読み取ることは、デバイス オン テスト (DUT) の刺激を生成する別の方法です。テストベンチのシーケンスとタイミングは、VHDL テストベンチによって 1 行ずつ読み込まれるスティミュラス ファイルにハードコードされています。これにより、テスト オブジェクトに供給したい波形のパターンを簡単に変更できます。
場合によっては、DUT に実行させたい非常に特殊なテスト パターンまたは一連のイベントがある場合があります。これを実現するには、ASCII ファイルで、各信号が持つべき信号値と、信号が変化する相対的なシミュレーション時間を指定します。このような戦略における VHDL テストベンチの役割は、スティミュラス ファイルからデータを読み取り、正しいタイミングで DUT 入力に値を適用することです。
この記事は、VHDL でのファイル アクセスに関するシリーズの 2 回目です。以前のブログ投稿で、ファイルから 16 進数、8 進数、および 2 進数の値を読み取る方法について説明しました。 VHDL のライブラリ。
このブログ投稿は、VHDL での TEXTIO ライブラリの使用に関するシリーズの一部です。ここで他の記事を読む:
TEXTIO を使用してファイルから RAM を初期化する方法
TEXTIO を使用して読み取った BMP ファイルのビットマップ イメージ
テスト ケース
サンプル DUT は、私の以前のブログ投稿の 1 つから取られた 4 入力マルチプレクサ (MUX) になります。これは、データ幅が 1 バイトの標準的な非同期 4:1 MUX です。出力のチェックは行わないため、この記事ではどのように機能するかは重要ではありません。これはデモンストレーションのみを目的としています。
MUX の実体を以下に示します。
entity mux_4 is port( -- Data in din_0 : in unsigned(7 downto 0); din_1 : in unsigned(7 downto 0); din_2 : in unsigned(7 downto 0); din_3 : in unsigned(7 downto 0); -- Selector sel : in unsigned(1 downto 0); -- Data out dout : out unsigned(7 downto 0)); end entity;
VHDL ファイルの先頭に必要なパッケージをインポートした後、DUT に接続する入力信号を宣言します。以下のリストからわかるように、これらは MUX エンティティ宣言の設計図です。
signal din_0 : unsigned(7 downto 0); signal din_1 : unsigned(7 downto 0); signal din_2 : unsigned(7 downto 0); signal din_3 : unsigned(7 downto 0); signal sel : unsigned(1 downto 0); signal dout : unsigned(7 downto 0);
エンティティのインスタンス化方法を使用して、テストベンチのアーキテクチャ領域の上部に「DUT」というラベルが付いた MUX のインスタンスを作成します。以下のコードに示すように、エンティティ シグナルは同じ名前のローカル テストベンチ シグナルに接続されます。
DUT: entity work.mux_4(rtl) port map ( din_0 => din_0, din_1 => din_1, din_2 => din_2, din_3 => din_3, sel => sel, dout => dout );
刺激ファイル
スティミュラス ファイルにはさまざまな形式があります。ここで紹介するものは、この記事を書いているときに頭の中で思いついた例にすぎません。それでも、私がどのように作成したかを理解すれば、必要に応じて変更できるはずです。
以下のリストは、この例で使用される完全な刺激ファイルを示しています。
# Column description: # wait_time | sel | din_0 | din_1 | din_2 | din3 # Optional console printout 0 ns 0 AA BB CC DD # Setting initial values 10 ns 1 AA BB CC DD # Testing by changing the selector signal 10 ns 2 AA BB CC DD 10 ns 3 AA BB CC DD 10 ns 3 A1 B1 C1 D1 # Testing by changing all data inputs 10 ns 3 A2 B2 C2 D2 10 ns 3 A3 B3 C3 D3 10 ns 3 00 00 00 D2 # Changing all unselected inputs 10 ns 3 01 02 03 D2 10 ns 3 11 22 33 D2 1 ns 0 CC DD EE FF # Changing all inputs fast 1 ns 1 DD EE FF CC 1 ns 2 EE FF CC DD 1 ns 3 FF CC DD EE 10 ns 0 00 00 00 00 # Simulation stop
ここではコメントを無視しましょう。それらは常に「#」文字で始まる、緑色でマークされたコメントです。各ラインは、シミュレーションの 1 つのタイム ステップを表します。各行には 6 列のコマンドがあり、実際には 7 列のテキストですが、最初の 2 列は同じデータ項目に属しています。
テキスト列 1 と 2 は、他の列にリストされている値を適用する前に、シミュレーターがその行で一時停止する時間の値を記述します。したがって、コマンドが実行されるときの絶対シミュレーション時間は、前の行で記述されたイベントに関連しています。 0、1、または 10 ナノ秒しか使用していませんが、1000 ナノ秒または 1000 時間 (18
)
残りの 5 つのテキスト列は、DUT 入力に適用する信号値を説明しています。これらは 16 進数のリテラルとして与えられ、シグナルの順序は 22
です。 、 35
、 47
、 54
、そして最後に 67
.
では、コメントに移りましょう。コメントには 2 つのタイプがあります。単一行のコメントと末尾のコメント。これらは、テストベンチによって異なる方法で処理されます。ファイルの先頭にあるような単一行のコメントは無視されます。一方、末尾のコメントは、シミュレータ コンソールに出力されます。それらを使用して、シミュレーションの実行中に何が起こっているかについての手がかりを得ることができます。
VHDL のスティミュラス ファイルの読み取り
VHDL はテキスト処理に最適な言語ではありませんが、十分に機能します。動的文字列のサポートは制限されており、空白の削除やスキップなどの便利なルーチンが不足しています。簡単にするために、スティミュラス ファイルが適切に作成されていると仮定します。テキスト要素の間に常に 1 つのスペースがあり、「#」文字とコメント テキストの間に単一のスペースがあることを確認するように細心の注意を払いましょう。また、刺激ファイルのどこにも余分な先頭または末尾のスペースはありません。
PROC_SEQUENCER : process file text_file : text open read_mode is "stimulus.txt"; variable text_line : line; variable ok : boolean; variable char : character; variable wait_time : time; variable selector : sel'subtype; variable data : dout'subtype; begin
75
の宣言領域 手順を上に示します。まず、特別な 85
を宣言します オブジェクト、VHDL ファイル ハンドラー タイプ。次に、90
型の変数を宣言します。 .これは単に文字列へのアクセス タイプであり、動的に割り当てられた文字列オブジェクトへのポインタです。 108
ブール型の変数は、読み取り操作が成功したことを確認するためのものです。最後に、4 つの変数 118
を宣言します。 、 126
、 130
、および 149
.これらの変数は、テキストのすべての行から各列のデータを抽出するためのものです。
while not endfile(text_file) loop readline(text_file, text_line); -- Skip empty lines and single-line comments if text_line.all'length = 0 or text_line.all(1) = '#' then next; end if;
プロセス本体では、スティミュラス ファイル内のすべてのテキスト行を反復処理する while ループに直接進みます。 154
プロシージャは 168
に新しいテキスト行を割り当てます このループの反復ごとに変数。行を読み取った後、行が空であるか、最初の文字が「#」であるかどうかを確認します。その場合、173
を使用してすぐに次の行に移動します。 ループの繰り返しをスキップするキーワード。 184
を使用していることに注意してください 193
内の文字列にアクセスするには オブジェクト。
read(text_line, wait_time, ok); assert ok report "Read 'wait_time' failed for line: " & text_line.all severity failure; hread(text_line, selector, ok); assert ok report "Read 'sel' failed for line: " & text_line.all severity failure; sel <= selector; hread(text_line, data, ok); assert ok report "Read 'din_0' failed for line: " & text_line.all severity failure; din_0 <= data; hread(text_line, data, ok); assert ok report "Read 'din_1' failed for line: " & text_line.all severity failure; din_1 <= data; hread(text_line, data, ok); assert ok report "Read 'din_2' failed for line: " & text_line.all severity failure; din_2 <= data; hread(text_line, data, ok); assert ok report "Read 'din_3' failed for line: " & text_line.all severity failure; din_3 <= data;
次に、205
からの多数の読み取りが続きます。 物体。 216
と 229
233
内の内部読み取り開始位置を移動するためにダミー読み取りを行う必要がないように、プロシージャ呼び出しは先頭のスペースをスキップします。 物体。 assert ステートメントを省略することもできましたが、読み取りが失敗した場合はシミュレーションを停止したいと考えています。少なくとも ModelSim では、これが発生してもシミュレーションは自動的に停止しません。 243
を除いて、正常に読み取られた各変数を関連する DUT 信号に割り当てます。 対応する DUT 入力を持たない変数。
wait for wait_time;
シグナル値を割り当てた後、指定された時間待機します。待機ステートメントにヒットすると、スケジュールされたシグナル値が同じデルタ サイクルで有効になります。
-- Print trailing comment to console, if any read(text_line, char, ok); -- Skip expected newline read(text_line, char, ok); if char = '#' then read(text_line, char, ok); -- Skip expected newline report text_line.all; end if; end loop; finish; end process;
最後に、プログラムが待機ステートメントから復帰すると、255
の追加の末尾のコメントを探します。 物体。コメントは、ダミー読み取りを使用して「#」文字とそれに続く空白を取り除いた後、report ステートメントを使用してコンソールに出力されます。
スティミュラス ファイルのテキストの最後の行が処理された後、while ループは終了します。 VHDL-2008 267
があります テストベンチの停止を担当するプロセスの最後にあるキーワード。
アウトプット
サンプル テストベンチは、ModelSim で実行されると、以下に示すテキストをシミュレータ コンソールに出力します。コメントは刺激ファイルからのものであることがわかります。出力された時間値は、スティミュラス ファイルで指定されたナノ秒の遅延に基づく累積シミュレーション時間です。
# ** Note: Setting initial values # Time: 0 ns Iteration: 1 Instance: /file_stim_tb # ** Note: Testing by changing the selector signal # Time: 10 ns Iteration: 0 Instance: /file_stim_tb # ** Note: Testing by changing all data inputs # Time: 40 ns Iteration: 0 Instance: /file_stim_tb # ** Note: Changing all unselected inputs # Time: 70 ns Iteration: 0 Instance: /file_stim_tb # ** Note: Changing all inputs fast # Time: 91 ns Iteration: 0 Instance: /file_stim_tbf # ** Note: Simulation stop # Time: 104 ns Iteration: 0 Instance: /file_stim_tb # Break in Process PROC_SEQUENCER at file_stim_tb.vhd line 98
シミュレーションの波形を以下に示します。これは、指定されたシミュレーション時間で、スティミュラス ファイルの値がシグナルにどのように適用されるかを視覚的に表したものです。
最終的な考え
適用する必要がある非常に特殊なテスト パターンがある場合は、ファイルからテストベンチ スティミュラスを読み取ると有利な場合があります。テストベンチ全体をテキスト ファイルで制御する必要はありません。この例は、VHDL でのファイル アクセスの可能性を示すことを目的としています。
ただし、DUT 出力のチェックについては、まだ説明していません。サンプル テストベンチは、出力をまったくチェックしません。たとえばビヘイビア モデルを使用して比較することにより、完全な VHDL テストベンチと同じように DUT の動作を検証できます。または、コードとスティミュラス ファイルを変更して、予想される出力値を含めることもできます。どちらの戦略を選択する場合でも、セルフチェック テストベンチを作成し、波形の手動チェックに頼らないようにしてください。
VHDL