Menu Close

Verilog 文件操作-$fdisplay,$fwrite,$fstrobe,$fmonitor

在Verilog 仿真中,利用$fopen打开文件后,需要对文件进行读写操作。在Verilog 语法中提供$fdisplay,$fwrite,$fstrobe,$fmonitor 等系统函数,帮助开发者将数据写回到文件中。下面就针对写操作的相关函数进行讲解。

1. $fdisplay 函数:

语法解析:

$fdisplay(<file_desc>, "<string>", variables);

file_desc :文件句柄,表示要对哪个文件进行写操作
string:为写入文件的格式
variables: 为写入的数值。

 

注意在string之后一般会使用特殊字符 (%) 表示有关variable的信息。 使用时,编译器会识别 string中的% 字符并知道variables的具体格式规范。 有关所有格式规范的完整说明,请参见下表。如果需要显示 % 字符,使用双百分号(%%)。

%d or %D 十进制
%b or %B 二进制
%h or %H 十六进制
%o or %O 八进制
%c or %C ASCII 字符
%s or %S 字符串
%t or %T 时间格式

$fdisplay 的使用方法和$display系统函数的使用方法很类似,$display是将格式化的结果输出到控制台上,而$fdisplay 是将格式化的输出结果写入到文件中。

例1 打开一个文本文件,并写入相关的数据:

`timescale 1ns / 1ps

module sim_top( );
    
localparam FILE_NAME = "../../../led_sim.txt";
integer file_handle = 0;
initial begin
    file_handle = $fopen(FILE_NAME,"w");
    if(!file_handle)
    begin
        $display("Could not open File \r");
        $stop;
    end
    $fdisplay (file_handle, "new data1: %h", file_handle);
    $fdisplay (file_handle, "new data2: %h", 16'h1234);
    $fdisplay (file_handle, "new data3: %d", 123);
 
    $fclose(file_handle);    

    #200;
    $stop;
end

endmodule

 

$fopen 用来打开操作系统上的文件,$fdisplay 将数据格式化写入到文件中去。$fclose 用于将文件关闭。由于打开的文件为文本格式的。 所以存储的文件也是可以被文本工具打开的。

 

verilog simulation $fopen

图1

从图1 中可以看出,使用$fdisplay 函数,每次操作自带换行操作。

$fdisplay函数与$display 函数非常类似,对不同过程中返回变量的结果,需要注意之间的先后顺序。

例2:观察$fdisplay 中使用了连续赋值的结果作为输入参数。

`timescale 1ns / 1ps
module sim_top( );
    

wire [3:0] y;
reg  [2:0] a = 1, b = 2;

assign y = a + b;

