原文网站: Verilog 文件操作-$fseek,$ftell,$feof – 芯片天地
在Verilog 仿真中, 我们有时需要定位文件读取或者写入的位置。在Verilog 语法中提供$fseek,$ftell,$feof,$frewind 等系统函数,帮助开发者将文件中的数据读出,或者写入数据到文件中。供仿真程序实现相关的功能。
$fseek 使用
<integer> = $fseek(<file_desc>, <offset_value>, <operation_number>); integer:定义整型变量,用于$fseek的返回值。如果$fseek成功执行,返回0; $fseek执行失败,返回-1。 file_desc:为打开的文件句柄 offset_value:相对于文件的参考指针,偏移的位置, 可以是正数,也可以是负数。 operation_number:定位文件指针的位置。 0,文件的起始位置;1,文件的当前位置; 2 文件结束的位置。
从文件中定位读写指针的位置,根据文件的参考点和偏移的位置,确定当前对文件读写的指针位置。
举例,从一个文本文件中读取数据(test.txt)
test.txt文本文件的内容如下:
1234
abc
k
world
hello
This is a test file.
仿真文件如下:
`timescale 1ns / 1ps
module sim_top(
);
reg stop_flag = 0;
localparam F_START = 0,
F_CURR = 1,
F_END = 2;
localparam FILE_TXT = "../../../test.txt";
//localparam FILE_TXT = "../../../test.bin";
integer fd;
integer ret;
integer i;
reg [7:0] fbuf = 0;
initial begin
i = 0;
ret = 0;
fd = $fopen(FILE_TXT, "r");
if(fd == 0)
begin
$display("$open file failed") ;
$stop;
end
$display("\n ============= file opened... ============= ") ;
ret = $fseek(fd, 1,F_START);
if($signed(ret) == -1)
begin
$display("$fseek failed") ;
$stop;
end
fbuf = $fgetc(fd);
#10;
$write("%c", fbuf) ;
i = i + 1;
ret = $fseek(fd, -5,F_END);
if($signed(ret) == -1)
begin
$display("$fseek failed") ;
$stop;
end
while ($signed(fbuf) != -1)
begin
fbuf = $fgetc(fd);
#10;
$write("%c", fbuf);
i = i + 1;
end
#10;
$fclose(fd) ;
$display("\n ============= file closed... ============= ") ;
stop_flag = 1;
#100;
$stop;
end
endmodule
ret = $fseek(fd, 1,F_START); 是从文本文件的起始位置,向后偏移一个字节。 然后开始读取文本文件的数据;ret = $fseek(fd, -5,F_END); 是将文件指针定位到文件结束的位置,向前偏移 5 个字节, 然后开始读取文本文件的数据。
仿真的结果如下:
$ftell使用
<reg> = $ftell(<file_desc>); reg:返回文件当前位置距离文件首部的偏移位置,初始位置为0. file_desc:为打开的文件句柄
这个系统函数的作用是找到当前的位置(距离文件首部),是以字节为单位的。
举例:(还是使用上面的test.txt) 文件作为输出文件。
仿真文件如下:
`timescale 1ns / 1ps
module sim_top(
);
reg stop_flag = 0;
localparam F_START = 0,
F_CURR = 1,
F_END = 2;
localparam FILE_TXT = "../../../test.txt";
integer fd;
integer ret;
integer i;
integer pos;
reg [7:0] fbuf = 0;
initial begin
i = 0;
ret = 0;
fd = $fopen(FILE_TXT, "r");
if(fd == 0)
begin
$display("$open file failed") ;
$stop;
end
$display("\n ============= file opened... ============= ") ;
ret = $fseek(fd, 1,F_START);
if($signed(ret) == -1)
begin
$display("$fseek failed") ;
$stop;
end
pos = $ftell(fd);
$display("pos = %d", pos) ;
fbuf = $fgetc(fd);
pos = $ftell(fd);
$display("pos = %d", pos) ;
#10;
$write("%c", fbuf) ;
i = i + 1;
ret = $fseek(fd, -5,F_END);
if($signed(ret) == -1)
begin
$display("$fseek failed") ;
$stop;
end
while ($signed(fbuf) != -1)
begin
fbuf = $fgetc(fd);
#10;
$write("%c", fbuf);
i = i + 1;
end
#10;
$fclose(fd) ;
$display("\n ============= file closed... ============= ") ;
stop_flag = 1;
#100;
$stop;
end
endmodule
仿真结果输出:
我们可以看到,$fseek (fd, 1, F_START); 后 使用 pos = $ftell(fd); 输出为1; 在读取一个字节后(fbuf = $fgetc(fd);), 再使用 pos = $ftell(fd),输出结果为 2。
$feof使用
<reg> = $feof(<file_desc>); reg:检查文件指针是否到达文件尾部, 如果到达文件尾部,返回1; 否则返回0; file_desc:为打开的文件句柄
这个系统函数的作用是判断文件指针是否到达文件尾部了。
举例:(还是使用上面的test.txt) 文件作为输出文件。
仿真文件如下:
`timescale 1ns / 1ps
module sim_top(
);
reg stop_flag = 0;
localparam F_START = 0,
F_CURR = 1,
F_END = 2;
localparam FILE_TXT = "../../../test.txt";
//localparam FILE_TXT = "../../../test.bin";
integer fd;
integer ret;
integer i;
integer pos;
reg [7:0] fbuf = 0;
initial begin
i = 0;
ret = 0;
fd = $fopen(FILE_TXT, "r");
if(fd == 0)
begin
$display("$open file failed") ;
$stop;
end
$display("\n ============= file opened... ============= ") ;
ret = $fseek(fd, 1,F_START);
if($signed(ret) == -1)
begin
$display("$fseek failed") ;
$stop;
end
pos = $ftell(fd);
$display("pos = %d", pos) ;
fbuf = $fgetc(fd);
pos = $ftell(fd);
$display("pos = %d", pos) ;
#10;
$write("%c", fbuf) ;
i = i + 1;
ret = $fseek(fd, -5,F_END);
if($signed(ret) == -1)
begin
$display("$fseek failed") ;
$stop;
end
while ($feof(fd) != 1)
begin
fbuf = $fgetc(fd);
#10;
$write("%c", fbuf);
i = i + 1;
end
#10;
$fclose(fd) ;
$display("\n ============= file closed... ============= ") ;
stop_flag = 1;
#100;
$stop;
end
endmodule
在之前的仿真工程中, 稍微做一点修改将
while ($signed(fbuf) != -1) 修改为
while ($feof(fd) != 1)
就可以实现文件结尾的的监控了。 注意, 使用$feof 判断文件结束才是仿真文件中判断结束常用做法。
仿真结果: