Getting Started With Verilog

Published: (February 4, 2026 at 02:26 AM EST)
5 min read
Source: Dev.to

Source: Dev.to

Cover image for Getting Started With Verilog

Silicon Monks

This post focuses on two things

  • Core Verilog syntax you must understand
  • The three main modeling styles used in real designs

If you are coming from a software background, think of Verilog as a way to describe hardware behavior over time, not a program that runs line‑by‑line.

What is Verilog?

Verilog is used to model digital systems such as

  • Combinational logic
  • Sequential logic
  • Finite state machines
  • Complete SoCs and ASIC designs

Verilog code can be

  • Simulated to verify functionality
  • Synthesized to generate real hardware

Basic Verilog Program Structure

Every Verilog design is built using modules.

module example_module (
    input  wire a,
    input  wire b,
    output wire y
);
    assign y = a & b;
endmodule

Key points

  • module and endmodule define a hardware block.
  • Inputs and outputs describe the interface.
  • Internal logic describes how outputs depend on inputs.

Common Data Types

Wire

Used for continuous connections.

wire sum;
assign sum = a ^ b;

Reg

Used to store values inside procedural blocks.

reg q;

Despite the name, reg does not always mean a flip‑flop. It simply means the signal is assigned inside an always block.

Operators You’ll Use Often

- Arithmetic   : +  -  *  /
- Logical     : &&
- Bitwise     : &
- Comparison  : ==  !=  
- Assignment  : =  (blocking)   <=  (non‑blocking)

Verilog Modeling Styles

Verilog supports three main modeling styles. Choosing the right one depends on what you are designing and how abstract you want the description to be.

1. Behavioral Modeling

Focuses on what the circuit does, not how it is built.

Example: 2:1 multiplexer

module mux2_behavioral (
    input  wire a,
    input  wire b,
    input  wire sel,
    output reg  y
);
    always @(*) begin
        if (sel)
            y = b;
        else
            y = a;
    end
endmodule

Characteristics

  • Uses always blocks.
  • Easy to read and write.
  • Ideal for control logic and FSMs.
  • Synthesizable when written carefully.

2. Dataflow Modeling

Describes logic using continuous assignments and expressions.

Example: Full adder

module full_adder_dataflow (
    input  wire a,
    input  wire b,
    input  wire cin,
    output wire sum,
    output wire cout
);
    assign sum  = a ^ b ^ cin;
    assign cout = (a & b) | (b & cin) | (a & cin);
endmodule

Characteristics

  • Uses assign statements.
  • Very close to Boolean equations.
  • Best for combinational logic.
  • Simple and concise.

3. Structural Modeling

Connects lower‑level modules together, similar to a schematic.

Example: Full adder using two half adders

module half_adder (
    input  wire a,
    input  wire b,
    output wire sum,
    output wire carry
);
    assign sum   = a ^ b;
    assign carry = a & b;
endmodule
module full_adder_structural (
    input  wire a,
    input  wire b,
    input  wire cin,
    output wire sum,
    output wire cout
);
    wire s1, c1, c2;

    half_adder ha1 (a,   b,   s1, c1);
    half_adder ha2 (s1,  cin, sum, c2);

    assign cout = c1 | c2;
endmodule

Characteristics

  • Hierarchical design.
  • Mirrors real hardware connections.
  • Common in large designs.
  • Improves reusability and clarity.

4. Gate‑level Modeling

Uses Verilog primitives directly.

Example: Half adder

module half_adder (
    input  wire a,
    input  wire b,
    output wire sum,
    output wire carry
);
    xor (sum,   a, b);
    and (carry, a, b);
endmodule

Characteristics

  • Pure gate‑level description.
  • Very cumbersome for large designs.

Blocking vs Non‑Blocking Assignments

This is critical in Verilog.

Blocking (=)

Used for combinational logic.

always @(*) begin
    x = a & b;
    y = x | c;
end

Non‑blocking (<=)

Used for sequential logic.

always @(posedge clk) begin
    q <= d;
end

Rule of thumb

  • Use = in combinational logic.
  • Use <= in clocked (sequential) logic.

Modeling Sequential Logic

Example: D flip‑flop with active‑low reset

module dff (
    input  wire clk,
    input  wire rst,
    input  wire d,
    output reg  q
);
    always @(posedge clk or negedge rst) begin
        if (!rst)
            q <= 1'b0;
        else
            q <= d;
    end
endmodule

All code snippets are written in Verilog‑2001 syntax and are synthesizable unless otherwise noted.

Verilog Flip‑Flop Example

module dff (
    input  wire clk,
    input  wire rst,
    input  wire d,
    output reg  q
);
    always @(posedge clk or negedge rst) begin
        if (!rst)
            q <= 1'b0;
        else
            q <= d;
    end
endmodule

This style is synthesizable and maps directly to hardware flip‑flops.

When to Use Each Modeling Style

  • Behavioral modeling – Best for control logic and finite‑state machines, where the focus is on what the circuit does rather than how it is built. Easier to read and maintain for complex decision‑making logic.
  • Dataflow modeling – Ideal for combinational logic. It closely matches Boolean equations and is commonly used for arithmetic circuits, multiplexers, and simple logic blocks where outputs are directly derived from inputs.
  • Structural modeling – Used for large, hierarchical designs. It connects smaller modules together to form bigger systems and mirrors the actual hardware structure, making it suitable for reusable and scalable designs.
  • Gate‑level modeling – Mainly for demonstration and learning purposes. It is rarely used in modern, large‑scale designs because it relies on Verilog gate primitives, which makes the code verbose and difficult to manage. Consequently, it is not suitable for building reusable or scalable designs.

In real projects, you will often mix three styles (Behavioral, Dataflow, Structural) in the same design.

Final Thoughts

Verilog is powerful because it lets you model hardware at different abstraction levels. Understanding the syntax is important, but mastering the various modeling styles is what makes your designs clean, scalable, and synthesizable.

Back to Blog

Related posts

Read more »

Switch Case

What is a switch statement? The switch keyword in Java is used to execute one block of code among many alternatives. The expression is evaluated once and compa...

MARKDOWN - kirish

Markdown — bu matnni oddiy belgilar yordamida formatlash tili. U vizual muharrirlardan farqli o'laroq, matnni yozish davomida shakllantirish imkonini beradi. Sa...