<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Circuit Cove]]></title><description><![CDATA[Sail the Seas of Circuit Design]]></description><link>https://circuitcove.com/</link><image><url>https://circuitcove.com/favicon.png</url><title>Circuit Cove</title><link>https://circuitcove.com/</link></image><generator>Ghost 5.39</generator><lastBuildDate>Tue, 23 Jun 2026 23:21:11 GMT</lastBuildDate><atom:link href="https://circuitcove.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Understanding $ferror in Verilog and SystemVerilog]]></title><description><![CDATA[The $ferror function provides detailed error messages beyond simple codes, aiding in efficient debugging. Learn how to use $ferror to improve your error handling strategy.]]></description><link>https://circuitcove.com/system-tasks-ferror/</link><guid isPermaLink="false">6656c27c65d41c04b80d9f7a</guid><category><![CDATA[System Tasks and Functions]]></category><dc:creator><![CDATA[Shou-Li Hsu]]></dc:creator><pubDate>Wed, 29 May 2024 06:04:47 GMT</pubDate><content:encoded><![CDATA[<p>Today, we&apos;re delving into how to handle I/O error statuses using the <code>$ferror</code> function in SystemVerilog. While typical file functions return error codes, <code>$ferror</code> gives you more detailed information about the most recent I/O operation error.</p><h2 id="error-codes-and-ferror">Error Codes and <code>$ferror</code></h2><p>When dealing with file operations in SystemVerilog, you&apos;ll often face situations where an operation might fail. Usually, these functions return an error code, but this has its limitations. Here&apos;s where <code>$ferror</code> comes in handy.</p><h3 id="basic-usage">Basic Usage</h3><pre><code class="language-verilog">integer errno;
errno = $ferror(fd, str);
</code></pre><ul><li><strong>fd</strong>: File descriptor</li><li><strong>str</strong>: String to store the error message</li><li><strong>errno</strong>: Error code, <code>0</code> if no error</li></ul><p>If the most recent I/O operation didn&apos;t fail, <code>errno</code> will be <code>0</code>, and <code>str</code> will be cleared. Otherwise, <code>errno</code> will contain the error code, and <code>str</code> will provide a descriptive error message.</p><p>Imagine you&apos;re debugging a complex piece of code with multiple file operations. Simply knowing that an error occurred isn&apos;t always enough&#x2014;you need to understand what went wrong and where. <code>$ferror</code> helps by giving you a detailed message, making it easier to diagnose and fix issues.</p><h2 id="example-logging-errors">Example: Logging Errors</h2><p>Here&apos;s a concise example of using <code>$ferror</code> to log errors during file operations:</p><pre><code class="language-verilog">integer fd, errno;
string error_message;

fd = $fopen(&quot;input.txt&quot;, &quot;r&quot;);
if (fd == 0) begin
  errno = $ferror(fd, error_message);
  $display(&quot;Error opening file: %s&quot;, error_message);
end
</code></pre><p>In this example, if the input file can&apos;t be opened, we retrieve the error status using <code>$ferror</code> and display the detailed error message. This way, instead of just knowing that an error occurred, you get a specific message explaining what went wrong, which can be invaluable for debugging.</p><hr><p>The <code>$ferror</code> function in SystemVerilog provides detailed information about I/O operation errors, offering more context than simple error codes. This aids in diagnosing and fixing issues more efficiently.</p>]]></content:encoded></item><item><title><![CDATA[Using $fflush to Manage File Buffers in Verilog and SystemVerilog]]></title><description><![CDATA[Flushing data to a file in SystemVerilog ensures data is immediately written from the buffer, preventing loss, aiding real-time processing, and improving debugging efficiency. This process is essential for critical data handling scenarios.
]]></description><link>https://circuitcove.com/system-tasks-fflush/</link><guid isPermaLink="false">6656bcd465d41c04b80d9f4d</guid><category><![CDATA[System Tasks and Functions]]></category><dc:creator><![CDATA[Shou-Li Hsu]]></dc:creator><pubDate>Wed, 29 May 2024 05:45:52 GMT</pubDate><content:encoded><![CDATA[<p>In this article, we&#x2019;ll explore the <code>$fflush</code> system task in SystemVerilog. This function is essential for ensuring your file operations are efficient and reliable. We&apos;ll cover why flushing is necessary, how to use it, and provide a practical example.</p><h2 id="why-do-we-need-to-flush">Why Do We Need to Flush?</h2><p>Flushing data to a file in SystemVerilog is useful in several scenarios:</p><ol><li><strong>Prevent Data Loss</strong>: Writing data goes into a buffer first. If the simulation crashes, buffered data is lost. Using <code>$fflush</code> ensures all buffered data is immediately written to the file, safeguarding your data.</li><li><strong>Real-Time Data Access</strong>: For real-time processing, flushing ensures that written data is available immediately, rather than waiting for the buffer to fill up.</li><li><strong>Effective Debugging</strong>: When debugging, you need to see output data right away. Flushing lets you review the latest data instantly, making it easier to diagnose issues.</li></ol><h2 id="how-to-use-fflush">How to Use $fflush</h2><p>The <code>$fflush</code> function can be used in three ways:</p><ul><li><strong>Specific Multi-Channel Descriptor</strong>: <code>mcd</code></li><li><strong>Specific File Descriptor</strong>: <code>fd</code></li><li><strong>No Argument</strong>: Flushes all open files</li></ul><p>Here&apos;s the syntax for each usage:</p><pre><code class="language-verilog">$fflush(mcd); // Flushes the file specified by multi-channel descriptor
$fflush(fd);  // Flushes the file specified by file descriptor
$fflush();    // Flushes all open files
</code></pre><p>For more details on file descriptors like <code>mcd</code> and <code>fd</code>, check out the <a href="https://circuitcove.com/system-tasks-file-io/" rel="noreferrer">File Operations</a> article.</p><h2 id="practical-example">Practical Example</h2><p>Let&apos;s look at an example to illustrate <code>$fflush</code> in action. Suppose we are logging data to a file in a simulation and want to ensure that this data is periodically written to avoid any loss.</p><pre><code class="language-verilog">module FlushExample;
  integer fd;

  initial begin
    fd = $fopen(&quot;output.log&quot;, &quot;w&quot;);
    if (fd == 0) begin
      $display(&quot;Error: Could not open file.&quot;);
      $finish;
    end
  end

  always_ff @(posedge clk) begin
    $fwrite(fd, &quot;Simulation time: %0t\n&quot;, $time);

    if ($time % 1000 == 0) begin
      $fflush(fd);
    end
  end

  final begin
    $fclose(fd);
  end
endmodule
</code></pre><p>In this example, we open a file <code>output.log</code> for writing and use <code>$fwrite</code> to log the simulation time at each clock cycle. We then use <code>$fflush(fd)</code> every 1000 cycles to ensure the buffer is written to the file periodically.</p><hr><p>Using <code>$fflush</code> in SystemVerilog is essential for managing file buffers efficiently and preventing data loss. By strategically flushing the buffer, you ensure that your critical data is always saved and promptly available. This practice is particularly useful for real-time data processing, debugging, and handling large data volumes in long simulations.</p>]]></content:encoded></item><item><title><![CDATA[Understanding File Positioning Functions in Verilog and SystemVerilog]]></title><description><![CDATA[Discover how to master file positioning functions in SystemVerilog, including $ftell, $fseek, and $rewind. Learn through practical examples and understand their applications in file navigation and manipulation.]]></description><link>https://circuitcove.com/system-tasks-file-positioning/</link><guid isPermaLink="false">6656b22665d41c04b80d9eff</guid><category><![CDATA[System Tasks and Functions]]></category><dc:creator><![CDATA[Shou-Li Hsu]]></dc:creator><pubDate>Wed, 29 May 2024 05:02:50 GMT</pubDate><content:encoded><![CDATA[<p>Hello SystemVerilog enthusiasts! Today, we&apos;re diving into the intricacies of file positioning functions: <code>$ftell</code>, <code>$fseek</code>, and <code>$rewind</code>. These functions enable precise navigation through files, much like their C counterparts. Let&apos;s delve into how these functions operate and where you might find them useful.</p><h2 id="the-basics-of-file-positioning-functions">The Basics of File Positioning Functions</h2><p>In SystemVerilog, we have three primary file positioning functions:</p><ul><li><code>$ftell(fd)</code></li><li><code>$fseek(fd, offset, operation)</code></li><li><code>$rewind(fd)</code></li></ul><p>Let&apos;s break these down one by one and see how they work and where you might use them.</p><h2 id="understanding-ftell-in-systemverilog">Understanding $ftell in SystemVerilog</h2><p>The <code>$ftell(fd)</code> function returns the current position of the file pointer. This is particularly useful when you need to remember your place in a file, perhaps to return to this spot later.</p><h3 id="example-tracking-your-position-in-a-file">Example: Tracking Your Position in a File</h3><p>Imagine you have a file, <code>example.txt</code>, containing some data. You want to track your position as you read through it. Here&apos;s how you can do that:</p><pre><code class="language-verilog">integer fd;
integer position;
string line;

fd = $fopen(&quot;example.txt&quot;, &quot;r&quot;);
if (fd) begin
  // Read the first line
  line = $fgets(fd);
  $display(&quot;First line: %s&quot;, line);

  // Get the current position
  position = $ftell(fd);
  $display(&quot;Position after reading first line: %0d&quot;, position);
  
  // Read the next line
  line = $fgets(fd);
  $display(&quot;Second line: %s&quot;, line);

  // Get the new position
  position = $ftell(fd);
  $display(&quot;Position after reading second line: %0d&quot;, position);
  
  $fclose(fd);
end
</code></pre><p>This code reads the first two lines of the file and displays the file pointer&apos;s position after each read, allowing you to track your progress.</p><h2 id="navigating-files-with-fseek">Navigating Files with $fseek</h2><p>The <code>$fseek(fd, offset, operation)</code> function sets the file pointer to a specific location. It&apos;s the setter for your file position and can handle various modes:</p><ul><li><code>operation == 0</code>: Set the position to <code>offset</code> bytes from the beginning.</li><li><code>operation == 1</code>: Set the position to the current location plus <code>offset</code> (which can be negative).</li><li><code>operation == 2</code>: Set the position to EOF plus <code>offset</code>.</li></ul><h3 id="example-jumping-to-specific-positions">Example: Jumping to Specific Positions</h3><p>Let&apos;s say you want to skip the first 20 bytes of a file and start reading from there. Here&apos;s how:</p><pre><code class="language-verilog">integer fd;
string line;

fd = $fopen(&quot;example.txt&quot;, &quot;r&quot;);
if (fd) begin
  // Move 20 bytes from the beginning of the file
  $fseek(fd, 20, 0);
  $display(&quot;Position after seeking 20 bytes from start: %0d&quot;, $ftell(fd));
  
  // Read from the new position
  line = $fgets(fd);
  $display(&quot;Line after seeking 20 bytes: %s&quot;, line);
  
  $fclose(fd);
end
</code></pre><p>This snippet moves the file pointer 20 bytes from the start, then reads from that new position, demonstrating <code>$fseek</code> in action.</p><h2 id="resetting-the-file-pointer-with-rewind">Resetting the File Pointer with $rewind</h2><p>The <code>$rewind(fd)</code> function is a shorthand for setting the file pointer to the beginning of the file. It&apos;s equivalent to <code>$fseek(fd, 0, 0)</code>.</p><h3 id="example-restarting-file-reading">Example: Restarting File Reading</h3><p>Suppose you read a few lines from a file and then want to start over. Here&apos;s how <code>$rewind</code> can help:</p><pre><code class="language-verilog">integer fd;
string line;

fd = $fopen(&quot;example.txt&quot;, &quot;r&quot;);
if (fd) begin
  // Read the first line
  line = $fgets(fd);
  $display(&quot;First read: %s&quot;, line);
  
  // Rewind to the beginning
  $rewind(fd);
  $display(&quot;Position after rewind: %0d&quot;, $ftell(fd));
  
  // Read the line again
  line = $fgets(fd);
  $display(&quot;Second read after rewind: %s&quot;, line);
  
  $fclose(fd);
