๐ Verilog Syntax Reference
This notebook summarizes the core syntax elements of Verilog HDL. Each construct is annotated with its purpose, behavior, and contrast with similar features. Designed for semantic clarity, vault-grade pedagogy, and rapid onboarding into digital design workflows.
๐งฑ Module Declaration
module my_module (
input wire a, b,
output wire y
);
// internal logic
endmodule- Purpose: Defines a reusable hardware block with named inputs/outputs.
- Difference: Unlike functions in software, modules describe physical logic and can be instantiated multiple times in a design hierarchy.
๐ Data Types
| Type | Usage | Notes |
|---|---|---|
wire | For continuous assignments | Cannot hold state |
reg | For procedural assignments | Can hold state in always blocks |
integer | Simulation-only counters | Not synthesizable |
logic | SystemVerilog extension | Combines wire and reg behavior |
๐ Vector Declaration
wire [7:0] byte_data; // 8-bit bus
reg [3:0] nibble;- MSB on the left, LSB on the right.
- Match widths during assignment to avoid synthesis errors.
๐ Continuous Assignment
assign y = a & b;- Purpose: Describes combinational logic outside procedural blocks.
- Difference: Unlike
alwaysblocks,assignis static and updates automatically when inputs change.
โฐ Procedural Blocks
Sequential Logic
always @(posedge clk) begin
q <= d;
end- Purpose: Models flip-flop behavior triggered by clock edges.
- Difference: Uses non-blocking
<=to avoid race conditions.
Combinational Logic
always @(*) begin
y = a & b;
end- Purpose: Describes logic that reacts to input changes.
- Difference: Uses blocking
=and must include all relevant signals in sensitivity list.
๐ Conditional Statements
if (a > b)
y = x;
else
y = z;- Purpose: Implements decision-making logic.
- Difference: Incomplete conditions may infer latchesโuse
elseordefaultto avoid.
Latch Inference โ What It Means and Why It Matters
In Verilog, a latch is inferred when a signal inside an always @* block is not assigned in every possible condition. This causes the synthesizer to generate hardware that remembers the last valueโjust like a physical latch.
The term “latch” comes from mechanical and electrical systems: a latch is a device that holds its state until explicitly changed. In digital logic, a latch behaves similarlyโit remains transparent when enabled and retains its value when disabled.
Example of latch inference:
always @* begin
if (enable)
q = d; // โ No else โ q retains previous value when enable is 0
end
This creates a level-sensitive latch because q is not updated when enable is false.
โ
Best Practice: Always assign outputs in all branches of conditional logic to avoid unintended latch behavior.
Latch Inference โ What It Means and Why It Matters
In Verilog, a latch is inferred when a signal inside an always @* block is not assigned in every possible condition. This causes the synthesizer to generate hardware that remembers the last valueโjust like a physical latch.
The term “latch” comes from mechanical and electrical systems: a latch is a device that holds its state until explicitly changed. In digital logic, a latch behaves similarlyโit remains transparent when enabled and retains its value when disabled.
Example of latch inference:
always @* begin
if (enable)
q = d; // โ No else โ q retains previous value when enable is 0
endThis creates a level-sensitive latch because q is not updated when enable is false.
โ Best Practice: Always assign outputs in all branches of conditional logic to avoid unintended latch behavior.
๐ Case Statements
case (sel)
2'b00: y = a;
2'b01: y = b;
default: y = 1'bx;
endcase- Purpose: Selects output based on discrete input values.
- Difference: More readable than nested
ifstatements for multi-way branching.
๐ฃ Operators
| Operator | Meaning | Notes |
|---|---|---|
~ | Bitwise NOT | Inverts each bit |
& | Bitwise AND | ANDs each bit |
| | Bitwise OR | ORs each bit |
^ | Bitwise XOR | Exclusive OR |
==, != | Equality | Compares values |
<<, >> | Shift | Logical shift |
?: | Ternary (if-else) | Compact conditional |
๐งฉ Module Instantiation
Named
my_mod U1 (.a(A), .b(B), .y(Y));Ordered
my_mod U1 (A, B, Y);- Purpose: Reuses a module in another design.
- Difference: Named instantiation avoids port-order errors and improves readability.
๐งช Simulation Constructs
initial begin
$display("Start");
#10 a = 1;
end- Purpose: Used in testbenches to simulate behavior.
- Difference: Not synthesizableโonly for simulation and debugging.
๐งฌ Concatenation, Replication & Width Behavior
๐ Concatenation
assign out = {a, b}; // Combines a and b into a wider vector
{}joins multiple signals into a single vector.- Order matters: MSB on the left.
๐ Replication
assign out = {4{a}}; // Replicates 'a' 4 times
{N{signal}}repeats the signal N times.- Useful for padding or pattern generation.
โ ๏ธ Truncation
wire [3:0] a;
assign a = 8'b10101010; // Only lower 4 bits assigned โ a = 4'b1010
- Higher bits are silently discarded.
๐ง Zero-Padding
wire [7:0] a;
assign a = 4'b1101; // a = 8'b00001101
- Left side is padded with zeros.
๐งฎ Parameters
Declaring Parameters
module adder #(parameter WIDTH = 8) (
input wire [WIDTH-1:0] a, b,
output wire [WIDTH-1:0] sum
);- Parameters allow scalable, reusable modules.
- Can be overridden during instantiation.
Overriding Parameters
adder #(.WIDTH(16)) U1 (
.a(a),
.b(b),
.sum(sum)
);- Use
#(.NAME(VALUE))syntax for named parameter override.
Local Parameters
localparam DEPTH = 32;- Internal constants that can’t be overridden.
๐ Multiple always Blocks and Concurrency
- All
alwaysblocks run concurrently, regardless of their order in the file. - Order of appearance does not affect executionโVerilog models parallel hardware.
always @* begin
a = b;
c = m;
end
always @* begin
y = ...;
z = ...;
endBest Practice: Assign each signal from only one block.
Difference: Unlike software, Verilog logic is synthesized as parallel hardware.
Exception: Inside a single
alwaysblock, statement order mattersโlast assignment wins.
always @* begin
y = a & b;
y = x | c; // Overrides previous y
end