DEV Community

Cover image for Verilog Overview: HDL Abstraction Levels
Semiwave Technologies
Semiwave Technologies

Posted on • Edited on

Verilog Overview: HDL Abstraction Levels

Verilog is a Hardware Description Language (HDL) used to model digital systems at multiple levels of abstraction. The name Verilog combines "verification" and "logic", reflecting its origins as a tool for simulating and verifying digital designs before fabrication.

Why Verilog Coding Styles Matter

Verilog’s flexibility lets you describe hardware at different abstraction levels, from low-level gates to high-level algorithms. Each coding style offers a unique way to model your design, impacting readability, synthesis, and verification. Here’s a quick overview before we dive into the details:

  • Structural: Describes hardware by connecting components (like a schematic).
  • Gate-Level: Models logic using primitive gates (AND, OR, etc.).
  • Dataflow: Uses continuous assignments to describe signal flow.
  • Behavioral: High-level, algorithmic description of functionality.

1. Structural Coding Style

The structural style is like drawing a schematic: you define and connect modules explicitly, specifying the hierarchy and interconnections. It’s low-level and closely mirrors the physical hardware.

Example: 2-to-1 MUX (Structural)

Submodule: AND gate equivalent

module and_gate (
    input wire a, b,
    output wire y
);
    assign y = a & b;
endmodule
Enter fullscreen mode Exit fullscreen mode

Submodule: OR gate equivalent

module or_gate (
    input wire a, b,
    output wire y
);
    assign y = a | b;
endmodule
Enter fullscreen mode Exit fullscreen mode

Submodule: NOT gate equivalent

module not_gate (
    input wire a,
    output wire y
);
    assign y = ~a;
endmodule
Enter fullscreen mode Exit fullscreen mode

Top-level 2-to-1 MUX

module mux_2to1_structural (
    input wire a, b, sel,
    output wire y
);
    wire sel_n, a_and_sel, b_and_sel_n;

    not_gate u1 (.a(sel), .y(sel_n));               // Invert sel
    and_gate u2 (.a(a), .b(sel), .y(a_and_sel));    // a * sel
    and_gate u3 (.a(b), .b(sel_n), .y(b_and_sel_n)); // b * ~sel
    or_gate  u4 (.a(a_and_sel), .b(b_and_sel_n), .y(y)); // Combine

endmodule
Enter fullscreen mode Exit fullscreen mode

Key Features

  • Hierarchy: Uses instantiated modules (and_gate, or_gate, etc.).
  • Explicit Connections: Signals are wired using .port(signal) syntax.
  • Use Case: Ideal for low-level designs or when you need to map directly to specific hardware components.

Pros:

  • Precise control over the design hierarchy.
  • Closely matches physical implementation.

Cons:

  • Verbose and time-consuming for complex designs.
  • Hard to modify or scale.

2. Gate-Level Coding Style

The gate-level style is a subset of structural, using Verilog’s built-in gate primitives (e.g., and, or, not). It’s often used for netlist-level descriptions post-synthesis or for low-level optimization.

Example: 2-to-1 MUX (Gate-Level)

module mux_2to1_gatelevel (
    input wire a, b, sel,
    output wire y
);
    wire sel_n, a_and_sel, b_and_sel_n;

    not (sel_n, sel);                   // Invert sel
    and (a_and_sel, a, sel);            // a * sel
    and (b_and_sel_n, b, sel_n);        // b * ~sel
    or  (y, a_and_sel, b_and_sel_n);    // Combine

endmodule
Enter fullscreen mode Exit fullscreen mode

Key Features

  • Primitives: Uses Verilog’s built-in gates (and, or, not, etc.).
  • Netlist-Like: Mimics the output of synthesis tools.
  • Use Case: Post-synthesis netlists or low-level gate modeling.

Pros:

  • Direct mapping to standard cell libraries.
  • Useful for gate-level simulation or timing analysis.

Cons:

  • Even more verbose than structural.
  • Not practical for high-level design.

3. Data Flow Coding Style

Example: 2-to-1 MUX (Dataflow)

module mux_2to1_dataflow (
    input wire a, b, sel,
    output wire y
);
    assign y = sel ? a : b;  // Conditional operator for MUX
endmodule
Enter fullscreen mode Exit fullscreen mode

Key Features

  • Continuous Assignments: Uses assign for combinational logic.
  • Concise: Expresses logic equations directly.
  • Use Case: Ideal for combinational logic like adders, MUXes, or decoders.

Pros:

  • Short and readable.
  • Naturally synthesizable for combinational logic.

Cons:

  • Limited to combinational logic (no sequential behavior).
  • Can get messy for complex expressions.

Tip: Use dataflow for simple combinational blocks or when you want to express logic as equations. Avoid overcomplicating assign statements.

4. Behavioral Coding Style

The behavioral style is the most abstract, using always blocks to describe functionality algorithmically. It’s like writing software but still synthesizable if done right.

Example: 2-to-1 MUX (Behavioral)

module mux_2to1_behavioral (
    input wire a, b, sel,
    output reg y
);
    always @(*) begin
        if (sel)
            y = a;
        else
            y = b;
    end
endmodule
Enter fullscreen mode Exit fullscreen mode

Key Features

  • Always Blocks: Uses always @(*) for combinational or always @(posedge clk) for sequential logic.
  • Algorithmic: Focuses on what the hardware does, not how it’s built.
  • Use Case: High-level designs, state machines, or complex sequential logic.

Pros:

  • Easy to write and modify.
  • Great for rapid prototyping or complex logic.

Cons:

  • Risk of unsynthesizable code if not careful (e.g., using delays or unsynthesizable constructs).
  • May lead to inefficient synthesis if overly abstract.

Comparing the Styles: 2-to-1 MUX Summary

Style Lines of Code Abstraction Use Case Synthesizable?
Structural 20+ Low Hierarchical designs, IPs Yes
Gate-Level 10-15 Very Low Netlists, gate simulation Yes
Dataflow 5-7 Medium Combinational logic Yes
Behavioral 7-10 High Complex logic, state machines Yes (if proper)

When to Use Each Style

  • Structural: When integrating modules or modeling specific hardware (e.g., connecting IP blocks).
  • Gate-Level: For post-synthesis netlists or low-level gate optimization.
  • Dataflow: For simple combinational logic (e.g., arithmetic, MUXes, decoders).
  • Behavioral: For complex sequential logic, state machines, or quick prototyping.

Hot sauce if you're wrong - web dev trivia for staff engineers

Hot sauce if you're wrong · web dev trivia for staff engineers (Chris vs Jeremy, Leet Heat S1.E4)

  • Shipping Fast: Test your knowledge of deployment strategies and techniques
  • Authentication: Prove you know your OAuth from your JWT
  • CSS: Demonstrate your styling expertise under pressure
  • Acronyms: Decode the alphabet soup of web development
  • Accessibility: Show your commitment to building for everyone

Contestants must answer rapid-fire questions across the full stack of modern web development. Get it right, earn points. Get it wrong? The spice level goes up!

Watch Video 🌶️🔥

Top comments (0)

Dev Diairies image

User Feedback & The Pivot That Saved The Project

🔥 Check out Episode 3 of Dev Diairies, following a successful Hackathon project turned startup.

Watch full video 🎥