Verilog文件操作

在Verilog仿真中,我们有时需要将仿真得到的数据回写到文件中去,在Verilog语法中提供$fdisplay, $fwrite, $fstrobe, $fmonitor等系统函数来帮助开发者将数据写回到文件中。

1. $display() 函数的使用

语法解析:

$fdisplay(<file_desc>,"string",variables);
// file_desc : 文件句柄,表示要对哪个文件进行写操作
// string    : 写入文件的格式
// variables : 写入的数值

$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
    $dispaly("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()用于将打开的文件关闭。由于打开的文件为文本格式的,所以存储的文件也可以被文本工具打开。

"led_sim.txt"的文件内容如下所示:

new data1: ffffb1e0
new data2: 1234
new data3: 123

2. $fwrite()函数的使用

语法解析:

$fwrite(<file_desc>,"string",variables);
// file_desc : 文件句柄,表示要对哪个文件进行写操作
// string    : 写入文件的格式
// variables : 写入的内容

$fwrite()的使用方法和$write()系统函数的使用也是很类似的。$fwrite()$fdisplay()功能一样,但是没有自动换行功能。

例2:

`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
    $dispaly("Could not open file \r ");
    $stop;
  end

  $fwrite(file_handle, "new data1: %h", file_handle);
  $fwrite(file_handle, "new data2: %h", 16'h1234);
  $fwrite(file_handle, "new data3: %d", 123);

  $fclose(file_handle);

  #200, $stop;
end

endmodule

"led_sim.txt"的文件内容如下所示:

new data1: ffffb1e0    new data2: 1234    new data3: 123

3. $fstrobe()函数的使用

语法解析:

$fstrobe(<file_desc>,"string",variables);
// file_desc : 文件句柄,表示要对哪个文件进行写操作
// string    : 输出文件的格式,参考$display()的格式用法
// variables : 准备写入的变量

$fstrobe()的使用方法和$strobe()系统函数的使用也是很类似的,都是在时间节点到达时,执行函数。

例3:

`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
    $dispaly("Could not open file \r ");
    $stop;
  end

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

  $fclose(file_handle);

  #200, $stop;
end

endmodule

"led_sim.txt"的文件内容如下所示:

00000000000000000000
5678
7
7

$fstrobe()被调用的时刻所有语句都执行完才开始打印。上面的代码被"#10"分割为两个执行时刻,"#10"之前所有语句执行完毕后"a=5"已经生效了,因此两次打印的y的值都是7。而"#10"之后所有语句执行完毕时文件已经被关闭了,所以a=9没有打印出来。

4.$fmonitor()函数的使用

语法解析:

$fmonitor(<file_desc>,"string",variables);
// file_desc : 文件句柄,表示要对哪个文件进行写操作
// string    : 输出文件的格式,参考$display()的格式用法
// variables : 写入的数据

$fmonitor()$monitor()系统函数的使用类似,只要参数列表中的variable发生变化,并且到了执行时刻其他语句都执行完毕,它就会执行。优点是,不必纠结在哪里打印输出,只要触发条件,就可以自动打印输出。

例4:

`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
    $dispaly("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;
  #10
  a = 3;
  #10
  a = 4;
  $fclose(file_handle);

  #200, $stop;
end

endmodule

"led_sim.txt"的文件内容如下所示:

00000000000000000000
5678
7
5

我们可以看到,$fmonitor()可以监控数据的变化,不需要每次都调用$fmonitor()。注意,上面的代码中的两个"#10"将执行过程分成了三个阶段,第一个阶段所有代码执行完毕时,"a=5"所以y打印出来是7,第二个阶段"a=3"所以y打印出来是5,第三个阶段所有代码执行完毕文件关闭了,所以a=4没有打印出来。

posted @ 2024-12-04 17:18  Vinson88  阅读(528)  评论(0)    收藏  举报