⚡ Verilog-2001 (.v) Standard • Comprehensive RTL & Simulation Reference

Verilog HDL Complete Cheat Sheet & Reference

104 exhaustive hardware engineering topics covering pure Verilog-2001 (.v): 4-state logic, vectors, operators, continuous assignments, blocking vs nonblocking (<=), golden RTL templates, Moore & Mealy FSMs, memory models, simulation tasks, and synthesis trap avoidance.

Filter: Showing 104 of 104 topics

No matching Verilog topics found

Try searching for a different keyword like always, reg, wire, case, posedge, or FSM.

MODULE 1 11 TOPICS

📐 Language Fundamentals & Types

Verilog file structure, 4-state logic, nets vs variables, vector indexing, numbers, signed types, and basic declarations.

§1

Basic Verilog file structure

Synthesizable RTL #
verilog
`timescale 1ns/1ps

module my_module (
    input  wire       clk,
    input  wire       rst,
    input  wire [7:0] a,
    output wire [7:0] y
);

    // declarations
    // logic
    // assign statements
    // always blocks

endmodule

A module can also have:

verilog
module my_module (
    input  wire clk,
    output wire y
);

endmodule

Or older Verilog-1995 style:

verilog
module my_module (clk, y);

    input clk;
    output y;

endmodule

§2

Comments

Syntax / Directive #
verilog
// Single-line comment

/*
   Multi-line
   comment
*/

§3

Numbers

Synthesizable RTL #

General syntax:

verilog
<size>'<base><value>

Bases:

  • b = binary
  • o = octal
  • d = decimal
  • h = hexadecimal

Examples:

verilog
8'b10101010
8'b00001111

8'hA5
16'h1234

8'd255
10'd512

6'o77

Underscores improve readability:

verilog
32'b1010_1100_0011_0101
16'hAB_CD

Unsized numbers:

verilog
10
255
'hFF
'b1010

Useful special values:

verilog
1'b0    // 0
1'b1    // 1
1'bx    // unknown
1'bz    // high impedance

§4

Four-state logic

Synthesizable RTL #

Verilog values have four states:

verilog
0 = logic low
1 = logic high
x = unknown
z = high impedance

Example:

verilog
reg a;

initial begin
    a = 1'bx;
    a = 1'bz;
end

§5

Nets vs variables

Synthesizable RTL #

This is very important.

wire

A wire represents a physical connection/net.

verilog
wire a;
wire [7:0] data;

Usually driven by:

verilog
assign data = a + b;

or by a module output:

verilog
some_module u1 (
    .out(data)
);

reg

A reg is a procedural variable.

verilog
reg a;
reg [7:0] data;

It can be assigned inside:

verilog
always @(...)
begin
    data = something;
end

or:

verilog
initial begin
    data = 8'h00;
end

Important: reg does NOT necessarily mean a hardware register.

A reg can represent combinational logic too.

verilog
reg y;

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

This synthesizes to an AND gate.


§6

Vectors

Synthesizable RTL #

Single bit:

verilog
wire a;
reg b;

8-bit vector:

verilog
wire [7:0] a;
reg  [7:0] b;

16-bit:

verilog
reg [15:0] data;

Range direction matters:

verilog
[7:0]    // 8 bits
[0:7]    // also 8 bits, reversed indexing

Access a bit:

verilog
data[3]

Access a part:

verilog
data[7:4]
data[3:0]

§7

Concatenation

Synthesizable RTL #

Join signals:

verilog
{a, b}

Example:

verilog
wire [7:0] y;

assign y = {a[3:0], b[3:0]};

Replicate:

verilog
{8{1'b0}}

creates:

verilog
00000000

Another example:

verilog
{4{a}}

If:

verilog
a = 1

then:

verilog
1111

§37

Signed values

Synthesizable RTL #

Classic Verilog supports:

verilog
reg signed [7:0] a;
wire signed [15:0] b;

Example:

verilog
reg signed [7:0] a;
reg signed [7:0] b;
reg signed [8:0] result;

always @(*) begin
    result = a + b;
end

Be careful with mixing signed and unsigned operands.


§60

integer

Syntax / Directive #
verilog
integer i;
integer count;

Often used for loop counters:

verilog
integer i;

initial begin
    for (i = 0; i < 10; i = i + 1)
        ...
end

§61

time

Simulation Only #
verilog
time start_time;

Example:

verilog
start_time = $time;

§62

real

Simulation Only #
verilog
real voltage;

Mostly simulation/testbench related.

Not normally synthesizable.


MODULE 2 7 TOPICS

⚡ Operators & Expressions

Arithmetic, relational, equality, bitwise, reduction, shift, ternary conditional, and standard precedence rules.

§8

Operators

Synthesizable RTL #

Arithmetic

verilog
+       // addition
-       // subtraction
*       // multiplication
/       // division
%       // modulo

Example:

verilog
assign y = a + b;

Relational

verilog
<
>
<=
>=

Example:

verilog
if (a < b)

Equality

Logical equality:

verilog
==
!=

Case equality:

verilog
===
!==

Difference:

verilog
a == b

can produce x when unknowns are involved.

verilog
a === b

compares 0, 1, x, and z exactly.

This is especially useful in testbenches.


§9

Logical operators

Synthesizable RTL #
verilog
&&      // logical AND
||      // logical OR
!       // logical NOT

Example:

verilog
if (enable && valid)

§10

Bitwise operators

Synthesizable RTL #
verilog
&       // AND
|       // OR
^       // XOR
~       // NOT
^~      // XNOR
~^      // XNOR

Example:

verilog
assign y = a & b;

For vectors:

verilog
a = 4'b1010;
b = 4'b1100;

a & b = 4'b1000

§11

Reduction operators

Synthesizable RTL #

Reduction turns an entire vector into one bit.

verilog
&a

AND all bits.

verilog
|a

OR all bits.

verilog
^a

XOR all bits.

Also:

verilog
~&a
~|a
~^a
^~a

Example:

verilog
wire parity;

assign parity = ^data;

§12

Shift operators

Synthesizable RTL #
verilog
<<      // left shift
>>      // right shift

Example:

verilog
assign y = a << 2;
assign y = a >> 1;

For signed arithmetic, right-shift behavior can depend on signedness.

For basic unsigned Verilog:

verilog
reg [7:0] a;

a >> 2

§13

Conditional operator

Synthesizable RTL #
verilog
condition ? true_value : false_value

Example:

verilog
assign y = sel ? a : b;

Equivalent conceptually to:

verilog
if (sel)
    y = a;
else
    y = b;

MUX:

verilog
assign y = sel ? d1 : d0;

§14

Operator precedence

Synthesizable RTL #

A useful simplified order:

verilog
()
[]
.
unary operators
*
/
%
+
-
<<
>>
<
<=
>
>=
==
!=
===
!==
&
^
|
&&
||
?:

When in doubt:

verilog
assign y = (a & b) | c;

Use parentheses.


MODULE 3 16 TOPICS

⚙️ RTL Modeling & Procedural Logic

Continuous assignment (assign), always blocks, blocking (=) vs nonblocking (<=) race conditions, if/else, case, loops, and named blocks.

§15

assign

Synthesizable RTL #

Continuous assignment:

verilog
wire y;

assign y = a & b;

MUX:

verilog
assign y = sel ? a : b;

Decoder:

verilog
assign y = enable ? data : 8'b0;

Multiple continuous assignments are possible:

verilog
assign a = b;
assign c = d & e;
assign f = x | y;

§16

always

Synthesizable RTL #

Procedural block:

verilog
always @(...)
begin
    ...
end

The sensitivity list tells Verilog when the block executes.


§17

Combinational always

Synthesizable RTL #

Preferred Verilog style:

verilog
always @(*) begin
    y = a & b;
end

Equivalent older explicit style:

verilog
always @(a or b) begin
    y = a & b;
end

For combinational logic:

verilog
always @(*) begin
    if (sel)
        y = a;
    else
        y = b;
end

Always assign every output in every possible path to avoid accidentally creating a latch.

Bad:

verilog
always @(*) begin
    if (enable)
        y = a;
end

If enable == 0, y retains its old value → latch.

Better:

verilog
always @(*) begin
    y = 0;

    if (enable)
        y = a;
end

§18

Sequential logic

Synthesizable RTL #

Positive-edge flip-flop:

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

Reset:

verilog
always @(posedge clk or posedge rst) begin
    if (rst)
        q <= 1'b0;
    else
        q <= d;
end

Negative-edge reset:

verilog
always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
        q <= 1'b0;
    else
        q <= d;
end

§19

Blocking vs nonblocking

Synthesizable RTL #

This is one of the most important Verilog concepts.

Blocking =

verilog
a = b;

Executes immediately in procedural order.

Usually use for combinational logic:

verilog
always @(*) begin
    y = a;
    z = y & b;
end

Nonblocking <=

verilog
a <= b;

Schedules the update.

Usually use for clocked/sequential logic:

verilog
always @(posedge clk) begin
    q1 <= d;
    q2 <= q1;
end

This correctly models two flip-flops.

Rule of thumb

verilog
Combinational → =
Sequential    → <=

Testbenches commonly use both depending on what is being modeled.


§20

Why <= matters

Synthesizable RTL #

Consider:

verilog
always @(posedge clk) begin
    q1 <= d;
    q2 <= q1;
end

At the clock edge:

verilog
q1 gets old d
q2 gets old q1

So:

verilog
d → FF1 → FF2

Using blocking:

verilog
always @(posedge clk) begin
    q1 = d;
    q2 = q1;
end

can make q2 immediately see the newly assigned q1 in simulation, which does not model the intended pair of flip-flops correctly.


§21

if

Synthesizable RTL #
verilog
if (condition) begin
    ...
end

Example:

verilog
always @(*) begin
    if (sel)
        y = a;
    else
        y = b;
end

Multiple conditions:

verilog
if (a)
    y = 1;
else if (b)
    y = 2;
else
    y = 3;

§22

case

Synthesizable RTL #
verilog
case (sel)
    2'b00: y = a;
    2'b01: y = b;
    2'b10: y = c;
    2'b11: y = d;
endcase

Always consider a default:

verilog
case (sel)
    2'b00: y = 0;
    2'b01: y = 1;
    2'b10: y = 2;
    2'b11: y = 3;
    default: y = 0;
endcase

§23

casez

Synthesizable RTL #

Allows z/? wildcard matching.

verilog
casez (opcode)
    4'b1???: y = 1;
    4'b01??: y = 2;
    default: y = 0;
endcase

§24

casex

Synthesizable RTL #

Treats x and z as don't-care.

verilog
casex (opcode)
    4'b1xxx: y = 1;
    default: y = 0;
endcase

Generally avoid casex in RTL, because it can hide unknown/X bugs in simulation.


§25

for loop

Synthesizable RTL #
verilog
integer i;

always @(*) begin
    for (i = 0; i < 8; i = i + 1) begin
        ...
    end
end

Example:

verilog
integer i;

always @(*) begin
    y = 0;

    for (i = 0; i < 8; i = i + 1)
        y = y | a[i];
end

A synthesis tool can unroll fixed-bound loops.


§26

while

Simulation Only #
verilog
while (condition) begin
    ...
end

More common in testbenches than synthesizable RTL.


§27

repeat

Simulation Only #
verilog
repeat (10) begin
    ...
end

Very useful in testbenches:

verilog
repeat (10)
    #10 clk = ~clk;

§28

forever

Simulation Only #
verilog
forever begin
    #5 clk = ~clk;
end

Classic testbench clock:

verilog
initial begin
    clk = 0;

    forever #5 clk = ~clk;
end

§58

Named blocks

Synthesizable RTL #
verilog
begin : my_block
    ...
end

Can be useful with generated structures and hierarchical references.


§59

disable

Simulation Only #

Used to terminate a named block/task.

verilog
begin : loop_block

    while (1) begin
        ...
    end

end

Then:

verilog
disable loop_block;

Mostly seen in older Verilog testbenches.


MODULE 4 18 TOPICS

🔬 Hardware Design Patterns & Idioms

Production RTL templates: MUXes, decoders, priority encoders, D flip-flops, registers, counters, shift registers, RAMs, and Moore/Mealy FSMs.

§68

Tri-state

Synthesizable RTL #
verilog
assign bus = enable ? data : 8'bz;

When disabled:

verilog
ZZZZZZZZ

Useful for modeling shared buses / I/O.


§69

Tri-state input/output

Synthesizable RTL #
verilog
module io (
    input wire enable,
    input wire data_out,
    inout wire pin,
    output wire data_in
);

assign pin = enable ? data_out : 1'bz;
assign data_in = pin;

endmodule

§70

Multiple drivers

Synthesizable RTL #

A wire can have multiple drivers:

verilog
assign bus = en1 ? data1 : 8'bz;
assign bus = en2 ? data2 : 8'bz;

But you must ensure only one driver actively drives the bus at a time.


§71

Combinational examples

Synthesizable RTL #

AND gate

verilog
module and_gate (
    input wire a,
    input wire b,
    output wire y
);

assign y = a & b;

endmodule

OR gate

verilog
assign y = a | b;

XOR

verilog
assign y = a ^ b;

NOT

verilog
assign y = ~a;

§72

MUX

Synthesizable RTL #
verilog
module mux2 (
    input wire a,
    input wire b,
    input wire sel,
    output wire y
);

assign y = sel ? b : a;

endmodule

Using always:

verilog
module mux2 (
    input wire a,
    input wire b,
    input wire sel,
    output reg y
);

always @(*) begin
    if (sel)
        y = b;
    else
        y = a;
end

endmodule

§73

Decoder

Synthesizable RTL #

2-to-4 decoder:

verilog
always @(*) begin
    case (sel)
        2'b00: y = 4'b0001;
        2'b01: y = 4'b0010;
        2'b10: y = 4'b0100;
        2'b11: y = 4'b1000;
        default: y = 4'b0000;
    endcase
end

§74

Encoder

Synthesizable RTL #

Example 4-to-2:

verilog
always @(*) begin
    case (in)
        4'b0001: out = 2'b00;
        4'b0010: out = 2'b01;
        4'b0100: out = 2'b10;
        4'b1000: out = 2'b11;
        default: out = 2'bxx;
    endcase
end

§75

D flip-flop

Synthesizable RTL #
verilog
module dff (
    input wire clk,
    input wire d,
    output reg q
);

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

endmodule

§76

D flip-flop with reset

Synthesizable RTL #
verilog
always @(posedge clk or posedge rst) begin
    if (rst)
        q <= 1'b0;
    else
        q <= d;
end

§77

Register

Synthesizable RTL #
verilog
reg [7:0] q;

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

§78

Enable

Synthesizable RTL #
verilog
always @(posedge clk) begin
    if (enable)
        q <= d;
end

If enable == 0, the flip-flop keeps its value.


§79

Counter

Synthesizable RTL #

8-bit counter:

verilog
reg [7:0] count;

always @(posedge clk or posedge rst) begin
    if (rst)
        count <= 8'd0;
    else
        count <= count + 1'b1;
end

§80

Up/down counter

Synthesizable RTL #
verilog
always @(posedge clk or posedge rst) begin
    if (rst)
        count <= 0;
    else if (up)
        count <= count + 1'b1;
    else
        count <= count - 1'b1;
end

§81

Shift register

Synthesizable RTL #
verilog
always @(posedge clk or posedge rst) begin
    if (rst)
        q <= 8'b0;
    else
        q <= {q[6:0], serial_in};
end

§82

Parallel load + shift

Synthesizable RTL #
verilog
always @(posedge clk or posedge rst) begin
    if (rst)
        q <= 8'b0;
    else if (load)
        q <= parallel_data;
    else
        q <= {q[6:0], serial_in};
end

§83

RAM

Synthesizable RTL #

Simple synchronous write:

verilog
module ram (
    input wire clk,
    input wire we,
    input wire [7:0] addr,
    input wire [7:0] din,
    output reg [7:0] dout
);

reg [7:0] mem [0:255];

always @(posedge clk) begin
    if (we)
        mem[addr] <= din;

    dout <= mem[addr];
end

endmodule

Exact RAM inference depends on the synthesis tool/FPGA.


§84

FSM — finite state machine

Synthesizable RTL #

Classic Verilog FSM style:

verilog
reg [1:0] state;

localparam IDLE = 2'b00;
localparam RUN  = 2'b01;
localparam DONE = 2'b10;

State register:

verilog
always @(posedge clk or posedge rst) begin
    if (rst)
        state <= IDLE;
    else
        state <= next_state;
end

Next-state logic:

verilog
always @(*) begin

    next_state = state;

    case (state)

        IDLE:
            if (start)
                next_state = RUN;

        RUN:
            if (finish)
                next_state = DONE;

        DONE:
            next_state = IDLE;

        default:
            next_state = IDLE;

    endcase

end

Outputs:

verilog
always @(*) begin

    done = 1'b0;

    case (state)
        DONE: done = 1'b1;
        default: done = 1'b0;
    endcase

end

§85

Mealy vs Moore

Synthesizable RTL #

Moore

Output depends on state:

verilog
always @(*) begin
    done = 0;

    case (state)
        DONE: done = 1;
    endcase
end

Mealy

Output depends on state + inputs:

verilog
always @(*) begin
    done = 0;

    if (state == RUN && finish)
        done = 1;
end

MODULE 5 12 TOPICS

🧱 Modularity, Parameters & Hierarchy

Module instantiation, named vs positional ports, parameter & localparam overrides, bus width parametrization, and generate blocks.

§32

Named port connections

Synthesizable RTL #

Preferred:

verilog
my_module dut (
    .clk(clk),
    .rst(rst),
    .data(data),
    .valid(valid),
    .result(result)
);

Format:

verilog
.port_in_module(signal_in_testbench)

You can also connect different names:

verilog
my_module dut (
    .clk(my_clk),
    .data(my_data)
);

§33

Positional port connections

Synthesizable RTL #
verilog
my_module dut (
    clk,
    rst,
    a,
    b,
    y
);

Works, but named connections are safer because changing port order can break things.


§34

Module parameters

Synthesizable RTL #
verilog
module counter #(
    parameter WIDTH = 8
)(
    input wire clk,
    input wire rst,
    output reg [WIDTH-1:0] count
);

Then:

verilog
counter #(
    .WIDTH(16)
) u_counter (
    .clk(clk),
    .rst(rst),
    .count(count)
);

Parameters are heavily used for configurable RTL.


§35

localparam

Synthesizable RTL #
verilog
localparam IDLE = 2'b00;
localparam RUN  = 2'b01;
localparam DONE = 2'b10;

Unlike parameter, localparam isn't intended to be overridden during module instantiation.


§36

parameter for widths

Synthesizable RTL #
verilog
module adder #(
    parameter WIDTH = 8
)(
    input  wire [WIDTH-1:0] a,
    input  wire [WIDTH-1:0] b,
    output wire [WIDTH-1:0] y
);

assign y = a + b;

endmodule

§40

Generate blocks

Synthesizable RTL #

Generate repetitive hardware.

verilog
genvar i;

generate
    for (i = 0; i < 8; i = i + 1) begin : gen
        assign y[i] = a[i] & b[i];
    end
endgenerate

Often used for parameterized structures.


§86

Hierarchy

Synthesizable RTL #

A module can instantiate another module:

verilog
module top;

wire y;

submodule u1 (
    .a(a),
    .b(b),
    .y(y)
);

endmodule

Hierarchy:

verilog
top
 ├── u1
 ├── u2
 └── u3

§87

wire connection between modules

Synthesizable RTL #
verilog
wire [7:0] internal_data;

producer p (
    .data(internal_data)
);

consumer c (
    .data(internal_data)
);

§88

Ports: common combinations

Synthesizable RTL #

Input:

verilog
input wire a;

Output driven by assign:

verilog
output wire y;

Output driven inside always:

verilog
output reg y;

Bidirectional:

verilog
inout wire bus;

§89

Local declarations

Synthesizable RTL #

Inside module:

verilog
wire [7:0] sum;
reg [7:0] temp;
integer i;

Inside procedural block, Verilog supports declarations, though for maximum compatibility many designs declare things at module scope:

verilog
integer i;

always @(*) begin
    ...
end

§90

Hierarchical references

Synthesizable RTL #

Simulation can access internal signals:

verilog
$display("state=%b", dut.state);

Testbench can sometimes force internal signals:

verilog
force dut.signal = 1'b1;

Then:

verilog
release dut.signal;

Useful for debugging, but generally not normal RTL methodology.


§99

genvar

Synthesizable RTL #

For generate loops:

verilog
genvar i;

generate
    for (i = 0; i < 8; i = i + 1) begin : g
        ...
    end
endgenerate

genvar is a generate-time loop variable, not a runtime variable.


MODULE 6 25 TOPICS

🧪 Simulation, Testbenches & Verification

Testbench skeletons, initial blocks, delays, clock/reset generation, $display, $monitor, tasks, functions, checkers, and VCD wave dumping.

§29

initial

Simulation Only #

initial executes once at simulation startup.

Very common in testbenches:

verilog
initial begin
    rst = 1;
    #20;
    rst = 0;
end

Typically not synthesizable for normal ASIC RTL.

Some FPGA tools allow certain initialization constructs, but don't assume that in generic Verilog RTL.


§30

Delays

Simulation Only #
verilog
#10

Example:

verilog
#10 a = 1;

Meaning: wait 10 simulation time units.

With:

verilog
`timescale 1ns/1ps

