在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 判断文件结束才是仿真文件中判断结束常用做法。
仿真结果: