Verilog中$fdisplay, $fwrite, $fmonitor和 $fstrobe的用法总结
1.前言
在verilog仿真中,利用$fopen打开文件后,对文件进行读写操作的系统函数有$fdisplay,$fwrite, $fmonitor, $fstrobe等系统函数,利用这些系统函数,可以将数据写到对应的文件中。下面就针对这些用法做一个梳理。本文主要讲\$fdisplay和\$fwrite,其他的用法后续会继续讲。
2.$fdisplay函数
$fdisplay系统函数的用法和系统函数$display的用法非常类似,$display是将格式化的结果输出到linux的terminal,而$fdisplay是将格式化的输出结果写入到相应的文件中。先让我看一下$display的用法。
2.1 $display的用法
如下图所示(IEEE1364),$display的用法和$write的用法很相近,IEEE中就放在一起介绍了,当然二者的差别(详见下图中的红色注释)也说得很清楚了。





下面来看官方给的一个$display的例子:


注意上图中的01000:8*9=‘d72=’b01001000。
2.2 $fdisplay的用法
2.2.1 $fdisplay的语法
`$fdisplay(<file_handle>, "<string>", variables);`
其中:file_handle为文件句柄,表示要对哪个文件进行写操作;string为写入文件的格式;variables为写入的数值。
下面给出一个例子:打开一个文本文件($fopen),并写入相关的数据
($fdisplay),$fopen用来打开操作系统上的文件,$fdisplay 将数据格式化写入到文件中。$fclose用于将文件关闭。由于打开的文件为文本格式, 所以存储的文件也是可以被文本工具打开的。

