ファイルの読み書き
テストベンチで、入力を予め用意したファイルから読み込んだり、出力をファイルに書き出して、後で期待値ファイルと比較する、という手もよく使う。
◇
配列(RAM相当)にHEX値を読み込むだけならば $readmemh を使う。
例) テキストファイルから配列memへHEX値を読み込む
reg[15:0] mem[0:256]; initial begin $readmemh("dat_in.txt",mem); end |
ファイルは「@先頭アドレス 値 値 ...」で16進数で書く。スペースやタブや改行が区切り。コメント行はVerilogと同じ。値を書かなかったアドレスは不定(x)のままになる。
/* dat_in.txt */ 1234 abcd bcde ... //アドレスを省略すると //0番地から始まる |
/* dat_in.txt */ @00 1234 @01 abcd @02 bcde ... //アドレスを //全部書いても可 |
/* dat_in.txt */ @10 1234 abcd @ff 5678 //10,11,ff番地と //飛び飛びでも可 |
◇◇
任意のフォーマットで読み込むには $fscanfを使う。
例) テキストファイルからフォーマットに従って読み込む
integer fd; // file descriptor initial begin // ファイルを開く(存在しないとfd=0になる) fd = $fopen("dat_in.txt","r"); if(fd===0) $finish; // ファイルから1行ずつフォーマットに従って読み込む // 1行目はヘッダ(a=13,b=25) num = $fscanf(fd,"a=%d,b=%d",a,b); // 2行目からはデータ while($feof(fd)===0) begin num = $fscanf(fd,"%d",dat); ... end $fclose(fd); end |
◇◇◇
書き出すには $fdisplay,$fwriteを使う。違いは、$fdisplayは改行つき、$fwriteは改行なし。
例) テキストファイルへフォーマットに従って書き出す
integer fd; // file descriptor reg[7:0] mem[0:N-1]; initial begin // ファイルを開く(空ファイルが作られる) fd = $fopen("dump.txt","w"); // ファイルへ8バイト/行で書き出す for(i=0; i<=N-1; i=i+1) begin if(i%8===0) $fwrite(fd,"%0d: ",i); $fwrite(fd,"%h",mem[i]); if(i%8==7 | i==N-1) $fwrite(fd,"\n"); end $fclose(fd); end |
何かの定数表を作るときも、CでなくVerilogを使った方が簡単なこともある。
例) IEEE754フォーマットのsinの表を作る
initial begin fd = $fopen("sin.txt","w"); for(int k=0; k<N; k++) begin $fdisplay(fd,"%h",$shortrealtobits($sin(PI*k/N)); end $fclose(fd); end |
◇◇◇◇
バイナリファイルへ書き出すには $fopen( ,"wb")で開いて、$fwrite( ,"%c", )を使う。
例) バイナリファイルへ1バイトずつ書き出す
integer fd; // file descriptor reg[7:0] mem[0:N-1]; initial begin // ファイルを開く(空ファイルが作られる) fd = $fopen("dat_out.bin","wb"); // 1バイトずつ書き出す for(i=0; i<=N-1; i=i+1) begin $fwrite(fd,"%c",mem[i]); end $fclose(fd); end |
◇◇◇◇◇
バイナリファイルから読み込むには $fopen( ,"rb")で開いて、$freadを使う。
例) バイナリファイルから1バイトずつ読み込む
integer fd; // file descriptor reg[7:0] dat; initial begin fd = $fopen("dat_in.bin","rb"); // 1バイトずつ読み込む,最後にEOFが読まれる while($feof(fd)===0) begin num = $fread(dat,fd); ... end $fclose(fd); end |
例) バイナリファイルからバイト数を指定して読み込む
integer fd; // file descriptor reg[7:0] head[0:M-1]; reg[7:0] data[0:N-1]; initial begin // ファイルを開く(存在しないとfd=0になる) fd = $fopen("dat_in.bin","rb"); if(fd===0) $finish; // 先頭からMバイト読み込む num = $fread(head,fd,0,M); // 続きからNバイト読み込む num = $fread(data,fd,0,N); ... $fclose(fd); end |