Verilog / SystemVerilog Quick Reference

The constructs you actually use in synthesizable RTL, in one page.

Module skeleton (Verilog-2001)

module my_block #(
    parameter integer WIDTH = 8
) (
    input  wire             clk,
    input  wire             rst,
    input  wire [WIDTH-1:0] din,
    input  wire             din_valid,
    output reg  [WIDTH-1:0] dout,
    output wire             busy
);
    // ...
endmodule

The three always blocks that matter

// 1. Sequential logic - non-blocking (<=) only
always @(posedge clk) begin
    if (rst) q <= '0';
    else     q <= d;
end

// 2. Combinational logic - blocking (=), full sensitivity
always @* begin
    y = a & b;          // every output assigned on every path,
    if (sel) y = c;     // or you've inferred a latch
end

// 3. SystemVerilog makes intent explicit
always_ff   @(posedge clk) q <= d;   // flip-flops
always_comb y = a & b;               // combinational, latch = error

Golden rules: non-blocking (<=) in clocked blocks, blocking (=) in combinational blocks, never mix, never assign one signal from two blocks.

Literals and operators

Syntax Meaning
8'hFF, 4'b1010, 16'd255 sized literals (width'base value)
'0, '1 (SV) all-zeros / all-ones, any width
{a, b, c} concatenation
{4{2'b01}} replication → 8'b01010101
&a, |a, ^a reduction AND / OR / XOR of a vector
a >>> 3 arithmetic shift right (needs signed)
$clog2(DEPTH) bits needed to index DEPTH items
w[7-:4] 4 bits, MSB at 7 (i.e. w[7:4])

Common inferences

// Mux: use case for wide, ?: for narrow
always @* case (sel)
    2'd0: y = a;  2'd1: y = b;
    2'd2: y = c;  default: y = d;
endcase

// Simple dual-port RAM (block RAM inference)
reg [7:0] mem [0:DEPTH-1];
always @(posedge clk) begin
    if (we) mem[waddr] <= wdata;
    rdata <= mem[raddr];        // registered read = BRAM
end

// FSM: localparam states + two blocks
localparam [1:0] IDLE = 2'd0, RUN = 2'd1, DONE = 2'd2;
reg [1:0] state, state_nxt;
always @(posedge clk) state <= rst ? IDLE : state_nxt;
always @* begin
    state_nxt = state;
    case (state)
        IDLE: if (start)   state_nxt = RUN;
        RUN:  if (last)    state_nxt = DONE;
        DONE:              state_nxt = IDLE;
        default:           state_nxt = IDLE;
    endcase
end

Signed arithmetic pitfalls

Simulation-only essentials

initial begin
    $dumpfile("wave.vcd"); $dumpvars(0, tb);   // for GTKWave
    #100 $display("t=%0t q=%h", $time, q);
    $finish;
end
`timescale 1ns/1ps

What NOT to write (synthesis)