The Two Forms
Verilog supports exactly two comment syntaxes, both copied from C:
That's the whole syntax. There's no # like Python, no -- like VHDL, no Lisp-style. Just // and /* ... */.
When to Use Each
// is what you reach for almost every time. It's shorter, it can't be accidentally unterminated, and it pairs naturally with the way you write Verilog (one declaration per line, with the comment on the same or adjacent line):
output reg [7:0] data, // byte we shift out on tx_serial
output reg valid, // high while data is being transmitted
input wire ready // downstream consumer is ready to accept
/* ... */ is mostly for two things: large header blocks at the top of a file, and temporarily disabling a chunk of code while debugging. The disable case is dangerous - read on.
The "No Nesting" Gotcha
Block comments don't nest. If you try to comment out a region that already contains a block comment, the first */ closes the outer block, not the inner:
/* outer
/* inner */ // <-- this */ closes the outer comment
still active in the source as far as the parser is concerned
*/
Result: a syntax error somewhere unexpected, on a line that looks correct.
When you need to disable a region, prefer one of:
-
Prefix every line with
//. Most editors do this on a keystroke. -
Use a preprocessor guard:
`ifdef DISABLED // code that should not compile `endif
The second pattern is also how you keep multiple build configurations in one file.
Synthesis Pragmas: Comments That Aren't Comments
Vendor tools use specially-formatted comments as out-of-band instructions. The simulator still ignores them, but the synthesis tool reads them:
// synthesis translate_off
initial begin
$display("simulator-only setup");
end
// synthesis translate_on
The two pragmas tell the synthesis tool "skip everything between these markers." The exact spellings vary by vendor (synthesis, synopsys, pragma, xilinx, etc.) - check your tool's docs. The thing to know: comments in Verilog are sometimes load-bearing.
Header-Block Conventions
Long-lived Verilog files almost always start with a header block. The exact format is team policy, but a typical example:
// -----------------------------------------------------------------------------
// Module : uart_tx
// Description : 8-N-1 UART transmitter. Accepts a byte on `data` when `valid`
// is asserted and shifts it out on `serial_out`. `baud_tick`
// must pulse once per baud period.
// Ports : clk - system clock
// reset_n - active-low synchronous reset
// baud_tick - 1-cycle pulse at each baud interval
// data - byte to transmit
// valid - asserted to start a transmission
// serial_out - the wire that leaves the FPGA
// busy - high while a frame is in flight
// Author : example@team
// Revision : 2026-05-26 - initial version
// -----------------------------------------------------------------------------
module uart_tx (
input wire clk,
input wire reset_n,
input wire baud_tick,
input wire [7:0] data,
input wire valid,
output reg serial_out,
output reg busy
);
// ... body ...
endmodule
The point isn't the decoration. The point is that someone opening this file in a year - probably you - can read four lines and know what it does, what it expects, and what it produces. That payoff scales with the size of the project.
Inline Comments That Earn Their Keep
A common mistake is commenting what a line does when the code already shows that:
// bad - the comment restates the code
count <= count + 1; // increment count
// better - the comment explains why this line is here
count <= count + 1; // free-running cycle counter for timestamping
The thing comments are uniquely good at is explaining the why that the code can't show by itself: which spec section a quirky encoding follows, why a register is one bit wider than it looks, why a default case is set to 'x instead of '0. Lean on them for that. Leave the obvious to the code.
Try It
The block below contains every comment form. Run it - the output won't surprise you, but the file structure should:
You've now seen every comment shape Verilog supports. The rest of the docs use them as you'd expect: header blocks at the top of long modules, single-line // next to ports, and block comments only when there's a paragraph's worth of reasoning to capture.
Frequently Asked Questions
How do you write a comment in Verilog?
Verilog supports two comment styles, both inherited from C. // starts a comment that runs to the end of the line. /* ... */ wraps a multi-line block. The compiler ignores everything between the markers; both styles are equally valid in any synthesizable or simulation-only file.
Are Verilog comments synthesizable?
Comments don't exist after parsing - the synthesis tool throws them away just like the simulator does. The only exception is synthesis pragmas: specially-formatted comments like // synthesis translate_off that vendor tools recognize as directives. The pragma syntax is tool-specific and not part of standard Verilog.
Can Verilog comments be nested?
No - and this trips up beginners who try to comment out a block that already contains /* ... */. The first */ inside closes the outer comment, leaving the rest of the block as live code. Use // on each line, or wrap the whole region in \ifdef SOMETHING_FALSE/`endif` if you really need to disable a chunk.
What should a Verilog header comment include?
Most teams put a small header at the top of every file: module name, one-sentence purpose, port summary, author/date, and a revision history. The exact format varies; what matters is that anyone opening the file can tell what it does without reading the body. Big designs add per-signal comments next to every port declaration.