Mastering $display in Verilog: Effective Debugging and Display Control Techniques

目次

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

What Does “display” Mean in Verilog?

In Verilog, $display is a system task used as a tool to “display” the internal state of a design during simulation. Similar to C’s printf, it lets you output signals, variable values, and strings to a terminal or console—playing a central role in debugging and functional verification.

Why Is $display Essential for Verilog Development?

  • Improved debugging efficiency: In complex circuit designs, visualizing whether internal signals are functioning correctly is critical. By using $display, you can instantly check the values of signals of interest during simulation.
  • Simulation visualization: When tracking value transitions at specific points in time, waveforms alone may be insufficient. Display logs provide a reliable means of indicating those precise moments.
  • Useful for documentation as well: When conveying design intent or operational rules to other engineers, inserting annotated display logs can enhance code understanding.

Purpose and Structure of This Article

In this article, we will methodically explain the following:
  1. Basic syntax and usage: A careful introduction to the fundamental syntax and usage of $display.
  2. Comparison with other system tasks: We will organize the differences among display-related tasks such as $write, $strobe, and $monitor.
  3. Format specifiers and advanced usage techniques: Use of format specifiers like %d, %b, %h, %s, and special display techniques will be introduced.
  4. Practical usage examples: We will show concrete usage in test benches and code with examples, providing immediately applicable know-how.
  5. Display-control applications: Example use cases will include hardware output such as LCD or monitor control and displaying text/image output.
With this structure, both beginners and intermediate users can properly understand $display in Verilog and apply it in practice. In each section that follows, we will proceed clearly using examples and diagrams whenever possible.

2. Basics of $display: Syntax, Use-Cases, and Precautions

Basic Syntax of $display

When using $display in Verilog, the basic syntax is as follows.
$display("string or format specifiers", signal1, signal2, ...);
  • String portion: Write any text or format specifiers (for example: %d, %b, %h).
  • Arguments: List signal names or variables to output in the corresponding format.
Example: Displaying clock count and signal values
$display("Time=%0t : clk=%b, reset=%b", $time, clk, reset);
In this example, the simulation time and values of the clock/reset signals are output.

Use-Cases of $display

  1. Grasping simulation progress By inserting $display at specific points in your design you can verify which part of the code the execution has reached.
  2. Signal value verification Even when waveform viewers make it hard to intuitively understand conditional branches or state transitions, outputting as text makes comprehension easier.
  3. Conditional message display By combining with if statements you can log messages only when specific conditions are met. if (reset) $display("Reset asserted at %0t", $time);

Difference Between $display and $write

$display automatically appends a newline at the end of the output. On the other hand, $write continues output without adding a newline. Example:
$display("Hello");
$display("World");
Output:
Hello
World
$write("Hello");
$write("World");
Output:
HelloWorld
If you need clearer line-by-line logs use $display. When you want to format outputs on one line use $write.

Precautions

  1. Avoid excessive output If you use $display every clock cycle, logs grow large and readability drops. → Use conditioning to reduce output.
  2. Utilize time display Outputting $time or $realtime lets you accurately capture timing of operations.
  3. Design-for-simulation only task $display cannot be used for synthesis (FPGA/ASIC implementation). It is strictly a simulation-only debug tool.

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

Verilog offers system tasks beyond $display for output. Their different use-cases and timing mean it is efficient to understand how to use them distinctly.

$display: Standard Display Task

  • Characteristics Automatically adds newline and logs one line per invocation.
  • Use-case Most commonly used as a basic debug method; you can call it at any time for one-time output.

$write: Display Without Newline

  • Characteristics Does not append newline and therefore continues output on the same line.
  • Use-case Useful when you want to display multiple values side-by-side.
  • Example $write("A=%d, ", a); $write("B=%dn", b); → Output: A=5, B=10.

$strobe: Output at End of Simulation Cycle

  • Characteristics Prints values after all simulation evaluations in the current step have completed.
  • Use-case Useful when avoiding race conditions (when multiple signals change simultaneously).
  • Example $strobe("Time=%0t, signal=%b", $time, sig); → While $display may show intermediate values, $strobe shows settled values.

$monitor: Automatic Tracking Output

  • Characteristics Automatically outputs when any monitored signal changes.
  • Use-case Convenient when you want to monitor a set of signals continuously.
  • Example $monitor("At %0t: a=%b, b=%b", $time, a, b); → Logs when either a or b changes.

Summary Table

TaskNewlineTiming of OutputMain Use-Case
$displayYesWhen invokedBasic log output
$writeNoWhen invokedSide-by-side formatting
$strobeYesAfter simulation cycle endsCheck settled values
$monitorYesAutomatically on signal changeContinuous monitoring

Tips for Effective Usage

  • Use $display by default: Readable and easy for beginners.
  • Use $write when you want a single-line combined output.
  • Use $strobe when you need settled values after changes.
  • Use $monitor when you need continuous signal monitoring.

4. Format Specifiers and Advanced Display Techniques

With tasks like $display or $write, you can include “format specifiers” in strings to output signals or variables in desired formats. Since it resembles C’s printf, properly using them based on your purpose significantly enhances debugging efficiency.

