Menu Close

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 个字节, 然后开始读取文本文件的数据。

仿真的结果如下:

 

%title插图%num

 

%title插图%num

 

$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

 

仿真结果输出:

%title插图%num

我们可以看到,$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 判断文件结束才是仿真文件中判断结束常用做法。

 

仿真结果:

%title插图%num

Posted in FPGA, FPGA, Verilog, Verilog, 教材与教案, 文章

发表评论

相关链接