`timescale 1ns / 1ps
module fdisplay_test( );
localparam FILE_NAME = "./fdisplay_test.txt";
integer file_handle ;
reg [2:0] a = 3;
reg [2:0] b = 5;
wire [3:0] y;
assign y = a + b;
initial begin
file_handle = $fopen(FILE_NAME,"w");
$display("file_handle is %h",file_handle);
if(!file_handle)
begin
$display("Could not open File \r");
$stop;
end
$fdisplay(file_handle, "fdisplay_data1: %h", file_handle);
$fdisplay(file_handle, "fdisplay_data2: %h", 32'habcdef);
$fdisplay(file_handle, "fdisplay_data3: %d", 123456);
$fdisplay(file_handle, "fdisplay_data4: %d", y);
#20ns;
$fdisplay(file_handle, "fdisplay_data4: %d", y);
$fclose(file_handle);
#300;
$finish;
end
endmodule
仿真结果如下面截图所示,符合预期。如果将上图中line21~line26的%d换成%c,就是以ASCII码格式输出的话,打印出来将是乱码,大家可以尝试一下。


3. $fwrite的用法
3.1 $fwrite的语法
`$fwrite(<file_handle>, "<string>", variables);`
其中:file_handle为文件句柄,表示要对哪个文件进行写操作;string为写入文件的格式;variables为写入的数值。
其中$fwrite和$fdisplay的唯一区别就是输出不换行。
下面看一个例子,就是将上面例子中的$fdisplay更换为$fwrite,

`timescale 1ns / 1ps
module fwrite_test( );
localparam FILE_NAME = "./fwrite_test.hex";
integer file_handle ;
reg [2:0] a = 3;
reg [2:0] b = 5;
wire [3:0] y;
assign y = a + b;
initial begin
file_handle = $fopen(FILE_NAME,"w");
$display("file_handle is %h",file_handle);
if(!file_handle)
begin
$display("Could not open File \r");
$stop;
end
$fwrite(file_handle, "fwrite_data1: %h", file_handle);
$fwrite(file_handle, "fwrite_data2: %h", 32'habcdef);
$fwrite(file_handle, "fwrite_data3: %h", 'h123456);
$fwrite(file_handle, "fwrite_data4: %h", y);
#20ns;
$fwrite(file_handle, "fwrite_data4: %h", y);
$fclose(file_handle);
#300;
$finish;
end
endmodule
下面是仿真结果,大家可以清楚的看到,输出到文件的内容没有换行。


4. $fmonitor的用法
4.1 $fmonitor的语法
$fmonitor(<file_handle>, "<string>", variables);
其中:file_handle为文件句柄,表示要对哪个文件进行写操作;string为写入文件的格式;variables为写入的数值。
$fmonitor和$monitor 系统函数的使用类似,但只有variables 列表中发生变化,时间节点到达时,才执行函数。优点是,不必纠结在哪里打印输出, 只要触发条件,就可以自动打印输出。
$monitor和$fmonitor的区别就是一个显示在terminal上,另一个写入到文件中,细节就不赘述了。下面看一个$fmonitor的例子:

`timescale 1ns / 1ps
module fmonitor_test( );
localparam FILE_NAME = "./fmonitor_test.txt";
integer file_handle ;
reg [7:0] a = 3;
reg [7:0] b = 5;
wire [8:0] y;
assign y = a + b;
initial begin
file_handle = $fopen(FILE_NAME,"w");
$display("file_handle is %h",file_handle);
if(!file_handle)
begin
$display("Could not open File \r");
$stop;
end
$fmonitor(file_handle, "fmonitor_data1: %h", file_handle);
$fmonitor(file_handle, "fmonitor_data2: %h", 32'habcdef);
$fmonitor(file_handle, "fmonitor_data3: %d", 123456);
$fmonitor(file_handle, "fmonitor_data4: %d", y);
a=4;
b=6;
#20ns;
a=8;
a=12;
a=9;
#20ns;
a=19;
//$fmonitor(file_handle, "fmonitor_data4: %d", y);
$fclose(file_handle);
#300;
$finish;
end
endmodule
仿真结果,如下图所示


几点注意事项:①从上例中可以看到,$fmonitor 可以监控数据的改变,不需要每次都调用$fmonitor。注意当a = 19时,文件就关闭了, 所以最后一次的计算,并没有写入到文件中;②上图中第35行是不必要的;③如果没有第26~33行的代码,$fmonitor是不会发生作用的。
5. $fstrobe的用法
5.1 $fstrobe的语法
$fstrobe(<file_handle>, "<string>", variables);
其中:file_handle为文件句柄,表示要对哪个文件进行写操作;string为写入文件的格式;variables为写入的数值。
$fstrobe和$strobe系统函数的使用类似,都是在时间节点到达时,执行函数。二者的区别就是一个显示在terminal上,另一个写入到文件中,细节就不赘述了。下面看一个$fstrobe的例子:

`timescale 1ns / 1ps
module fstrobe_test();
localparam FILE_NAME = "./fstrobe_test.txt";
integer file_handle ;
reg [7:0] a = 3;
reg [7:0] b = 5;
wire [8:0] y;
assign y = a + b;
initial begin
file_handle = $fopen(FILE_NAME,"w");
$display("file_handle is %h",file_handle);
if(!file_handle)
begin
$display("Could not open File \r");
$stop;
end
$fstrobe(file_handle, "fstrobe_data1: %h", file_handle);
$fstrobe(file_handle, "fstrobe_data2: %h", 32'habcdef);
$fstrobe(file_handle, "fstrobe_data3: %d", 123456);
$fstrobe(file_handle, "fstrobe_data4: %d", y);
a=6;
$fstrobe(file_handle, "fstrobe_data4: %d", y);
#20ns;
a=12;
a=9;
$fstrobe(file_handle, "fstrobe_data4: %d", y);
#20ns;
a=19;
$fstrobe(file_handle, "fstrobe_data4: %d", y);
$fclose(file_handle);
#300;
$finish;
end
endmodule
仿真结果,如下图所示,

从上面的仿真结果可以看出:只有到得了时间节点后,$fstrobe 系统函数才进行统一的赋值输出。当 a=19时虽然后面还有$fstrobe 函数, 但是这时文件已经关闭了, 所以 最新的y 值并没有被写入到文件中去,其余的大家应该能看懂了吧。
参考文献:
[1]https://ica123.com/archives/16060
浙公网安备 33010602011771号