Basic Format Specifiers

SpecifierDescriptionOutput Example
%bbinary1010
%ddecimal10
%hhexadecimalA
%ooctal12
%cASCII characterA
%sstringHello
%tsimulation time#100 etc.
%mmodule hierarchy nametop.u1.u2

Practical Examples

  1. Display a signal in multiple formats reg [7:0] data = 8'b10101010; $display("data = %b (bin), %d (dec), %h (hex)", data, data, data); → Example output: data = 10101010 (bin), 170 (dec), AA (hex)
  2. Check module hierarchy $display("Current module hierarchy is %m"); → Example output: Current module hierarchy is top.u1.counter
  3. Display simulation time $display("Time=%0t: clk=%b", $time, clk); → Example output: Time=100: clk=1

Advanced Display Techniques

  • Zero-padding & field width You can specify zero-padding or field width such as %0d. Example: $display("Count=%04d", count); → Output: Count=0012
  • Signed vs unsigned distinction %d treats values as signed, %u treats them as unsigned. If a negative value isn’t displayed as expected, revise the specifier.
  • Multi-line messages formatting Use \n to break lines for readability. Example: $display("Start of test\nSignal A=%b\nSignal B=%b", A, B);

Precautions

  • Mind the bit-width: Verilog signals may have different widths; using %d can cause truncation or sign-extension issues.
  • Handling undefined values (X, Z): If you include undefined bits, using %b will display x or z directly.

5. Practical Examples: Using $display in Test Benches and Modules

From here we will introduce effective uses of $display through real Verilog code examples, covering basics of test benches to conditional debug logging.

Basic Example: Output in a Test Bench

By inserting $display into a test bench, you can observe 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;  // invert 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
In this example, each rising clock triggers output of reset and count. Because you can inspect text logs as well as waveforms, tracking behavior becomes easier.

Conditional Display Example

