入力にタスクを使う
入力波形をべた書きするよりも、taskを使った方が読みやすくなる。taskはfunctionと似ているが、functionは出力が1個なのに対して、taskでは外部のreg変数に代入することができる。
× // 入力波形をべた書きする initial begin // 初期値入力 wr = 1'b0; rd = 1'b0; adr = 8'bx; dat = 16'bz; // バスライト動作 @(posedge clk); wr <= #(TCO) 1'b1; adr <= #(TCO) 8'h05; dat <= #(TCO) 16'h5555; @(posedge clk); wr <= #(TCO) 1'b0; adr <= #(TCO) 8'bx; dat <= #(TCO) 16'bz; // バスライト動作 @(posedge clk); wr <= #(TCO) 1'b1; adr <= #(TCO) 8'h0a; dat <= #(TCO) 16'haaaa; @(posedge clk); wr <= #(TCO) 1'b0; adr <= #(TCO) 8'bx; dat <= #(TCO) 16'bz; ... $finish; end |
○ // 入力波形をtaskで書く initial begin $timeformat(-6,3," us",10); // "000.000 us" wr = 1'b0; rd = 1'b0; adr = 8'h00; dat = 16'bz; bus_wr(8'h05,16'h5555); bus_wr(8'h0a,16'haaaa); bus_rd(8'h05,16'hxxxx); bus_rd(8'h0a,16'haaaa); ... $finish; end
// バスライト動作のタスク task bus_wr (input[7:0] a // アドレス ,input[15:0] d // ライト値 ); begin @(posedge clk); wr <= #(TCO) 1'b1; adr <= #(TCO) a; dat <= #(TCO) d; @(posedge clk); while(ack!==1'b1) @(posedge clk); // ackを待つ wr <= #(TCO) 1'b0; adr <= #(TCO) 8'bx; dat <= #(TCO) 16'bz; $display("--(%t) %m(%h,%h)",$time,a,d); end endtask
// バスリード動作のタスク task bus_rd (input[7:0] a // アドレス ,input[15:0] d // リード値の期待値 ); begin @(posedge clk) rd <= #(TCO) 1'b1; adr <= #(TCO) a; @(posedge clk); while(ack!==1'b1) @(posedge clk); // ackを待つ rd <= #(TCO) 1'b0; adr <= #(TCO) 8'bx; // リード値datの判定 $write("--(%t) %m(%h,%h) dat=%h",$time,a,d,dat); if(d===16'bx) $display(""); else if(d===dat) $display(" [PASS]"); else $display(" [FAIL]"); end endtask |
(構文の補足)
$write( )は改行なし、$display( )は改行ありが違うだけ。
%mは現在の階層名を表示するので表示は次のようになる
--( 0.010 us) tb.bus_mod.bus_wr(05,5555) --( 0.210 us) tb.bus_mod.bus_wr(0a,aaaa) --( 0.310 us) tb.bus_mod.bus_rd(05,xxxx) dat=5555 --( 0.410 us) tb.bus_mod.bus_rd(0a,aaaa) dat=aaaa [PASS] |