end
</code></pre><p>This example reads the first line, rewinds to the beginning, and reads the first line again, demonstrating how to reset the file pointer easily.</p><h2 id="practical-applications-of-file-positioning-functions">Practical Applications of File Positioning Functions</h2><p>You might wonder when these functions are particularly useful. Here are a few practical applications:</p><ul><li><strong>Log File Analysis</strong>: Skipping headers or sections in log files to read specific entries.</li><li><strong>Data Parsing</strong>: Jumping to specific sections of a data file to read relevant information.</li><li><strong>File Manipulation</strong>: Rewinding and re-reading parts of a file for verification or reprocessing.</li></ul><hr><p>Understanding and using these file positioning functions in SystemVerilog can greatly enhance your file handling capabilities. Whether you&apos;re analyzing logs, parsing data, or simply navigating through files efficiently, <code>$ftell</code>, <code>$fseek</code>, and <code>$rewind</code> are invaluable tools in your SystemVerilog toolkit.</p>]]></content:encoded></item><item><title><![CDATA[Reading Data from a File in Verilog and SystemVerilog]]></title><description><![CDATA[Reading data from files in SystemVerilog involves using tasks like fgetc, ungetc, fgets, fscanf, sscanf, and fread. Each task serves specific use cases, from reading single characters and lines to formatted and binary data.
]]></description><link>https://circuitcove.com/system-tasks-file-read/</link><guid isPermaLink="false">6655783265d41c04b80d9e2b</guid><category><![CDATA[System Tasks and Functions]]></category><dc:creator><![CDATA[Shou-Li Hsu]]></dc:creator><pubDate>Tue, 28 May 2024 07:14:27 GMT</pubDate><content:encoded><![CDATA[<p>In our previous tutorials, we&apos;ve already covered the basics of <a href="https://circuitcove.com/system-tasks-file-io/">file operations</a> and <a href="https://circuitcove.com/system-tasks-file-output/">how to write to files</a> in SystemVerilog. Today, let&apos;s dive into reading data from a file, a crucial task for processing or analyzing external data within your Verilog code.</p><p>To get started, you need to know that SystemVerilog provides a variety of tasks for reading data, including <code>$fgetc</code>, <code>$ungetc</code>, <code>$fgets</code>, <code>$fscanf</code>, <code>$sscanf</code>, and <code>$fread</code>. Each of these has its own use case and characteristics. Let&apos;s go through them one by one.</p><h2 id="opening-a-file">Opening a File</h2><p>First things first, you need to open a file for reading, which is done using the <code>$fopen</code> system task with the <code>r</code> or <code>r+</code> flags.</p><h2 id="reading-a-single-character-with-fgetc">Reading a Single Character with $fgetc</h2><p>The <code>$fgetc</code> task reads a single character from the file, which is 8 bits wide. If there is an error during reading, <code>$fgetc</code> returns <code>EOF</code> (which is -1). For example, a lexer would be a client of this function because the basic element for lexing tokens is a character.</p><h3 id="example">Example</h3><pre><code class="language-verilog">integer file, c;
file = $fopen(&quot;example.txt&quot;, &quot;r&quot;);
if (file) begin
  c = $fgetc(file);
  // Process the character &apos;c&apos;
  $fclose(file);
end
</code></pre><p><em>Note: It&apos;s good practice to ensure the variable used for reading is more than 8 bits to differentiate between -1 and actual data 0xFF.</em></p><h2 id="putting-a-character-back-with-ungetc">Putting a Character Back with $ungetc</h2><p>The <code>$ungetc</code> task puts the character specified by <code>c</code> back into the buffer associated with the file descriptor <code>fd</code>. This means the next time you call <code>$fgetc</code>, you&apos;ll get the character <code>c</code> again. This only changes the buffer, not the file.</p><h3 id="example-1">Example</h3><pre><code class="language-verilog">integer file, c;
file = $fopen(&quot;example.txt&quot;, &quot;r&quot;);
if (file) begin
  c = $fgetc(file);
  $ungetc(c, file);
  c = $fgetc(file); // &apos;c&apos; will be the same character as before
  $fclose(file);
end
</code></pre><h2 id="reading-a-line-with-fgets">Reading a Line with $fgets</h2><p>The <code>$fgets</code> task reads a line from the file until a newline character, the end of the string buffer, or EOF is reached. The return value indicates the number of characters read or 0 if an error occurs. This method is commonly used to process files line by line.</p><h3 id="example-2">Example</h3><pre><code class="language-verilog">integer file;
string line;
file = $fopen(&quot;example.txt&quot;, &quot;r&quot;);
if (file) begin
  line = $fgets(file);
  // Process the line
  $fclose(file);
end
</code></pre><h2 id="reading-formatted-data-with-fscanf-and-sscanf">Reading Formatted Data with $fscanf and $sscanf</h2><p>These tasks read formatted data from a file or string, respectively, and are similar to the C <code>fscanf</code> function. You specify a format string, and the scanned values are stored in the provided arguments. This method is one approach to handling formatted data. It reads back the formatted string and processes it accordingly. This is particularly useful for structured text files, such as CSVs, where data is organized in a consistent manner.</p><h3 id="example-with-csv-file">Example with CSV File</h3><p>Suppose you have a CSV file <code>data.csv</code> with the following content:</p><pre><code class="language-csv">1,John,25
2,Jane,30</code></pre><p>We want to read each line of this CSV file and extract the values into appropriate variables.</p><pre><code class="language-verilog">integer file, id, age, code;
string name;
file = $fopen(&quot;data.csv&quot;, &quot;r&quot;);
if (file) begin
  while (!$feof(file)) begin
    code = $fscanf(file, &quot;%d,%s,%d\n&quot;, id, name, age);
    if (code == 3) begin
      $display(&quot;ID: %d, Name: %s, Age: %d&quot;, id, name, age);
    end else if (code == -1) begin
      // Error occurred
      break;
    end
  end
  $fclose(file);
