Mastering $display in Verilog: Debugging, Formatting, and Practical Applications

目次

1. Introduction: The Importance and Purpose of “display” in Verilog

What is “display” in Verilog?

In Verilog, the $display system task is a tool used to “display” the internal state of a program during simulation. Similar to C’s printf, it can output signals, variable values, and strings to the terminal or console. It plays a central role in debugging and verifying circuit behavior.

Why is $display indispensable in Verilog development?

  • Improved debugging efficiency: In complex circuit designs, visualizing internal signals is critical. With $display, you can quickly check values of interest during simulation.
  • Simulation visualization: Waveforms alone may not provide enough clarity. Display logs make transitions at specific timings explicit and reliable.
  • Useful for documentation: When sharing design intent or behavior with other engineers, annotated display logs improve code readability and understanding.

Purpose and structure of this article

This article explains the following step by step:

  1. Basic syntax and usage: A clear introduction to $display syntax and examples.
  2. Comparison with other system tasks: Organizing differences between $write, $strobe, and $monitor.
  3. Format specifiers and advanced techniques: How to use %d, %b, %h, %s, and more.
  4. Practical examples: Real testbench use cases with code for hands-on learning.
  5. Applications in display control: Examples of applying Verilog for LCD/monitor text and image display.

With this structure, both beginners and intermediate learners can understand and apply $display effectively. Each section includes examples and diagrams for clarity.

2. Basics of $display: Syntax, Usage, and Caveats

Basic syntax of $display

The fundamental syntax for using $display in Verilog is as follows:

$display("string or format specifier", signal1, signal2, ...);
  • String part: Contains text and format specifiers (e.g., %d, %b, %h).
  • Arguments: Signals or variables to be output in the specified format.

Example: Displaying clock count and signal values

$display("Time=%0t : clk=%b, reset=%b", $time, clk, reset);

This prints the simulation time and values of the clock/reset signals.

Use cases of $display

  1. Track simulation progress
    Insert $display in specific locations to confirm execution flow.
  2. Check signal values
    Complex conditions or state transitions can be easier to grasp in text form.
  3. Conditional messages
    Combine with if statements for selective logging: if (reset) $display("Reset asserted at %0t", $time);

Difference between $display and $write

$display automatically adds a newline at the end, while $write continues output on the same line.

Example:

$display("Hello");
$display("World");

Output:

Hello
World
$write("Hello");
$write("World");

Output:

HelloWorld

Choose $display for readability or $write for compact inline logging.

Caveats

  1. Avoid excessive output
    Printing on every clock can flood logs; use conditional filtering.
  2. Leverage time display
    Use $time or $realtime for precise timing.
  3. Simulation-only
    $display cannot be synthesized; it is for simulation/debugging only.

3. Comparison of Log Output System Tasks: $display, $write, $strobe, $monitor

Besides $display, Verilog provides other system tasks for output. Each differs in timing and usage, so understanding them helps with efficient debugging.

$display: Standard display task

  • Feature
    Automatically adds a newline, organizing logs line by line.
  • Usage
    Most commonly used for one-time debugging output.

$write: Display without newline

  • Feature
    Does not add a newline, allowing continuous output.
  • Usage
    Useful when displaying multiple values in a single line.
  • Example $write("A=%d, ", a); $write("B=%d", b); → Output: A=5, B=10

$strobe: Output final values at end of simulation cycle

  • Feature
    Prints values after all updates in the current cycle are resolved.
  • Usage
    Useful for avoiding race condition effects.
  • Example $strobe("Time=%0t, signal=%b", $time, sig); → Ensures stable values are displayed.

$monitor: Automatic tracking output

  • Feature
    Automatically outputs whenever specified signals change.
  • Usage
    Great for monitoring multiple signals continuously.
  • Example $monitor("At %0t: a=%b, b=%b", $time, a, b);

Comparison table

TaskNewlineOutput timingMain usage
$displayYesImmediately when calledBasic log output
$writeNoImmediately when calledInline display, log formatting
$strobeYesAfter simulation cycle endsConfirm stable values
$monitorYesWhenever signals changeContinuous monitoring

Tips for choosing

  • Default: $display — simple and readable.
  • For inline multiple values: $write.
  • For stable values: $strobe.
  • For ongoing monitoring: $monitor.

4. Format Specifiers and Special Display Techniques

With $display and $write, you can embed format specifiers inside strings to output signals in different representations. Similar to C’s printf, proper use boosts debugging efficiency.

Basic format specifiers

SpecifierMeaningExample output
%bBinary1010
%dDecimal10
%hHexadecimalA
%oOctal12
%cASCII characterA
%sStringHello
%tSimulation time#100
%mModule hierarchy nametop.u1.u2

Practical examples

  1. Display in multiple formats reg [7:0] data = 8'b10101010; $display("data = %b, %d, %h", data, data, data);data = 10101010, 170, AA
  2. Check hierarchy $display("Current module: %m");
  3. Print simulation time $display("Time=%0t: clk=%b", $time, clk);

Special display techniques

  • Zero-padding and width control
    %04d formats numbers with leading zeros: Count=0012.
  • Signed vs unsigned
    %d for signed, %u for unsigned output.
  • Multi-line messages
    Use \n for clear line breaks in logs.

Cautions

  • Bit-width awareness: Mismatched widths can cause truncation or sign extension issues.
  • Undefined values (X, Z): %b shows x and z explicitly if present.

5. Practical Examples: Using $display in Testbenches and Modules

Let’s explore how to use $display effectively through real Verilog examples. From basic testbenches to conditional debugging, we’ll cover practical use cases.

Basic example: Output in a testbench

