📜  Verilog文件操作

📅  最后修改于: 2021-01-11 15:16:52             🧑  作者: Mango

Verilog文件操作

Verilog具有系统任务和功能,可以打开文件,将值输出到文件,从文件中读取值以及加载到其他变量和关闭文件中。

此应用程序描述了Verilog模型或测试平台如何读取文本和二进制文件以加载内存,施加刺激以及控制仿真。文件I / O函数格式基于C stdio例程,例如fopen,fgetc,fprintffscanf

Verilog语言具有一组系统功能来写入文件($ fdisplay,$ fwrite等),但仅读取具有固定格式的文件($ readmem)。

过去,如果我们想读取不是$ readmem格式的文件,则必须学习编程语言接口(PLI)和C语言,编写C代码以读取文件并将值传递给Verilog,然后调试组合的C和Verilog代码。另外,Verilog一次最多只能打开32个文件。

但是,使用新的文件I / O系统功能,我们可以直接从Verilog执行文件I / O。我们可以将Verilog HDL编写为:

  • 读取激励文件以将模式应用于模型的输入。
  • 读取期望值文件以与模型进行比较。
  • 阅读命令脚本以驱动仿真。
  • 将ASCII或二进制文件读入Verilog寄存器和存储器。
  • 同时打开数百个日志文件(尽管它们一次写入一个)。

该文件中所有示例的代码都包含在文件I / O功能的示例目录中。

注意:这些系统任务的行为与等效的stdio例程相同。例如,$ fscanf将跳过空白,包括空白行,就像fscanf()一样。我们可以使用C语言编写原型代码,然后将其转换为Verilog。

打开和关闭文件

$ fopen函数将打开一个文件,并以无大小限制的整数格式返回一个多通道描述符。这对于每个文件都是唯一的。模拟器和文件之间的所有通信都是通过文件描述符进行的。用户只能指定文件名作为参数。它将在默认文件夹或完整路径说明中给定的文件夹中创建一个文件。

我们使用$ fclose函数关闭打开的文件。调用该函数不带任何参数。它只是关闭所有打开的文件。如果指定了参数,它将仅关闭给出了描述符的文件。默认情况下,在模拟器终止之前,将关闭所有打开的文件。这意味着用户不必关闭任何文件,并且关闭是由模拟器自动完成的。

所有文件输出任务的工作方式与其相应的显示任务相同。唯一的区别是文件描述符在函数参数列表中显示为第一个参数。这些功能只能将数据追加到文件,而不能从文件读取数据。

module tb;
    // Declare a variable to store the file handler
    integer fd;

    initial begin
        // Open a new file by the name "my_file.txt"
        // with "write" permissions, and store the file
        // handler pointer in variable "fd"
        fd = $fopen("my_file.txt", "w");

        // Close the file handle pointed to by "fd"
        $fclose(fd);
    end
endmodule

打开文件模式

Argument Description
“r” or “rb” Open for reading.
“w” or “wb” Create a new file for writing. If the file exists, truncate it to zero length and overwrite it.
“a” or “ab” If the file exists, append (open for writing at EOF), else create a new file.
“r+”, “r+b” or “rb+” Open for both reading and writing.
“w+”, “w+b” or “wb+” Truncate or create for an update.
“a+”, “a+b”, or “ab+” Append, or create a new file for an update at EOF.

如何写文件

Function Description
$fdisplay Similar to $display, write out to file instead
$fwrite Similar to $write, write out to file instead
$fstrobe Similar to $strobe, write out to file instead
$fmonitor Similar to $monitor, write out to file instead

上述每个系统功能均以十进制基数打印值。它们还具有其他三个版本,以二进制,八进制和十六进制值打印值。