end
</code></pre><p>In this example, we open the <code>data.csv</code> file for reading. We then use a <code>while</code> loop to read each line of the CSV file until the end of the file is reached. The <code>$fscanf</code> task parses each line according to the format specified: <code>%d, %s, %d\n</code>. This format specifies that each line contains an integer, a string (name), and another integer, separated by commas. The variable <code>code</code> stores the number of successfully matched and assigned input items. If <code>code</code> equals 3, we have successfully read the <code>ID</code>, <code>name</code>, and <code>age</code> from the line, and we display them using <code>$display</code>. If <code>code</code> equals -1, an error occurred while scanning the data, and we break out of the loop.</p><h2 id="reading-binary-data-with-fread">Reading Binary Data with $fread</h2><p>The <code>$fread</code> task reads binary data from a file into memory, byte by byte, in big-endian format. This function is particularly useful when you need to handle raw binary data directly, offering better performance compared to reading data as text. It is often used in situations where efficiency and speed are critical, such as processing large data files or handling complex data structures.</p><h3 id="usage">Usage</h3><p>You can use <code>$fread</code> to read data into memory, specifying optional <code>start</code> and <code>count</code> parameters:</p><ul><li><code>start</code>: The start index of the memory.</li><li><code>count</code>: The maximum indices of memory to read.</li></ul><h3 id="example-3">Example</h3><p>Consider a binary file <code>data.bin</code> where each byte is 0xFF. The following example demonstrates reading from this file into a 32-bit memory array:</p><pre><code class="language-verilog">`timescale 1ns/1ns

module MonitorTB;
  int fd, code;
  logic [31:0] mem [0:255]; // Define memory array to store the data
  int start = 2; // Start index
  int count = 4; // Maximum memory index to read

  initial begin
    fd = $fopen(&quot;data.bin&quot;, &quot;r&quot;);
    if (fd == 0) begin
      $display(&quot;Error: Could not open file.&quot;);
      $finish;
    end

    // Read data from the file into memory array
    code = $fread(mem, fd, start, count);
    if (code == 0) begin
      $display(&quot;Error: Could not read data.&quot;);
    end else begin
      $display(&quot;Read %0d bytes of data.&quot;, code);
    end
    
    // Display the contents of the first few memory locations
    for (int i = 0; i &lt; 8; i++) begin
      $display(&quot;mem[%0d] = %h&quot;, i, mem[i]);
    end
    
    $fclose(fd);
  end
endmodule
</code></pre><p>The file <code>data.bin</code> is opened for reading. <code>$fread(mem, file, start, count)</code> reads data starting from memory index 2 and fills up to 4 memory locations. Since each memory location is 32 bits, a total of 16 bytes are read. The data is read in big-endian format, so each 32-bit memory location gets 0xFFFFFFFF (all bits set to 1).</p><p>Given that the file contains all 0xFF bytes and the memory starts as <code>X</code>, the expected output after reading is:</p><pre><code>Read 16 bytes of data.
mem[0] = xxxxxxxx
mem[1] = xxxxxxxx
mem[2] = ffffffff
mem[3] = ffffffff
mem[4] = ffffffff
mem[5] = ffffffff
mem[6] = xxxxxxxx
mem[7] = xxxxxxxx
</code></pre><p>This output shows that data loading starts at memory index 2 and continues for 4 memory locations, each receiving 0xFFFFFFFF, while the other locations remain unchanged.</p><hr><p>Reading data from a file in SystemVerilog can be straightforward once you understand the various tasks available. Each task has its specific use case: <code>$fgetc</code> for single characters, <code>$ungetc</code> for putting characters back into the buffer, <code>$fgets</code> for reading lines, <code>$fscanf</code> and <code>$sscanf</code> for formatted data, and <code>$fread</code> for binary data. Understanding these tools and how to use them effectively can significantly enhance your ability to handle external data within your SystemVerilog projects.</p>]]></content:encoded></item><item><title><![CDATA[Formatting Data to a String in Verilog and SystemVerilog]]></title><description><![CDATA[In this article, we explore SystemVerilog functionalities for formatting data into strings using $swrite, $sformat, and $sformatf. These tasks are essential for logging, debugging, or displaying readable results.
]]></description><link>https://circuitcove.com/system-tasks-format-string/</link><guid isPermaLink="false">6655680565d41c04b80d9df3</guid><category><![CDATA[System Tasks and Functions]]></category><dc:creator><![CDATA[Shou-Li Hsu]]></dc:creator><pubDate>Tue, 28 May 2024 05:20:56 GMT</pubDate><content:encoded><![CDATA[<p>In this article, we&#x2019;re going to dive into some neat Verilog and SystemVerilog functionalities that allow us to format data into strings. We&#x2019;ll be exploring <code>$swrite</code>, <code>$sformat</code>, and <code>$sformatf</code>. If you&apos;re like me, you&apos;ve probably found yourself needing to convert data into strings for logging, debugging, or even just displaying results in a readable format. Well, these three tasks are perfect for that.</p><h2 id="swrite-system-task">$swrite System Task</h2><p>Let&apos;s start with <code>$swrite</code>. It&apos;s quite similar to <code>$fwrite</code>, but instead of writing to a file, it writes to a string variable. This can be incredibly useful when you want to manipulate the string further within your code.</p><h3 id="example">Example</h3><p>Here&apos;s a simple example to illustrate <code>$swrite</code>:</p><pre><code class="language-verilog">module ExampleSwrite;
  string my_str;
  int a = 5;
  real b = 3.14;

  initial begin
    $swrite(my_str, &quot;Integer: %0d, Real: %0.2f&quot;, a, b);
    $display(&quot;Formatted String: %s&quot;, my_str);
  end
endmodule
</code></pre><p>In this example, <code>my_str</code> is our target string variable. We format the string to include the integer <code>a</code> and the real number <code>b</code>, then display it. Easy, right?</p><h2 id="sformat-system-task">$sformat System Task</h2><p>Next up is <code>$sformat</code>. It&apos;s a bit more flexible because it allows the format string to be a variable or an expression. This means you can build your format string dynamically if needed.</p><h3 id="example-1">Example</h3><p>Let&apos;s see <code>$sformat</code> in action:</p><pre><code class="language-verilog">module ExampleSformat;
  string my_str;
  int a = 10;
  string format_str = &quot;The value of a is: %0d&quot;;

  initial begin
    $sformat(my_str, format_str, a);
    $display(&quot;Formatted String: %s&quot;, my_str);
  end
endmodule
</code></pre><p>In this case, we define <code>format_str</code> separately and use it in <code>$sformat</code>. The output will still be the same, but this method gives us more flexibility.</p><h2 id="sformatf-system-function">$sformatf System Function</h2><p>Finally, there&apos;s <code>$sformatf</code>, which is almost identical to <code>$sformat</code> but operates as a function. Instead of assigning the formatted string to a variable, it returns the string directly.</p><h3 id="example-2">Example</h3><p>Here&apos;s an example of <code>$sformatf</code>:</p><pre><code class="language-verilog">module ExampleSformatf;
  string result;
  int a = 42;
  real b = 2.718;

  initial begin
    result = $sformatf(&quot;Answer: %0d, Euler&apos;s number: %0.3f&quot;, a, b);
    $display(&quot;Formatted String: %s&quot;, result);
  end
endmodule
</code></pre><p>With <code>$sformatf</code>, the formatted string is returned directly and can be assigned to <code>result</code>.</p><hr><p>I hope this gives you a clear understanding of how to use these formatting functions in SystemVerilog. They each have their own niche uses and can make handling strings much more straightforward and flexible.</p>]]></content:encoded></item><item><title><![CDATA[File Output System Tasks in Verilog and SystemVerilog]]></title><description><![CDATA[The file output system tasks in SystemVerilog: $fdisplay, $fwrite, $fmonitor, and $fstrobe, are crucial for logging and debugging simulation data. This article explores their usage, focusing on how to direct outputs to files using file descriptors and multichannel descriptors.]]></description><link>https://circuitcove.com/system-tasks-file-output/</link><guid isPermaLink="false">66555de165d41c04b80d9db5</guid><category><![CDATA[System Tasks and Functions]]></category><dc:creator><![CDATA[Shou-Li Hsu]]></dc:creator><pubDate>Tue, 28 May 2024 05:03:27 GMT</pubDate><content:encoded><![CDATA[<p>In this article, we&apos;ll dive into the file output system tasks in Verilog and SystemVerilog: <code>$fdisplay</code>, <code>$fwrite</code>, <code>$fmonitor</code>, and <code>$fstrobe</code>. These tasks are incredibly useful when you want to log or output data to files during simulation. If you&apos;re familiar with the basic display and write tasks, this will be an extension of those concepts.</p><h2 id="introduction">Introduction</h2><p>We&apos;ve previously introduced the display and write tasks in SystemVerilog, including <code>$display</code>, <code>$write</code>, and <code>$strobe</code>. These tasks are essential for printing information to the console. If you haven&apos;t checked those out yet, you can find the articles here:</p><ul><li><a href="https://circuitcove.com/system-tasks-display/" rel="noreferrer">Display and Write Tasks</a></li><li><a href="https://circuitcove.com/system-tasks-strobe/" rel="noreferrer">Strobe Task</a></li><li><a href="https://circuitcove.com/system-tasks-monitor/" rel="noreferrer">Monitor Task</a></li><li><a href="https://circuitcove.com/system-tasks-file-io/" rel="noreferrer">File Operation Tasks</a></li></ul><p>Now, we&apos;ll look at how <code>$fdisplay</code>, <code>$fwrite</code>, <code>$fmonitor</code>, and <code>$fstrobe</code> can be used to direct this output to files in Verilog and SystemVerilog.</p><h2 id="understanding-file-output-system-tasks-in-verilog">Understanding File Output System Tasks in Verilog</h2><p>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 (<code>fd</code>) or multichannel descriptors (<code>mcd</code>). You can learn more about <code>fd</code> and <code>mcd</code> in the <a href="https://circuitcove.com/system-tasks-file-io/" rel="noreferrer">File Operation Tasks article</a>.</p><h2 id="example-producer-and-consumer-logging-with-file-output-tasks">Example: Producer and Consumer Logging with File Output Tasks</h2><p>Let&apos;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.</p><pre><code class="language-verilog">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(&quot;producer.log&quot;);
    mcd_consumer = $fopen(&quot;consumer.log&quot;);

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

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

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

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

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

endmodule
</code></pre><h3 id="explanation">Explanation</h3><ol><li><strong>Multichannel Descriptors</strong>: We open separate files for the producer and consumer using <code>$fopen</code>. These multichannel descriptors are stored in <code>mcd_producer</code> and <code>mcd_consumer</code>. We then create the broadcasting descriptor (<code>mcd_broadcast</code>) by ORing these file descriptors with <code>32&apos;b1</code> to include STDOUT.</li><li><strong>Producer Activity</strong>: The producer generates some data (<code>data = 8&apos;hA5</code>) and logs this activity to <code>producer.log</code> using <code>$fdisplay</code>.</li><li><strong>Consumer Activity</strong>: The consumer processes the data (e.g., adding <code>8&apos;h5A</code> to <code>data</code>) and logs the result to <code>consumer.log</code> using <code>$fdisplay</code>.</li><li><strong>Final Message Logging</strong>: 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.</li><li><strong>Closing Files</strong>: Finally, we close both files using <code>$fclose</code>.</li></ol><hr><p>By using <code>$fdisplay</code>, <code>$fwrite</code>, <code>$fmonitor</code>, and <code>$fstrobe</code> 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.</p>]]></content:encoded></item><item><title><![CDATA[Verilog and SystemVerilog File Operations: $fopen and $fclose]]></title><description><![CDATA[Explore file operations in SystemVerilog, focusing on `$fopen` and `$fclose`. Learn about syntax, usage, file modes, and the importance of closing files to manage resources effectively in your simulations.]]></description><link>https://circuitcove.com/system-tasks-file-io/</link><guid isPermaLink="false">6654403065d41c04b80d9d5b</guid><category><![CDATA[System Tasks and Functions]]></category><dc:creator><![CDATA[Shou-Li Hsu]]></dc:creator><pubDate>Mon, 27 May 2024 08:29:55 GMT</pubDate><content:encoded><![CDATA[<p>In this article, we&apos;ll delve into the details of file operations in SystemVerilog, focusing on <code>$fopen</code> and <code>$fclose</code>. We&apos;ll cover the syntax, usage, and practical insights, making it easy to understand and apply in your projects.</p><h2 id="introduction-to-file-operations">Introduction to File Operations</h2><p>SystemVerilog provides built-in system functions for file operations, allowing you to open, read, write, and close files. The primary functions we&apos;ll discuss are <code>$fopen</code> for opening files and <code>$fclose</code> for closing them. These functions are crucial for managing file I/O operations in your testbenches and simulation environments.</p><h2 id="the-fopen-function">The $fopen Function</h2><p>The <code>$fopen</code> function is used to open a file. It takes a file name as an argument and returns a file descriptor (<code>fd</code>) or a multichannel descriptor (<code>mcd</code>). The type of descriptor returned depends on the arguments provided.</p><h3 id="syntax">Syntax</h3><pre><code class="language-verilog">int fd;
fd = $fopen(&quot;filename&quot;, &quot;mode&quot;);
</code></pre><ul><li><code>filename</code>: The name of the file you want to open.</li><li><code>mode</code>: The mode in which you want to open the file (optional).</li></ul><h3 id="file-modes">File Modes</h3><p>When working with files, you can use different modes with <code>$fopen</code> to specify how you want to interact with the file. Here&#x2019;s a summary of the modes:</p><!--kg-card-begin: html--><table><thead><tr><th>Argument</th><th>Description</th></tr></thead><tbody><tr><td><code>r</code>, <code>rb</code></td><td>Open the file for reading.</td></tr><tr><td><code>w</code>, <code>wb</code></td><td>Open the file for writing, creating a new file or truncating an existing one.</td></tr><tr><td><code>a</code>, <code>ab</code></td><td>Open the file for writing at the end (append mode), creating a new file if it doesn&apos;t exist.</td></tr><tr><td><code>r+</code>, <code>rb+</code></td><td>Open the file for both reading and writing.</td></tr><tr><td><code>w+</code>, <code>wb+</code></td><td>Open the file for reading and writing, creating a new file or truncating an existing one.</td></tr><tr><td><code>a+</code>, <code>ab+</code></td><td>Open the file for reading and writing in append mode, creating a new file if it doesn&apos;t exist.</td></tr></tbody></table><!--kg-card-end: html--><p>If you only provide the filename without specifying a mode, <code>$fopen</code> returns a multichannel descriptor (<code>mcd</code>). When a mode is specified, it returns a file descriptor (<code>fd</code>). Both descriptors are 32-bit packed arrays, with each bit indicating an open file.</p><h3 id="example">Example</h3><p>Here&apos;s an example of opening a file for writing:</p><pre><code class="language-verilog">int fd;
fd = $fopen(&quot;output.txt&quot;, &quot;w&quot;);
if (fd == 0) begin
    $display(&quot;Error: Unable to open file.&quot;);
end
</code></pre><p>The binary mode (indicated by the <code>b</code> in modes like <code>&quot;rb&quot;</code> or <code>&quot;wb+&quot;</code>) is used when you need to work with binary files rather than text files. Binary mode ensures that the file is read or written byte-by-byte, which is crucial for files that contain non-text data.</p><h3 id="pre-opened-files">Pre-opened Files</h3><p>Certain files like <code>STDIN</code>, <code>STDOUT</code>, and <code>STDERR</code> are pre-opened by the system. These are useful for standard input, output, and error handling.</p><h2 id="the-fclose-function">The $fclose Function</h2><p>Once you&apos;re done with file operations, it&apos;s important to close the file using <code>$fclose</code>. This function takes a file descriptor (<code>fd</code>) or a multichannel descriptor (<code>mcd</code>) as an argument and closes the associated file(s).</p><h3 id="syntax-1">Syntax</h3><pre><code class="language-verilog">$fclose(fd);
</code></pre><p>Closing a file also implicitly cancels any active <code>$fmonitor</code> and <code>$fstrobe</code> operations on that file descriptor.</p><p>It&apos;s important to note that if you don&apos;t close files, you might encounter resource leaks. This can lead to performance issues or even cause your simulation to crash. This behavior is similar to languages like C++ and operating systems like Linux, where failing to close files can exhaust the available file handles, resulting in errors when attempting to open new files.</p><hr><p>Understanding file operations in SystemVerilog, particularly <code>$fopen</code> and <code>$fclose</code>, is essential for effective file handling in your simulations. By grasping the different file modes and descriptors, you can manage files more efficiently and avoid common pitfalls. Remember to always close your files to free up resources and maintain clean code.</p>]]></content:encoded></item><item><title><![CDATA[Understanding $monitor System Task in Verilog and SystemVerilog]]></title><description><![CDATA[The $monitor system task in SystemVerilog continuously tracks specified variables, printing messages when changes occur. It operates at the end of the simulation time step and only one $monitor can be active at a time. You can control it using $monitoron and $monitoroff tasks.]]></description><link>https://circuitcove.com/system-tasks-monitor/</link><guid isPermaLink="false">6653bf0365d41c04b80d9d00</guid><category><![CDATA[System Tasks and Functions]]></category><dc:creator><![CDATA[Shou-Li Hsu]]></dc:creator><pubDate>Sun, 26 May 2024 23:25:38 GMT</pubDate><content:encoded><![CDATA[<p>Hey there! Welcome back to another installment of our SystemVerilog tutorial. Today, we&apos;re diving into a very useful feature in SystemVerilog &#x2014; the <code>$monitor</code> system task. If you&apos;ve ever wondered how you can continuously keep an eye on your variables during simulation, then this is the tutorial for you. Let&apos;s jump right in!</p><h2 id="what-is-the-monitor-system-task">What is the $monitor System Task?</h2><p>The <code>$monitor</code> system task is akin to having an ever-vigilant watchdog over your variables. It keeps tabs on changes in the specified variables and prints out messages whenever those changes occur. It operates at the end of the simulation time step, similar to <code>$strobe</code>. If you&apos;re curious about <code>$strobe</code>, we&apos;ve got a detailed explanation over <a href="https://circuitcove.com/system-tasks-strobe/" rel="noreferrer">here</a>.</p><h3 id="key-points-to-remember">Key Points to Remember</h3><ul><li><strong>Continuous Monitoring:</strong> <code>$monitor</code> keeps track of changes in specified variables and prints a message whenever there&apos;s a change.</li><li><strong>End of Simulation Time:</strong> It runs in the postponed events region, the last region in the simulation time, so it prints out the final value after all the blocking/non-blocking updates.</li><li><strong>Single Active Monitor:</strong> Only one <code>$monitor</code> can be active at a time. If you invoke a new <code>$monitor</code> during the simulation, it will replace the previous one.</li><li><strong>Control Tasks:</strong> You can control the monitoring using <code>$monitoron</code> and <code>$monitoroff</code> tasks. By default, monitoring is turned on at the start of the simulation.</li><li><strong>Monitor List Exception:</strong> Changes in <code>$time</code>, <code>$stime</code>, or <code>$realtime</code> will not trigger a monitor event.</li></ul><h2 id="simple-testbench-example">Simple Testbench Example</h2><p>Let&apos;s take a closer look at how the <code>$monitor</code> system task works with a straightforward testbench.</p><pre><code class="language-verilog">`timescale 1ns/1ns

