//一般常用到的系统函数有几个:$readmemb,$readmemh,$display,$fmonitor,$fwrite,$fopen,$fclose等
fscanf函数: $fscanf(文件指针,读取格式,数组)
注意:该系统函数每次读取文件中的每一行数据,这当中需要特别注意一点,每一行只能是同一种数据格式,例如:0011_0001,如果出现0b0011_0001,则无法正常的读取。
文件指针:指向某一文件的开头,举个栗子,f_r = $fopen(‘xxx.txt’, ‘r’),文件指针f_r指向xxx.txt文件的开头。
读取格式:%d %b %h为分别表示十进制、2进制、16进制。
数组:存放从xxx.txt读取的数据,例如xxx.txt第一行存放0011_0001,则数组a=0011_0001。此时若没有将数组a中的数据及时的进行处理(写入另外一个文件、给寄存器reg1)在读取xxx.txt文件中的下一行(1111_1111)数据时,之前存放于数组a的数据将会被覆盖,即此时数组a中的数据为0011_0001。依次类推。
关闭:使用fclose系统函数。
fscanf函数的返回值:例如count = $fscanf(fp_r,"%b" ,img_rgb_dat_reg)返回值为1,返回值为1表示成功,读取格式可以为%b,%d,%h(注意,如果读取格式为二进制,则文件中只能识别 0 1)
1 integer = count;
2 count=$fscanf(fp_r,"%b" ,reg1) ; //fp_r文件指针,%b读取格式,reg1:数组
举个例子:reg [7:0]reg1,表示定义8bits的数组一个,该数组最大只能存放8bits的数据,如果读取的数据小于8bits,则在数据的前面补零(亲测)。
函数所参考的网络资料的链接:
https://blog.csdn.net/weizhl10131729/article/details/78556489
https://blog.csdn.net/cxc19890214/article/details/41146531
实际举例用$fscanf读txt中的数据:
注意:图中第一行定义一个文件句柄。由于打开的文件中一行中有两个10bit的十进制数据,所以定义了2个reg变量。
第6行到12行就是文件的读取过程。
使用的系统函数$fopen打开文件;
使用$feof判断文件是否读完(eof :end of file),如果文件结束,则返回非0值,如果没结束返回0;
使用$fscanf读取文件内容。
在实际验证中,仿真一段时间后,仿真会结束,注意在仿真结束时,要使用$fclose(dti_fid)关闭文件。
用$fwrite函数把数据写入到 txt文件中:
在写文件时,首先要建一个文件句柄如15行;
147-148行,声明2个10bit的输出数据dto_i和dto_r;
150-152行,以写的方式打开一个文件,;
154-159行,写文件。dto_vld是dto_i和dto_r数据的有效指示。
还是要注意在仿真结束时,要用$fclose(dto_fid)关闭文件句柄。
$display ("string")
关于$fopen,
$readmemb(把txt文档中的数据写入到数组中),
$fdisplay(把数据写入到制定的文件中去)
在工程文件夹目录下,有一个meomoryb.txt的文本文件,文件内容如下:
10101101 00011101 01101111 01100001
00000001 11111110 11111111 11101110
有一个meomoryh.txt的文本文件,文件内容如下:
ef ab 3e 4f
这个文件就符合要求,可以通过$readmemb读取。10101101第一个数据地址为0,向后以此类推。
举例:
module readmem;
reg [7:0] mem[7:0];
reg [2:0] i;
integer file;
initial
begin
file = $fopen("memory.txt","w");//以写的方式打开文件
$readmemb("memoryb.txt",mem,4,0);// 从文本中读取数据向mem[4]开始写入,直到写到mem[0]
for(i =0;i<7;i= i+1)
begin
$display("mem[%d] = %b",i,mem[i]);
$fdisplay(file,"mem[%d] = %b",i,mem[i]);//$fdisplay(文件指针,"显示内容",显示变量)
end
$readmemh("memoryh.txt",mem);//如果没有地址的限制,就默认从//mem[0]到mem定义的最大地址。
for(i =0;i<7;i= i+1)
begin
$display("mem[%d] = %h",i,mem[i]);
$fdisplay(file,"mem[%d] = %h",i,mem[i]);
end
$fclose(file);
end
endmodule
控制台输出与生成的memory.txt中内容一致。
mem[0] = 00000001
mem[1] = 01100001
mem[2] = 01101111
mem[3] = 00011101
mem[4] = 10101101
mem[5] = xxxxxxxx
mem[6] = xxxxxxxx
mem[0] = 32
mem[1] = 36
mem[2] = 4f
mem[3] = 8a
mem[4] = ad
mem[5] = xx
mem[6] = xx
//结果分析:
// 首先读取memoryb.txt中从地址4到地址0的数据写入mem[0]至 mem[4],没有写入的存储器内容为xx,
// 然后读取memoryh.txt从地址0到地址6的数据写入mem[0]至mem[6],由于 memoryh.txt只有4个数据,mem[4]以后的数据就没有了,
//保持上一次写的内容,所以,mem[4]为ad(十六进制)即二进制 10101101
`define NULL 0
module file_scanf;
integer fp_r,fp_w;
integer flag1,flag2;
reg [3:0] bin;
reg [15:0] data_in [15:0];
reg [15:0] cnt = 15;
initial
begin :file_fscanf
fp_r = $fopen("data_in.txt","r");
fp_w = $fopen("data_out.txt","w");
if(fp_r == `NULL)
$display("failture to open data_in.txt ");
if(fp_w == `NULL)
$display("failture to open data_out.txt ");
//repeat(10)
while(!$feof(fp_r))
begin
flag1 = $fscanf(fp_r,"%h",data_in[cnt]);//flag1 为$fscanf的返回值
$display("data_in[%d]=%h ",cnt,data_in[cnt]);
$fdisplay(fp_w,"%h",data_in[cnt]);
// cnt = cnt -1;
end
$fclose(fp_w);
$fclose(fp_r);
end
endmodule
1.文件打开和关闭:首先定义integer指针,然后调用$fopen(file_name,mode)任务,不需要文件时,调用$fclose(file_name)
2.输出到文件:显示任务前加f,调用格式:
$fdisplay(文件指针,"显示内容",显示变量),再如$fmonitor(…)