文字列を生成する、似たようなシステムタスクです。$sformatは、引数の中にstring変数をおいて、そこに結果を入れます。$psprintf, $sformatf は、返り値としてstringを返します。同じ挙動のようです。
string s;int i; i=10;$sformat(s, "This is a pen. %0d", i);s = $psprintf("This is a pen. %0d",i);/// 上記2行の結果は同じ参考にしたページはこちら。ファイルを開いてログなどを書きだすのに使います。
integer filehandle;filehandle = $fopen("filename", attribute);/// attribute : "w" or "r" or "a" or ...$fdisplay(filehandle, "xxx %d yyy...", ...); :$fclose(filehandle);参考にしたページはこちら。$fopenで開いたファイルを読み出すシステムタスクです。$fgetcは、1文字を取得するタスク、$fgetsは各行の行単位で文字列を取得するタスクのようです。
使用例:($fgetc, $fscanf)
---- test.sv ---`define EOF 32'hFFFF_FFFFmodule test; initial begin integer fp; byte scan_data; fp = $fopen("readmemb","r"); ///readmembファイルは下記$readmembと同じ if(fp!=0)begin ///ファイルが開けたら while($fgetc(fp) != `EOF)begin ///ファイルの最後でなければ void'($fscanf(fp,"%08b",scan_data)); ///返り値を無視するcast #10 $display("[%0d] readmemb : %b", $stime, scan_data); end end else begin $display("Error : readmemb can not open..."); end endendmoduleただ、このコードを実行すると、ちょっと意図しない動作をします。
# [10] readmemb : 00000001# [20] readmemb : 00000010# [30] readmemb : 00000100# [40] readmemb : 00001000# [50] readmemb : 00010000# [60] readmemb : 00100000# [70] readmemb : 01000000# [80] readmemb : 10000000# [90] readmemb : 10000000 ← この行が余計なぜ9行目が表示されるのかはわかりませんが、実用レベルで最後の行が2回処理されるのは困るので、ファイルの終了を示す記号を記述しておき、それを検出したらbreakで抜ける方法で回避すればいいかな?と思っています。(解決したら上記コードも修正しておきます…)
指定したファイルから、bin($readmemb), hex($readmemh)で記述された数値を読み込みます。読み込んだデータを格納する配列は、Dynamic Arrayに格納ができます。このときは、newしなくていいようです。(ModelSim上の動作確認ではOKでした)
$readmemb("ファイル名", array);
$readmemh("ファイル名", array);
※arrayはDynamic Arrayでもよさそう。この場合はDynamic Arrayをnewしなくても、システムタスクで取り込んだ分の配列サイズになるもよう。
例:8bitのbin記述ファイルから、配列に数値を格納
--- file : readmemb ---0000000100000010000001000000100000010000001000000100000010000000--- file : readmemh ---0102040810204080--- file : test.sv ---module test; initial begin byte memb []; byte memh []; $readmemb("readmemb", memb); $readmemh("readmemh", memh); foreach (memb[i]) $display("readmemb : %08b", memb[i]); foreach (memh[i]) $display("readmemh : %02h", memh[i]); endendmodule--- 実行結果 ---# readmemb : 00000001# readmemb : 00000010# readmemb : 00000100# readmemb : 00001000# readmemb : 00010000# readmemb : 00100000# readmemb : 01000000# readmemb : 10000000# readmemh : 01# readmemh : 02# readmemh : 04# readmemh : 08# readmemh : 10# readmemh : 20# readmemh : 40# readmemh : 80参考にしたページはこちら。$timeformatを使うと、時間表示するときの単位を指定できるようになります。例えば、timescaleが1nsだったときと1psだったとき、$display文はどちらのtimescaleが使われているかわからないので、ログにnsと出せばいいのかpsと出せばいいのかわかりません。この問題は、$timeformatを使用した上で、時間表示を%tで行えば解決します。
$timeformat(arg0, arg1, arg2, arg3)
例えば、時間表示を1ns単位にしたいときは、
$timeformat(-9, 3, "ns" ,9);
とします。arg3は表示に使用する文字数になりますので、上記設定はarg0でnsにあわせて、arg1で少数3桁(psまで)、arg2でns表記にすることになります。arg2でnsと2文字消費するため、数値表示は最低7文字で表現されることになります。
上記設定でtimescale=1ps/1psとして、以下のコード
#10ns $display("[%t]",$stime);#10ns $display("[%t]",$stime);#10ps $display("[%t]",$stime);を実行すると、
# [ 10.000ns]# [ 20.000ns]# [ 20.010ns]となります。
指定インスタンス、もしくはカレントmoduleのtimescaleを表示させることができます。getできるわけではないので、timescaleを取得して処理をモゴモゴすることはできないと思いますが、「あれ?この moduleのtimescaleは1ns/1psではないのか?」などのように、おかしいな、というときに該当moduleに暫定組み込み、もしくはifdefで組み込んでおくといいかもしれません。
例:topの下にtest1とtest2のインスタンスがある
module top; test1 test1(); test2 test2(); initial begin $printtimescale(test1); $printtimescale(test2); $printtimescale; endendmodule`timescale 100ns/1psmodule test1;endmodule`timescale 10ns/1nsmodule test2;endmodule実行すると、
# run -all# Time scale of (top.test1) is 100ns / 1ps# Time scale of (top.test2) is 10ns / 1ns# Time scale of (top) is 1ps / 1psこのように表示されます。