module MonitorTB;
  logic       clk;
  logic [3:0] count;

  // Initialize the variables
  initial begin
    clk = 0;
    count = 0;
  end

  // Generate clock signal
  always #5 clk = ~clk;

  // Increment count on the positive edge of the clock
  always @(posedge clk) begin
    count &lt;= count + 1;
  end

  // Monitor changes in count and clk
  initial begin
    $monitor(&quot;At time %0t, count = %0d&quot;, $time, count);
    #30 $monitoroff; // Disable monitoring after 30 time units
    #40 $monitoron;  // Re-enable monitoring after 70 time units
  end

  // Stop the simulation after a certain time
  initial begin
    #100 $finish;
  end
endmodule
</code></pre><h3 id="explanation">Explanation</h3><ol><li><strong>Initialization</strong>: The <code>$monitor</code> task prints the value of <code>count</code> and the current simulation time whenever <code>count</code> changes.</li><li><strong>Monitor Control</strong>: <code>$monitoroff</code> is called after 30 time units to stop monitoring.</li><li><strong>Resuming Monitoring</strong>: <code>$monitoron</code> is called after 70 time units to resume monitoring.</li></ol><h3 id="result">Result</h3><p>Here&#x2019;s what the output looks like during the simulation:</p><pre><code>At time 0, count = 0
At time 5000, count = 1
At time 15000, count = 2
At time 25000, count = 3
At time 70000, count = 7
At time 75000, count = 8
At time 85000, count = 9
At time 95000, count = 10</code></pre><p>The <code>$monitor</code> task tracks changes in <code>count</code>, printing its value each time it updates. Monitoring is turned off at 30 time units and back on at 70 time units.</p><hr><p>And there you have it! The <code>$monitor</code> system task is an essential tool in your SystemVerilog toolkit for continuous monitoring of variable changes. Whether you&apos;re debugging or just keeping an eye on things, <code>$monitor</code> makes it easy to get the information you need, right when you need it.</p>]]></content:encoded></item><item><title><![CDATA[Understanding $strobe in SystemVerilog and Verilog: A Practical Guide]]></title><description><![CDATA[In this article, we explore $strobe in SystemVerilog, a task that executes at the end of the simulation time step, showing final variable values. Using an accumulator example, we demonstrate how $strobe provides clearer insights than $display for debugging and verification.]]></description><link>https://circuitcove.com/system-tasks-strobe/</link><guid isPermaLink="false">6653b7c465d41c04b80d9cc9</guid><category><![CDATA[System Tasks and Functions]]></category><dc:creator><![CDATA[Shou-Li Hsu]]></dc:creator><pubDate>Sun, 26 May 2024 22:47:23 GMT</pubDate><content:encoded><![CDATA[<p>Hey there! Today, I want to delve into a topic in SystemVerilog that often goes unnoticed but is incredibly useful: the <code>$strobe</code> system task. If you&apos;ve ever wondered how it differs from <code>$display</code> or <code>$write</code>, you&apos;re not alone. Let&apos;s break it down and understand its unique advantages.</p><h2 id="what-is-strobe">What is $strobe?</h2><p>In SystemVerilog, <code>$strobe</code> is a system task that resembles <code>$display</code> and <code>$write</code>. You might have used those for debugging or to check the state of your simulation at specific moments. The crucial difference lies in the timing of their execution: while <code>$display</code> and <code>$write</code> execute immediately, <code>$strobe</code> waits until the end of the current simulation time step to execute.</p><h2 id="when-to-use-strobe">When to Use $strobe?</h2><p>So, when is it appropriate to use <code>$strobe</code>? Consider a sequential module, such as an accumulator, that updates its value on a clock edge. Here&#x2019;s a simple example:</p><pre><code class="language-verilog">module Accumulator(
  input  logic       clk,
  input  logic       rst,
  input  logic [7:0] in,
  output logic [7:0] out
);
  always @(posedge clk) begin
    if (rst)
      out &lt;= 0;
    else
      out &lt;= out + in;
  end
endmodule
</code></pre><p>Now, let&apos;s add some debug statements using <code>$display</code> and <code>$strobe</code> to observe their behavior:</p><pre><code class="language-verilog">always @(posedge clk or posedge rst) begin
  if (rst)
    out &lt;= 0;
  else
    out &lt;= out + in;
    
  $display(&quot;Time: %0t | $display: out = %0d&quot;, $time, out);
  $strobe(&quot;Time: %0t | $strobe: out = %0d&quot;, $time, out);
end
</code></pre><h3 id="what%E2%80%99s-going-on">What&#x2019;s Going On?</h3><p>When you run this simulation, <code>$display</code> prints the value of <code>out</code> before the clock edge updates it. This is because, in SystemVerilog&#x2019;s event scheduling, the <code>always</code> block runs in the Active region first, so <code>$display</code> executes immediately. The non-blocking assignment (<code>out &lt;= out + in;</code>) then happens in the Nonblocking Assign Update region, updating <code>out</code>. Finally, <code>$strobe</code> runs in the Postponed region, after all other events in the current time step, displaying the updated value of <code>out</code>.</p><p>SystemVerilog&#x2019;s event scheduling can be intricate, but the key takeaway is this: <code>$display</code> shows the value at the point of its execution, while <code>$strobe</code> shows the value after all updates in the current time step.</p><h2 id="practical-insights">Practical Insights</h2><p>Using <code>$strobe</code> can be especially beneficial when you need to verify the final value of variables after all operations for the current time step are complete. It&apos;s akin to having a final check at the end of the simulation slice, giving you the most accurate state of your variables.</p><hr><p><code>$strobe</code> is a powerful addition to your SystemVerilog toolkit, particularly useful for debugging and understanding the final values of your variables after all events in a time step. The next time you encounter unexpected values in your simulation, try using <code>$strobe</code> to gain clearer insights.</p>]]></content:encoded></item><item><title><![CDATA[Mastering Format Specifications in Verilog and SystemVerilog: A Comprehensive Guide]]></title><description><![CDATA[Understand and use SystemVerilog's format specifiers for clearer, context-specific data displays. Learn how specifiers like %b, %d, %h, and others can significantly improve your coding and debugging process.]]></description><link>https://circuitcove.com/system-tasks-format-spec/</link><guid isPermaLink="false">647978e165d41c04b80d9c28</guid><category><![CDATA[System Tasks and Functions]]></category><dc:creator><![CDATA[Shou-Li Hsu]]></dc:creator><pubDate>Sat, 03 Jun 2023 08:11:24 GMT</pubDate><content:encoded><![CDATA[<p>A key aspect of Verilog and SystemVerilog that significantly aids in debugging and understanding code is the use of format specifications. These specifications determine how data appears when using I/O system tasks, thus enhancing readability and comprehension.</p><p>In this detailed guide, we will explore the most common format specifications to help you effectively decode and output data in Verilog and SystemVerilog. Let&#x2019;s dive in and uncover these essential tools!</p><!--kg-card-begin: html--><div class="table-container"><table><thead><tr><th>Format</th><th>Description</th></tr></thead><tbody><tr><td><code>%d, %o, %h, %x, %b</code></td><td>Display in decimal, octal, hexadecimal (either <code>%h</code> or <code>%x</code>), binary format</td></tr><tr><td><code>%c, %s</code></td><td>Display ASCII characters and strings</td></tr><tr><td><code>%e, %f, %g</code></td><td>Display real numbers in various formats</td></tr><tr><td><code>%l, %m</code></td><td>Display library binding information, hierarchical names</td></tr><tr><td><code>%v</code></td><td>Display net signal strength</td></tr><tr><td><code>%p</code></td><td>Display as an assignment pattern</td></tr><tr><td><code>%t</code></td><td>Display in current time format</td></tr><tr><td><code>%u, %z</code></td><td>Unformatted 2 and 4 value data</td></tr></tbody></table></div><!--kg-card-end: html--><h2 id="decoding-numerical-formats-d-o-h-x-b">Decoding Numerical Formats: %d, %o, %h, %x, %b</h2><p>In the realm of Verilog and SystemVerilog programming, the <code>$display</code> function is frequently employed to showcase data in a chosen format. Specific format specifiers, such as <code>%d</code> for decimal, <code>%o</code> for octal, <code>%h</code> or <code>%x</code> for hexadecimal, and <code>%b</code> for binary, allow precise control over data presentation.</p><p>Consider this example where a 12-bit register value is displayed in various formats:</p><figure class="kg-card kg-code-card"><pre><code class="language-verilog">logic [11:0] twelveBitReg = 12&apos;d1023;  // decimal format
$display(&quot;Decimal Format: %4d&quot;, twelveBitReg);
$display(&quot;Octal Format: %o&quot;, twelveBitReg);
$display(&quot;Hexadecimal Format: %3h&quot;, twelveBitReg);  // three characters for hexadecimal
$display(&quot;Same Hexadecimal Format: %3x&quot;, twelveBitReg);  // %x acts the same as %h
$display(&quot;Binary Format: %b&quot;, twelveBitReg);
</code></pre><figcaption>loi</figcaption></figure><p>The output will display the <code>twelveBitReg</code> value in each of the specified formats. Notice the use of <code>%4d</code> and <code>%3h</code> or <code>%3x</code> to control the output width &#x2014; this feature is particularly useful for managing data of different sizes, thus enhancing the clarity and readability of your output.</p><h2 id="interpreting-ascii-and-string-formats-c-s">Interpreting ASCII and String Formats: %c, %s</h2><p>Verilog and SystemVerilog also provide the capability to interpret ASCII codes as characters and display strings, which is invaluable for printing messages or data in a human-readable format.</p><p>The <code>%c</code> format specifier is used to display the ASCII character equivalent of a byte, while <code>%s</code> is employed to display strings. For instance:</p><pre><code class="language-verilog">byte asciiByte = 8&apos;h41; // ASCII code for &apos;A&apos;
$display(&quot;ASCII character: %c&quot;, asciiByte);

string strVal = &quot;Hello, SystemVerilog!&quot;;
$display(&quot;String: %s&quot;, strVal);
</code></pre><p>This will output the ASCII character corresponding to <code>asciiByte</code> and the string &quot;Hello, SystemVerilog!&quot;.</p><h2 id="displaying-real-numbers-e-f-g">Displaying Real Numbers: %e, %f, %g</h2><p>SystemVerilog allows you to display real numbers in exponential, decimal, or a shorter combined format, which is invaluable for managing large floating-point or precise decimal numbers.</p><ul><li><code>%e</code> shows the number in exponential notation.</li><li><code>%f</code> displays the number in decimal format.</li><li><code>%g</code> selects the shorter of the two formats, either exponential or decimal, based on the value.</li></ul><pre><code class="language-verilog">real num = 12345.6789;
$display(&quot;Exponential: %e, Decimal: %f, Short: %g&quot;, num, num, num);</code></pre><p>This will output <code>num</code> in exponential, decimal, and the shorter format.</p><h2 id="deciphering-assignment-patterns-p">Deciphering Assignment Patterns: %p</h2><p>SystemVerilog&apos;s <code>%p</code> format specifier is a powerful tool for displaying complex data structures. It enables a clear representation of unpacked structures, enums, strings, and unique types.</p><p>For example, consider an unpacked structure:</p><pre><code class="language-verilog">typedef struct {
    int a;
    string b;
} abStruct;