then:

verilog
#10

means 10 ns.

Delays are generally testbench/simulation constructs, not synthesizable RTL.


§31

Testbench skeleton

Simulation Only #
verilog
`timescale 1ns/1ps

module tb;

    reg clk;
    reg rst;
    reg a;
    reg b;

    wire y;

    my_module dut (
        .clk(clk),
        .rst(rst),
        .a(a),
        .b(b),
        .y(y)
    );

    initial begin
        clk = 0;
        rst = 1;
        a = 0;
        b = 0;

        #10;
        rst = 0;

        #10;
        a = 1;
        b = 1;

        #10;
        a = 0;

        #20;
        $finish;
    end

    always #5 clk = ~clk;

endmodule

dut conventionally means device/design under test.


§41

Functions

Synthesizable RTL #

A Verilog function returns one value.

verilog
function [7:0] add8;
    input [7:0] a;
    input [7:0] b;

    begin
        add8 = a + b;
    end
endfunction

Use:

verilog
assign y = add8(a, b);

Functions execute without simulation time delays.


§42

Tasks

Simulation Only #

Tasks can have multiple outputs and can contain timing controls.

verilog
task send_data;
    input [7:0] data;

    begin
        #10;
        $display("Sending %h", data);
    end
endtask

Call:

verilog
initial begin
    send_data(8'hAA);
end

Tasks are particularly useful in testbenches.


§43

System tasks

Simulation Only #

Common simulation system tasks:

verilog
$display
$monitor
$write
$finish
$stop
$time
$random
$readmemh
$readmemb

§44

$display

Simulation Only #

Print once when executed:

verilog
$display("Hello");

With values:

verilog
$display("a=%b b=%b y=%b", a, b, y);

Common formatting:

verilog
%b   binary
%d   decimal
%h   hexadecimal
%o   octal
%s   string
%t   simulation time

Example:

verilog
$display("time=%0t a=%h y=%h", $time, a, y);

§45

$monitor

Simulation Only #

Automatically prints whenever one of its arguments changes.

verilog
initial begin
    $monitor("time=%0t a=%b b=%b y=%b",
             $time, a, b, y);
end

§46

$write

Simulation Only #

Like $display, but doesn't automatically add a newline.

verilog
$write("a=%b ", a);
$write("b=%b\n", b);

§47

$finish

Simulation Only #

Ends simulation:

verilog
$finish;

Very common at the end of a testbench.


§48

$stop

Simulation Only #

Pauses/stops simulation depending on simulator behavior.

verilog
$stop;

Use $finish when you want the testbench to terminate cleanly.


§49

$time

Simulation Only #

Current simulation time:

verilog
$display("Time = %0t", $time);

§50

Random values

Simulation Only #

Classic Verilog:

verilog
integer r;

initial begin
    r = $random;
end

Or:

verilog
a = $random;

Useful for simple randomized testbenches.


§51

Assertions — classic Verilog style

Simulation Only #

SystemVerilog has assert, but classic Verilog does not.

Use:

verilog
if (y !== expected)
    $display("ERROR!");

Example:

verilog
if (y !== 8'hAA)
    $display("FAIL: y=%h", y);
else
    $display("PASS");

For testbenches, !== is often useful because it detects X/Z mismatches too.


§52

Testbench checker

Simulation Only #
verilog
task check;
    input [7:0] expected;

    begin
        if (y !== expected)
            $display("FAIL: expected=%h got=%h",
                     expected, y);
        else
            $display("PASS: y=%h", y);
    end
endtask

Then:

verilog
initial begin
    a = 8'h10;
    b = 8'h20;

    #1;
    check(8'h30);

    $finish;
end

§53

Clock generation

Simulation Only #

Classic:

verilog
initial begin
    clk = 0;
    forever #5 clk = ~clk;
end

With 10 ns period:

verilog
0 → 5 ns → 10 ns → 15 ns → ...

§54

Reset generation

Simulation Only #

Active-high:

verilog
initial begin
    rst = 1;
    #20;
    rst = 0;
end

Active-low:

verilog
initial begin
    rst_n = 0;
    #20;
    rst_n = 1;
end

§55

Testbench timing

Simulation Only #

Example:

verilog
initial begin
    rst = 1;
    a = 0;
    b = 0;

    #20;
    rst = 0;

    #10;
    a = 5;
    b = 10;

    #10;
    a = 20;

    #10;
    $finish;
end

§56

Event controls

Simulation Only #

Wait for a clock:

verilog
@(posedge clk);

Wait for negative edge:

verilog
@(negedge clk);

Wait for either:

verilog
@(posedge clk or negedge rst);

Wait for signal change:

verilog
@(a);

§57

wait

Simulation Only #
verilog
wait (ready == 1'b1);

Example:

verilog
initial begin
    wait (done);
    $display("Operation complete");
end

§91

force / release

Simulation Only #
verilog
force signal = 1'b0;

Override normal drivers.

verilog
release signal;

Release the override.

Primarily simulation/debugging.


§92

$dumpfile / $dumpvars

Simulation Only #

Common with Icarus Verilog/GTKWave workflows:

verilog
initial begin
    $dumpfile("wave.vcd");
    $dumpvars(0, tb);
end

Then run simulation and inspect wave.vcd.


§93

A practical testbench

Simulation Only #

Suppose DUT:

verilog
module adder (
    input wire [7:0] a,
    input wire [7:0] b,
    output wire [7:0] y
);

assign y = a + b;

endmodule

Testbench:

verilog
`timescale 1ns/1ps

