System Verilog allows us to read and write into files in the disk.

How to open and close a file ?

A file can be opened for either read or write using the $fopen() system task. This task will return a 32-bit integer handle called a file descriptor. This handle should be used to read and write into that file until it is closed. The file descriptor can be closed with the $fclose() system task. No further reads or writes to the file descriptor is allowed once it is closed.

Example

In the code shown below, we will declare a int variable called fd to hold the file descriptor. fd is initially zero, and gets a valid value from $fopen() and can be checked to see if the file opened successfully. The file is finally closed when $fclose() is executed.


module tb;
  initial begin
  	// 1. Declare an integer variable to hold the file descriptor
  	int fd; 		
  	
  	// 2. Open a file called "note.txt" in the current folder with a "read" permission
  	// If the file does not exist, then fd will be zero
    fd = $fopen ("./note.txt", "r"); 	
    if (fd)  $display("File was opened successfully : %0d", fd);
    else     $display("File was NOT opened successfully : %0d", fd);
    
    // 2. Open a file called "note.txt" in the current folder with a "write" permission
    //    "fd" now points to the same file, but in write mode
    fd = $fopen ("./note.txt", "w"); 	
    if (fd)  $display("File was opened successfully : %0d", fd);
    else     $display("File was NOT opened successfully : %0d", fd);
    
    // 3. Close the file descriptor
    $fclose(fd);
  end
endmodule

It is important to close all open files before end of simulation to completely write contents into the file

 Simulation Log
ncsim> run
Open failed on file "./note.txt". No such file or directory
File was NOT opened successfully : 0
File was opened successfully : -2147483645
ncsim: *W,RNQUIE: Simulation is complete.

How to open in read and append modes ?

By default a file is opened in the write w mode. The file can also be opened in other modes by providing the correct mode type. The following table shows all the different modes a file can be opened in.

ArgumentDescription
"r"Open for reading
"w"Create for writing, overwrite if it exists
"a"Create if file does not exist, else append; open for writing at end of file
"r+"Open for update (reading and writing)
"w+"Truncate or create for update
"a+"Append, open or create for update at EOF

Example

In the following code, we will see how to use the different file access modes as described in the table above.


module tb;
  initial begin
  	int fd_w, fd_r, fd_a, fd_wp, fd_rp, fd_ap; 
        
    fd_w = $fopen ("./todo.txt", "w"); 	// Open a new file in write mode and store file descriptor in fd_w
    fd_r = $fopen ("./todo.txt", "r"); 	// Open in read mode
    fd_a = $fopen ("./todo.txt", "a"); 	// Open in append mode
  
    
    if (fd_w)     $display("File was opened successfully : %0d", fd_w);
    else      	  $display("File was NOT opened successfully : %0d", fd_w);
    
    if (fd_r)     $display("File was opened successfully : %0d", fd_r);
    else      	  $display("File was NOT opened successfully : %0d", fd_r);
    
    if (fd_a)     $display("File was opened successfully : %0d", fd_a);
    else      	  $display("File was NOT opened successfully : %0d", fd_a);
    
    // Close the file descriptor
    $fclose(fd_w);
    $fclose(fd_r);
    $fclose(fd_a);
  end
endmodule

As you can see from the log shown below, all three variables have a different value and each one points to the same file, but with different access permissions.

 Simulation Log
ncsim> run
ncsim: *W,VFOPTW: File ./todo.txt being opened by Initial stmt (file: ./testbench.sv, line: 2 in worklib.tb [module]) has been opened earlier.
File was opened successfully : -2147483645
File was opened successfully : -2147483644
File was opened successfully : -2147483643
ncsim: *W,RNQUIE: Simulation is complete.

How to read and write to a file ?

Files should be opened in the write w mode, or append a mode. System tasks like $fdisplay() and $fwrite() can be used to write a formatted string into the file. The first argument of these tasks is the file descriptor handle and the second will be the data to be stored.