abStruct example = &apos;{a: 10, b: &quot;Hello&quot;};
$display(&quot;Structure: %p&quot;, example);
</code></pre><p>The <code>%p</code> specifier will present <code>example</code> as <code>&apos;{a: 10, b: &quot;Hello&quot;}</code>. Highlights of its usage include:</p><ul><li>Structures are shown with named elements.</li><li>Enums are displayed as their names if valid.</li><li>Strings appear in quotes.</li><li>Unique types like class handles are shown distinctly, with null values as <code>&apos;null&apos;</code>.</li><li>Other types are printed unformatted.</li></ul><p>For a condensed view, <code>%0p</code> provides a compact, implementation-dependent format.</p><h2 id="tracking-simulation-time-t">Tracking Simulation Time: %t</h2><p>The <code>%t</code> format specifier is used to display the current simulation time, which is crucial for tracking event timing during simulations.</p><pre><code class="language-verilog">module TimeModule;
  initial begin
    #5; // wait for 5 time units
    $display(&quot;Current Time: %t&quot;, $time);
  end
endmodule
</code></pre><p>This will display the current simulation time (5 time units) when it is called.</p><hr><p>Whether you&apos;re an experienced developer or a newcomer to Verilog and SystemVerilog, mastering format specifications can greatly enhance your coding and debugging process. These specifications enable clear, concise, and context-specific data displays, improving the readability of your output and making your code easier to debug.</p>]]></content:encoded></item><item><title><![CDATA[Mastering $display and $write in Verilog and SystemVerilog]]></title><description><![CDATA[Dive into the world of Verilog and SystemVerilog. This post simplifies $display and $write tasks, and decodes escape sequences, equipping you with the essential skills for your coding projects.]]></description><link>https://circuitcove.com/system-tasks-display/</link><guid isPermaLink="false">6471cf8d65d41c04b80d9bc5</guid><category><![CDATA[System Tasks and Functions]]></category><dc:creator><![CDATA[Shou-Li Hsu]]></dc:creator><pubDate>Sat, 27 May 2023 10:04:09 GMT</pubDate><content:encoded><![CDATA[<p>In this blog post, we delve into the world of Verilog and SystemVerilog, focusing on the <code>$display</code> and <code>$write</code> tasks, as well as the unique concept of escape sequences. This tutorial will offer insights and practical examples to help you master these tasks and sequences effectively.</p><h2 id="understanding-the-basics-display-and-write-tasks">Understanding the Basics: $display and $write Tasks</h2><p>Both Verilog and SystemVerilog endorse the <code>$display</code> and <code>$write</code> tasks, paving the way for the formulation of personalized messages in your simulation logs.</p><p>Here is an illustration of a rudimentary <code>$display</code> task in SystemVerilog:</p><pre><code class="language-verilog">module DisplayTask;
  initial begin
    $display(&quot;Hello, world!&quot;);
  end
endmodule
</code></pre><p>In this scenario, the <code>$display</code> task will output the string &quot;Hello, world!&quot; onto the console as soon as the simulation initiates.</p><h2 id="differences-between-display-and-write-tasks-spotting-the-discrepancies">Differences Between $display and $write Tasks: Spotting the Discrepancies</h2><p>Though they may seem identical at first glance, <code>$display</code> and <code>$write</code> tasks possess slight variations. The <code>$display</code> task automatically adds a newline character at the end of the output, whereas the <code>$write</code> task refrains from doing so.</p><pre><code class="language-verilog">module WriteTask;
  initial begin
    $write(&quot;Hello, world!&quot;);
  end
endmodule
</code></pre><p>In the above example, the <code>$write</code> task will output &quot;Hello, world!&quot;, however, contrary to the <code>$display</code> task, it will not add a newline character.</p><h2 id="unraveling-arguments-comprehending-display-and-write-tasks">Unraveling Arguments: Comprehending $display and $write Tasks</h2><p>Both tasks are capable of accepting multiple arguments. The subsequent example exemplifies the display of an integer variable.</p><pre><code class="language-verilog">module DisplayVariable;
  reg [7:0] myVariable;
  
  initial begin
    myVariable = 8&apos;hA5;
    $display(&quot;The value of myVariable is: %h&quot;, myVariable);
  end
endmodule
</code></pre><p>This example will output &quot;The value of myVariable is: A5&quot; onto the console.</p><h2 id="understanding-escape-sequences-and-special-characters">Understanding Escape Sequences and Special Characters</h2><p>Escape sequences are pretty handy in Verilog and SystemVerilog. They help us represent specific characters, like literal or non-printable ones, in our strings. Basically, they give us a way to include characters that we normally can&apos;t type out.</p><p>When you see the special character <code>\</code>, know that the character right after it should be viewed as a literal or non-printable character. Escape sequences, when mixed into a string argument, create special characters. Here are some common escape sequences you&apos;ll come across:</p><ul><li><code>\n</code>: This stands for a newline character.</li><li><code>\t</code>: This represents a tab character.</li><li><code>\\</code>: This is for the <code>\</code> character.</li><li><code>\&quot;</code>: This is the <code>&quot;</code> character.</li><li><code>\v</code>: This is a vertical tab.</li><li><code>\f</code>: This stands for a form feed.</li><li><code>\a</code>: This is a bell.</li><li><code>\ddd</code>: This is a character specified in 1 to 3 octal digits, where 0 &#x2264; d &#x2264; 7. If you use less than three characters, the next character shouldn&apos;t be an octal digit.</li><li><code>\xdd</code>: This is a character specified in 2 hexadecimal digits, where 0 &#x2264; d &#x2264; F.</li></ul><p>If an escaped character isn&apos;t part of the list above, it will just be printed as it is. For example, if you have a string argument <code>\b</code>, it will simply print out as <code>b</code>.</p><h2 id="up-next-delving-deeper-into-format-specifications">Up Next: Delving Deeper into Format Specifications</h2><p>In our subsequent piece, we&apos;ll be deep-diving into the realm of format specifications in Verilog and SystemVerilog. <a href="https://circuitcove.com/system-tasks-format-spec/">Explore this advanced guide</a> as we continue to unravel these powerful languages.</p><hr><p>As we conclude this tutorial, you should now have a better grasp of the <code>$display</code> and <code>$write</code> tasks, as well as escape sequences in Verilog and SystemVerilog. Remember that practice is what makes you better. So, keep practicing these tasks and sequences, and before you know it, you&apos;ll be using them with ease in your coding projects.</p>]]></content:encoded></item><item><title><![CDATA[Programmable Logic Array (PLA) Tasks in Verilog and SystemVerilog]]></title><description><![CDATA[Explore the essentials of Programmable Logic Array (PLA) tasks in Verilog and SystemVerilog. From the syntax and array types to real-world implementation with a full adder, get an in-depth guide.]]></description><link>https://circuitcove.com/system-tasks-pla/</link><guid isPermaLink="false">646f03c065d41c04b80d9b53</guid><category><![CDATA[System Tasks and Functions]]></category><dc:creator><![CDATA[Shou-Li Hsu]]></dc:creator><pubDate>Thu, 25 May 2023 07:37:29 GMT</pubDate><content:encoded><![CDATA[<p>Programmable Logic Arrays (PLAs) are essential components of digital system design. Verilog and SystemVerilog provide system tasks for modeling PLAs, offering a versatile approach to manage digital logic tasks. This guide will explore these tasks, their operations, and illustrate practical examples.</p><h2 id="pla-system-tasks-syntax">PLA System Tasks Syntax</h2><p>System tasks in Verilog and SystemVerilog follow a distinct syntax: <code>$arrayType$logic$format</code>. In this construction:</p><ul><li><code>arrayType</code> could be <code>sync</code> (for synchronous) or <code>async</code> (for asynchronous).</li><li><code>logic</code> indicates the type of logic operation (and, or, nand, nor).</li><li><code>format</code> denotes the personality format (array or plane).</li></ul><p>Consider this format in action: <code>$sync$and$array(memoryId, inputTerms, outputTerms)</code>. Here, <code>memoryId</code> refers to the particular memory, <code>inputTerms</code> are the input expressions, and <code>outputTerms</code> are the output variables.</p><h2 id="synchronous-vs-asynchronous-tasks">Synchronous vs. Asynchronous Tasks</h2><p>These two types of tasks differ based on timing. Asynchronous tasks activate as soon as the input terms or memory words change. In contrast, synchronous tasks allow control over when the logic array is evaluated and the output terms are updated.</p><p>Here&apos;s a quick look at each in code:</p><h3 id="asynchronous-example">Asynchronous Example</h3><pre><code class="language-verilog">module AsynchronousMagic(
  input wire[7:1] aWire,
  output logic[3:1] bReg
);
  $async$and$array(memoryId, aWire, bReg);
endmodule
</code></pre><h3 id="synchronous-example">Synchronous Example</h3><pre><code class="language-verilog">module SynchronousMagic(
  input wire clk,
  input wire[7:1] aWire, 
  output logic[3:1] bReg,
);
  always @(posedge clk) begin
    $sync$or$plane(memoryId, aWire, bReg);
  end
endmodule
</code></pre><p>In the synchronous example, operations occur at the positive edge of the clock.</p><h2 id="logic-array-types-in-system-tasks">Logic Array Types in System Tasks</h2><p>The four logic array types usable in SystemVerilog PLA tasks are AND, OR, NAND, and NOR. These types specify the kind of logic operation within the PLA task. For instance, the <code>$sync$and$array</code> task performs a synchronous AND operation, whereas <code>$async$nand$plane</code> executes an asynchronous NAND operation.</p><h3 id="sample-logic-array-types">Sample Logic Array Types</h3><pre><code class="language-verilog">module LogicArrayFun(input wire[7:1] aWire, output logic[3:1] bReg);
  $sync$or$array(memoryId, aWire, bReg);
  $async$nand$plane(memoryId, aWire, bReg);
endmodule
</code></pre><h2 id="declaring-and-loading-logic-array-personalities">Declaring and Loading Logic Array Personalities</h2><p>The personality of the logic array is declared as an array of variables. This personality can be loaded from a text data file using the <code>$readmemb</code> or <code>$readmemh</code> system tasks. Alternatively, the personality data can be directly written into the memory using assignment statements.</p><pre><code class="language-verilog">module LoadPersonality(input wire[7:1] aWire, output logic[3:1] bReg);
  logic [1:7] memoryId[1:3];
  initial begin
    $readmemb(&quot;memoryData.dat&quot;, memoryId);
    $async$and$array(memoryId, aWire, bReg);
  end
endmodule
</code></pre><p>Here, the personality is loaded from a file named &quot;memoryData.dat&quot;.</p><h2 id="array-and-plane-system-calls">Array and Plane System Calls</h2><p>The array and plane system calls are two distinct ways to script the PLA tasks. The array system call uses a straightforward approach with a 1 for taking the input value and a 0 for ignoring it. The plane system call enables the expression of complemented input values, true input values, worst-case input values, and &quot;do not care&quot; conditions.</p><h2 id="implementing-a-full-adder-with-pla-tasks">Implementing a Full Adder with PLA Tasks</h2><p>PLA tasks in SystemVerilog are employed to create a full adder, providing an effective example of these tasks in action.</p><h3 id="logical-expression-for-a-full-adder">Logical Expression for a Full Adder</h3><p>The logical expressions for the sum and carry out of a full adder are as follows:</p><p>Sum: <code>A B&apos; C_in&apos; + A&apos; B C_in&apos; + A&apos; B&apos; C_in</code></p><p>Carry out: <code>A B + A C_in + B C_in</code></p><h3 id="full-adder-example-with-array-tasks">Full Adder Example with Array Tasks</h3><p>Consider a scenario with inputs <code>{A A&apos; B B&apos; C_in C_in&apos;}</code>. Here is an example of implementing a full adder using these inputs:</p><pre><code class="language-verilog">module FullAdder1 (
  input  logic a, b, cIn,
  output logic sum, cOut
);

  bit [5:0] memProduct[7];  // Memory for storing product terms
  bit [6:0] memSum[2];  // Memory for storing sum terms

  logic [6:0] internal;

  initial begin
    memProduct[0] = 6&apos;b100101; // A B&apos; Cin&apos;
    memProduct[1] = 6&apos;b011001; // A&apos; B C_in&apos;
    memProduct[2] = 6&apos;b010110; // A&apos; B&apos; C_in
    memProduct[3] = 6&apos;b101010; // A B C_in
    memProduct[4] = 6&apos;b101000; // A B
    memProduct[5] = 6&apos;b100010; // A C_in
    memProduct[6] = 6&apos;b001010; // B C_in

    memSum[0] = 7&apos;b1111000; // OR plane for sum
    memSum[1] = 7&apos;b0000111; // OR plane for cOut
  end

  $async$and$array(memProduct, {a, ~a, b, ~b, cIn, ~cIn}, internal);
  $async$or$array(memSum, internal, {cOut, sum});

