はじめに
Constrained Randomの考え方を使ってテストベンチを作成します。
実装
では、実際にテストベンチを作成します。
まずは制約なしで作成します。
構成は以下の通りです。

DUTの仕様
in_validがHighのとき、din1とdin2を加算した結果doutを出力する。
dut.sv
module top(
input clk,
input rst_n,
input in_valid,
input [3:0] din1,
input [3:0] din2,
output logic [3:0] dout
);
always_ff @(posedge clk, negedge rst_n) begin
if (!rst_n) begin
dout <= '0;
end
else begin
if (in_valid) begin
dout <= din1 + din2;
end
end
end
endmodule
テストベンチの仕様
test_data.svh
入力データを生成します。
class test_data;
rand bit [3:0] din1;
rand bit [3:0] din2;
endclass
tb.sv
テストシーケンスの実装、モニタで期待値比較を行います。
module tb;
bit clk = 0;
bit rst_n = 1;
always #5 clk = ~clk;
bit in_valid;
bit [3:0] din1;
bit [3:0] din2;
bit [3:0] dout;
dut i_dut(
.clk(clk),
.rst_n(rst_n),
.in_valid(in_valid),
.din1(din1),
.din2(din2),
.dout(dout)
);
`include "test_data.svh"
class monitor;
int exp_;
function set(int din1, din2);
exp_ = din1 + din2;
endfunction
task start;
@(posedge clk iff in_valid);
if (dout != exp_) begin
$display("[ERROR]: [act] %d, [exp] %d", dout, exp_);
end
else begin
$display("[INFO]: [act] %d, [exp] %d", dout, exp_);
end
endtask
endclass
initial begin
test_data a = new();
monitor mon = new();
// 初期化シーケンス
@(posedge clk);
rst_n = 1;
repeat(5) @(posedge clk);
for (int i = 0; i < 20; i++) begin
// 入力データと期待値生成
a.randomize();
mon.set(a.din1, a.din2);
// モニタ開始
fork
mon.start();
join_none
// テストシーケンス
din1 = a.din1;
din2 = a.din2;
repeat(5) @(posedge clk);
in_valid = 1'b1;
@(posedge clk);
in_valid = 1'b0;
end
$finish;
end
endmodule
動作確認
doutが4ビットなので、加算結果が16以上のときはERRORとなります。
[ERROR]: [act] 5, [exp] 21
[INFO]: [act] 14, [exp] 14
[INFO]: [act] 4, [exp] 4
[ERROR]: [act] 7, [exp] 23
[ERROR]: [act] 6, [exp] 22
[ERROR]: [act] 6, [exp] 22
[ERROR]: [act] 1, [exp] 17
[ERROR]: [act] 4, [exp] 20
[ERROR]: [act] 3, [exp] 19
[ERROR]: [act] 3, [exp] 19
[INFO]: [act] 9, [exp] 9
[INFO]: [act] 14, [exp] 14
[ERROR]: [act] 3, [exp] 19
[ERROR]: [act] 1, [exp] 17
[ERROR]: [act] 11, [exp] 27
[INFO]: [act] 8, [exp] 8
[ERROR]: [act] 3, [exp] 19
[INFO]: [act] 11, [exp] 11
[INFO]: [act] 11, [exp] 11
[ERROR]: [act] 12, [exp] 28
波形

制約を付ける(constraint)
さきほどはモニタがオーバーフローを考慮していなかったので、期待値不一致(ERROR)が発生しました。
DUTの使用制約でオーバーフローするデータを入力しない場合、テストベンチでは不必要な入力データを生成しています。
そこで、test_data.svhに定義しているクラスに制約(constraint)を付けます。
class test_data;
rand bit [3:0] din1;
rand bit [3:0] din2;
// din1 + din2 は16以上にしない制約
constraint max {
din1 + din2 < 16;
}
endclass
動作確認
さきほどはERRORがありましたが、入力データに制約を付けることで解消されました。
[INFO]: [act] 10, [exp] 10
[INFO]: [act] 11, [exp] 11
[INFO]: [act] 15, [exp] 15
[INFO]: [act] 12, [exp] 12
[INFO]: [act] 7, [exp] 7
[INFO]: [act] 15, [exp] 15
[INFO]: [act] 15, [exp] 15
[INFO]: [act] 5, [exp] 5
[INFO]: [act] 10, [exp] 10
[INFO]: [act] 14, [exp] 14
[INFO]: [act] 8, [exp] 8
[INFO]: [act] 13, [exp] 13
[INFO]: [act] 7, [exp] 7
[INFO]: [act] 15, [exp] 15
[INFO]: [act] 15, [exp] 15
[INFO]: [act] 10, [exp] 10
[INFO]: [act] 7, [exp] 7
[INFO]: [act] 12, [exp] 12
[INFO]: [act] 13, [exp] 13
[INFO]: [act] 15, [exp] 15
まとめ
Constrained Randomの考え方を使ってテストベンチを作成しました。
コメント