File Output System Tasks in Verilog and SystemVerilog

In this article, we'll dive into the file output system tasks in Verilog and SystemVerilog: $fdisplay, $fwrite, $fmonitor, and $fstrobe. These tasks are incredibly useful when you want to log or output data to files during simulation. If you're familiar with the basic display and write tasks, this will be an extension of those concepts.

Introduction

We've previously introduced the display and write tasks in SystemVerilog, including $display, $write, and $strobe. These tasks are essential for printing information to the console. If you haven't checked those out yet, you can find the articles here:

Now, we'll look at how $fdisplay, $fwrite, $fmonitor, and $fstrobe can be used to direct this output to files in Verilog and SystemVerilog.

Understanding File Output System Tasks in Verilog

The file output tasks in Verilog and SystemVerilog are similar to their console counterparts but with an added twist: they can direct output to files instead of the console. The arguments for these tasks are the same, with the primary difference being the first argument, which is the file descriptor (fd) or multichannel descriptors (mcd). You can learn more about fd and mcd in the File Operation Tasks article.

Example: Producer and Consumer Logging with File Output Tasks

Let's create a simple example of a producer-consumer module where both the producer and consumer log their activities to separate files, and then log a final message to both files using a broadcasting descriptor.

module ProducerConsumerSystem;

  integer mcd_producer, mcd_consumer;
  integer mcd_broadcast;
  logic [7:0] data;
  logic [7:0] result;

  initial begin
    // Open files for producer and consumer
    mcd_producer = $fopen("producer.log");
    mcd_consumer = $fopen("consumer.log");

    // Combine files for broadcast
    mcd_broadcast = mcd_producer | mcd_consumer | 32'b1;

    // Producer activity
    data = 8'hA5; // Example data produced
    $fdisplay(mcd_producer, "Producer generated data: %h at time %0t", data, $time);

    // Consumer activity
    result = data + 8'h5A; // Example processing
    $fdisplay(mcd_consumer, "Consumer processed data to: %h at time %0t", result, $time);

    // Log final message to both files
    $fdisplay(mcd_broadcast, "Final message: Producer and Consumer have completed their tasks at time %0t", $time);

    // Close files
    $fclose(mcd_producer);
    $fclose(mcd_consumer);
  end

endmodule

Explanation

  1. Multichannel Descriptors: We open separate files for the producer and consumer using $fopen. These multichannel descriptors are stored in mcd_producer and mcd_consumer. We then create the broadcasting descriptor (mcd_broadcast) by ORing these file descriptors with 32'b1 to include STDOUT.
  2. Producer Activity: The producer generates some data (data = 8'hA5) and logs this activity to producer.log using $fdisplay.
  3. Consumer Activity: The consumer processes the data (e.g., adding 8'h5A to data) and logs the result to consumer.log using $fdisplay.
  4. Final Message Logging: We use the broadcasting descriptor to log a final message to both files and STDOUT, indicating that the producer and consumer have completed their tasks.
  5. Closing Files: Finally, we close both files using $fclose.

By using $fdisplay, $fwrite, $fmonitor, and $fstrobe in Verilog and SystemVerilog, you can direct your simulation outputs to files, which is particularly useful for debugging and logging simulation data. Experiment with these tasks in your own projects to get a better grasp of how they work and how they can be used to improve your simulation logging.