Inserting $display into a testbench allows you to check behavior during simulation.

module tb_counter;
  reg clk;
  reg reset;
  wire [3:0] count;

  // DUT (Device Under Test)
  counter uut (
    .clk(clk),
    .reset(reset),
    .count(count)
  );

  // Clock generation
  initial begin
    clk = 0;
    forever #5 clk = ~clk;  // Toggle every 5 units
  end

  // Test scenario
  initial begin
    reset = 1;
    #10 reset = 0;

    #50 $finish;
  end

  // Display state
  always @(posedge clk) begin
    $display("Time=%0t | reset=%b | count=%d", $time, reset, count);
  end
endmodule

This outputs reset and count values at each clock edge, making it easier to trace behavior with both waveforms and logs.

Conditional display example

Use if conditions to print only when needed:

always @(posedge clk) begin
  if (count == 4'd10) begin
    $display("Count reached 10 (Time=%0t)", $time);
  end
end

→ This avoids unnecessary logs while capturing key events.

Debugging messages

To catch unexpected states:

always @(posedge clk) begin
  if (count > 4'd12) begin
    $display("WARNING: count overflow detected! Time=%0t, value=%d", $time, count);
  end
end

Monitoring multiple signals together

$display("Time=%0t | clk=%b | reset=%b | A=%h | B=%h | SUM=%h",
         $time, clk, reset, A, B, SUM);

Summary of practical tips

  • Insert in testbenches to visualize progress
  • Use conditions to filter logs
  • Output warnings for anomalies
  • Combine multiple signals for clean logs

6. Applications of Display Control (Pixel/Text/Image Output)

So far, $display has referred to simulation/debug text output.
Verilog can also be used for hardware display control (LCD, VGA, HDMI). Let’s look at how to display on screens with hardware logic.

Basic concepts of display control

Displaying text/images requires generating video signals:

  • HSYNC (horizontal sync): Line boundaries
  • VSYNC (vertical sync): Frame boundaries
  • RGB data: Pixel colors (e.g., 24-bit color)

Example 1: Displaying color bars

always @(posedge clk) begin
  if (h_counter < 100)       rgb <= 24'hFF0000; // Red
  else if (h_counter < 200)  rgb <= 24'h00FF00; // Green
  else if (h_counter < 300)  rgb <= 24'h0000FF; // Blue
  else                       rgb <= 24'h000000; // Black
end

Example 2: Displaying text

// Display 'A' using font ROM patterns
if (font_rom[char_code][y][x] == 1'b1)
    rgb <= 24'hFFFFFF;  // White
else
    rgb <= 24'h000000;  // Black

Example 3: Displaying images

rgb <= image_rom[addr];  // Load pixel data from ROM

Difference from debugging $display

  • $displayText output (simulation only)
  • Display control → Video signal generation (hardware implementation)

Practical applications

  • Seven-segment LEDs and small LCDs in FPGA boards
  • VGA/HDMI for GUIs or games
  • Overlay debug info (counters, coordinates) directly on screen

7. Choosing the Right Tool by Use Case

In Verilog, “display” can mean simulation text output tasks or hardware display logic. Choosing correctly saves time and improves debugging.

Simulation use

  1. Debug logs with $display
  2. Avoid excessive output: filter with conditions
  3. Use appropriate tasks:
    • $monitor → continuous watch
    • $strobe → stable values
    • $write → inline formatting

Hardware display use

  1. Seven-segment displays: show counter values
  2. LCD/VGA monitors: output text/images using font or image ROM
  3. Debug overlays: render variables on screen in real time

Professional tips

  • Sim → hardware flow: Verify with $display, then move to actual display logic.
  • Combine logs + waveforms: Text logs for timing, waveforms for detail.
  • Standardize log format: Helps teamwork in debugging.

Summary

  • $display = simulation observation tool
  • Display control = hardware display method
  • Using both appropriately ensures efficient development

8. FAQ (Frequently Asked Questions)

Q1. What’s the difference between $display and $monitor?

A. $display prints once when called. $monitor continuously outputs whenever signals change.

Q2. When should I use $strobe?

A. Use $strobe to output stable values after the current cycle finishes, avoiding transient outputs.

Q3. What is the purpose of the %m specifier?

A. It prints the current module hierarchy name, useful for large designs.

Q4. My log got too large with many $display. What can I do?

A. Filter with if, log only critical events, or output to files for later analysis.

Q5. Can $display be used in FPGA/ASIC synthesis?

A. No, it’s simulation-only. For hardware output, use seven-segment displays, LCD, VGA, etc.

Q6. How do I display text/images on hardware?

A. Generate video signals instead of $display. Use font ROMs for text, image ROMs for pictures, and HSYNC/VSYNC + RGB signals for VGA/LCD output.

9. Summary and Next Steps

Article recap

  1. $display basics: Simulation-only text output, similar to C’s printf.
  2. Related tasks: $write, $strobe, $monitor.
  3. Format specifiers: %b, %d, %h, %m, %t, etc.
  4. Practical examples: Testbenches, conditional logs, warnings.
  5. Display control: Hardware video signal generation for text/images.

Next steps

  • Explore SystemVerilog: Advanced debugging with assertions and enhanced tasks.
  • Combine logs and waveforms: Cross-check timing and behavior.
  • Practice hardware output: Try FPGA projects with seven-seg or LCD.
  • Standardize in teams: Define consistent message formats.

Closing

$display is more than a print tool—it’s a powerful debugging ally. And with hardware display logic, Verilog lets you bring visuals to real monitors via FPGA. Mastering both worlds makes you more effective in simulation and hardware design.