By combining with if statements you can log only when specific conditions are met.
always @(posedge clk) begin
  if (count == 4'd10) begin
    $display("Count has reached 10 (Time=%0t)", $time);
  end
end
→ This lets you avoid superfluous logs while pinpointing the events you care about.

Debug-Message Example

During design debugging it’s effective to catch when a signal enters an “unexpected state”.
always @(posedge clk) begin
  if (count > 4'd12) begin
    $display("WARNING: count overflow detected! Time=%0t, value=%d", $time, count);
  end
end
→ You can quickly discover design faults or unexpected simulation behavior.

Monitoring Multiple Signals Together

When outputting many signals, collecting them into one line using $display makes logs more readable.
$display("Time=%0t | clk=%b | reset=%b | A=%h | B=%h | SUM=%h",
         $time, clk, reset, A, B, SUM);

Summary of Practical Tips

  • Place $display in the test bench to visualize progress
  • Use conditional branches to refine logs
  • Generate warning messages to detect anomalies
  • Consolidate multiple signals in one line to improve readability

6. Display-Control Applications (Pixel/Text/Image Display)

Up to now, we introduced $display for simulation logs. Meanwhile Verilog is also widely used for “display control” in hardware implementations (LCD, VGA, HDMI output). In this section, we briefly introduce how to implement screen display at the hardware level.

Fundamental Concept of Display Control

To display text or images on a screen, you must generate video signals rather than simply use $display. Typical control signals include:
  • HSYNC (Horizontal Sync): Signal that denotes the end of each line
  • VSYNC (Vertical Sync): Signal that denotes the end of each frame
  • RGB Data: Signal representing the color of each pixel (e.g., 8bit × 3 = 24bit color)
In Verilog, you control these signals via counters and state machines and output them based on timing to realize “screen display”.

Example 1: Displaying Color Bars

The most basic example is outputting color bars horizontally on a display.
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
→ This results in red, green, and blue color bars aligned across the screen horizontally.

Example 2: Text Display

For text display you prepare a font ROM and convert each character’s dot pattern into pixels.
// Referencing the pattern of 'A' from the font ROM and displaying
if (font_rom[char_code][y][x] == 1'b1)
    rgb <= 24'hFFFFFF;  // white for display
else
    rgb <= 24'h000000;  // black background
→ This draws a particular character (e.g., “A”) on the screen.

Example 3: Image Display

To display an image you read pre-stored bitmap data (ROM or external memory) and convert that into pixel output.
rgb <= image_rom[addr];  // Retrieve color data from ROM
In embedded systems using FPGAs, this method lets you display simple icons or logos.

Difference Compared to Debug $display

  • $display is text output (simulation only)
  • Display control is video signal generation (hardware-implementable)
Though their purposes differ, learners of Verilog often confuse the two.
  • “I want to verify behavior during simulation” → Use $display
  • “I want to output to actual screen on FPGA” → Design video-signal logic

Expansion of Applications

  • On learning FPGA boards, Verilog is frequently used for 7-segment LED display or small LCD display.
  • Advancing further, you can build systems supporting VGA/HDMI output for game development or GUI display.
  • By combining knowledge of $display with display-control logic you can handle “display” in both simulation and actual hardware.

7. Appropriate Usage and Tips Based on Application Scenarios

When we speak of “display” in Verilog there are two aspects: the simulation-only $display tasks, and the hardware implementation display control. Using each appropriately leads to efficient development and debugging.

Use in Simulation

  1. $display as debug log
    • Output critical variables or signals with $display to check if your design behaves as expected.
    • Verifying “values under specific conditions” or “counter reaching points” via logs is efficient.
  2. Avoid excessive output
    • Outputting at every clock cycle floods logs and reduces readability. Narrow the conditions.
    • Example: if (state == ERROR) $display("Error occured at %0t", $time);
  3. Differentiate between tasks
    • $monitor → For signals you wish to watch continuously
    • $strobe → When you need to output settled values
    • $write → For formatted horizontal output

Use in Hardware Display Control

  1. 7-segment display for learning
    • In FPGA beginner projects, displaying a counter value on a 7-segment LED is standard.
    • Combine with $display simulation output to deepen understanding of display vs simulation.
  2. LCD or VGA monitor control
    • Use font ROM or image ROM to display text or image.
    • By also using $display in simulation you can doubly verify that the video-signal generation is correct.
  3. Debug overlay in hardware
    • You can overlay “counter value”, “coordinates”, “debug messages” on actual video output.
    • In FPGA development it is common to “make the screen itself a debugging tool”.

Practical Tips

  • Follow simulation → hardware flow First use $display to verify behavior in simulation, then move to display-control logic for hardware implementation.
  • Use logs and waveforms in tandem Text logs from $display indicate “event occurrence timing”, while waveforms show “detailed transitions”. Using both raises debugging precision.
  • Unify message format in team development Standardizing $display message format (prefix, time display, etc.) makes log analysis easier when multiple people work together.

Summary

  • $display-type tasks are simulation-only “observation tools”
  • Display control means hardware implementation “display method”
  • By using each appropriately and combining them you can enable efficient development

8. FAQ (Frequently Asked Questions)

Q1. What is the difference between $display and $monitor?

A. $display outputs once at the moment it is called. In contrast, $monitor automatically outputs whenever a registered signal changes.
  • For one-time debugging → $display
  • For continuous monitoring → $monitor

Q2. When should I use $strobe?

A. $strobe outputs the settled value at the end of a simulation cycle. For example, when multiple signals change simultaneously on a clock edge, $display might show intermediate values. In such cases $strobe is convenient for showing the final values.

Q3. What is the use of format specifier %m?

A. %m outputs the current module hierarchy name. In large designs, logging “which hierarchy the message came from” makes analysis far easier.
$display("Current module: %m");
Example output:
Current module: top.u1.counter

Q4. My logs became enormous because I used many $display. What should I do?

A. The following measures are effective:
  • Use if statements to filter output
  • Only output error detection or specific events
  • Use $monitor to watch only the minimum required signals
  • Output to a log file and apply filtering tools during analysis

Q5. Can $display be used for synthesis (FPGA/ASIC)?

A. No. $display is strictly a simulation-only task. Synthesis tools ignore it so it does not reflect in actual hardware. If you want to display output on real hardware you must design with “7-segment LED”, “LCD”, “VGA control logic”, etc., in Verilog.

Q6. How do I display text or images on actual hardware?

A. Not via $display, but by generating video signals.
  • 7-segment display → For simple numeric or character display
  • VGA/LCD → Generate HSYNC, VSYNC, RGB signals and control them
  • Text → Use font ROM and output dot patterns
  • Images → Store bitmaps in ROM or external memory and output pixels accordingly

9. Conclusion & Next Steps

Summary of This Article

In this article we covered “display” in Verilog from fundamentals to applications. Key points included:
  1. Basics of $display
    • A simulation task that displays signals or variables, usable similar to C’s printf.
  2. Differences with related tasks
    • $write → Display without newline
    • $strobe → Output settled values at end of simulation cycle
    • $monitor → Automatically monitor signal changes
  3. Using format specifiers
    • By using %b, %d, %h, %m, %t, you can output clearer and more practical logs.
  4. Practical examples
    • Insert $display into test benches to monitor progress.
    • Use conditional messages to enable efficient debugging.
  5. Applications in display control
    • $display is simulation only; hardware implementation uses HSYNC, VSYNC, RGB to output text/image.
    • From learning 7-segment display to advanced VGA/HDMI control, expansions are possible.

Next Steps

  • Advance to SystemVerilog → In the successor language SystemVerilog you can use more advanced debug features (assertions, enhanced $display, etc.).
  • Combine with waveform viewer → By combining $display logs and waveform data you can analyze both numerical values and transitions, boosting debugging precision.
  • Learn hardware display output → In a small FPGA board project try outputting on 7-segment or LCD to experience the difference between “simulation display” and “hardware display control”.
  • Apply in team development → By standardizing $display message format you improve log analysis efficiency in multi-person development.

In Closing

$display is more than mere “text output”. It is a powerful tool for simulation debugging. And when you step into the world of display control, you can experience the joy of showing graphics on real monitors via FPGA. I hope this article helps Verilog learners understand both “simulation debugging” and “hardware display output” clearly.