タスクでテストベンチを効率化する
(1)ここで学ぶ内容
概要
- テストベンチの記述効率を高める
taskについて理解する - CPUのバス動作など
taskの記述例を学ぶ
目標
以下の項目を理解し説明できる
taskの定義と呼び出しtaskの引き数taskによるテストベンチの記述taskとfunctionの共通点と相違点
修了判定1
本文に示した基本タスクの動作確認をする
設問:CPUバスのReadアクセス(指定したアドレスからデータを読み出す)を行う task である cpu_read を記述せよ。アドレスを引数で受け取り、読み出したデータを別の引数で返すこと。
解答例
task cpu_read;
input [7:0] adr; // 読み出し先アドレス
output [7:0] dat; // 読み出したデータ
begin
// アドレスと制御信号をセット
ADDR = adr;
CS_N = 1'b0;
RD_N = 1'b0;
WR_N = 1'b1;
// 1サイクル待ってデータを取得
@(posedge CLK);
dat = DATA_OUT;
// 制御信号をネゲート
CS_N = 1'b1;
RD_N = 1'b1;
@(posedge CLK);
end
endtask
修了判定2
データ入力付きカウンタの、データ入力動作をタスクで記述する
修了判定3
シミュレータを使って、データ入力タスクの動作確認を行う
条件:修了判定2を先に実施する
普通のプログラミングではサブルーチンをつかって効率的に処理を表現しています。VerilogHDLのタスクもサブルーチンと同じように使えます。タスクを覚えるとテストベンチがすっきりかけます。
(2)taskとは
initial 文の begin〜end の中に記述されたテストベンチは、記述の順番に実行されます。
記述の中で同じ処理を何回も実行することがあれば、この処理をまとめることが出来ます。そしてまとめた処理に名前をつけて、initial 文側で呼び出すことでテストベンチを簡潔にまとめることが出来ます。
この場合処理ABCが二か所で呼び出されています。戻り場所はそれぞれ呼び出した場所になります。VerilogHDLではこのような仕組みをタスクと呼びます。
initial 文(呼び出し側)
処理ABC(タスク定義)
(3)taskの定義と呼び出し
タスクを利用するときにはタスクを定義する記述とテスト入力側で呼び出す記述が必要です。タスクもモジュールアイテムですので、モジュール内で定義します。タスクの呼び出しはステートメントですので、initial 文などの中で記述します。
テストベンチの構成
tasktaskの定義endtask
initial begin・テスト入力作成
・taskの呼び出し
end
taskの定義
task タスク名;
引数宣言
内部信号宣言
begin
処理の記述
end
endtask
taskの呼び出し
タスク名(引き数, 引き数, ...);
- タスクの定義は
taskで始まりendtaskで終わる taskに続いて、タスク名・引き数宣言・内部信号を宣言する- 引数や内部信号のないタスクも存在する
- タスクの処理は多くの場合2行以上になるので
begin〜endが必要 - 引数のないタスクではタスク名とセミコロンだけで呼び出せる
(4)taskによるテストベンチ記述例
タスクの簡単な記述例を紹介します。アップダウンカウンタのテストベンチに利用した例です。このカウンタに対し、リセット→カウントアップ→リセット→カウントダウンを行っています。
アップダウン・カウンタ
| 端子 | 説明 |
|---|---|
| CK | 立ち上がりで up/down |
| RES | 1で非同期リセット |
| UP | 1のとき up、0のとき down |
| Q | カウンタ出力(4bit) |
reg CK, RES, UP;
initial begin // テスト入力
UP = 0; // 初期設定
reset_counter; // カウンタのリセット
UP = 1; // カウントアップ
#(STEP*20);
reset_counter; // カウンタのリセット
UP = 0; // カウントダウン
#(STEP*20);
$finish;
end
タスクの定義(カウンタのリセット)
task reset_counter;
begin
RES = 0;
#STEP RES = 1;
#STEP RES = 0;
end
endtask
←STEP→←STEP→
|‾‾‾‾|
RES ____| 1 |____
- モジュール内で宣言した信号
RESに対し、タスク内で参照・代入できる - タスクの中に遅延を記述できるため、呼び出すたびにシミュレーション時刻が進む
(5)taskの引き数
引数とはタスクの呼び出し側と処理側でデータのやり取りをする仕組みです。引数はタスク名に続いて宣言します。モジュールのポートと同じく input, output, inout の3種類があります。
引数の方向
| 宣言 | 意味 |
|---|---|
input | タスクの中で参照する(呼び出し側→タスク) |
output | タスクの中で代入する(タスク→呼び出し側) |
inout | タスクの中で参照/代入する |
taskの定義(構造)
task タスク名;
引数宣言
内部信号宣言
begin
処理の記述
end
endtask
taskの呼び出し
タスク名(引き数, 引き数, ...);
引数ありタスクの記述例
task count_updown;
input dir;
begin
UP = dir;
#(STEP*20);
end
endtask
呼び出し例
reset_counter;
count_updown(1'b1);
reset_counter;
count_updown(1'b0);
- 呼び出し側で実際に与える引数 → 実引き数
- 定義側で宣言した引数 → 仮引き数
| 引数方向 | 実引き数に使用できる型 |
|---|---|
input | 定数、ネット型(wire)、レジスタ型(reg) |
output | レジスタ型(reg)だけ |
inout | レジスタ型(reg)だけ |
(6)taskの効果的な利用
タスクは本格的なテストベンチの作成に効果的です。例えばCPUに接続される周辺チップを設計し、検証しているとします。CPUはこのチップに対し内部レジスタへの書き込みを行います。また、内部レジスタの読み出しを行います。
書き込みや読み出しの一連の動作をタスクで記述 → バスモデル
システム全体のボードレベル検証にとても役立つ
(7)taskによるバス動作の記述
検証対象の回路を想定して、タスクの記述例を紹介します。この回路には8ビットの内部レジスタが4つあります。これらを区別するための2ビットのアドレス信号A、8ビットのデータ入力DIN、データ出力DOUTがあります。また読み出し信号REB、書き込み信号WEBがあり、これらは0で動作します。
検証対象回路(DUT)
| 端子 | 幅 | 説明 |
|---|---|---|
| A | 2 | アドレス入力 |
| DIN | 8 | データ入力 |
| DOUT | 8 | データ出力 |
| REB | 1 | 読み出し信号(0で動作) |
| WEB | 1 | 書き込み信号(0で動作) |
書き込みタイミング(3クロック/1データ)
←100nS→
CLK _|‾|_____|‾|_____
←25nS→
A[1:0] ‾‾‾‾addr‾‾‾‾‾‾
←25nS→
DIN[7:0] ‾‾‾data‾‾‾‾‾‾
←25nS→←200nS→←25nS→
WEB ‾‾‾‾‾‾‾|_____|‾‾‾‾
initialブロック内] TB1 --> W1[CS=1, WR=0, ADDR=0, DATA=A
#10 CS=0, WR=1] TB1 --> W2[CS=1, WR=0, ADDR=1, DATA=B
#10 CS=0, WR=1] TB1 --> W3[CS=1, WR=0, ADDR=2, DATA=C
#10 CS=0, WR=1] end style TB1 fill:#ffebee,stroke:#c62828;
initialブロック内] TASK{{task cpu_write
バスの制御手順をカプセル化}} TB2 -->|cpu_write(0, A)| TASK TB2 -->|cpu_write(1, B)| TASK TB2 -->|cpu_write(2, C)| TASK end style TB2 fill:#e8f5e9,stroke:#388e3c; style TASK fill:#e3f2fd,stroke:#1976d2;
バスモデルの記述
// 接続信号宣言
reg [1:0] A;
reg [7:0] DIN;
reg REB, WEB;
wire [7:0] DOUT;
// レジスタへの書き込みタスク
task write_reg;
input [1:0] addr;
input [7:0] data;
begin
# 25 A = addr;
# 25 DIN = data;
# 25 WEB = 0 ;
#200 WEB = 1 ;
# 25 ;
end
endtask
// タスクの呼び出し
initial begin
WEB = 1;
write_reg( 2'h0, 8'h03 );
write_reg( 2'h2, 8'hFC );
end
- システムクロック3周期(300ns)で1データの書き込み
- 0番レジスタに
03、2番レジスタにFCを書き込む
(8)task と function の共通点
task と function には以下の共通点があります。
- 内部信号を宣言して使用できる(
parameterも宣言できる) - 仮引き数・実引き数がある
- 定義部と呼び出し部がある
- モジュール内に記述する(モジュール外に記述するとエラー)
- モジュール内の信号にアクセスできる(ただし
functionでは実行時に誤りを起こしやすいため非推奨)
task — 内部信号の宣言例
task TEMP;
input a;
reg b;
begin
b = 1;
...
endtask
function — 内部信号の宣言例
function FUNC;
input a;
reg b;
begin
b = 1;
...
endfunction
(2)仮引き数・実引き数の例(task)
task TEMP;
input a;
...
endtask
initial begin
TEMP( EN ); // EN が実引き数
...
end
(2)仮引き数・実引き数の例(function)
function FUNC;
input a;
...
endfunction
assign Q = FUNC( EN ); // EN が実引き数
(4)モジュール内に記述(task)
module XYZ;
...
task TEMP;
input a;
...
endtask
...
endmodule
(4)モジュール内に記述(function)
module XYZ;
...
function FUNC;
input a;
...
endfunction
...
endmodule
(5)モジュール内の信号アクセス(task)
module XYZ;
...
reg a;
task TEMP;
... // a に代入できる
endtask
...
endmodule
(5)モジュール内の信号アクセス(function)
module XYZ;
...
reg a;
function FUNC;
...
FUNC = a; // 実行時の誤りを起こしやすい
endfunction
...
endmodule
function では引数宣言せずにモジュール内の信号を参照するのは避けること
(9)task と function の相違点
| task | function | |
|---|---|---|
| (1)引き数 | 入力・出力・双方向すべてOK | 入力だけ |
| (2)戻り値の数 | output 宣言すればいくつでも |
ファンクション名に代入するので1つだけ |
| (3)遅延の記述 | 記述できる | 記述できない(文法エラーになる) |
| (4)呼び出し側 | ステートメント | 式 |
| (5)主な用途 | テストベンチ | 組み合わせ回路 |
(1)引き数
// task: 入力・出力・双方向すべてOK
task TEMP;
input a;
output b;
inout c;
...
endtask
// function: 入力だけ
function FUNC;
input a;
...
endfunction
(2)戻り値の数
// task: output宣言すればいくつでも
task TEMP;
output a, b, c;
...
endtask
// function: ファンクション名に代入→1つだけ
function FUNC;
...
FUNC = 1;
endfunction
(3)遅延の記述
// task: 遅延を記述できる
task TEMP;
...
#STEP a = 0; // OK
...
endtask
(3)遅延の記述
// function: 遅延を記述できない
function FUNC;
...
#STEP FUNC = 1; // エラー
endfunction
(4)呼び出し側 — task はステートメント
initial begin
...
COUNT( EN ); // ステートメントとして呼び出す
...
end
(4)呼び出し側 — function は式
always @( posedge CK )
Q <= FUNC( EN ); // 式として使用できる
// 代入文の右辺、入力引き数、モジュール接続の入力ポートなど
(5)主な用途 — task
task WRITE_REG;
input ADDR;
input DATA;
...
endtask // テストベンチ向き
(5)主な用途 — function
function [3:0] SUM;
...
SUM = A + B;
endfunction // 組み合わせ回路向き
task で順序回路、function でテストベンチを書くことも可能
(10)ワンポイント・アドバイス
テストベンチも「階層構造」
initial begin ... 応用タスク呼び出し ... end
- 基本タスクを呼び出して機能を起動
- 内部レジスタの読み/書き
- 外部ファイルのアクセス
テストベンチ本体から検証対象に直接アクセスせず、すべてタスクを通じて制御することで効率的な検証が行える
(11)修了判定1
write_reg と、ここに示すタスク read_reg の動作確認をする。ファイル:basic_task.v
read_reg タスクの定義
task read_reg;
input [1:0] addr;
output [7:0] data;
begin
# 25 A = addr;
#100 REB = 0 ;
#150 data = DOUT;
REB = 1 ;
# 25 ;
end
endtask
読み出しタイミング(3クロック/1データ)
←100nS→
CLK _|‾|_____|‾|_____
←25nS→
A[1:0] ‾‾‾‾addr‾‾‾‾‾‾
←100nS→←150nS→←25nS→
REB ‾‾‾‾‾‾‾|____|‾‾‾‾‾‾‾‾
DOUT[7:0] DOUT出力
↑dataへ取り込み
シミュレーション波形(修了判定1)
| 信号名 | 波形の変化(各ステップ) | |||||||
|---|---|---|---|---|---|---|---|---|
| CLK | 高速クロック繰り返し | |||||||
| A[1:0] | 0 | 1 | 2 | 3 | 1 | 3 | 0 | 2 |
| DIN[7:0] | 10 | a5 | f7 | 03 | — | |||
| WEB | 書き込み期間(0で動作) | 読み出し期間 | ||||||
| REB | 1(非活性) | 0で活性(読み出し) | ||||||
| DOUT[7:0] | zz(出力なし) | a5 | 03 | 10 | f7 | |||
シミュレーション出力ログ(抜粋)
0 CLK=1 DIN=xx WEB=1 REB=1 DOUT=zz 25 CLK=1 A=0 DIN=xx WEB=1 REB=1 DOUT=zz 50 CLK=0 A=0 DIN=10 WEB=1 REB=1 DOUT=zz 75 CLK=0 A=0 DIN=10 WEB=1 REB=1 DOUT=zz 100 CLK=1 A=0 DIN=10 WEB=0 REB=1 DOUT=zz 150 CLK=0 A=0 DIN=10 WEB=0 REB=1 DOUT=zz 200 CLK=0 A=0 DIN=10 WEB=0 REB=1 DOUT=zz 250 CLK=0 A=0 DIN=10 WEB=0 REB=1 DOUT=zz 275 CLK=0 A=0 DIN=10 WEB=1 REB=1 DOUT=zz 300 CLK=1 A=0 DIN=10 WEB=1 REB=1 DOUT=zz 325 CLK=1 A=1 DIN=10 WEB=1 REB=1 DOUT=zz 350 CLK=0 A=1 DIN=a5 WEB=1 REB=1 DOUT=zz 375 CLK=0 A=1 DIN=a5 WEB=0 REB=1 DOUT=zz 400 CLK=1 A=1 DIN=a5 WEB=0 REB=1 DOUT=zz 450 CLK=0 A=1 DIN=a5 WEB=0 REB=1 DOUT=zz 500 CLK=1 A=1 DIN=a5 WEB=0 REB=1 DOUT=zz 550 CLK=0 A=1 DIN=a5 WEB=0 REB=1 DOUT=zz 575 CLK=0 A=1 DIN=a5 WEB=1 REB=1 DOUT=zz 600 CLK=1 A=1 DIN=a5 WEB=1 REB=1 DOUT=zz 625 CLK=1 A=2 DIN=a5 WEB=1 REB=1 DOUT=zz 650 CLK=0 A=2 DIN=f7 WEB=1 REB=1 DOUT=zz 675 CLK=0 A=2 DIN=f7 WEB=0 REB=1 DOUT=zz 700 CLK=1 A=2 DIN=f7 WEB=0 REB=1 DOUT=zz 750 CLK=0 A=2 DIN=f7 WEB=0 REB=1 DOUT=zz 800 CLK=1 A=2 DIN=f7 WEB=0 REB=1 DOUT=zz 850 CLK=0 A=2 DIN=f7 WEB=0 REB=1 DOUT=zz 875 CLK=0 A=2 DIN=f7 WEB=1 REB=1 DOUT=zz 900 CLK=1 A=2 DIN=f7 WEB=1 REB=1 DOUT=zz 925 CLK=1 A=3 DIN=f7 WEB=1 REB=1 DOUT=zz 950 CLK=0 A=3 DIN=03 WEB=1 REB=1 DOUT=zz 975 CLK=0 A=3 DIN=03 WEB=0 REB=1 DOUT=zz 1000 CLK=1 A=3 DIN=03 WEB=0 REB=1 DOUT=zz 1050 CLK=0 A=3 DIN=03 WEB=0 REB=1 DOUT=zz 1100 CLK=1 A=3 DIN=03 WEB=0 REB=1 DOUT=zz 1150 CLK=0 A=3 DIN=03 WEB=0 REB=1 DOUT=zz 1175 CLK=0 A=3 DIN=03 WEB=1 REB=1 DOUT=zz 1200 CLK=1 A=3 DIN=03 WEB=1 REB=1 DOUT=zz 1225 CLK=1 A=1 DIN=03 WEB=1 REB=1 DOUT=zz 1250 CLK=0 A=1 DIN=03 WEB=1 REB=1 DOUT=zz 1300 CLK=1 A=1 DIN=03 WEB=1 REB=1 DOUT=zz 1325 CLK=1 A=1 DIN=03 WEB=1 REB=0 DOUT=a5 1350 CLK=0 A=1 DIN=03 WEB=1 REB=0 DOUT=a5 1400 CLK=0 A=1 DIN=03 WEB=1 REB=0 DOUT=a5 1450 CLK=0 A=1 DIN=03 WEB=1 REB=0 DOUT=a5 1475 CLK=0 A=1 DIN=03 WEB=1 REB=1 DOUT=zz 1500 CLK=1 A=1 DIN=03 WEB=1 REB=1 DOUT=zz 1525 CLK=1 A=3 DIN=03 WEB=1 REB=1 DOUT=zz 1550 CLK=0 A=3 DIN=03 WEB=1 REB=1 DOUT=zz 1600 CLK=1 A=3 DIN=03 WEB=1 REB=0 DOUT=03 1625 CLK=1 A=3 DIN=03 WEB=1 REB=0 DOUT=03 1650 CLK=0 A=3 DIN=03 WEB=1 REB=0 DOUT=03 1700 CLK=0 A=3 DIN=03 WEB=1 REB=0 DOUT=03 1750 CLK=0 A=3 DIN=03 WEB=1 REB=0 DOUT=03 1775 CLK=0 A=3 DIN=03 WEB=1 REB=1 DOUT=zz 1800 CLK=1 A=3 DIN=03 WEB=1 REB=1 DOUT=zz 1825 CLK=1 A=0 DIN=03 WEB=1 REB=1 DOUT=zz 1850 CLK=0 A=0 DIN=03 WEB=1 REB=1 DOUT=zz 1900 CLK=1 A=0 DIN=03 WEB=1 REB=0 DOUT=10 1925 CLK=1 A=0 DIN=03 WEB=1 REB=0 DOUT=10 1950 CLK=0 A=0 DIN=03 WEB=1 REB=0 DOUT=10 2000 CLK=1 A=0 DIN=03 WEB=1 REB=0 DOUT=10 2050 CLK=0 A=0 DIN=03 WEB=1 REB=0 DOUT=10 2075 CLK=0 A=0 DIN=03 WEB=1 REB=1 DOUT=zz 2100 CLK=1 A=0 DIN=03 WEB=1 REB=1 DOUT=zz 2125 CLK=1 A=2 DIN=03 WEB=1 REB=1 DOUT=zz 2150 CLK=0 A=2 DIN=03 WEB=1 REB=1 DOUT=zz 2200 CLK=1 A=2 DIN=03 WEB=1 REB=0 DOUT=f7 2225 CLK=1 A=2 DIN=03 WEB=1 REB=0 DOUT=f7 2250 CLK=0 A=2 DIN=03 WEB=1 REB=0 DOUT=f7 2300 CLK=1 A=2 DIN=03 WEB=1 REB=0 DOUT=f7 2350 CLK=0 A=2 DIN=03 WEB=1 REB=0 DOUT=f7 2375 CLK=0 A=2 DIN=03 WEB=1 REB=1 DOUT=zz
(12)修了判定2
data_load を完成する
COUNT4LD 回路の仕様
| RES | LD | CK | Q |
|---|---|---|---|
| 1 | X | X | 0 |
| 0 | 1 | ↑ | D |
| 0 | 0 | ↑ | Q₀+1 |
←STEP→
CK _|‾|______|‾|___
LD ‾‾‾‾|___|‾‾‾‾‾‾
D ← 4'h9 →
クロック2周期分のタスク
data_load タスクの記述(完成形)
reg CK, RES, LD; // カウンタ入力
reg [3:0] D; // カウンタ入力
wire [3:0] Q; // カウンタ出力
// 検証対象(カウンタ)接続
COUNT4LD C1( CK, RES, LD, D, Q );
// データのロードを行うタスク
// 呼び出し例: data_load( 4'h9 );
task data_load;
input [3:0] din;
begin
#(STEP/2) LD = 1;
D = din;
#STEP LD = 0;
#(STEP/2);
end
endtask
(13)修了判定3
data_load の動作を確認する。条件:修了判定2を先に実施する
| ファイル種別 | ファイル名 |
|---|---|
| 回路記述ファイル | count4ld.v |
| テストベンチ・ファイル | count4ld_test.v |
シミュレーション波形(修了判定3)
| 信号名 | 変化の様子 |
|---|---|
| CK | 高速クロック繰り返し |
| RES | 最初だけ短時間 HIGH(非同期リセット) |
| LD | data_load 呼び出し時に 1 → 0 と変化 |
| D[3:0] | 0 → 9(0x9)→ 6(0x6)と変化 |
| Q[3:0] | 0 1 2 3 4 5 6 7 8 9 a b c d e f | 0 1 2 3 4 5 9 a b c d e f | 0 1 2 6 7 8 9 a b c d e f ... |
シミュレーション出力ログ(抜粋)
0 CK=1 RES=0 LD=0 D=0 Q=x
500 CK=0 RES=1 LD=0 D=0 Q=0
1000 CK=1 RES=1 LD=0 D=0 Q=0
1500 CK=0 RES=0 LD=0 D=0 Q=0
2000 CK=1 RES=0 LD=0 D=0 Q=1
2500 CK=0 RES=0 LD=0 D=0 Q=1
3000 CK=1 RES=0 LD=0 D=0 Q=2
3500 CK=0 RES=0 LD=0 D=0 Q=2
4000 CK=1 RES=0 LD=0 D=0 Q=3
4500 CK=0 RES=0 LD=0 D=0 Q=3
5000 CK=1 RES=0 LD=0 D=0 Q=4
5500 CK=0 RES=0 LD=0 D=0 Q=4
6000 CK=1 RES=0 LD=0 D=0 Q=5
6500 CK=0 RES=0 LD=0 D=0 Q=5
7000 CK=1 RES=0 LD=0 D=0 Q=6
7500 CK=0 RES=0 LD=0 D=0 Q=6
8000 CK=1 RES=0 LD=0 D=0 Q=7
8500 CK=0 RES=0 LD=0 D=0 Q=7
9000 CK=1 RES=0 LD=0 D=0 Q=8
9500 CK=0 RES=0 LD=0 D=0 Q=8
10000 CK=1 RES=0 LD=0 D=0 Q=9
10500 CK=0 RES=0 LD=0 D=0 Q=9
11000 CK=1 RES=0 LD=0 D=0 Q=a
11500 CK=0 RES=0 LD=0 D=0 Q=a
12000 CK=1 RES=0 LD=0 D=0 Q=b
12500 CK=0 RES=0 LD=0 D=0 Q=b
13000 CK=1 RES=0 LD=0 D=0 Q=c
13500 CK=0 RES=0 LD=0 D=0 Q=c
14000 CK=1 RES=0 LD=0 D=0 Q=d
14500 CK=0 RES=0 LD=0 D=0 Q=d
15000 CK=1 RES=0 LD=0 D=0 Q=e
15500 CK=0 RES=0 LD=0 D=0 Q=e
16000 CK=1 RES=0 LD=0 D=0 Q=f
16500 CK=0 RES=0 LD=0 D=0 Q=f
17000 CK=1 RES=0 LD=0 D=0 Q=0
17500 CK=0 RES=0 LD=0 D=0 Q=0
18000 CK=1 RES=0 LD=0 D=0 Q=1
18500 CK=0 RES=0 LD=0 D=0 Q=1
19000 CK=1 RES=0 LD=0 D=0 Q=2
19500 CK=0 RES=0 LD=0 D=0 Q=2
20000 CK=1 RES=0 LD=0 D=0 Q=3
20500 CK=0 RES=0 LD=0 D=0 Q=3
21000 CK=1 RES=0 LD=0 D=0 Q=4
21500 CK=0 RES=0 LD=0 D=0 Q=4
22000 CK=1 RES=0 LD=1 D=9 Q=9 ← data_load(9) ロード
22500 CK=0 RES=0 LD=1 D=9 Q=9
23000 CK=1 RES=0 LD=0 D=9 Q=9
23500 CK=0 RES=0 LD=0 D=9 Q=9
24000 CK=1 RES=0 LD=0 D=9 Q=a
24500 CK=0 RES=0 LD=0 D=9 Q=a
25000 CK=1 RES=0 LD=0 D=9 Q=b
25500 CK=0 RES=0 LD=0 D=9 Q=b
26000 CK=1 RES=0 LD=0 D=9 Q=c
26500 CK=0 RES=0 LD=0 D=9 Q=c
27000 CK=1 RES=0 LD=0 D=9 Q=d
27500 CK=0 RES=0 LD=0 D=9 Q=d
28000 CK=1 RES=0 LD=0 D=9 Q=e
28500 CK=0 RES=0 LD=0 D=9 Q=e
29000 CK=1 RES=0 LD=0 D=9 Q=f
29500 CK=0 RES=0 LD=0 D=9 Q=f
30000 CK=1 RES=0 LD=0 D=9 Q=0
30500 CK=0 RES=0 LD=0 D=9 Q=0
31000 CK=1 RES=0 LD=0 D=9 Q=1
31500 CK=0 RES=0 LD=0 D=9 Q=1
32000 CK=1 RES=0 LD=1 D=6 Q=6 ← data_load(6) ロード
32500 CK=0 RES=0 LD=1 D=6 Q=6
33000 CK=1 RES=0 LD=0 D=6 Q=6
33500 CK=0 RES=0 LD=0 D=6 Q=6
34000 CK=1 RES=0 LD=0 D=6 Q=7
34500 CK=0 RES=0 LD=0 D=6 Q=7
35000 CK=1 RES=0 LD=0 D=6 Q=8
35500 CK=0 RES=0 LD=0 D=6 Q=8
36000 CK=1 RES=0 LD=0 D=6 Q=9
36500 CK=0 RES=0 LD=0 D=6 Q=9
37000 CK=1 RES=0 LD=0 D=6 Q=a
37500 CK=0 RES=0 LD=0 D=6 Q=a
38000 CK=1 RES=0 LD=0 D=6 Q=b
38500 CK=0 RES=0 LD=0 D=6 Q=b
39000 CK=1 RES=0 LD=0 D=6 Q=c
39500 CK=0 RES=0 LD=0 D=6 Q=c
40000 CK=1 RES=0 LD=0 D=6 Q=d
40500 CK=0 RES=0 LD=0 D=6 Q=d
41000 CK=1 RES=0 LD=0 D=6 Q=e
41500 CK=0 RES=0 LD=0 D=6 Q=e
42000 CK=1 RES=0 LD=0 D=6 Q=f
42500 CK=0 RES=0 LD=0 D=6 Q=f
43000 CK=1 RES=0 LD=0 D=6 Q=0
43500 CK=0 RES=0 LD=0 D=6 Q=0
📌 まとめ
taskはサブルーチンのように繰り返し処理をまとめてテストベンチを簡潔にするtaskの定義はtask〜endtask。引数はinput/output/inoutの3方向task内部には遅延・内部信号・parameterを記述できる- バスモデルとして活用すると、ボードレベル検証が効率的になる
- タスクを「基本タスク」「応用タスク」と階層化することで大規模テストベンチを整理できる
functionとの主な違い: 引数方向・戻り値数・遅延記述の可否・呼び出し構文(ステートメント vs 式)
お疲れさま!タスクを使ったテストベンチの記述、理解できたかな?🐾
タスクをうまく使えば、複雑な検証シナリオもスッキリと書けるようになるね!
