テストベンチの基本形
テストベンチとはテスト対象モジュールDesign Under Test(DUT)をシミュレーションするためのトップモジュールである。論理合成向けのRTL記述と違って定型的な書き方はないが、次図のように4つの機能に分けて書くとよい。
(1) テストシナリオ:DUTへの入力をトランザクションレベル(リード・ライト動作など)のドライバタスクで記述したもの。
(2) ドライバタスク:トランザクションレベルの動作をピンレベルの波形に変換して DUTへ入力したり出力を期待値比較する記述
(3) モニタ:ピンレベルの波形をトランザクションレベルに変換して表示や期待値比較する記述
(4) 周辺回路: DUTの出力に応答して入力を返す記述
テストシナリオはinitial文で時間順に記述し、ドライバタスクはtaskで記述し、モニタと周辺回路は受動的に動くalwaysブロックやmoduleで記述する。
テストベンチの基本形は次のようになる。詳細は次項から説明していく。
/* tb.v - testbench */ `timescale 1ns/1ps module tb; /* パラメータ */ parameter TCLK_HALF = 5; // クロックの半周期[ns] parameter TCO = TCLK_HALF; // 入力の遅延時間[ns] ... /* 信号とレジスタ */ reg rst_n; reg clk; ... /* DUT */ dut dut_0(.rst_n(rst_n),.clk(clk),...);
/* クロック生成 */ initial begin clk = 1'b1; forever #(TCLK_HALF) clk = ~clk; end
/* ドライバタスク */ task reset; begin rst_n = 1'b0; #(RST_WIDTH) rst_n = 1'b1; end endtask ...
/* 周辺回路 */ always @(posedge clk) begin if(req) ack <= #(TCO) 1'b1; end ...
/* モニタ */ always @(posedge clk) begin if(enb) $display("-- dat=%h",dat); end ...
/* テストシナリオ */ initial begin reset; repeat(15) @(posedge clk); bus_wr(16'h0040,16'h55aa); bus_rd(16'h0040,16'hxxxx); ... while(dut_ready!==1'b1) @(posedge clk); data_input(32'h1234_5678); ... $finish; end endmodule |