endmodule
</code></pre><h3 id="full-adder-implementation-with-plane-tasks">Full Adder Implementation with Plane Tasks</h3><p>An alternative way of implementing a full adder uses plane tasks, specifically the <code>$async$and$plane</code> and <code>$async$or$plane</code> tasks. The input pattern in this case is simpler: <code>{A B C_in}</code>.</p><pre><code class="language-verilog">module FullAdder2 (
  input  logic a, b, cIn,
  output logic sum, cOut
);

  bit [2:0] memProduct[7];  // Memory for storing product terms
  bit [6:0] memSum[2];  // Memory for storing sum terms

  logic [6:0] internal;

  initial begin
    memProduct[0] = 3&apos;b100; // A B&apos; Cin&apos;
    memProduct[1] = 3&apos;b010; // A&apos; B C_in&apos;
    memProduct[2] = 3&apos;b001; // A&apos; B&apos; C_in
    memProduct[3] = 3&apos;b111; // A B C_in
    memProduct[4] = 3&apos;b11?; // A B
    memProduct[5] = 3&apos;b1?1; // A C_in
    memProduct[6] = 3&apos;b?11; // B C_in

    memSum[0] = 7&apos;b1111???; // OR plane for sum
    memSum[1] = 7&apos;b????111; // OR plane for cOut
  end

  $async$and$plane(memProduct, {a, b, cIn}, internal);
  $async$or$plane(memSum, internal, {cOut, sum});

endmodule
</code></pre><hr><p>In digital system design, Programmable Logic Array (PLA) tasks in Verilog and SystemVerilog are fundamental tools. The asynchronous and synchronous tasks, array and plane formats, and the four logic array types - AND, OR, NAND, and NOR - provide a robust and versatile set of options for modelling complex systems. PLA tasks, while initially complex, become more manageable and intuitive with practice. They form the basis for a wide range of digital logic designs and as such, are worth learning thoroughly. Understanding and mastering these tasks offer significant opportunities for effective and efficient digital system design.</p>]]></content:encoded></item><item><title><![CDATA[Verilog and SystemVerilog Stochastic Analysis Functions]]></title><description><![CDATA[Learn how to manage queues in Verilog and SystemVerilog using stochastic analysis functions. Create, modify, and gather queue information for digital design and verification.]]></description><link>https://circuitcove.com/system-tasks-stochastic/</link><guid isPermaLink="false">644a0f2365d41c04b80d9ab0</guid><category><![CDATA[System Tasks and Functions]]></category><dc:creator><![CDATA[Shou-Li Hsu]]></dc:creator><pubDate>Thu, 27 Apr 2023 08:01:39 GMT</pubDate><content:encoded><![CDATA[<p>Stochastic analysis is a useful tool in digital design and verification for modeling random processes and simulating real-world scenarios. In this beginner-friendly tutorial, we&apos;ll explore the Verilog and SystemVerilog stochastic analysis functions for managing queues. We&apos;ll learn how to create, modify, and gather information about queues using these functions, and discuss the role of status codes in queue management.</p><p>Imagine you&apos;re designing a system that simulates a coffee shop with multiple customers arriving and leaving. You can use the Verilog and SystemVerilog stochastic analysis functions to manage the queue of customers, simulating their service durations.</p><h2 id="creating-new-queues-with-qinitialize">Creating New Queues with $q_initialize</h2><p>To create a new queue, use the <code>$q_initialize</code> function. This function needs four input arguments:</p><ol><li>A unique identifier (<code>q_id</code>) for the new queue.</li><li>The queue type (<code>q_type</code>): either First-In-First-Out (FIFO) or Last-In-First-Out (LIFO).</li><li>The maximum number of entries allowed in the queue (<code>max_length</code>).</li><li>A status code (<code>status</code>) to indicate the success or failure of the queue creation. This is an output.</li></ol><p>Here&apos;s an example of creating a new FIFO queue with a maximum length of 5:</p><pre><code class="language-verilog">module CoffeeShopQueue;
  integer queueId;
  integer queueType = 1; // 1 for FIFO, 2 for LIFO
  integer maxLength = 5;
  integer status;

  initial begin
    $q_initialize(queueId, queueType, maxLength, status);
  end
endmodule
</code></pre><h2 id="adding-entries-to-the-queue-with-qadd">Adding Entries to the Queue with $q_add</h2><p>To add an entry to the queue, use the <code>$q_add</code> function. This function needs four input arguments:</p><ol><li>The queue identifier (<code>q_id</code>).</li><li>The job identifier (<code>job_id</code>), which represents the customer. This value is provided as input.</li><li>An additional user-defined piece of information (<code>inform_id</code>), such as the customer&apos;s item ID. This value is also provided as input.</li><li>A status code (<code>status</code>), which indicates whether adding the entry was successful or not. This is an output.</li></ol><p>Here&apos;s an example of adding a customer to the coffee shop queue:</p><pre><code class="language-verilog">module CoffeeShopQueue;
  // ...
  integer customerNumber = 1;
  integer itemId = 10;

  initial begin
    $q_initialize(queueId, queueType, maxLength, status);
    $q_add(queueId, customerNumber, itemId, status);
  end
endmodule
</code></pre><h2 id="removing-entries-from-the-queue-with-qremove">Removing Entries from the Queue with $q_remove</h2><p>The <code>$q_remove</code> function allows you to remove an entry from the queue. This function takes four arguments:</p><ol><li>The queue identifier (<code>q_id</code>).</li><li>A job identifier (<code>job_id</code>) for the removed customer. This is an output.</li><li>An additional piece of information (<code>inform_id</code>) associated with the removed customer, such as their item ID. This is also an output.</li><li>A status code (<code>status</code>) to indicate the success or failure of removing the entry. This is an output.</li></ol><p>Here&apos;s an example of removing a customer from the coffee shop queue:</p><pre><code class="language-verilog">module CoffeeShopQueue;
  // ...
  integer removedCustomer;
  integer removedItemId;

  initial begin
    $q_initialize(queueId, queueType, maxLength, status);
    $q_add(queueId, customerNumber, itemId, status);
    $q_remove(queueId, removedCustomer, removedItemId, status);
  end
endmodule
</code></pre><h2 id="checking-queue-availability-with-qfull">Checking Queue Availability with $q_full</h2><p>The <code>$q_full</code> function checks if there is space available in the queue for a new entry. It returns 0 if there is space available, and 1 if the queue is full. This function has two arguments:</p><ol><li>The queue identifier (<code>q_id</code>).</li><li>A status code (<code>status</code>) to indicate whether the availability check was successful or not. This is an output.</li></ol><p>Here&apos;s an example of checking the availability of the coffee shop queue:</p><pre><code class="language-verilog">module CoffeeShopQueue;
  // ...
  integer isFull;

  initial begin
    $q_initialize(queueId, queueType, maxLength, status);
    $q_add(queueId, customerNumber, arrivalTime, status);
    isFull = $q_full(queueId, status);
  end
endmodule
</code></pre><h2 id="qexam-gathering-queue-statistics">$q_exam: Gathering Queue Statistics</h2><p>The <code>$q_exam</code> function allows you to obtain statistical information about a specific queue. It takes four arguments:</p><ol><li>The queue identifier (<code>q_id</code>).</li><li>An integer specifying the type of statistical information to retrieve (<code>q_stat_code</code>).</li><li>An output value (<code>q_stat_value</code>) that returns the requested statistical information.</li><li>A status code (<code>status</code>) indicating the success or failure of the queue examination process. This is an output.</li></ol><p>The following table shows the possible values for <code>q_stat_code</code> and their corresponding returned information:</p><!--kg-card-begin: html--><div class="table-container"><table><thead><tr><th>Value requested in q_stat_code</th><th>Information received back from q_stat_value</th></tr></thead><tbody><tr><td>1</td><td>Current queue length</td></tr><tr><td>2</td><td>Mean interarrival time</td></tr><tr><td>3</td><td>Maximum queue length</td></tr><tr><td>4</td><td>Shortest wait time ever</td></tr><tr><td>5</td><td>Longest wait time for jobs still in the queue</td></tr><tr><td>6</td><td>Average wait time in the queue</td></tr></tbody></table></div><!--kg-card-end: html--><p>Below is an example of the <code>CoffeeShopQueue</code> module with <code>$q_exam</code> function calls for all the available <code>q_stat_code</code> values:</p><pre><code class="language-verilog">module CoffeeShopQueue;
  integer queueId;
  integer queueType = 1; // 1 for FIFO, 2 for LIFO
  integer maxLength = 5;
  integer status;

  // Customer information
  integer customerNumber;
  integer itemId;

  // Variables for storing queue exam results
  integer currentQueueLength;
  integer meanInterarrivalTime;
  integer maxQueueLength;
  integer shortestWaitTime;
  integer longestWaitTime;
  integer averageWaitTime;

  initial begin
    $q_initialize(queueId, queueType, maxLength, status);

    // First customer arrives at time 10
    #10;
    customerNumber = 1;
    itemId = 10;
    $q_add(queueId, customerNumber, itemId, status);
    $display(&quot;[%0t] Customer %0d arrives with item %0d&quot;, $time, customerNumber, itemId);

    // Second customer arrives at time 30
    #20;
    customerNumber = 2;
    itemId = 12;
    $q_add(queueId, customerNumber, itemId, status);
    $display(&quot;[%0t] Customer %0d arrives with item %0d&quot;, $time, customerNumber, itemId);

    // Third customer arrives at time 50
    #20;
    customerNumber = 3;
    itemId = 22;
    $q_add(queueId, customerNumber, itemId, status);
    $display(&quot;[%0t] Customer %0d arrives with item %0d&quot;, $time, customerNumber, itemId);

    // First customer is served at time 50
    $q_remove(queueId, customerNumber, itemId, status); // Now the customerNumber and itemId become output
    $display(&quot;[%0t] Customer %0d is served with item %0d&quot;, $time, customerNumber, itemId);

    // Second customer is served at time 60
    #10;
    $q_remove(queueId, customerNumber, itemId, status);
    $display(&quot;[%0t] Customer %0d is served with item %0d&quot;, $time, customerNumber, itemId);

    // Gather queue statistics at time 90
    #50;
    $q_exam(queueId, 1, currentQueueLength, status);   // Current queue length
    $q_exam(queueId, 2, meanInterarrivalTime, status); // Mean interarrival time
    $q_exam(queueId, 3, maxQueueLength, status);       // Maximum queue length
    $q_exam(queueId, 4, shortestWaitTime, status);     // Shortest wait time ever
    $q_exam(queueId, 5, longestWaitTime, status);      // Longest wait time for jobs still in the queue
    $q_exam(queueId, 6, averageWaitTime, status);      // Average wait time in the queue

    $display(&quot;Current queue length: %0d&quot;, currentQueueLength);  
    // 1 (customer 3 has not been served)

    $display(&quot;Mean interarrival time: %0d&quot;, meanInterarrivalTime); 
    // 16667 (10000 for customer 1 + 20000 for customer 2 + 20000 for customer 3) / 3

    $display(&quot;Maximum queue length: %0d&quot;, maxQueueLength); 
    // 3 (max 3 customers in history)

    $display(&quot;Shortest wait time ever: %0d&quot;, shortestWaitTime); 
    // 30000 (customer 2 waited for 30000 ps)

    $display(&quot;Longest wait time for jobs still in the queue: %0d&quot;, longestWaitTime); 
    // 60000 (customer 3 has not been served yet, and he has been waiting for 60000 ps)

    $display(&quot;Average wait time in the queue: %0d&quot;, averageWaitTime); 
    // 60000 (customer 3 is the only one in the queue at this time)
  end
