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
- Declare both operands
signedor the whole expression goes unsigned. - A sized literal like
8'hFFis unsigned; use8'sd255/$signed(). - Widths: multiplication of
[7:0] x [7:0]needs[15:0]; addition needs one extra bit per adder stage.
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)
#delays,initial(except FPGA register init),fork/join- Incomplete
ifinalways @*→ latch - Clock generated by logic (
assign clk2 = a & clk) → use clock enables - Async signals sampled without a 2-flop synchronizer