// TWO-STATE (0, 1) - Faster simulation
bit single_bit; // 1-bit
bit [7:0] byte_val; // 8-bit vector
byte signed_byte; // 8-bit signed (-128 to 127)
shortint short_val; // 16-bit signed
int int_val; // 32-bit signed
longint long_val; // 64-bit signed
// FOUR-STATE (0, 1, X, Z) - Hardware modeling
logic logic_bit; // Can be X or Z
logic [7:0] logic_byte;
reg [31:0] reg_val; // Same as logic
wire [7:0] wire_val; // For connections
// REAL NUMBERS
real real_val; // 64-bit floating point
shortreal short_real; // 32-bit floating point
// STRING
string text = "Hello"; // Dynamic string
// TIME
time sim_time; // 64-bit time value
realtime real_time; // Real time value
User-Defined Types
// Typedef
typedef bit[7:0] byte_t;
typedef logic[31:0] word_t;
byte_t my_byte = 8'hAA;
word_t my_word = 32'hDEAD_BEEF;
// Enum
typedef enum logic[1:0] {
IDLE = 2'b00,
ACTIVE = 2'b01,
WAIT = 2'b10,
DONE = 2'b11
} state_t;
state_t current_state, next_state;
// Enum with auto increment
typedef enum {RED, GREEN, BLUE} color_t; // RED=0, GREEN=1, BLUE=2
// Struct (packed)
typedef struct packed {
bit [7:0] opcode;
bit [3:0] dest;
bit [3:0] src;
} instruction_t;
instruction_t inst;
inst.opcode = 8'h42;
// Struct (unpacked)
typedef struct {
int addr;
int data;
bit write;
} transaction_t;
transaction_t txn;
txn.addr = 100;
// Union (packed)
typedef union packed {
bit [31:0] word;
bit [15:0] half[2];
bit [7:0] byte[4];
} data_union_t;
data_union_t data;
data.word = 32'hDEAD_BEEF;
// Can also access as: data.byte[0] = 0xEF
2. Operators
Arithmetic
a + b // Addition
a - b // Subtraction
a * b // Multiplication
a / b // Division
a % b // Modulus
a ** b // Power (a^b)
a++ // Post-increment
++a // Pre-increment
a-- // Decrement
a += b // a = a + b
a -= b // a = a - b
a *= b // a = a * b
Bitwise
a & b // Bitwise AND
a | b // Bitwise OR
a ^ b // Bitwise XOR
~a // Bitwise NOT
a ~& b // NAND
a ~| b // NOR
a ~^ b // XNOR
a << b // Logical left shift
a >> b // Logical right shift
a <<< b // Arithmetic left shift
a >>> b // Arithmetic right shift (sign extend)
Reduction
&data // AND all bits
|data // OR all bits
^data // XOR all bits (parity)
~&data // NAND all bits
~|data // NOR all bits
~^data // XNOR all bits
Comparison
// Numeric
a == b // Equal
a != b // Not equal
a < b // Less than
a > b // Greater than
a <= b // Less than or equal
a >= b // Greater than or equal
// Case equality (checks X and Z)
a === b // Equal (4-state)
a !== b // Not equal (4-state)
// Wildcard equality (? = don't care)
a ==? b // Wildcard equal
a !=? b // Wildcard not equal
// Examples
if (data === 8'bXXXX_0000) // Matches X in upper nibble
if (opcode ==? 4'b10??) // Matches 1000, 1001, 1010, 1011
Logical
a && b // Logical AND
a || b // Logical OR
!a // Logical NOT
a ? b : c // Conditional (ternary)
// Example
result = (sel) ? data_a : data_b;
mux = (sel == 2'b00) ? in0 :
(sel == 2'b01) ? in1 :
(sel == 2'b10) ? in2 : in3;
Special
{a, b} // Concatenation: {4'h5, 4'hA} = 8'h5A
{n{a}} // Replication: {8{1'b1}} = 8'hFF
a inside {[m:n], val} // Range/set check
// if (addr inside {[0:127], 256})
$bits(var) // Width of variable
$countones(data) // Number of 1s
$onehot(val) // Exactly one bit is 1
$onehot0(val) // At most one bit is 1
$clog2(n) // Ceiling log2
// Dynamic array
int dyn_arr[];
// Allocate
dyn_arr = new[10]; // 10 elements
dyn_arr[5] = 100;
// Resize (copies old data)
dyn_arr = new[20](dyn_arr);
// Delete
dyn_arr.delete();
// Size
int size = dyn_arr.size();
Associative Arrays
// Associative array (sparse)
int assoc[string]; // String index
int mem[bit[31:0]]; // Address index
// Access
assoc["apple"] = 10;
assoc["orange"] = 20;
mem[32'h1000] = 42;
// Methods
if (assoc.exists("apple")) // Check existence
$display("Found");
assoc.delete("apple"); // Delete entry
int count = assoc.num(); // Number of entries
// Iterate
string key;
if (assoc.first(key)) // Get first key
do begin
$display("%s => %0d", key, assoc[key]);
end while (assoc.next(key)); // Get next key
Queues
// Queue (dynamic, indexed)
int q[$]; // Unbounded queue
int bounded_q[$:15]; // Max 16 elements (0-15)
// Operations
q.push_back(10); // Add to end
q.push_front(5); // Add to front
int val = q.pop_back(); // Remove from end
int val2 = q.pop_front(); // Remove from front
q.insert(2, 99); // Insert at index 2
q.delete(3); // Delete index 3
q.delete(); // Delete all
int size = q.size(); // Get size
// Initialize
int q[$] = {1, 2, 3, 4, 5};
Array Methods
int arr[5] = '{10, 20, 30, 40, 50};
// Reduction
int sum = arr.sum(); // 150
int prod = arr.product(); // 12000000
int max_val = arr.max(); // 50
int min_val = arr.min(); // 10
// Manipulation
arr.reverse(); // Reverse order
arr.sort(); // Ascending sort
arr.rsort(); // Descending sort
arr.shuffle(); // Random order
// Locator methods (return queue)
int q[$];
q = arr.find with (item > 25); // {30, 40, 50}
q = arr.find_index with (item > 25); // {2, 3, 4} (indices)
q = arr.find_first with (item > 25); // {30}
q = arr.find_last with (item < 45); // {40}
// Unique
q = arr.unique(); // Remove duplicates
4. Control Structures
Conditional Statements
// If-else
if (condition) begin
// Code
end else if (other_condition) begin
// Code
end else begin
// Code
end
// Single line (no begin-end needed)
if (a > b) result = a;
else result = b;
// Ternary operator
result = (condition) ? true_val : false_val;
// Unique/Priority if
unique if (a) action_a(); // Warns if multiple true
else if (b) action_b();
priority if (a) action_a(); // First true wins
else if (b) action_b();
Case Statements
// Case
case (select)
2'b00: out = in0;
2'b01: out = in1;
2'b10: out = in2;
2'b11: out = in3;
default: out = 0;
endcase
// Case inside (range matching)
case (data) inside
[0:63]: $display("Low");
[64:127]: $display("Mid");
[128:255]: $display("High");
endcase
// Casex (X and Z are don't cares)
casex (opcode)
4'b0000: nop();
4'b001X: read(); // Matches 0010, 0011
4'b01XX: write(); // Matches 0100-0111
endcase
// Casez (Z is don't care)
casez (grant)
4'b0001: master0();
4'b001?: master1(); // Matches 0010, 0011
4'b01??: master2(); // Matches 0100-0111
endcase
// Unique case (warns if overlap or not all covered)
unique case (state)
IDLE: next = ACTIVE;
ACTIVE: next = DONE;
DONE: next = IDLE;
endcase
// Priority case (first match wins)
priority case (cmd)
4'b0000: nop();
4'b001?: read(); // Has priority
4'b01??: write();
endcase
Loops
// For loop
for (int i = 0; i < 10; i++) begin
$display("i = %0d", i);
end
// While loop
while (count < 100) begin
count++;
end
// Do-while
do begin
count++;
end while (count < 100);
// Repeat
repeat (10) begin
@(posedge clk);
end
// Foreach (arrays)
int arr[5] = '{1, 2, 3, 4, 5};
foreach (arr[i]) begin
$display("arr[%0d] = %0d", i, arr[i]);
end
// Forever
forever begin
@(posedge clk);
// Process
end
// Loop control
break; // Exit loop
continue; // Next iteration
return; // Exit function/task
5. Procedural Blocks
Always Blocks
// Combinational logic
always_comb begin
sum = a + b;
product = a * b;
end
// Sequential logic (flip-flops)
always_ff @(posedge clk or negedge reset_n) begin
if (!reset_n)
q <= 0;
else
q <= d;
end
// Latch (avoid!)
always_latch begin
if (enable)
q <= d;
end
// Initial (runs once at time 0)
initial begin
clk = 0;
reset_n = 0;
#100ns reset_n = 1;
end
// Final (runs at end of simulation)
final begin
$display("Simulation complete");
$display("Total errors: %0d", error_count);
end
Fork-Join
// fork-join: Wait for ALL threads
fork
#10ns process1();
#20ns process2();
#15ns process3();
join
// Continues at 20ns (when all complete)
// fork-join_any: Wait for FIRST thread
fork
#10ns process1();
#20ns process2();
join_any
// Continues at 10ns (when first completes)
// fork-join_none: Don't wait
fork
#10ns process1();
#20ns process2();
join_none
// Continues immediately
// Disable fork (kill all threads)
fork
forever #10ns $display("Thread 1");
forever #20ns $display("Thread 2");
join_none
#100ns;
disable fork; // Kill all forked processes
// Wait fork (wait for all forked to complete)
wait fork;
6. Modules and Ports
Module Definition
module adder #(
parameter WIDTH = 8
)(
input logic clk,
input logic reset_n,
input logic [WIDTH-1:0] a,
input logic [WIDTH-1:0] b,
output logic [WIDTH-1:0] sum
);
always_ff @(posedge clk or negedge reset_n) begin
if (!reset_n)
sum <= 0;
else
sum <= a + b;
end
endmodule
// Instantiation
adder #(.WIDTH(16)) adder_inst (
.clk(clk),
.reset_n(reset_n),
.a(data_a),
.b(data_b),
.sum(result)
);
// Implicit port connection (.*)
adder #(.WIDTH(16)) adder_inst (.*);
// Connects ports with same names
Port Types
// Input/Output/Inout
input logic [7:0] data_in;
output logic [7:0] data_out;
inout logic [7:0] data_bidir;
// Output types
output logic data; // Can be driven in procedural
output wire data; // Continuous assignment only
// Ref port (pass by reference)
module check(ref logic[7:0] data);
// Can read/write original data (no copy)
endmodule
7. Always Blocks Deep Dive
Always_comb
// Combinational logic (auto-sensitivity)
always_comb begin
y = a & b;
z = c | d;
// Automatically sensitive to a, b, c, d
end
// Can read from arrays
logic [7:0] rom[256];
logic [7:0] addr, data;
always_comb begin
data = rom[addr]; // Legal in always_comb!
end
// Must assign in all branches
always_comb begin
case (sel)
2'b00: out = in0;
2'b01: out = in1;
2'b10: out = in2;
2'b11: out = in3;
// Must cover all cases or use default
endcase
end
Always_ff
// D Flip-Flop
always_ff @(posedge clk) begin
q <= d;
end
// With async reset
always_ff @(posedge clk or negedge reset_n) begin
if (!reset_n)
q <= 0;
else
q <= d;
end
// With sync reset
always_ff @(posedge clk) begin
if (!reset_n)
q <= 0;
else
q <= d;
end
// Multiple clock domains
always_ff @(posedge clk_a) begin
data_a <= input_a;
end
always_ff @(posedge clk_b) begin
data_b <= input_b;
end
Blocking vs Non-Blocking
// Non-blocking (<=) for sequential logic
always_ff @(posedge clk) begin
a <= b;
c <= a; // Uses OLD value of a
end
// Blocking (=) for combinational logic
always_comb begin
temp = a + b;
result = temp * 2; // Uses NEW value of temp
end
// RULE: Use <= in always_ff, = in always_comb
8. Functions and Tasks
Functions
// Function (no time delay, returns value)
function int add(int a, int b);
return a + b;
endfunction
int result = add(5, 3);
// Automatic function (re-entrant)
function automatic int factorial(int n);
if (n <= 1)
return 1;
else
return n * factorial(n-1);
endfunction
// Void function (no return)
function void print_data(int data);
$display("Data: %0d", data);
endfunction
// Default arguments
function int add_with_default(int a, int b = 10);
return a + b;
endfunction
result = add_with_default(5); // 15 (uses default b=10)
result = add_with_default(5, 20); // 25
Tasks
// Task (can have time delay, no return value)
task wait_cycles(int n);
repeat(n) @(posedge clk);
endtask
wait_cycles(10);
// Task with output
task read_memory(input int addr, output int data);
@(posedge clk);
data = mem[addr];
endtask
int read_data;
read_memory(32'h100, read_data);
// Automatic task (re-entrant)
task automatic drive_transaction(transaction_t txn);
@(posedge clk);
bus.addr = txn.addr;
bus.data = txn.data;
endtask
// Ref argument (pass by reference)
task modify_data(ref int data);
data = data * 2; // Modifies original
endtask
9. Classes and OOP
Basic Class
class packet;
// Properties
rand bit [7:0] addr;
rand bit [31:0] data;
rand bit write;
// Constructor
function new(string name = "packet");
$display("Creating %s", name);
endfunction
// Methods
function void display();
$display("addr=%h, data=%h, write=%b", addr, data, write);
endfunction
task send();
#10ns;
$display("Sending packet");
endtask
endclass
// Usage
packet pkt;
pkt = new("my_packet");
pkt.addr = 8'h10;
pkt.display();
Inheritance
// Base class
class base_packet;
rand bit [7:0] addr;
function void display();
$display("Base: addr=%h", addr);
endfunction
endclass
// Derived class
class extended_packet extends base_packet;
rand bit [31:0] data;
// Override method
function void display();
super.display(); // Call parent method
$display("Extended: data=%h", data);
endfunction
// New method
function void process();
$display("Processing...");
endfunction
endclass
// Polymorphism
extended_packet ext = new();
base_packet base = ext; // Upcast
base.display(); // Calls extended version if virtual
Virtual Methods
class base;
virtual function void show();
$display("Base");
endfunction
endclass
class derived extends base;
function void show();
$display("Derived");
endfunction
endclass
// Polymorphism
base b;
derived d = new();
b = d;
b.show(); // Prints "Derived" (dynamic binding)
Static Members
class counter;
static int count = 0; // Shared across all instances
int id; // Unique per instance
function new();
count++;
id = count;
endfunction
static function int get_count();
return count;
endfunction
endclass
counter c1 = new(); // count=1, id=1
counter c2 = new(); // count=2, id=2
$display("Total: %0d", counter::get_count()); // 2
// Simple clock
logic clk = 0;
always #5ns clk = ~clk; // 10ns period, 100MHz
// Clock with duty cycle
logic clk = 0;
always begin
#3ns clk = 1; // High for 3ns
#7ns clk = 0; // Low for 7ns
end
// Reset generation
logic reset_n;
initial begin
reset_n = 0;
#100ns reset_n = 1;
end
// Synchronous reset
logic reset;
initial begin
reset = 1;
repeat(5) @(posedge clk);
reset = 0;
end
14.2 Memory Model
module memory #(
parameter DEPTH = 256,
parameter WIDTH = 32
)(
input logic clk,
input logic wr_en,
input logic rd_en,
input logic [7:0] addr,
input logic [WIDTH-1:0] wr_data,
output logic [WIDTH-1:0] rd_data
);
logic [WIDTH-1:0] mem [DEPTH];
// Write
always_ff @(posedge clk) begin
if (wr_en)
mem[addr] <= wr_data;
end
// Read
always_ff @(posedge clk) begin
if (rd_en)
rd_data <= mem[addr];
end
endmodule
14.3 FSM Pattern
typedef enum logic [1:0] {
IDLE = 2'b00,
ACTIVE = 2'b01,
WAIT = 2'b10,
DONE = 2'b11
} state_t;
state_t state, next_state;
// State register
always_ff @(posedge clk or negedge reset_n) begin
if (!reset_n)
state <= IDLE;
else
state <= next_state;
end
// Next state logic
always_comb begin
next_state = state; // Default: stay in current state
case (state)
IDLE: begin
if (start)
next_state = ACTIVE;
end
ACTIVE: begin
if (done)
next_state = WAIT;
else if (error)
next_state = IDLE;
end
WAIT: begin
if (ready)
next_state = DONE;
end
DONE: begin
next_state = IDLE;
end
endcase
end
// Output logic
always_comb begin
busy = (state != IDLE);
complete = (state == DONE);
end
14.4 Handshake Protocols
// 2-phase handshake (valid-ready)
task send_data(bit[7:0] data);
valid = 1;
data_out = data;
@(posedge clk iff ready); // Wait for ready
@(posedge clk);
valid = 0;
endtask
// 4-phase handshake (req-ack)
task four_phase(bit[7:0] data);
req = 1;
data_out = data;
wait(ack == 1);
req = 0;
wait(ack == 0);
endtask
// Pipelined handshake
always_ff @(posedge clk) begin
if (valid && ready) begin
data_reg <= data_in;
// Transfer occurs
end
end
14.5 FIFO Template
module fifo #(
parameter DEPTH = 16,
parameter WIDTH = 32
)(
input logic clk,
input logic reset_n,
input logic wr_en,
input logic rd_en,
input logic [WIDTH-1:0] wr_data,
output logic [WIDTH-1:0] rd_data,
output logic full,
output logic empty
);
logic [WIDTH-1:0] mem [DEPTH];
logic [$clog2(DEPTH):0] count;
logic [$clog2(DEPTH)-1:0] wr_ptr, rd_ptr;
assign full = (count == DEPTH);
assign empty = (count == 0);
// Write
always_ff @(posedge clk or negedge reset_n) begin
if (!reset_n)
wr_ptr <= 0;
else if (wr_en && !full) begin
mem[wr_ptr] <= wr_data;
wr_ptr <= wr_ptr + 1;
end
end
// Read
always_ff @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
rd_ptr <= 0;
rd_data <= 0;
end else if (rd_en && !empty) begin
rd_data <= mem[rd_ptr];
rd_ptr <= rd_ptr + 1;
end
end
// Count
always_ff @(posedge clk or negedge reset_n) begin
if (!reset_n)
count <= 0;
else begin
case ({wr_en && !full, rd_en && !empty})
2'b10: count <= count + 1;
2'b01: count <= count - 1;
default: count <= count;
endcase
end
end
endmodule
// Display
$display("Format", args); // Print with newline
$write("Format", args); // Print without newline
$monitor("expr=%d", expr); // Print on change
$strobe("val=%d", val); // Print at end of timestep
// Format specifiers
%b // Binary
%d // Decimal
%h // Hex
%o // Octal
%t // Time
%s // String
%0d // No leading spaces
// Simulation control
$finish; // End simulation
$stop; // Pause simulation
$exit; // Exit current process
// Time
$time; // Current simulation time
$realtime; // Real time
#10ns; // Delay 10ns
// File I/O
$fopen("file.txt", "w");
$fclose(fd);
$fdisplay(fd, "data=%h", data);
$readmemh("file.hex", mem);
$writememh("out.hex", mem);
// Random
$urandom(); // Random 32-bit
$urandom_range(min, max); // Range [min:max]
// VCD dump
$dumpfile("waves.vcd");
$dumpvars(0, top);
$dumpon; $dumpoff;
// Assertion control
$assertoff; $asserton;
$assertkill;
Common Idioms
// Wait for condition
wait(done == 1);
@(posedge clk iff ready);
// Edge detection
@(posedge clk); // Wait for rising edge
@(negedge clk); // Wait for falling edge
@(clk); // Wait for any edge
// Delay
#10ns; // Absolute delay
#(2*CLK_PERIOD); // Calculated delay
repeat(5) @(posedge clk); // 5 clock cycles
// Default values
int data = 0;
logic [7:0] addr = 8'h00;
// Array initialization
int arr[5] = '{1, 2, 3, 4, 5}; // Positional
int arr2[5] = '{default: 0}; // All zeros
int arr3[10] = '{0:99, 5:55, default:0}; // Specific + default
// Structure assignment
typedef struct {int a; int b;} pair_t;
pair_t p = '{a: 10, b: 20};
pair_t p2 = '{default: 0};
// Bit manipulation
data[3] = 1'b1; // Set bit 3
data = data | (1 << n); // Set bit n
data = data & ~(1 << n); // Clear bit n
data = data ^ (1 << n); // Toggle bit n
// Swap
{a, b} = {b, a};
// Multiple assign
{high, low} = {data[15:8], data[7:0]};
Complete Examples
Example 1: Simple Counter
module counter #(
parameter WIDTH = 8
)(
input logic clk,
input logic reset_n,
input logic enable,
output logic [WIDTH-1:0] count
);
always_ff @(posedge clk or negedge reset_n) begin
if (!reset_n)
count <= 0;
else if (enable)
count <= count + 1;
end
endmodule
Example 2: Mux
module mux4to1 #(parameter WIDTH = 8)(
input logic [1:0] sel,
input logic [WIDTH-1:0] in0, in1, in2, in3,
output logic [WIDTH-1:0] out
);
always_comb begin
case (sel)
2'b00: out = in0;
2'b01: out = in1;
2'b10: out = in2;
2'b11: out = in3;
endcase
end
endmodule
Example 3: Testbench
module tb;
logic clk = 0;
logic reset_n;
logic [7:0] data_in, data_out;
// Clock generation
always #5ns clk = ~clk;
// DUT instantiation
dut dut_inst(
.clk(clk),
.reset_n(reset_n),
.data_in(data_in),
.data_out(data_out)
);
// Test stimulus
initial begin
reset_n = 0;
data_in = 0;
#100ns reset_n = 1;
repeat(100) begin
@(posedge clk);
data_in = $urandom();
end
#100ns;
$finish;
end
// Monitor
always @(posedge clk) begin
if (reset_n)
$display("Time=%0t: in=%h, out=%h", $time, data_in, data_out);
end
endmodule
Example 4: Class-Based Testbench
class transaction;
rand bit [7:0] addr;
rand bit [31:0] data;
constraint addr_c {
addr inside {[0:127]};
}
function void display();
$display("addr=%h, data=%h", addr, data);
endfunction
endclass
class driver;
virtual dut_if vif;
function new(virtual dut_if v);
vif = v;
endfunction
task drive(transaction txn);
@(posedge vif.clk);
vif.addr <= txn.addr;
vif.data <= txn.data;
endtask
endclass
module tb;
dut_if bus(clk);
driver drv;
initial begin
transaction txn;
drv = new(bus);
repeat(100) begin
txn = new();
assert(txn.randomize());
drv.drive(txn);
end
$finish;
end
endmodule
SystemVerilog in One Page
//=============================================================================
// SYSTEMVERILOG COMPLETE SYNTAX
//=============================================================================
// DATA TYPES
bit [7:0] b; // 2-state
logic [7:0] l; // 4-state
int i; byte by; shortint si; longint li;
real r; string s;
// ARRAYS
int arr[10]; // Static
int dyn[]; // Dynamic: dyn = new[10]
int assoc[string]; // Associative
int q[$]; // Queue
// OPERATORS
// Arithmetic: + - * / % **
// Bitwise: & | ^ ~ << >> <<< >>>
// Reduction: &vec |vec ^vec
// Logical: && || !
// Compare: == != < > <= >= === !== ==?
// Concat: {a,b} Replicate: {n{a}}
// PROCEDURAL
always_comb y = a & b; // Combinational
always_ff @(posedge clk) q <= d; // Sequential
always_latch if(en) q <= d; // Latch
initial begin end // Once at t=0
final begin end // At end
// CONTROL
if (c) {} else if {} else {}
case (x) endcase
for (int i=0; i<n; i++) {}
while (c) {}
foreach (arr[i]) {}
repeat (n) @(posedge clk);
// FUNCTIONS/TASKS
function int add(int a, b);
return a + b;
endfunction
task wait_cycles(int n);
repeat(n) @(posedge clk);
endtask
// CLASSES
class packet;
rand bit[7:0] addr;
constraint c {addr < 128;}
function new(); endfunction
endclass
packet p = new();
assert(p.randomize());
// INTERFACE
interface bus_if(input clk);
logic [7:0] data;
modport master(output data);
modport slave(input data);
endinterface
// COVERAGE
covergroup cg;
coverpoint addr;
cross addr, write;
endgroup
// ASSERTIONS
property p1;
@(posedge clk) req |=> gnt;
endproperty
assert property (p1);
// SYSTEM TASKS
$display, $write, $monitor
$finish, $stop, $time
$urandom, $urandom_range
$readmemh, $writememh
Quick Lookup Tables
Signal Initialization
Pattern
Example
Result
Default all
arr[5] = ‘{default: 0}
All = 0
Positional
arr = ‘{1,2,3}
arr[0]=1, arr[1]=2, arr[2]=3
Named
arr = ‘{0:10, 2:20, default:0}
arr[0]=10, arr[2]=20, rest=0
Replicate
arr = ‘{4{8’hFF}}
First 4 = 0xFF
Process Control
Statement
Meaning
@(posedge clk)
Wait for rising edge
@(negedge clk)
Wait for falling edge
@(clk)
Wait for any edge
@(*)
Combinational sensitivity
#10ns
Wait 10 nanoseconds
wait(condition)
Wait for condition true
->event
Trigger event
@(event)
Wait for event
fork-join
Wait for all threads
fork-join_any
Wait for first thread
fork-join_none
Don’t wait
disable fork
Kill all threads
wait fork
Wait for all forked
Severity Levels
Task
When to Use
Effect
$fatal
Critical error
Terminates simulation
$error
Functional error
Report, continue
$warning
Unexpected condition
Report, continue
$info
Informational
Report, continue
$display
General output
Print message
For Hardware Engineers
Log File Parser
module log_parser;
int fd;
string line;
int errors = 0;
int warnings = 0;
initial begin
fd = $fopen("sim.log", "r");
while (!$feof(fd)) begin
$fgets(line, fd);
if (line.match("ERROR"))
errors++;
if (line.match("WARNING"))
warnings++;
// Extract hex values
if (line.match("Data: 0x([0-9A-Fa-f]+)")) begin
// Process hex data
end
end
$fclose(fd);
$display("Errors: %0d, Warnings: %0d", errors, warnings);
end
endmodule
Stimulus Generation
module stimulus_gen;
logic clk;
logic [7:0] data;
logic valid;
// Random stimulus
initial begin
valid = 0;
repeat(100) begin
@(posedge clk);
data = $urandom_range(0, 255);
valid = $urandom_range(0, 1);
end
end
// Pattern generation
initial begin
// Walking ones
for (int i = 0; i < 8; i++) begin
@(posedge clk);
data = (1 << i);
end
// Walking zeros
for (int i = 0; i < 8; i++) begin
@(posedge clk);
data = ~(1 << i);
end
// All zeros
@(posedge clk); data = 8'h00;
// All ones
@(posedge clk); data = 8'hFF;
// Alternating
@(posedge clk); data = 8'hAA;
@(posedge clk); data = 8'h55;
end
endmodule
## Quick Reference Guide for SystemVerilog
*Your one-stop SystemVerilog reference for rapid development*
---
## 1. Data Types
```systemverilog
// TWO-STATE (0, 1) - Faster
bit b; // 1-bit
bit [7:0] byte_val; // 8-bit
byte sb; // 8-bit signed (-128..127)
shortint si; // 16-bit signed
int i; // 32-bit signed
longint li; // 64-bit signed
// FOUR-STATE (0, 1, X, Z) - Hardware
logic l; // Can be X, Z
logic [7:0] lv;
reg [31:0] r; // Same as logic
wire [7:0] w;
// OTHER
real f; // 64-bit float
string s = "text"; // Dynamic string
time t; // 64-bit time
// USER-DEFINED
typedef bit[7:0] byte_t;
typedef enum logic[1:0] {
IDLE, ACTIVE, WAIT, DONE
} state_t;
typedef struct packed {
bit [7:0] opcode;
bit [7:0] data;
} instruction_t;
2. Arrays
// PACKED (single vector)
bit [7:0] byte_val; // 8-bit
byte_val[3] = 1'b1; // Bit access
// UNPACKED (separate elements)
int memory[256]; // 256 integers
int matrix[4][8]; // 4x8 matrix
// DYNAMIC
int dyn[];
dyn = new[10]; // Allocate 10
dyn = new[20](dyn); // Resize, copy
dyn.delete(); // Free
// ASSOCIATIVE (sparse)
int assoc[string]; // String key
assoc["key"] = 100;
if (assoc.exists("key")) ...
assoc.delete("key");
// QUEUE (FIFO-like)
int q[$]; // Unbounded
q.push_back(10);
q.push_front(5);
int val = q.pop_back();
int val2 = q.pop_front();
// INITIALIZATION
int arr[5] = '{1, 2, 3, 4, 5}; // Positional
int arr2[10] = '{default: 0}; // All zeros
int arr3[10] = '{0:99, 5:55, default:0}; // Named + default
// METHODS
sum = arr.sum();
arr.reverse();
arr.sort();
arr.shuffle();
q = arr.find with (item > 5);
3. Operators
// ARITHMETIC
+ - * / % ** // a ** b = a^b
// BITWISE
& | ^ ~ ~& ~| ~^ // AND OR XOR NOT NAND NOR XNOR
<< >> <<< >>> // Shift
// REDUCTION
&data |data ^data // AND/OR/XOR all bits
// COMPARISON
== != < > <= >= // Numeric
=== !== // 4-state (checks X, Z)
==? !=? // Wildcard (? = don't care)
// LOGICAL
&& || ! // AND OR NOT
// SPECIAL
{a, b} // Concatenate
{n{a}} // Replicate: {8{1'b1}} = 8'hFF
a ? b : c // Conditional
inside {[m:n], val} // Range check
// USEFUL FUNCTIONS
$bits(var) // Width
$countones(data) // Number of 1s
$onehot(val) // Exactly one bit
$clog2(n) // Ceiling log2
$urandom() // Random 32-bit
$urandom_range(min, max) // Random in range
4. Procedural Blocks
// COMBINATIONAL
always_comb begin
y = a & b;
end
// SEQUENTIAL
always_ff @(posedge clk or negedge reset_n) begin
if (!reset_n)
q <= 0;
else
q <= d;
end
// INITIAL (once at t=0)
initial begin
clk = 0;
#100ns reset_n = 1;
end
// FINAL (at end)
final begin
$display("Done");
end
// FORK-JOIN
fork
#10ns task1();
#20ns task2();
join // Wait all
join_any // Wait first
join_none // Don't wait
disable fork; // Kill all
wait fork; // Wait all forked
5. Control Structures
// IF-ELSE
if (a > b) result = a;
else result = b;
// TERNARY
result = (a > b) ? a : b;
// CASE
case (sel)
2'b00: out = in0;
2'b01: out = in1;
default: out = 0;
endcase
// CASE INSIDE
case (data) inside
[0:63]: low();
[64:127]: mid();
endcase
// LOOPS
for (int i = 0; i < 10; i++) {}
while (cond) {}
foreach (arr[i]) {}
repeat (n) @(posedge clk);
forever begin end
// CONTROL
break; // Exit loop
continue; // Next iteration
return; // Exit function
6. Functions and Tasks
// FUNCTION (no delay, returns value)
function int add(int a, int b);
return a + b;
endfunction
// AUTOMATIC (re-entrant)
function automatic int factorial(int n);
return (n <= 1) ? 1 : n * factorial(n-1);
endfunction
// TASK (can delay, no return)
task wait_cycles(int n);
repeat(n) @(posedge clk);
endtask
// REF ARGUMENT (pass by reference)
task modify(ref int data);
data = data * 2;
endtask
// CONST REF (read-only reference)
function void process(const ref bit[1000:0] large);
// No copy, can't modify
endfunction
7. Classes and OOP
// BASIC CLASS
class packet;
rand bit [7:0] addr;
rand bit [31:0] data;
function new();
endfunction
function void display();
$display("addr=%h, data=%h", addr, data);
endfunction
endclass
packet p = new();
p.addr = 8'h10;
// INHERITANCE
class extended extends packet;
rand bit write;
function void display();
super.display(); // Call parent
$display("write=%b", write);
endfunction
endclass
// VIRTUAL (polymorphism)
class base;
virtual function void show();
$display("Base");
endfunction
endclass
class derived extends base;
function void show();
$display("Derived");
endfunction
endclass
base b = new derived();
b.show(); // Prints "Derived"
// STATIC
class counter;
static int count = 0;
int id;
function new();
count++;
id = count;
endfunction
endclass
8. Constraints
class constrained;
rand bit [7:0] addr;
rand bit [31:0] data;
rand bit write;
// BASIC
constraint c1 {
addr inside {[0:127]};
data != 0;
}
// DISTRIBUTION
constraint c2 {
write dist {0 := 30, 1 := 70}; // 30% read, 70% write
}
// IMPLICATION
constraint c3 {
(addr > 100) -> (data < 1000);
}
// IF-ELSE
constraint c4 {
if (write)
data != 0;
else
data == 0;
}
// SOLVE-BEFORE
constraint c5 {
solve addr before data;
}
endclass
// RANDOMIZE
assert(obj.randomize());
// INLINE CONSTRAINTS
assert(obj.randomize() with {
addr < 50;
write == 1;
});
// DISABLE CONSTRAINT
obj.c1.constraint_mode(0); // Off
obj.c1.constraint_mode(1); // On
9. Coverage
covergroup cg;
// COVERPOINT
addr_cp: coverpoint addr {
bins low = {[0:63]};
bins mid = {[64:127]};
bins high = {[128:255]};
}
// AUTO BINS
write_cp: coverpoint write {
bins vals[] = {0, 1}; // One bin per value
}
// EXPRESSION
data_cp: coverpoint data {
bins even[] = {[0:255]} with (item % 2 == 0);
}
// CROSS
cross_cp: cross addr_cp, write_cp;
// TRANSITIONS
state_cp: coverpoint state {
bins t1 = (IDLE => ACTIVE);
bins t2 = (ACTIVE => DONE);
bins seq = (IDLE => ACTIVE => DONE);
}
// IGNORE/ILLEGAL
cmd_cp: coverpoint cmd {
bins valid = {[0:10]};
ignore_bins skip = {11};
illegal_bins bad = {[12:15]};
}
endgroup
cg my_cg = new();
my_cg.sample();
real coverage = my_cg.get_coverage();
10. Assertions
// IMMEDIATE (in procedural)
always @(posedge clk) begin
assert (data < 256) else $error("Overflow!");
end
// CONCURRENT (temporal)
property req_gnt;
@(posedge clk) disable iff (!reset_n)
req |=> gnt;
endproperty
assert property (req_gnt)
else $error("Grant missing!");
// OPERATORS
|-> // Overlapping (same cycle)
|=> // Non-overlapping (next cycle)
##N // Delay N cycles
##[m:n] // Delay m to n cycles
[*n] // Exactly n consecutive
[*m:n] // m to n consecutive
[+] // 1 or more consecutive
[->n] // Goto nth occurrence
// SYSTEM FUNCTIONS
$rose(sig) // Rising edge
$fell(sig) // Falling edge
$stable(sig) // Unchanged
$past(sig, N) // N cycles ago
$onehot(sig) // Exactly one bit
// EXAMPLES
property p1;
@(posedge clk) disable iff (!reset_n)
req |-> ##[1:5] gnt; // Grant in 1-5 cycles
endproperty
property p2;
@(posedge clk) disable iff (!reset_n)
busy[*3] ##1 done; // Busy 3 cycles, done next
endproperty
property p3;
logic [7:0] addr;
@(posedge clk) disable iff (!reset_n)
(start, addr = addr_in) |->
##[1:10] (done && (addr_out == addr));
endproperty
// Clock
logic clk = 0;
always #5ns clk = ~clk; // 10ns period
// Reset
logic reset_n;
initial begin
reset_n = 0;
#100ns reset_n = 1;
end
FSM
typedef enum {IDLE, ACTIVE, DONE} state_t;
state_t state, next_state;
// State register
always_ff @(posedge clk or negedge reset_n) begin
if (!reset_n) state <= IDLE;
else state <= next_state;
end
// Next state logic
always_comb begin
next_state = state;
case (state)
IDLE: if (start) next_state = ACTIVE;
ACTIVE: if (done) next_state = DONE;
DONE: next_state = IDLE;
endcase
end
// Outputs
assign busy = (state != IDLE);
Counter
logic [7:0] count;
always_ff @(posedge clk or negedge reset_n) begin
if (!reset_n)
count <= 0;
else if (enable)
count <= count + 1;
end
FIFO
logic [7:0] fifo[16];
logic [3:0] wr_ptr, rd_ptr;
logic [4:0] count;
assign full = (count == 16);
assign empty = (count == 0);
// Write
always_ff @(posedge clk) begin
if (wr_en && !full) begin
fifo[wr_ptr] <= wr_data;
wr_ptr <= wr_ptr + 1;
end
end
// Read
always_ff @(posedge clk) begin
if (rd_en && !empty) begin
rd_data <= fifo[rd_ptr];
rd_ptr <= rd_ptr + 1;
end
end
// Count
always_ff @(posedge clk or negedge reset_n) begin
if (!reset_n)
count <= 0;
else
case ({wr_en && !full, rd_en && !empty})
2'b10: count <= count + 1;
2'b01: count <= count - 1;
endcase
end