endmodule</code></pre><p>In this example, the <code>CoffeeShopQueue</code> module simulates a scenario where three customers arrive at a coffee shop and are served using a FIFO queue system. Customer 1 arrives at time 10 ns, customer 2 at time 30 ns, and customer 3 at time 50 ns. Customer 1 is served at time 50 ns, customer 2 at time 60 ns, and customer 3 remains unserved.</p><p>At time 90 ns, the <code>$q_exam</code> function is called with all the <code>q_stat_code</code> values to gather the statistical information about the queue. The results show the current queue length, mean interarrival time, maximum queue length, shortest wait time ever, longest wait time for jobs still in the queue, and average wait time in the queue.</p><h2 id="understanding-status-codes-in-queue-management-tasks-and-functions">Understanding Status Codes in Queue Management Tasks and Functions</h2><p>All of the queue management tasks and functions return an output status code. The status code values and corresponding information are described in the table below:</p><!--kg-card-begin: html--><div class="table-container"><table><thead><tr><th>Status code values</th><th>What it means</th></tr></thead><tbody><tr><td>0</td><td>OK</td></tr><tr><td>1</td><td>Queue full, cannot add</td></tr><tr><td>2</td><td>Undefined q_id</td></tr><tr><td>3</td><td>Queue empty, cannot remove</td></tr><tr><td>4</td><td>Unsupported queue type, cannot create queue</td></tr><tr><td>5</td><td>Specified length &lt;= 0, cannot create queue</td></tr><tr><td>6</td><td>Duplicate q_id, cannot create queue</td></tr><tr><td>7</td><td>Not enough memory, cannot create queue</td></tr></tbody></table></div><!--kg-card-end: html--><hr><p>By mastering the Verilog and SystemVerilog stochastic analysis functions, you can effectively manage queues and implement complex stochastic queueing models in your digital design and verification projects. These functions provide an easy-to-understand interface for queue creation, manipulation, examination, and statistics gathering, making your work more efficient and precise. Remember to pay close attention to the status codes to ensure your queue management tasks and functions are operating as expected.</p>]]></content:encoded></item><item><title><![CDATA[Verilog/SystemVerilog Random and Distribution Functions]]></title><description><![CDATA[Dive into probabilistic distribution functions in Verilog & SystemVerilog. Harness $random, $urandom, & distribution functions for versatile simulations.]]></description><link>https://circuitcove.com/system-tasks-random/</link><guid isPermaLink="false">644a04b665d41c04b80d9a62</guid><category><![CDATA[System Tasks and Functions]]></category><dc:creator><![CDATA[Shou-Li Hsu]]></dc:creator><pubDate>Thu, 27 Apr 2023 05:26:06 GMT</pubDate><content:encoded><![CDATA[<p>In this tutorial, we&apos;ll dive into the world of probabilistic distribution functions in Verilog and SystemVerilog. These functions enable us to generate random numbers according to different distribution types, allowing for more realistic and varied simulations. Let&apos;s start by exploring the <code>$random</code> and <code>$urandom</code> functions, then move on to the various distribution functions available in SystemVerilog.</p><h2 id="random-and-urandom-functions-generating-random-numbers">$random and $urandom Functions: Generating Random Numbers</h2><p>The <code>$random</code> and <code>$urandom</code> functions in Verilog and SystemVerilog offer a straightforward way to generate random numbers. While <code>$random</code> generates 32-bit signed integers, <code>$urandom</code> generates 32-bit unsigned integers. Both functions take an optional seed argument to control the random number generation.</p><h3 id="understanding-the-seed-argument">Understanding the Seed Argument</h3><p>The seed argument allows you to influence the sequence of random numbers generated by <code>$random</code> and <code>$urandom</code>. By providing a <code>seed</code>, you can create a repeatable and predictable sequence of random numbers, which can be useful for debugging purposes. The <code>seed</code> should be an integral expression, and it&apos;s recommended to assign a value to it before calling the functions.</p><p>Here&apos;s an example of using <code>$urandom</code> with a <code>seed</code>:</p><pre><code class="language-verilog">module RandomNumberGenerator;
  int seed = 42;
  int unsigned randomNumber;
  
  initial begin
    randomNumber = $urandom(seed);
    $display(&quot;Random unsigned number: %d&quot;, randomNumber);
  end
endmodule
</code></pre><h3 id="generating-random-numbers-within-a-range-using-urandomrange">Generating Random Numbers within a Range using $urandom_range()</h3><p>The <code>$urandom_range()</code> function returns an unsigned integer within a specified range. It takes two arguments: <code>maxval</code> and an optional <code>minval</code>, with a default value of 0. The function returns a random number within the range of <code>maxval ... minval</code>, inclusive.</p><p>Here&apos;s an example of using <code>$urandom_range()</code> to generate a random number between 0 and 10:</p><pre><code class="language-verilog">module RandomNumberWithinRange;
  int unsigned randomNumber;
  
  initial begin
    randomNumber = $urandom_range(10);
    $display(&quot;Random unsigned number between 0 and 10: %d&quot;, randomNumber);
  end
endmodule
</code></pre><h2 id="distribution-functions-exploring-different-random-number-characteristics">Distribution Functions: Exploring Different Random Number Characteristics</h2><p>SystemVerilog provides a range of distribution functions for generating random numbers with specific characteristics. These functions help you create more varied and realistic simulations by offering different types of random number distributions.</p><h3 id="distuniform-creating-uniformly-distributed-numbers">$dist_uniform: Creating Uniformly Distributed Numbers</h3><p>The <code>$dist_uniform</code> function generates random numbers that are uniformly distributed within a specified range. It takes three arguments: <code>seed</code>, <code>start</code>, and <code>end</code>. The <code>start</code> and <code>end</code> values determine the range of the generated numbers.</p><p>Here&apos;s an example of using <code>$dist_uniform</code>:</p><pre><code class="language-verilog">module UniformDistribution;
  int seed = 123;
  int randomNumber;
  
  initial begin
    randomNumber = $dist_uniform(seed, 0, 10);
    $display(&quot;Uniformly distributed random number: %d&quot;, randomNumber);
  end
endmodule
</code></pre><h3 id="distnormal-generating-normally-distributed-numbers">$dist_normal: Generating Normally Distributed Numbers</h3><p>The <code>$dist_normal</code> function generates random numbers that follow a normal distribution (also known as Gaussian distribution). It takes three arguments: <code>seed</code>, <code>mean</code>, and <code>standard_deviation</code>.</p><p>Here&apos;s an example of using <code>$dist_normal</code>:</p><pre><code class="language-verilog">module NormalDistribution;
  int seed = 456;
  int randomNumber;
  
  initial begin
    randomNumber = $dist_normal(seed, 10, 3);
    $display(&quot;Normally distributed random number: %d&quot;, randomNumber);
  end
endmodule
</code></pre><h3 id="distexponential-creating-exponentially-distributed-numbers">$dist_exponential: Creating Exponentially Distributed Numbers</h3><p>The <code>$dist_exponential</code> function generates random numbers that follow an exponential distribution. It takes two arguments: <code>seed</code> and <code>mean</code>.</p><p>Here&apos;s an example of using <code>$dist_exponential</code>:</p><pre><code class="language-verilog">module ExponentialDistribution;
  int seed = 789;
  int randomNumber;
  
  initial begin
    randomNumber = $dist_exponential(seed, 5);
    $display(&quot;Exponentially distributed random number: %d&quot;, randomNumber);
  end
endmodule
</code></pre><h3 id="distpoisson-generating-poisson-distributed-numbers">$dist_poisson: Generating Poisson Distributed Numbers</h3><p>The <code>$dist_poisson</code> function generates random numbers that follow a Poisson distribution. It takes two arguments: <code>seed</code> and <code>mean</code>.</p><p>Here&apos;s an example of using <code>$dist_poisson</code>:</p><pre><code class="language-verilog">module PoissonDistribution;
  int seed = 159;
  int randomNumber;
  
  initial begin
    randomNumber = $dist_poisson(seed, 4);
    $display(&quot;Poisson distributed random number: %d&quot;, randomNumber);
  end
endmodule
</code></pre><h3 id="distchisquare-creating-chi-square-distributed-numbers">$dist_chi_square: Creating Chi-Square Distributed Numbers</h3><p>The <code>$dist_chi_square</code> function generates random numbers that follow a chi-square distribution. It takes two arguments: <code>seed</code> and <code>degree_of_freedom</code>.</p><p>Here&apos;s an example of using <code>$dist_chi_square</code>:</p><pre><code class="language-verilog">module ChiSquareDistribution;
  int seed = 753;
  int randomNumber;
  
  initial begin
    randomNumber = $dist_chi_square(seed, 5);
    $display(&quot;Chi-square distributed random number: %d&quot;, randomNumber);
  end
endmodule
</code></pre><h3 id="distt-generating-t-distributed-numbers">$dist_t: Generating T-Distributed Numbers</h3><p>The <code>$dist_t</code> function generates random numbers that follow a t-distribution. It takes two arguments: <code>seed</code> and <code>degree_of_freedom</code>.</p><p>Here&apos;s an example of using <code>$dist_t</code>:</p><pre><code class="language-verilog">module TDistribution;
  int seed = 951;
  int randomNumber;
  
  initial begin
    randomNumber = $dist_t(seed, 3);
    $display(&quot;T-distributed random number: %d&quot;, randomNumber);
  end
endmodule
</code></pre><h3 id="disterlang-creating-erlang-distributed-numbers">$dist_erlang: Creating Erlang Distributed Numbers</h3><p>The <code>$dist_erlang</code> function generates random numbers that follow an Erlang distribution. It takes three arguments: <code>seed</code>, <code>k_stage</code>, and <code>mean</code>.</p><p>Here&apos;s an example of using <code>$dist_erlang</code>:</p><pre><code class="language-verilog">module ErlangDistribution;
  int seed = 357;
  int randomNumber;
  
  initial begin
    randomNumber = $dist_erlang(seed, 2, 6);
    $display(&quot;Erlang distributed random number: %d&quot;, randomNumber);
  end
