Verilog Basic Syntax

Understanding Verilog syntax is the first step to writing hardware descriptions. This tutorial covers comments, identifiers, numbers, and other lexical conventions.

Comments

Verilog supports two types of comments, similar to C/C++:

Comments in Verilog
// This is a single-line comment
/* This is a
   multi-line comment
   spanning several lines */
module example;
    wire a;  // Inline comment after code
endmodule

Best Practice: Use comments liberally to explain your design intent, especially for complex logic and state machines.

Identifiers

Identifiers are names for modules, wires, registers, and other objects. Rules:

  • Must start with a letter or underscore (_)
  • Can contain letters, digits, underscores, and dollar signs ($)
  • Case-sensitive (Data and data are different)
  • Cannot be a Verilog keyword
Valid and Invalid Identifiers
// Valid identifiers
wire data_bus;
wire _internal_signal;
wire Data123;
wire $special;      // $ is allowed but avoid in RTL
// Invalid identifiers
// wire 123data;    // Cannot start with number
// wire if;         // 'if' is a keyword
// wire my-signal;  // Hyphen not allowed

Naming Conventions

Use descriptive names like read_enable instead of re. Common styles: snake_case for signals, UPPERCASE for parameters.

Number Formats

Verilog has a specific format for representing numbers: [size]'[base][value]

Number Representations
// Format: [size]'[base][value]
// Bases: b=binary, o=octal, d=decimal, h=hexadecimal
8'b10101010    // 8-bit binary: 170 in decimal
8'hAA          // 8-bit hex: same as above (170)
8'd170         // 8-bit decimal: same value
8'o252         // 8-bit octal: same value
// Unsized numbers (default 32-bit)
'hFF           // 32-bit hex value 255
100            // 32-bit decimal value 100
// Negative numbers (2's complement)
-8'd5          // 8-bit value: 11111011 (251 unsigned)
// Underscores for readability (ignored)
32'hDEAD_BEEF  // Same as 32'hDEADBEEF
16'b1010_1010_1010_1010
// X and Z values
4'b10x1        // x = unknown
4'b10z1        // z = high impedance (tri-state)

Important: Always specify the bit width for synthesis. Unsized numbers default to 32 bits and can cause width mismatch warnings.

Verilog Keywords

Verilog has reserved keywords that cannot be used as identifiers. Common ones:

Category Keywords
Module module, endmodule, input, output, inout
Data Types wire, reg, integer, real, time
Control if, else, case, for, while
Procedural always, initial, begin, end, assign
Gates and, or, not, nand, nor, xor

Whitespace and Formatting

Verilog is free-form – whitespace (spaces, tabs, newlines) is mostly ignored. Use consistent indentation for readability:

Good Formatting Example
module counter (
    input  wire        clk,
    input  wire        rst_n,
    output reg  [7:0]  count
);
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n)
            count <= 8'd0;
        else
            count <= count + 1'b1;
    end
endmodule

Best Practices:

  • Use 4-space indentation (or consistent tabs)
  • Align port declarations for readability
  • One statement per line
  • Add blank lines between logical sections

Naming Things (Identifiers)

Think of identifiers as labels you put on wires, switches, and boxes in your design. While the computer doesn't care if you name a wire a or main_data_input_bus, your future self definitely will!

In professional designs, we follow specific naming patterns to make the code look clean and "standard." This is called a Naming Convention.

Simple Naming Tips:

  • _n or _b suffix: Use this for "active-low" signals (signals that perform an action when they are 0, like a reset rst_n).
  • _clk suffix: Always label your clock signals clearly.
  • CamelCase vs snake_case: Most Verilog engineers prefer snake_case for signals because it looks more like hardware hardware descriptions.

Number Languages: Talking to Hardware

Computers lived in a world of 1s and 0s, but Humans like Decimal (0-9) or Hexadecimal (0-F). Verilog lets you speak "Human" while telling the hardware exactly how many "bits" (wires) to use.

When you write 8'hFF, you are telling the computer: "Take 8 wires and set them all to high (1)."

The Mystery of X and Z

In the real world, a wire isn't always just 1 or 0. Sometimes things go wrong:

  • X (Unknown): This usually means something is broken. Maybe two different things are trying to drive the same wire at once, or you forgot to give a wire a starting value.
  • Z (High Impedance): This is like disconnecting a wire completely. It's used when you want a wire to "float" so another part of the chip can take control of it (common in data buses).

Compiler Shortcuts (Directives)

Sometimes you want to give the computer "pre-instructions" before it even starts reading your hardware code. We use a backtick (`) for these.

Useful Shortcuts
// 1. The Shortcut (`define)
`define DATA_WIDTH 32
wire [`DATA_WIDTH-1:0] my_bus; // This becomes 31:0 automatically!
// 2. The File Includer (`include)
`include "my_constants.v" // Pulls in code from another file
// 3. The Time Scale (`timescale)
`timescale 1ns / 1ps // Tells the simulator how to count time

Using `define is great because if you ever need to change your design from 32 bits to 64 bits, you only have to change one number at the top of your file instead of searching through thousands of lines of code.

Common Interview Questions

  1. What does 4'bx mean?

    It represents a 4-bit value where all bits are unknown (X). In simulation, X indicates an uninitialized or conflicting state.

  2. Is Verilog case-sensitive?

    Yes, Verilog is case-sensitive. Signal and signal are different identifiers.

  3. What happens if you don't specify the size in a number?

    The number defaults to at least 32 bits. This can cause synthesis warnings for width mismatches.