localparam FILE_NAME = "../../../led_sim.txt";
integer file_handle = 0;
initial begin
    file_handle = $fopen(FILE_NAME,"w");
    if(!file_handle)
    begin
        $display("Could not open File \r");
        $stop;
    end

    $fdisplay (file_handle, "new data1: %h", file_handle);
    $fdisplay (file_handle, "new data2: %h", 16'h1234);
    $fdisplay (file_handle, "new data3: %d", y);
    #10;
    $fdisplay (file_handle, "new data3: %d", y);
  
    $fclose(file_handle);    
    #200;
    $stop;
end

endmodule

图2

从图2 中可以看出第一次对new data3 输出没有得到 y = a + b 的结果,之后延迟了10ns后,再次写入new data3 得到了正确的结果。

打开一个二进制文件,并写入相关的数据:

`timescale 1ns / 1ps

module sim_top( );
    
wire [3:0] y;
reg  [2:0] a = 1, b = 2;
assign y = a + b;

localparam FILE_NAME = "../../../led_sim.hex";
integer file_handle = 0;
initial begin
    file_handle = $fopen(FILE_NAME,"wb+");
    
    if(!file_handle)
    begin
        $display("Could not open File \r");
        $stop;
    end
    $fdisplay (file_handle, "%c", 16'h1234);
    $fdisplay (file_handle, "%c", 16'h39);
    $fdisplay (file_handle, "%x", 16'h1234);
    $fdisplay (file_handle, "%c", 16'h1234);
    $fdisplay (file_handle, "%c", y);
    #10;
    $fdisplay (file_handle, "%c", y);

    $fclose (file_handle);  
  
    #200;
    $stop;
end
    
endmodule

 

图3

图4

从图3,图4 可以看出:

  • 1)16’h1234 ,由于是%c 作为参数,所以只有8’h34 被写入到文件中
  • 2)8’h39 被写入到文件中
  • 3)16’h1234 ,虽然使用%x作为参数,但是却被当中字符串形式写入。即 1 => 31;2 => 32;3 => 33;4 => 34;
  • 4)情况和 1)相同
  • 5)由于 assign y = a + b; 所以这时还没有得到结果,这一点和$display 函数相同
  • 6)过了10ns 后,y 的结果已经确定 为 3, 所以这时写入文件是8’h03。

从这里我们可以看出, $fdisplay 写入二进制文件时,只有%c 比较好用,其他格式都会有些不好理解。 同时$fdisplay 有换行的操作,不利于二进制文件生成。

2 使用$fwrite 系统函数

$fwrite(<file_desc>, "<string>", variables);

file_desc:文件句柄, 指示需要被写入的文件。
string:文件写入格式
variables:写入文件的内容。

$fwrite 和$write 的使用也是很类似的,和$display,$fdisplay  系统函数比较,但没有自动换行操作。

$fwrite 函数的使用方法与$fdisplay 类似, 只是$fwrite 信号没有缺省的换行操作。

`timescale 1ns / 1ps

module sim_top( );
    
wire [3:0] y;
reg  [2:0] a = 1, b = 2;
assign y = a + b;

localparam FILE_NAME = "../../../led_sim.hex";
integer file_handle = 0;
initial begin
    file_handle = $fopen(FILE_NAME,"wb+");
    
    if(!file_handle)
    begin
        $display("Could not open File \r");
        $stop;
    end
    $fwrite (file_handle, "%c", 16'h1234);
    $fwrite (file_handle, "%c", 16'h39);
    $fwrite (file_handle, "%x", 16'h1234);
    $fwrite (file_handle, "%c", y);
    #10;
    $fwrite (file_handle, "%c", y);

    $fclose (file_handle);  
  
    #200;
    $stop;
end
    
endmodule

 

图5

图6

从图5,图6 可以看出, $fwrite函数和$fdisplay 函数写入文件非常类似,只是$fwrite 没有换行输出特性, 可以连续写入数据。 使用%c 可以写入相应的二进制数据到文件中。

注意:

1)%c 写入二进制文件时是 8bit的格式。例如: $fwrite (file_handle, “%c”, 16’h1234); 输入数据是16’h1234,但是只有 8’h34被写入到文件中。

2)%x 在使用$fwrite 时,和$fdisplay 情况相同,都是按照字符串形式写入到二进制文件中。

 

3 $fstrobe 使用

$fstrobe(<file_desc>, "<string>", variables);

file_desc: 文件句柄,表示对哪个文件进行写操作
string:输出文件的格式,可以参考$display 的格式用法
variables:准备写入的变量

$fstrobe 和 $strobe 函数的使用类似,都是在时间节点到达时,执行函数。

`timescale 1ns / 1ps
module sim_top( );
    
wire [3:0] y;
reg  [2:0] a = 1, b = 2;
assign y = a + b;

localparam FILE_NAME = "../../../led_sim.hex";
integer file_handle = 0;
initial begin
    file_handle = $fopen(FILE_NAME,"wb+");
    
    if(!file_handle)
    begin
        $display("Could not open File \r");
        $stop;
    end

    $fstrobe (file_handle, "%h", $time);
    $fstrobe (file_handle, "%h", 16'h5678);
    $fstrobe (file_handle, "%h", y);
    $fstrobe (file_handle, "%c", y);
    a = 5;
    $fstrobe (file_handle, "%h", y);
    #10;
    a = 4;
    $fstrobe (file_handle, "%c", y);

    $fclose (file_handle);    
    #200;
    $stop;
end

endmodule

 

图7-1 文本显示

图7-2 二进制显示

从上图7-1,图7-2的仿真结果可以看出:$fstrobe 系统函数的使用和$strobe 函数的使用非常类似, 也就是说只有到了时间节点后,如果变量相同,到了时间节点后,统一评估,并写入到文件中。当 a = 4时,虽然后面还有$fstrobe 函数, 但是这时文件已经关闭了, 所以 最新的y 值并没有被写入到文件中去。

 

4 $fmonitor函数使用

$fmonitor(<file_desc>, "<string>", variables);

file_desc: 文件句柄,需要写入的文件
string:字符表达式,具体可以参考$display
variables:写入的数据

$fmonitor和$monitor 系统函数的使用类似,只有当variables 列表中发生变化,时间节点到达时才执行函数。也就是说,只要触发条件就可以自动打印输出。

`timescale 1ns / 1ps

module sim_top( );

wire [3:0] y;
reg  [2:0] a = 1, b = 2;
assign y = a + b;

localparam FILE_NAME = "../../../led_sim.hex";
integer file_handle = 0;
initial begin
    file_handle = $fopen(FILE_NAME,"wb+");
    
    if(!file_handle)
    begin
        $display("Could not open File \r");
        $stop;
    end

    $fmonitor (file_handle, "%h", $time);
    $fmonitor (file_handle, "%h", 16'h5678);
    $fmonitor (file_handle, "%h", y);
    a = 5;
    a = 4;
    #10;
    a = 3; 
    a = 4;
    a = 7;
    #10;
    a = 4; 

    $fclose (file_handle);    
end

endmodule

 

图8

上例中, 我们可以看到,$fmonitor 可以监控数据的改变,不需要每次都调用$fmonitor。 当时间节点到达时,如果变量被多次赋值,按照最后一次赋值的结果输出。

注意当a = 4时,文件就关闭了, 所以最后一次的计算,并没有写入到文件中。

 

5 总结

$fdisplay : 适合文本文件格式输出,可以随时写入。

$fwrite :适合二进制文件格式输出, 没有额外的换行操作。 可以随时写入的文件。

$fstrobe:在时间节点或事件到达时,统一评估变量的值,并输出每个$fstrobe 的结果到文件中。

$fmonitor:对于变量监控,只要在初始化时,声明一次即可。

 

注:在文件文件打开和关闭中介绍了基本文件操作模式, 其实,文件的操作模式还可以扩展使用:

“r+”, “rb+” Open for both reading and writing
“w+”, “wb+” Truncate or create for update
“a+”,  “ab+” Append, or create new file for update at EOF

更多的细节,请参照相关视频。

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

发表回复

相关链接