endmodule
</code></pre><hr><p>Now that you have a solid understanding of the various random number generation functions in SystemVerilog, you can utilize them in your simulations to create more realistic and varied scenarios. Happy coding!</p>]]></content:encoded></item><item><title><![CDATA[Delving into SystemVerilog's Built-In Coverage Functions]]></title><description><![CDATA[Discover SystemVerilog coverage functions for better test coverage, merging and saving coverage data, and ensuring your designs meet quality standards.]]></description><link>https://circuitcove.com/system-tasks-coverage/</link><guid isPermaLink="false">6447805965d41c04b80d99ac</guid><category><![CDATA[System Tasks and Functions]]></category><dc:creator><![CDATA[Shou-Li Hsu]]></dc:creator><pubDate>Tue, 25 Apr 2023 08:21:47 GMT</pubDate><content:encoded><![CDATA[<p>In this tutorial, we will discuss the various built-in coverage functions in SystemVerilog, which play a crucial role in obtaining and managing test coverage information. Understanding these functions will help you improve the test coverage of your designs and ultimately create more reliable and robust systems.</p><h2 id="obtaining-test-coverage-information">Obtaining Test Coverage Information</h2><h3 id="coveragecontrol-managing-and-querying-test-coverage">$coverage_control : Managing and Querying Test Coverage</h3><p>The <code>$coverage_control</code> function is a key component in managing and querying coverage information in SystemVerilog. The function accepts four arguments: <code>control_constant</code>, <code>coverage_type</code>, <code>scope_def</code>, and <code>modules_or_instance</code>. The table below summarizes the pre-defined macros that can be used as arguments.</p><h4 id="coverage-control">Coverage Control</h4><!--kg-card-begin: html--><div class="table-container"><table><thead><tr><th>Macro</th><th>Value</th><th>Description</th></tr></thead><tbody><tr><td><code>SV_COV_START</code></td><td>0</td><td>Start collecting coverage data</td></tr><tr><td><code>SV_COV_STOP</code></td><td>1</td><td>Stop collecting coverage data</td></tr><tr><td><code>SV_COV_RESET</code></td><td>2</td><td>Reset coverage data</td></tr><tr><td><code>SV_COV_CHECK</code></td><td>3</td><td style="white-space: nowrap;">Check coverage against threshold</td></tr></tbody></table></div><!--kg-card-end: html--><h4 id="scope-definition-hierarchy-traversalaccumulation-type">Scope Definition (Hierarchy Traversal/Accumulation Type)</h4><!--kg-card-begin: html--><div class="table-container"><table><thead><tr><th>Macro</th><th>Value</th><th>Description</th></tr></thead><tbody><tr><td><code>SV_COV_MODULE</code></td><td>10</td><td>Coverage for specific modules</td></tr><tr><td><code>SV_COV_HIER</code></td><td>11</td><td style="white-space: nowrap;">Coverage for module hierarchies</td></tr></tbody></table></div><!--kg-card-end: html--><h4 id="coverage-type-identification">Coverage Type Identification</h4><!--kg-card-begin: html--><div class="table-container"><table><thead><tr><th>Macro</th><th>Value</th><th>Description</th></tr></thead><tbody><tr><td><code>SV_COV_ASSERTION</code></td><td>20</td><td>Assertion coverage</td></tr><tr><td><code>SV_COV_FSM_STATE</code></td><td>21</td><td style="white-space: nowrap;">Finite State Machine state coverage</td></tr><tr><td><code>SV_COV_STATEMENT</code></td><td>22</td><td>Statement coverage</td></tr><tr><td><code>SV_COV_TOGGLE</code></td><td>23</td><td>Toggle coverage</td></tr></tbody></table></div><!--kg-card-end: html--><h4 id="status-results">Status Results</h4><!--kg-card-begin: html--><div class="table-container"><table><thead><tr><th>Macro</th><th>Value</th><th>Description</th></tr></thead><tbody><tr><td><code>SV_COV_OVERFLOW</code></td><td>-2</td><td style="white-space: nowrap;">Coverage overflow</td></tr><tr><td><code>SV_COV_ERROR</code></td><td>-1</td><td>Coverage error</td></tr><tr><td><code>SV_COV_NOCOV</code></td><td>0</td><td>No coverage</td></tr><tr><td><code>SV_COV_OK</code></td><td>1</td><td>Coverage is OK</td></tr><tr><td><code>SV_COV_PARTIAL</code></td><td>2</td><td>Partial coverage</td></tr></tbody></table></div><!--kg-card-end: html--><p>Here&apos;s an example of using <code>$coverage_control</code> to start collecting statement coverage data for a specific module:</p><pre><code class="language-verilog">module TestBench;
  initial begin
    $coverage_control(`SV_COV_START, `SV_COV_STATEMENT, `SV_COV_MODULE, &quot;MyModule&quot;);
  end
endmodule
</code></pre><p>In this example, the <code>$coverage_control</code> function is used with the <code>SV_COV_START</code> control constant to begin collecting statement coverage data for the module named &quot;MyModule&quot;.</p><h3 id="coveragegetmax-obtaining-maximum-coverage-value">$coverage_get_max: Obtaining Maximum Coverage Value</h3><p>The <code>$coverage_get_max</code> function is essential for acquiring the highest possible coverage value for a particular coverage type and hierarchy scope. The function takes three arguments: <code>coverage_type</code>, <code>scope_def</code>, and <code>modules_or_instance</code>.</p><p>The function returns an integer representing the maximum coverage number for the specified coverage type and hierarchy. The return values can have different meanings:</p><ul><li>-2 (<code>`SV_COV_OVERFLOW</code>): The value is too large to be represented as an integer.</li><li>-1 (<code>`SV_COV_ERROR</code>): An error has occurred, usually due to incorrect arguments.</li><li>0 (<code>`SV_COV_NOCOV</code>): There is no available coverage for the specified coverage type and hierarchy.</li><li>+pos_num: A number that can only be positive. It tells you the maximum number of things that can be covered for a specific type of coverage. This number is calculated by adding up all the things that can be covered within a certain group or hierarchy.</li></ul><p>Below is an example demonstrating how to use the <code>$coverage_get_max</code> function to acquire the maximum statement coverage value for a specific module:</p><pre><code class="language-verilog">module TestBench;
  integer maxCoverageValue;
  initial begin
    maxCoverageValue = $coverage_get_max(`SV_COV_STATEMENT, `SV_COV_MODULE, &quot;MyModule&quot;);
    $display(&quot;Maximum statement coverage value for MyModule: %0d&quot;, maxCoverageValue);
  end
endmodule
</code></pre><p>In this example, the <code>$coverage_get_max</code> function is used with the <code>SV_COV_STATEMENT</code> coverage type and <code>SV_COV_MODULE</code> scope definition to retrieve the maximum statement coverage value for the &quot;MyModule&quot; module. The obtained value is stored in the <code>maxCoverageValue</code> variable and displayed on the console.</p><h3 id="coverageget-retrieving-current-coverage-value">$coverage_get: Retrieving Current Coverage Value</h3><p>The <code>$coverage_get</code> function is used to obtain the current coverage value for a specific coverage type and hierarchy scope. This function takes the same arguments as the <code>$coverage_get_max</code> function: <code>coverage_type</code>, <code>scope_def</code>, and <code>modules_or_instance</code>.</p><p>Similar to the <code>$coverage_get_max</code> function, <code>$coverage_get</code> returns an integer value, with the following meanings:</p><ul><li>-2 (<code>`SV_COV_OVERFLOW</code>): The value is too large to be represented as an integer.</li><li>-1 (<code>`SV_COV_ERROR</code>): An error has occurred, usually due to incorrect arguments.</li><li>0 (<code>`SV_COV_NOCOV</code>): There is no available coverage for the specified coverage type and hierarchy.</li><li>+pos_num: This is a positive number that shows the current value of coverage. It tells you the sum of all the things that have been covered for a specific type of coverage within a certain group or hierarchy.</li></ul><p>You can calculate the coverage rate (in percentage) by dividing the current coverage value returned by <code>$coverage_get</code> by the maximum coverage value returned by <code>$coverage_get_max</code>, and then multiplying by 100.</p><p>Here&apos;s an example that demonstrates how to use the <code>$coverage_get</code> function to calculate the statement coverage rate for a specific module:</p><pre><code class="language-verilog">module TestBench;
  integer currentCoverageValue, maxCoverageValue;
  real coverageRate;
  initial begin
    maxCoverageValue = $coverage_get_max(`SV_COV_STATEMENT, `SV_COV_MODULE, &quot;MyModule&quot;);
    currentCoverageValue = $coverage_get(`SV_COV_STATEMENT, `SV_COV_MODULE, &quot;MyModule&quot;);
    coverageRate = (currentCoverageValue * 100.0) / maxCoverageValue;
    $display(&quot;Statement coverage rate for MyModule: %.2f%%&quot;, coverageRate);
  end
endmodule
</code></pre><p>In this example, the <code>$coverage_get</code> function retrieves the current statement coverage value for the &quot;MyModule&quot; module, while the <code>$coverage_get_max</code> function obtains the maximum statement coverage value. The coverage rate is calculated and displayed on the console.</p><h3 id="coveragemerge-merging-coverage-data">$coverage_merge: Merging Coverage Data</h3><p>The <code>$coverage_merge</code> function helps you load and combine coverage data from a saved coverage database for a specific coverage type. It takes two arguments: <code>coverage_type</code> and <code>name</code>. The <code>name</code> is a string that the tool uses to find the coverage database in a unique way based on the implementation.</p><pre><code class="language-verilog">module TestModule;
  initial begin
    // Load and merge coverage data from a saved coverage database
    int mergeResult;
    mergeResult = $coverage_merge(`SV_COV_ASSERTION, &quot;coverageDatabase&quot;);
    if (mergeResult == `SV_COV_OK) begin
      $display(&quot;Coverage data has been found and merged.&quot;);
    end
  end
endmodule
</code></pre><p>The function returns the following values:</p><ul><li><code>`SV_COV_OK</code>: The coverage data was found and merged successfully.</li><li><code>`SV_COV_NOCOV</code>: The coverage data was found but didn&apos;t contain the requested coverage type.</li><li><code>`SV_COV_ERROR</code>: The coverage data couldn&apos;t be found, didn&apos;t match this design, or another issue occurred.</li></ul><h3 id="coveragesave-saving-coverage-data">$coverage_save: Saving Coverage Data</h3><p>The <code>$coverage_save</code> function allows you to save the current coverage state to the tool&apos;s coverage database, linking it with the given <code>name</code>. It also takes two arguments: <code>coverage_type</code> and <code>name</code>. The <code>name</code> maps to the coverage database based on the implementation.</p><pre><code class="language-verilog">module TestModule;
  initial begin
    // Save the current state of coverage to the tool&apos;s coverage database
    int saveResult;
    saveResult = $coverage_save(`SV_COV_ASSERTION, &quot;coverageDatabase&quot;);
    if (saveResult == `SV_COV_OK) begin
      $display(&quot;Coverage data was successfully saved.&quot;);
    end
  end
endmodule
</code></pre><p>This function returns:</p><ul><li><code>`SV_COV_OK</code>: The coverage data was saved successfully.</li><li><code>`SV_COV_NOCOV</code>: There&apos;s no available coverage data for this design (nothing was saved).</li><li><code>`SV_COV_ERROR</code>: An error occurred during the save process. The tool will automatically remove the coverage database entry for the <code>name</code> to maintain the database&apos;s integrity. Overwriting an existing name is not considered an error.</li></ul><h2 id="managing-coverage-data-with-system-tasks-and-functions">Managing Coverage Data with System Tasks and Functions</h2><h3 id="setcoveragedbname-setting-coverage-database-name">$set_coverage_db_name: Setting Coverage Database Name</h3><p>The <code>$set_coverage_db_name</code> system task enables you to define the name for your coverage database. You can set the database name using the following example:</p><pre><code class="language-verilog">module TestBench;
  initial begin
    $set_coverage_db_name(&quot;MyCoverageDatabase&quot;);
  end
endmodule
</code></pre><h3 id="loadcoveragedb-loading-coverage-data">$load_coverage_db: Loading Coverage Data </h3><p>The <code>$load_coverage_db</code> system function allows you to import coverage data from a coverage database file into the simulator. Here&apos;s an example demonstrating how to use <code>$load_coverage_db</code> to load the coverage data:</p><pre><code class="language-verilog">module TestBench;
  bit loadSuccess;
  
  initial begin
    $load_coverage_db(&quot;MyCoverageDatabase&quot;);
  end
endmodule
</code></pre><h3 id="getcoverage-retrieving-overall-coverage">$<strong>get_coverage</strong>: Retrieving Overall Coverage</h3><p>The <code>$get_coverage</code> system function returns a real number between 0 and 100, representing the overall coverage across all coverage group types. This value is calculated as previously described. Here&apos;s an example of how to use <code>$get_coverage</code> to retrieve the overall coverage:</p><pre><code class="language-verilog">module TestBench;
  real overallCoverage;

  initial begin
    overallCoverage = $get_coverage();
    $display(&quot;Overall coverage: %.2f%%&quot;, overallCoverage);
  end
endmodule
</code></pre><hr><p>SystemVerilog offers various built-in functions for obtaining and managing test coverage information. Mastering these functions allows you to create more robust and reliable systems by identifying and improving test coverage gaps. By using these functions, you can control and query coverage, obtain maximum and current coverage values, merge and save coverage data, and check coverage against a threshold. Make sure to explore and understand these functions to enhance your testing strategies and ensure your designs meet the desired level of quality.</p>]]></content:encoded></item></channel></rss>