๐งโ๐ป Verilog Coding Best Practices & Pitfalls to Avoid
This notebook outlines best practices for writing clean, modular, and synthesis-friendly Verilog codeโplus common traps and bad habits to avoid. Ideal for collaborative environments, semantic audits, and vault-grade pedagogy.
โ Best Practices
You should follow these practices
๐ค Descriptive and Mnemonic Naming
- Use meaningful names for modules, ports, and signals.
- Example:
carry_outinstead ofco,suminstead ofs.
๐งฉ Favor Named Instantiation
- Improves readability and reduces port-order errors.
add_half M1 (.a(A), .b(B), .sum(w1), .cout(w2));๐งฑ Modular Design
- Break logic into reusable submodules.
- Use parameters for scalable designs.
module adder #(parameter WIDTH = 8) (...);๐จ Consistent Formatting
- Align declarations and logic blocks.
- Use consistent indentation for visual clarity.
โฐ Use Clocked Always Blocks
- Prefer
always @(posedge clk)for sequential logic. - Avoid latch inference from incomplete conditions.
๐ Explicit Reset Logic
always @(posedge clk or posedge reset) begin
if (reset)
state <= IDLE;
else
state <= next_state;
end๐ Use Non-Blocking Assignments for Sequential Logic
- Use
<=in clocked blocks. - Use
=only for combinational logic.
๐งฌ Signal Assignment Discipline
- If a signal is assigned inside an
alwaysblock, do not assign it anywhere else. - Avoid mixing
assignstatements or multiplealwaysblocks for the same signal. - Each
alwaysblock should own its assigned signals exclusively. - Group signals into a single block only if they follow similar logic.
always @* begin
x = a & b; // x assigned here
y = a | b;
end
// โ Don't do this elsewhere:
assign x = something_else; // Conflicting driver
๐ Statement Order Matters in always Blocks
- Statements inside an
alwaysblock are executed in order, top to bottom. - If a signal is assigned multiple times, the last assignment wins.
- Synthesis tools collapse this into combinational logic, but the order defines the final behavior.
always @* begin
y = a & b;
y = x | c; // This overrides the previous y
x = ~c;
end- Best Practice: Avoid reassigning the same signal within a block unless intentional.
- Pedagogy: Reinforces the difference between procedural flow and hardware mapping.
๐ฌ Strategic Commenting
- Explain non-obvious logic and edge cases.
- Avoid redundant comments.
๐ข Avoid Magic Numbers
- Use
parameterorlocalparamfor constants.
parameter WIDTH = 8;๐งช Simulate Before Synthesis
- Write testbenches to verify behavior.
- Use assertions and waveform inspection.
๐ซ Avoid Vendor-Specific Constructs
- Stick to synthesizable, portable Verilog.
- Avoid
initialblocks unless targeting specific FPGAs.
๐งญ Use Case Defaults
- Always include a
default:case to prevent unintended behavior.
๐ Document Module Interfaces
- Include comments or headers for module purpose, inputs, and outputs.
๐ ๏ธ Audit Synthesis Logs
- Review for inferred latches, unused signals, or resource-heavy constructs.
โ Bad Practices & Traps to Avoid
You should avoid these practices
โ ๏ธ Vector Width Mismatches
wire [3:0] a;
assign a = 5; // โ RHS is 3'b101, not 4 bits
โ ๏ธ Unintended Latch Inference
always @(a or b)
if (a) y = b; // โ No else โ latch inferred
โ ๏ธ Mixed Blocking and Non-Blocking Assignments
- Mixing
=and<=in the samealwaysblock leads to race conditions.
โ ๏ธ Ambiguous Signal Driving
assign x = a;
assign x = b; // โ Multiple drivers
โ ๏ธ Overuse of assign for Sequential Logic
assignis for combinational logic only. Usealwaysfor sequential behavior.
โ ๏ธ Missing Sensitivity List Entries
always @(a) y = a & b; // โ Missing b
โ ๏ธ Using initial for Synthesis
initialblocks are not synthesizable in most ASIC flows.
โ ๏ธ Case-Sensitivity Errors
- Verilog is case-sensitive.
Sumโsum.
โ ๏ธ Implicit Net Declarations
- Avoid undeclared wires. Use
default_nettype noneto catch these.
๐ง Summary Table
| Practice / Pitfall | Impact |
|---|---|
| Named instantiation | โ Semantic clarity |
| Vector width mismatch | โ Synthesis errors |
| Latch inference | โ Unintended memory behavior |
| Mixed blocking/non-blocking | โ Race conditions |
| Multiple drivers | โ Undefined behavior |
Statement order in always | โ Defines final logic behavior |
| Strategic commenting | โ Improves teachability |
| Simulation before synthesis | โ Functional verification |
Signal ownership in always | โ Prevents driver conflicts |
Last updated on