全文地址:http://hubeixunbaoren.blog.163.com/blog/static/111127004200982725032948/
系統函數$fopen用於開啟一個檔案,並還回一個整數指標.然後,$fdisplay就可以使用這個檔案指標在檔案中寫入資訊,寫完後,則可以使用$fclose系統關閉這個檔案
例如:
integer write_out_file;//定義一個檔案指標
integer write_out_file=$fopen("write_out_file.txt");
$fdisplay(write_out_file,"@%h\n%h",addr,data);
$fclose("write_out_file");
以上文法是將addr,data分別顯示在"@%h\n%h"中的2個%h的位置,並寫入write_out_file檔案指標所指向的write_out_file.txt中.
從檔案中讀取資料,可以用 $readmemb $readmemh 從檔案中讀入資料,該檔案格式是一定的.
reg[7:0] data[47:0];
$readmemh("file_name.txt",data );
就是將file_name.txt中的資料讀入到data數組中,然後就可以使用這些資料了.
還有一種方式可以把指定的資料放入指定的儲存空間地址單元內,就是在存放資料的文字檔內,給相應的資料規定其記憶體位址,形式如下:
@address_in_hexadecimal data
@2f 20
兩個系統任務可以在模擬的任何時刻被執行使用,其使用格式共有以下六種:
1) $readmemb("<資料檔案名>",<存貯器名>);
2) $readmemb("<資料檔案名>",<存貯器名>,<起始地址>);
3) $readmemb("<資料檔案名>",<存貯器名>,<起始地址>,<結束位址>);
4) $readmemh("<資料檔案名>",<存貯器名>);
5) $readmemh("<資料檔案名>",<存貯器名>,<起始地址>);
6) $readmemh("<資料檔案名>",<存貯器名>,<起始地址>,<結束位址>);
在這兩個系統任務中,被讀取的資料檔案的內容只能包含:空白位置(空格,換行,製表格(tab)和form-feeds),注釋行(//形式的和/*...*/形式的都允許),二進位或十六進位的數字。數字中不能包含位寬說明和格式說明,對於$readmemb系統任務,每個數字必須是位元字,對於$readmemh系統任務,每個數字必須是十六進位數字。數字中不定值x或X,高阻值z或Z,和底線(_)的使用方法及代表的意義與一般Verilog HDL程式中的用法及意義是一樣的。另外數字必須用空白位置或注釋行來分隔開。
在下面的討論中,地址一詞指對存貯器(memory)建模的數組的定址指標。當資料檔案被讀取時,每一個被讀取的數字都被存放到地址連續的存貯器單元中去。存貯器單元的存放位址範圍由系統任務聲明語句中的起始地址和結束位址來說明,每個資料的存放地址在資料檔案中進行說明。當地址出現在資料檔案中,其格式為字元“@”後跟上十六進位數。如:
@hh...h
對於這個十六進位的地址數中,允許大寫和小寫數字。在字元“@”和數字之間不允許存在空白位置。可以在資料檔案裡出現多個地址。當系統任務遇到一個地址說明時,系統任務將該地址後的資料存放到存貯器中相應的地址單元中去。
對於上面六種系統任務格式,需補充說明以下五點:
1) 如果系統任務聲明語句中和資料檔案裡都沒有進行地址說明,則預設的存放起始地址為該存貯器定義語句中的起始地址。資料檔案裡的資料被連續存放到該存貯器中,直到該存貯器單元存滿為止或資料檔案裡的資料存完。
2) 如果系統任務中說明了存放的起始地址,沒有說明存放的結束位址,則資料從起始地址開始存放,存放到該存貯器定義語句中的結束位址為止。
3) 如果在系統任務聲明語句中,起始地址和結束位址都進行了說明,則資料檔案裡的資料按該起始地址開始存放到存貯器單元中,直到該結束位址,而不考慮該存貯器的定義語句中的起始地址和結束位址。
4) 如果地址資訊在系統任務和資料檔案裡都進行了說明,那麼資料檔案裡的地址必須在系統任務中地址參數聲明的範圍之內。否則將提示錯誤資訊,並且裝載資料到存貯器中的操作被中斷。
5) 如果資料檔案裡的資料個數和系統任務中起始地址及結束位址暗示的資料個數不同的話,也要提示錯誤資訊。
下面舉例說明:
先定義一個有256個地址的位元組存貯器 mem:
reg[7:0] mem[1:256];
下面給出的系統任務以各自不同的方式裝載資料到存貯器mem中。
initial $readmemh("mem.data",mem);
initial $readmemh("mem.data",mem,16);
initial $readmemh("mem.data",mem,128,1);
第一條語句在模擬時刻為0時,將裝載資料到以地址是1的存貯器單元為起始存放單元的存貯器中去。第二條語句將裝載資料到以單元地址是16的存貯器單元為起始存放單元的存貯器中去,一直到地址是256的單元為止。第三條語句將從地址是128的單元開始裝載資料,一直到地址為1的單元。在第三種情況中,當裝載完畢,系統要檢查在資料檔案裡是否有128個資料,如果沒有,系統將提示錯誤資訊。
"引用 參考"
1.開啟檔案
integer file_id;
file_id = fopen("file_path/file_name");
2.寫入檔案
//$fmonitor只要有變化就一直記錄
$fmonitor(file_id, "%format_char", parameter);
eg:$fmonitor(file_id, "%m: %t in1=%d o1=%h", $time, in1, o1);
//$fwrite需要觸發條件才記錄
$fwrite(file_id, "%format_char", parameter);
//$fdisplay需要觸發條件才記錄
$fdisplay(file_id, "%format_char", parameter);
$fstrobe();
3.讀取檔案
integer file_id;
file_id = $fread("file_path/file_name", "r");
4.關閉檔案
$fclose(fjile_id);
5.由檔案設定儲存空間初值
$readmemh("file_name", memory_name"); //初始化資料為十六進位
$readmemb("file_name", memory_name"); //初始化資料為二進位
轉:
http://zengbo.blogbus.com/logs/19569780.htmlVerilog
提供了豐富的系統函數,這為Testbench的編寫提供了方便。尤其是IEEE1364-2005,其系統級建模的能力更強。
以前我一般常用到的系統函數只有幾個:$readmemb,$readmemh,$display,$fmonitor,$fwrite,$fopen,$fclose等。通常需要對檔案作預先處理,才能用於Testbench讀取。今天又嘗試了幾個其他的檔案輸入輸出函數,不需要對檔案進行預先處理,直接使用需要的檔案,只對需要的部分進行讀取。
$fseek,檔案定位,可以從任意點對檔案進行操作;
$fscanf,對檔案一行進行讀寫。
下面是一些常見的應用:
1、讀寫檔案
`timescale 1 ns/1 ns
module FileIO_tb;
integer fp_r, fp_w, cnt;
reg [7:0] reg1, reg2, reg3;
initial begin
fp_r = $fopen("data_in.txt", "r");
fp_w = $fopen("data_out.txt", "w");
while(!$feof(fp_r)) begin
cnt = $fscanf(fp_r, "%d %d %d", reg1, reg2, reg3);
$display("%d %d %d", reg1, reg2, reg3);
$fwrite(fp_w, "%d %d %d\n", reg3, reg2, reg1);
end
$fclose(fp_r);
$fclose(fp_w);
end
endmodule
2、
integer file, char;
reg eof;
initial begin
file = $fopenr("myfile.txt");
eof = 0;
while (eof == 0) begin
char = $fgetc(file);
eof = $feof (file);
$display ("%s", char);
end
end
3、檔案處理定位
`define SEEK_SET 0
`define SEEK_CUR 1
`define SEEK_END 2
integer file, offset, position, r;
r = $fseek(file, 0, `SEEK_SET); /* Beginning */
r = $fseek(file, 0, `SEEK_CUR); /* No effect */
r = $fseek(file, 0, `SEEK_END); /* End of file */
r = $fseek(file, position, `SEEK_SET); /* Previous loc */
4、
integer r, file, start, count;
reg [15:0] mem[0:10], r16;
r = $fread(file, mem[0], start, count);
r = $fread(file, r16);
5、
integer file, position;
position = $ftell(file);
6、
integer file, r, a, b;
reg [80*8:1] string;
file = $fopenw("output.log");
r = $sformat(string, "Formatted %d %x", a, b);
r = $sprintf(string, "Formatted %d %x", a, b);
r = $fprintf(file, "Formatted %d %x", a, b);
7、
integer file, r;
file = $fopenw("output.log");
r = $fflush(file);
8、
// This is a pattern file - read_pattern.pat
// time bin dec hex
10: 001 1 1
20.0: 010 20 020
50.02: 111 5 FFF
62.345: 100 4 DEADBEEF
75.789: XXX 2 ZzZzZzZz
`timescale 1ns / 10 ps
`define EOF 32'hFFFF_FFFF
`define NULL 0
`define MAX_LINE_LENGTH 1000
module read_pattern;
integer file, c, r;
reg [3:0] bin;
reg [31:0] dec, hex;
real real_time;
reg [8*`MAX_LINE_LENGTH:0] line; /* Line of text read from file */
initial
begin : file_block
$timeformat(-9, 3, "ns", 6);
$display("time bin decimal hex");
file = $fopenr("read_pattern.pat");
if (file == `NULL) // If error opening file
disable file_block; // Just quit
c = $fgetc(file);
while (c != `EOF)
begin
/* Check the first character for comment */
if (c == "/")
r = $fgets(line, `MAX_LINE_LENGTH, file);
else
begin
// Push the character back to the file then read the next time
r = $ungetc(c, file);
r = $fscanf(file," %f:\n", real_time);
// Wait until the absolute time in the file, then read stimulus
if ($realtime > real_time)
$display("Error - absolute time in file is out of order - %t",
real_time);
else
#(real_time - $realtime)
r = $fscanf(file," %b %d %h\n",bin,dec,hex);
end // if c else
c = $fgetc(file);
end // while not EOF
r = $fcloser(file);
end // initial
// Display changes to the signals
always @(bin or dec or hex)
$display("%t %b %d %h", $realtime, bin, dec, hex);
endmodule // read_pattern
9、自動比較輸出結果
`define EOF 32'hFFFF_FFFF
`define NULL 0
`define MAX_LINE_LENGTH 1000
module compare;
integer file, r;
reg a, b, expect, clock;
wire out;
reg [`MAX_LINE_LENGTH*8:1];
parameter cycle = 20;
initial
begin : file_block
$display("Time Stim Expect Output");
clock = 0;
file = $fopenr("compare.pat");
if (file == `NULL)
disable file_block;
r = $fgets(line, MAX_LINE_LENGTH, file); // Skip comments
r = $fgets(line, MAX_LINE_LENGTH, file);
while (!$feof(file))
begin
// Wait until rising clock, read stimulus
@(posedge clock)
r = $fscanf(file, " %b %b %b\n", a, b, expect);
// Wait just before the end of cycle to do compare
#(cycle - 1)
$display("%d %b %b %b %b", $stime, a, b, expect, out);
$strobe_compare(expect, out);
end // while not EOF
r = $fcloser(file);
$stop;
end // initial
always #(cycle / 2) clock = !clock; // Clock generator
and #4 (out, a, b); // Circuit under test
endmodule // compare
10、從檔案中讀資料到mem(這個好像一般人用的最多了)
`define EOF 32'HFFFF_FFFF
`define MEM_SIZE 200_000
module load_mem;
integer file, i;
reg [7:0] mem[0:`MEM_SIZE];
reg [80*8:1] file_name;
initial
begin
file_name = "data.bin";
file = $fopenr(file_name);
i = $fread(file, mem[0]);
$display("Loaded %0d entries \n", i);
i = $fcloser(file);
$stop;
end endmodule // load_mem