Verilog · Chapter 4.6 · Lexical Conventions
Identifier Declaration in Verilog
Every wire, register, module, port, parameter and instance in Verilog has a name you chose, and those names follow a small set of rules. This lesson covers what makes a name legal, why Verilog treats capitalisation as meaningful, what the escaped form with a backslash is for and where you will actually meet it, and how dotted hierarchical names are built from ordinary identifiers. It finishes with the naming conventions experienced RTL engineers use — the active-low suffix, the registered-and-next pair, the instance prefix — which are not language rules at all but do more for readability than any of them.
Foundation15 min readVerilogIdentifiersNamingSyntax
Chapter 4 · Page 4.6 · Lexical Conventions
1. Every Name in Verilog Is an Identifier
Look at a line of RTL and separate what the language owns from what you chose:
module mux2 (input wire sel, input wire a, input wire b, output wire y);Two kinds of word are on that line:
- Keywords — the language owns them.
module,input,wire,output. They mean the same thing in every Verilog file ever written. - Identifiers — names you invented.
mux2,sel,a,b,y. They mean whatever this design makes them mean.
Verilog attaches no meaning to the name itself. rst_n is a reset because of what the code does with it, not because of its spelling. That is why this page has two halves: the rules the language actually enforces, and the conventions that carry meaning to the next human.
2. What Makes a Simple Identifier Legal
The everyday form is the simple identifier. Four rules cover it:
| Rule | Allowed | Not allowed |
|---|---|---|
| First character | a letter or _ | a digit, or $ |
| Later characters | letters, digits, _, $ | anything else — - . / + space |
| Case | meaningful — see §4 | — |
| Collisions | must not be a Verilog keyword | wire, reg, module, … |
reg data_q; // fine
reg [3:0] count_4b; // digits after the first character
wire rst_n; // fine
parameter WIDTH = 8; // fine
reg _internal; // a leading underscore is allowed// reg 8th_bit; // starts with a digit
// reg data-q; // '-' is not a legal identifier character
// reg $myname; // '$' cannot start a name — see §7
// reg wire; // 'wire' is a keyword$ is legal inside a name — clk$gated parses — but almost nobody writes it, because readers expect $ to mean a system task. Treat it as allowed-but-avoided.
3. Why the First Character Matters
The first character is what separates a name from a number. Identifiers begin with a letter or an underscore; numeric literals begin with a digit. That is the entire reason for the rule.
So 8th_bit is simply not a legal identifier — the language has no way to read it as a name. It is enough to know that; you do not need a theory about what the tool does with the text instead.
4. Verilog Is Case-Sensitive
reg rst;
reg Rst;
reg RST;Those are three different identifiers. Capitalisation is part of the name, not decoration.
This catches people coming from VHDL, which is case-insensitive — there, rst and Rst are the same signal, and RTL ported across can carry the wrong assumption with it.
The practical protection is the one from Chapter 3: put `default_nettype none at the top of every design file. A mistyped Data_Ready then becomes an error you see immediately, rather than a silently invented one-bit wire that nothing drives.
Pick one convention per project — lowercase with underscores for signals is the common one — and stay inside it.
5. How Long Can a Name Be?
Longer than you will ever want. The standard requires tools to support identifiers of at least 1024 characters, and most allow more.
So length is never the constraint that matters. Readability is: a name long enough to need scrolling costs the reader more than it explains. Descriptive and short beats exhaustive.
6. Names You Cannot Use
A name that matches a Verilog keyword cannot be a simple identifier — the language already knows what that word means.
// reg wire; // 'wire' is a keyword
// reg time; // so is 'time'
// reg output; // and 'output'The words that catch people out are the ones that are also ordinary engineering vocabulary: time, output, input, signed, force, and, or, not. The fix is always the same — say what you actually mean:
reg [31:0] time_q; // not 'time'
reg [7:0] input_data; // not 'input'
reg and_result; // not 'and'The full keyword list, how it grew across the standard's revisions, and the porting traps around it are the very next lesson — Keyword Usage, Chapter 4.7. You do not need to memorise it; descriptive names like data_valid and count_q were never going to collide.
7. The $ Prefix
A name cannot begin with $, because that prefix is reserved for system tasks and functions:
$display("..."); // a system task
$time // a system function
$finish // a system taskKeeping $ reserved at the start is what makes the two namespaces unambiguous: if a token starts with $, it is the simulator's, not yours. What those tasks do is System Tasks & Functions, Chapter 8.
8. Escaped Identifiers
Occasionally a name has to contain characters the simple form does not allow. Verilog's answer is the escaped identifier: start with a backslash, and end at the next whitespace.
wire \data[7] = some_signal; // the name is data[7]
wire \net.7 = x; // the name is net.7
wire \1st_bit = sig; // the name is 1st_bitEverything between the backslash and the terminating whitespace is part of the name — brackets, dots, a leading digit, characters that would otherwise be operators. Three points to hold:
- The backslash and the terminating space are not part of the name. They are delimiters.
- The terminating whitespace is required. Without it the tool keeps reading, and the next token gets swallowed into the name.
- A name that needs escaping needs it everywhere. Declare
\rst-nand every reference must be written\rst-ntoo, because there is no simple-form spelling of that name.
You will rarely write one by hand. Where you will see them is tool output — a post-synthesis netlist that has split a vector into individual bits needs a legal name for each one, and \data[7] is how it gets one. Recognising the form when you open such a file is the whole skill here.
One thing not to do: the escaped form will technically let you name something \reg or \time . It parses, and every reader after you will stop and wonder why. If a keyword collides with the word you want, rename as in §6.
9. Hierarchical Names
A dotted path names something inside an instance:
initial begin
$display("r0 = %h", tb.dut.regfile.r0);
endEach segment between the dots — tb, dut, regfile, r0 — is an ordinary identifier following the rules above. That is the lexical point, and it is the only one this chapter needs.
Beyond that: hierarchical references are a simulation and debug tool. Synthesis tools generally do not accept them, so keep them in testbench code. Module hierarchy itself is covered in Design & Testbench Creation, Chapter 9.
10. Naming Conventions That Make RTL Readable
None of this is enforced by the language. All of it is what experienced RTL reads like, and adopting it will make your code legible to anyone who has worked on a chip.
| Pattern | Used for | Example |
|---|---|---|
snake_case | signals, ports, modules | addr_valid, axi_master |
ALL_CAPS | parameters and localparam | DATA_WIDTH, FIFO_DEPTH |
_n suffix | active-low signals | rst_n, cs_n |
_q suffix | a registered value — a flip-flop output | data_q, count_q |
_d suffix | the value heading into that flip-flop | data_d, count_d |
u_ prefix | an instance name | u_fifo, u_alu |
tb_ prefix | testbench code | tb_top |
The _d / _q pair is the one worth internalising first, because it names the central fact of sequential RTL: _d is what the flip-flop will take at the next clock edge, _q is what it is holding now. Seeing both in a module tells you where the state is before you read a line of logic.
Here is a small module where the names do the explaining:
module pipe_register #(
parameter DATA_WIDTH = 32 // ALL_CAPS — a parameter
) (
input wire clk,
input wire rst_n, // _n — active low
input wire [DATA_WIDTH-1:0] data_d, // _d — heading into the flop
output reg [DATA_WIDTH-1:0] data_q // _q — held by the flop
);
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
data_q <= {DATA_WIDTH{1'b0}};
else
data_q <= data_d;
end
endmoduleRead the port list alone and you already know: there is a clock, an active-low reset, one value going into a register and one coming out. That is what naming discipline buys — and it costs nothing.
pipe_register #(.DATA_WIDTH(32)) u_pipe (
.clk (clk),
.rst_n (rst_n),
.data_d (payload_d),
.data_q (payload_q)
);Whichever set you adopt matters less than applying it consistently. Mixed conventions inside one project cost more than any single choice among them.
11. Common Mistakes
A case mismatch. data_ready and Data_Ready are different names. With `default_nettype none this is an error you see; without it, it can pass quietly.
Forgetting the space after an escaped identifier. \rst_n with no trailing space does not end — the tool keeps reading, and whatever follows becomes part of the name. Always write the space.
Using the escaped form to reuse a keyword. \reg is a legal name spelled reg. It parses; it also guarantees every future reader stops to work out what you meant.
Starting a name with $. $mysig is not a legal identifier — that prefix belongs to system tasks.
Hierarchical references in synthesisable RTL. They belong in testbench code. Synthesis tools generally reject them.
12. Exercises
Work each one out before reading the answers.
Exercise 1 — Legal or not?
data_q
8th_bit
_internal
$myname
data-q
wireWhich are legal simple identifiers, and why do the others fail?
Exercise 2 — Count the names
reg rst;
reg Rst;
reg RST;How many distinct identifiers is this?
Exercise 3 — Read an escaped identifier
wire \data[7] = sig;What is the name being declared? What are the backslash and the space doing?
Exercise 4 — Why the $ rule?
Why can a Verilog identifier contain $ in the middle but never begin with one?
Exercise 5 — Read the names
module counter (
input wire clk,
input wire rst_n,
input wire en,
output reg [3:0] count_q
);Without reading any logic, what do these names tell you about the module?
Answers
Exercise 1.
| Name | Legal? | Why |
|---|---|---|
data_q | ✅ | starts with a letter; letters, underscore, letter |
8th_bit | ❌ | starts with a digit |
_internal | ✅ | a leading underscore is allowed |
$myname | ❌ | $ cannot start a name — reserved for system tasks |
data-q | ❌ | - is not a legal identifier character |
wire | ❌ | it is a Verilog keyword |
Exercise 2. Three. Verilog is case-sensitive, so rst, Rst and RST are three unrelated signals that merely look similar. This is exactly the shape of the bug in §4.
Exercise 3. The name is data[7] — square brackets included, as literal characters in the name rather than a bit-select. The backslash opens the escaped form and the space closes it; neither is part of the name. You would meet this in a post-synthesis netlist where a vector has been split into individual bits.
Exercise 4. Because a leading $ is how the language marks the system-task and system-function namespace — $display, $time, $finish. Reserving it at the start keeps that namespace unambiguous: a token beginning with $ is the simulator's. In the middle of a name there is no such ambiguity, so it is permitted — though convention avoids it.
Exercise 5. Quite a lot, before reading a single statement:
clk— the module is clocked, so it holds state.rst_n— the reset is active low, so the reset condition is!rst_n.en— there is an enable, so the counter does not advance every cycle.count_q— the_qsays this is a registered output, the value a flip-flop is currently holding, four bits wide.
None of that is enforced by Verilog. It is carried entirely by the names — which is the argument for the conventions in §10.
13. Summary
- An identifier is a name you chose. Verilog attaches no meaning to the spelling.
- Legal shape: start with a letter or
_; continue with letters, digits,_or$; do not use a keyword; do not start with$. - Case is part of the name.
rst,RstandRSTare three identifiers. - Length is never the problem — tools support at least 1024 characters. Readability is the real limit.
- The escaped form — a backslash, then the name, then a space — exists for names the simple form cannot spell. You will mostly read them, not write them.
- A hierarchical name is just identifiers joined by dots, and belongs in testbench code.
- Conventions carry the meaning the language does not.
_nfor active low,_dand_qfor the two sides of a flip-flop,u_for an instance.
Next, Keyword Usage covers the other half of the naming story — the words the language has already claimed.
Related Tutorials
- Lexical Conventions — Chapter 4 overview; the parent layer.
- String Handling — Chapter 4.5; the previous sub-topic.
- Keyword Usage — Chapter 4.7; the full keyword list.
- Number Representation — Chapter 4.4; the literal-syntax companion.
- System Tasks & Functions — Chapter 8; the
$-prefixed namespace. - Design & Testbench Creation — Chapter 9; module hierarchy and where hierarchical names belong.
- RTL Designing — Chapter 3; where these naming conventions earn their keep.
Standards & specifications
- Governing standard
- IEEE Std 1364 (Verilog)(opens IEEE in a new tab)
Defines the Verilog language and its simulation semantics, including the event scheduling model. Synthesis support is defined by tools, not by this standard.
This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.
Where this fits
Part of the Verilog HDL curriculum.