Function Description
$fdisplay() Prints in decimal by default
$fdisplayb() Prints in binary
$fdisplayo() Prints in octal
$fdisplayh() Prints in hexadecimal
module tb;
    integer      fd;
    integer     i;
    reg [7:0]     my_var;

    initial begin
        // Create a new file
        fd = $fopen("my_file.txt", "w");
        my_var = 0;

      $fdisplay(fd, "Value displayed with $fdisplay");
        #10 my_var = 8'h1A;
        $fdisplay(fd, my_var);      // Displays in decimal
        $fdisplayb(fd, my_var);     // Displays in binary
        $fdisplayo(fd, my_var);     // Displays in octal
        $fdisplayh(fd, my_var);     // Displays in hex

      // $fwrite does not print the newline char '\n' automatically at
      // the end of each line; So we can predict all the values printed
      // below to appear on the same line
      $fdisplay(fd, "Value displayed with $fwrite");
        #10 my_var = 8'h2B;
        $fwrite(fd, my_var);
        $fwriteb(fd, my_var);
        $fwriteo(fd, my_var);
        $fwriteh(fd, my_var);


      // Jump to new line with '\n', and print with strobe which takes
      // the final value of the variable after non-blocking assignments
      // are done
      $fdisplay(fd, "\nValue displayed with $fstrobe");
        #10 my_var <= 8'h3C;
        $fstrobe(fd, my_var);
        $fstrobeb(fd, my_var);
        $fstrobeo(fd, my_var);
        $fstrobeh(fd, my_var);
      #10 $fdisplay(fd, "Value displayed with $fmonitor");
      $fmonitor(fd, my_var);
        for(i = 0; i < 5; i= i+1) begin
            #5 my_var <= i;
        end
      #10 $fclose(fd);
    end
endmodule

上面的代码提供以下输出,例如:

Value displayed with $fdisplay
26
00011010
032
1a
The value displayed with $fwrite
43001010110532b
The value displayed with $fstrobe
60
00111100
074
3c
The value displayed with $fmonitor
60
0
1
2
3
4

读取文件

要从内存文件读取和存储数据,我们使用$ readmemh$ readmemb函数。

$ readmemb任务读取二进制数据,而$ readmemh读取十六进制数据。数据必须存在于文本文件中。允许使用空格来提高可读性以及单行和块中的注释。数字必须存储为二进制或十六进制值。一个存储器文件的基本形式含有通过加载到存储器新行字符分隔的数字。

如果在没有开始和结束地址的情况下调用函数,则会从第一个单元开始将数据加载到内存中。起始地址和结束地址只能用于将数据加载到内存的特定部分。

该地址可以是显式的,在文件中以@字符,后跟一个十六进制地址,数据之间用空格分隔。记住文件中指定的开始和结束地址范围非常重要。函数调用中的参数必须彼此匹配。否则,将显示错误消息,并终止加载过程。

读线

系统函数$与fgets直到STR填充从由[HL] FD [/ HD]指定为变量str的文件中读取的字符,或一个字符被读出并传送到STR,或者遇到一个EOF条件。

如果读取期间发生错误,则返回代码零。否则,它返回读取的字符数。

检测EOF

找到EOF时,系统函数$ feof返回非零值,否则对于给定文件描述符作为参数返回零。

module tb;
    reg[8*45:1] str;
    integer      fd;

    initial begin
      fd = $fopen("my_file.txt", "r");

      // Keep reading lines until EOF is found
      while (! $feof(fd)) begin

          // Get current line into the variable 'str'
        $fgets(str, fd);

        // Display contents of the variable
        $display("%0s", str);
      end
      $fclose(fd);
    end
endmodule

要显示的多个参数

当给$ fdisplay多个变量时,它只是简单地以给定的顺序打印所有变量而没有空格。

  reg [3:0] a, b, c, d;
  reg [8*30:0] str;
  integer fd;

  initial begin
    a = 4'ha;
    b = 4'hb;
    c = 4'hc;
    d = 4'hd;

    fd = $fopen("my_file.txt", "w");
    $fdisplay(fd, a, b, c, d);
    $fclose(fd);
  end
endmodule

将数据格式化为字符串

$ sformat系统函数的第一个参数是将结果放入其中的变量名称。

第二个参数是format_string ,它告诉如何将以下参数格式化为字符串。

module tb;
    reg [8*19:0] str;
    reg [3:0] a, b;


    initial begin
        a = 4'hA;
        b = 4'hB;

        // Format 'a' and 'b' into a string given
        // by the format, and store into 'str' variable
        $sformat(str, "a=%0d b=0x%0h", a, b);
        $display("%0s", str);
    end
endmodule