To read a file, it has to be opened in either read r mode or read-write r+ mode. $fgets() is a system task that will read a single line from the file. If this task is called 10 times, then it will read 10 lines.

Example

The code shown below demonstrates how to open a file and write contents into it using $fdisplay(). The file is then opened in read mode and contents are read back using $fgets() into a local variable. This is then printed out using the standard display task $display()


module tb;
  int 	 fd; 			// Variable for file descriptor handle
  string line; 			// String value read from the file
  
  initial begin
    
    // 1. Lets first open a new file and write some contents into it
    fd = $fopen ("trial", "w");
    
    // Write each index in the for loop to the file using $fdisplay
    // File handle should be the first argument
    for (int i = 0; i < 5; i++) begin
      $fdisplay (fd, "Iteration = %0d", i);
    end
    
    // Close this file handle
    $fclose(fd);
    
    
    // 2. Let us now read back the data we wrote in the previous step
    fd = $fopen ("trial", "r");
    
    // Use $fgets to read a single line into variable "line"
    $fgets(line, fd);
    $display ("Line read : %s", line);
    
    // Get the next line and display
    $fgets(line, fd);
    $display ("Line read : %s", line);
    
    // Close this file handle
    $fclose(fd);
  end
endmodule
 Simulation Log
ncsim> run
Line read : Iteration = 0

Line read : Iteration = 1

ncsim: *W,RNQUIE: Simulation is complete.

How to read until end of file ?

In the previous example, we used $fgets() system task twice to read two lines from the file. SystemVerilog has another task called $feof() that returns true when end of the file has reached. This can be used in a loop as follows to read the entire contents of a file.

Example


module tb;
  int 	 fd; 			// Variable for file descriptor handle
  string line; 			// String value read from the file
  
  initial begin
    // 1. Lets first open a new file and write some contents into it
    fd = $fopen ("trial", "w");
    for (int i = 0; i < 5; i++) begin
      $fdisplay (fd, "Iteration = %0d", i);
    end
    $fclose(fd);
    
    
    // 2. Let us now read back the data we wrote in the previous step
    fd = $fopen ("trial", "r");
    
    while (!$feof(fd)) begin
      $fgets(line, fd);
      $display ("Line: %s", line);
    end
    
    // Close this file handle
    $fclose(fd);
  end
endmodule
 Simulation Log
ncsim> run
Line: Iteration = 0

Line: Iteration = 1

Line: Iteration = 2

Line: Iteration = 3

Line: Iteration = 4

Line: 
ncsim: *W,RNQUIE: Simulation is complete.

How to parse a line for values ?

SystemVerilog has another system task called $fscanf() that allows us to scan and get certain values.

Example


module tb;
  int 	 fd; 			// Variable for file descriptor handle
  int 	 idx;
  string str;
  
  initial begin
    // 1. Lets first open a new file and write some contents into it
    fd = $fopen ("trial", "w");
    for (int i = 0; i < 5; i++) 
      $fdisplay (fd, "Iteration = %0d", i);
    $fclose(fd);
    
    
    // 2. Let us now read back the data we wrote in the previous step
    fd = $fopen ("trial", "r");
    
    // fscanf returns the number of matches
    while ($fscanf (fd, "%s = %0d", str, idx) == 2) begin
      $display ("Line: %s = %0d", str, idx);
    end
    
    // Close this file handle
    $fclose(fd);
  end
endmodule
 Simulation Log
ncsim> run
Line: Iteration = 0
Line: Iteration = 1
Line: Iteration = 2
Line: Iteration = 3
Line: Iteration = 4
ncsim: *W,RNQUIE: Simulation is complete.

What are multichannel file descriptors ?

The mcd is a 32-bit packed array value in which a single bit is set indicating which file is opened. The LSB of an mcd always refers to the standard output. Output is directed to two or more files opened with multichannel descriptors by bitwise OR-ing together their mcds, and writing to the resultant value.