module tb;

reg [7:0] a;
reg [7:0] b;
wire [7:0] y;

adder dut (
    .a(a),
    .b(b),
    .y(y)
);

initial begin

    $dumpfile("wave.vcd");
    $dumpvars(0, tb);

    a = 8'd10;
    b = 8'd20;

    #10;

    if (y !== 8'd30)
        $display("FAIL: expected 30, got %d", y);
    else
        $display("PASS");

    a = 8'd100;
    b = 8'd50;

    #10;

    if (y !== 8'd150)
        $display("FAIL");
    else
        $display("PASS");

    $finish;

end

endmodule

§94

Clocked testbench

Simulation Only #
verilog
initial begin
    clk = 0;
    forever #5 clk = ~clk;
end

Stimulus:

verilog
initial begin

    rst = 1;
    d = 0;

    #12;
    rst = 0;

    @(posedge clk);
    d = 1;

    @(posedge clk);
    d = 0;

    #20;

    $finish;

end

§95

Testbench task

Simulation Only #

A nice reusable pattern:

verilog
task apply_test;
    input [7:0] a_in;
    input [7:0] b_in;
    input [7:0] expected;

    begin

        a = a_in;
        b = b_in;

        #1;

        if (y !== expected)
            $display(
                "FAIL: a=%h b=%h expected=%h got=%h",
                a_in, b_in, expected, y
            );
        else
            $display(
                "PASS: a=%h b=%h y=%h",
                a_in, b_in, y
            );

    end
endtask

Then:

verilog
initial begin

    apply_test(8'd1, 8'd2, 8'd3);
    apply_test(8'd10, 8'd20, 8'd30);
    apply_test(8'd100, 8'd50, 8'd150);

    $finish;

end

MODULE 7 10 TOPICS

💾 Memory, File I/O & Directives

Memory arrays, $readmemh/$readmemb hex loading, compiler directives (`define, `include, `timescale), and file I/O operations.

§38

Memories / arrays

Synthesizable RTL #

A memory:

verilog
reg [7:0] memory [0:255];

Means:

verilog
256 entries
8 bits per entry

Read:

verilog
data = memory[address];

Write:

verilog
always @(posedge clk) begin
    memory[address] <= write_data;
end

§39

Memory initialization

Synthesizable RTL #

Testbench:

verilog
initial begin
    memory[0] = 8'h12;
    memory[1] = 8'h34;
    memory[2] = 8'h56;
end

Or load from file:

verilog
$readmemh("memory.hex", memory);

Binary:

verilog
$readmemb("memory.bin", memory);

§63

Compiler directives

Syntax / Directive #

Begin with:

verilog
`

Common ones:

verilog
`timescale
`define
`include
`ifdef
`ifndef
`else
`endif
`default_nettype

§64

define

Syntax / Directive #

Macro:

verilog
`define WIDTH 8

Use:

verilog
reg [`WIDTH-1:0] data;

Parameterized macro:

verilog
`define MAX(a,b) ((a) > (b) ? (a) : (b))

Be careful with macros; they are textual substitution.


§65

include

Syntax / Directive #
verilog
`include "definitions.v"

Copies the contents of the included file into the source during preprocessing.


§66

Conditional compilation

Syntax / Directive #
verilog
`ifdef DEBUG

    $display("Debug enabled");

`else

    // normal

`endif

Also:

verilog
`ifndef SOME_DEFINE
`define SOME_DEFINE
...
`endif

§67

timescale

Syntax / Directive #
verilog
`timescale 1ns/1ps

Format:

verilog
`timescale <unit>/<precision>

Example:

verilog
`timescale 1ns/1ps

means:

  • simulation unit = 1 ns
  • timing precision = 1 ps

Then:

verilog
#5

means 5 ns.


§96

File-based test vectors

Simulation Only #

Read hexadecimal values:

verilog
reg [7:0] memory [0:99];

initial begin
    $readmemh("vectors.hex", memory);
end

Then:

verilog
integer i;

initial begin

    for (i = 0; i < 100; i = i + 1) begin
        ...
    end

end

§97

File I/O

Simulation Only #

Open:

verilog
integer fd;

initial begin
    fd = $fopen("results.txt", "w");
end

Write:

verilog
$fdisplay(fd, "a=%h y=%h", a, y);

Close:

verilog
$fclose(fd);

Common:

verilog
$fopen
$fclose
$fdisplay
$fwrite

§98

Common Verilog system functions/tasks

Simulation Only #
verilog
$display
$write
$monitor

$finish
$stop

$time
$realtime

$random

$readmemh
$readmemb

$fopen
$fclose
$fwrite
$fdisplay

$dumpfile
$dumpvars

MODULE 8 5 TOPICS

🏆 Synthesis Traps, Golden RTL & Mental Models

Accidental latch avoidance, wrong sensitivity lists, combinational vs sequential cheat table, Verilog vs SystemVerilog pitfalls, and golden templates.

§100

Common synthesis traps

Design Rule #

Accidental latch

Bad:

verilog
always @(*) begin
    if (enable)
        y = a;
end

Good:

verilog
always @(*) begin
    y = 0;

    if (enable)
        y = a;
end

Wrong sensitivity list

Bad:

verilog
always @(a) begin
    y = a & b;
end

Changes in b won't trigger simulation.

Good:

verilog
always @(*) begin
    y = a & b;
end

Blocking in sequential logic

Prefer:

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

Multiple procedural drivers

Avoid having multiple always blocks drive the same reg.

Bad:

verilog
always @(posedge clk)
    q <= a;

always @(posedge clk)
    q <= b;

§101

Combinational vs sequential cheat table

Design Rule #
HardwareTypical Verilog
AND gateassign y = a & b;
MUXassign y = sel ? a : b;
Combinational blockalways @(*)
Flip-flopalways @(posedge clk)
Async reset FFalways @(posedge clk or posedge rst)
Registerreg \+ clocked always
Counterclocked always
FSM stateclocked always
FSM next statealways @(*)
RAMmemory array + always
Testbench stimulusinitial
Testbench delay#delay
Testbench clockforever #...
Testbench checkingif (...) $display(...)

§102

Verilog vs SystemVerilog — don't accidentally use .sv

Design Rule #

Since you specifically want Verilog .v, avoid these SystemVerilog constructs:

verilog
logic

Use:

verilog
reg
wire

Avoid:

verilog
always_comb
always_ff
always_latch

Use:

verilog
always @(*)
always @(posedge clk)

Avoid:

verilog
typedef
struct
enum
interface
class
package

Avoid SystemVerilog assertions:

verilog
assert (...)

Use ordinary Verilog checks:

verilog
if (actual !== expected)
    $display("FAIL");

Avoid:

verilog
always_comb begin

Use:

verilog
always @(*) begin

Avoid:

verilog
$display("%0d", ...); // Actually this is fine in Verilog

$display, $finish, $random, etc. are available in traditional Verilog simulation.


§103

The "memorize these" section

Design Rule #

If you're learning Verilog for exams/labs/interviews, these are the constructs I'd memorize first:

verilog
module
endmodule

input
output
inout

wire
reg
integer
parameter
localparam

assign

always @(*)
always @(posedge clk)
always @(negedge clk)

if
else
case
default

for
while
repeat
forever

begin
end

function
task

initial

#10
@(posedge clk)

posedge
negedge

=
<=
==
!=
===
!==
&
|
^
~
&&
||
!
<<
>>
?:

{a,b}
{8{a}}

$display
$monitor
$finish
$stop
$time
$random
$readmemh
$readmemb

§104

The golden RTL templates

Synthesizable RTL #

Combinational

verilog
always @(*) begin
    // defaults
    y = 0;

    if (condition)
        y = a;
    else
        y = b;
end

Flip-flop

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

Flip-flop + async reset

verilog
always @(posedge clk or posedge rst) begin
    if (rst)
        q <= 0;
    else
        q <= d;
end

Counter

verilog
always @(posedge clk or posedge rst) begin
    if (rst)
        count <= 0;
    else
        count <= count + 1'b1;
end

FSM

verilog
always @(posedge clk or posedge rst) begin
    if (rst)
        state <= IDLE;
    else
        state <= next_state;
end

always @(*) begin
    next_state = state;

    case (state)
        IDLE: begin
            if (start)
                next_state = RUN;
        end

        RUN: begin
            if (done)
                next_state = IDLE;
        end

        default:
            next_state = IDLE;
    endcase
end

Testbench

verilog
module tb;

reg clk;
reg rst;

wire y;

dut uut (
    .clk(clk),
    .rst(rst),
    .y(y)
);

initial begin
    clk = 0;
    forever #5 clk = ~clk;
end

initial begin

    rst = 1;

    #20;
    rst = 0;

    #100;

    $finish;

end

endmodule

One-page mental model

Think of Verilog .v as five major things:

verilog
                 VERILOG
                    │
        ┌───────────┼───────────┐
        │           │           │
     STRUCTURE   HARDWARE    SIMULATION
        │           │           │
     module      assign       initial
     ports       always       #delay
     wire        reg          $display
     parameter   case         @(...)
                 if           $finish
                 clock
                 FSM
                 RAM

And the single most important distinction:

verilog
COMBINATIONAL
    ↓
always @(*)
    ↓
blocking =
    ↓
assign every output

SEQUENTIAL
    ↓
always @(posedge clk ...)
    ↓
nonblocking <=
    ↓
usually represents flip-flops

If you're using Icarus Verilog + GTKWave, this cheat sheet is also enough to cover the bulk of the Verilog you'll encounter in typical digital-logic/FPGA coursework.