Synthesizable RTL is a subset of Verilog/SystemVerilog that tools can map to flops, RAM, and combo logic. Simulation-only constructs belong in testbenches.
Prefer
| Construct | Role |
|---|---|
always_ff @(posedge clk) |
Flip-flops |
always_comb |
Combinational |
assign |
Continuous combo |
enum, struct, typedef |
Clarity (SV) |
unique case / priority case |
Explicit decode intent |
Avoid in DUT (device under test)
| Construct | Why |
|---|---|
#delay |
Not hardware time |
initial for logic |
Not portable / not synth in most flows |
force / release |
Testbench |
fork / join |
Parallel TB threads |
| Unlimited loops waiting on events | Sim-only |
instanceof-style OOP in RTL datapath |
Verification world |
always @(posedge clk) still works; always_ff documents intent and enables better lint.
Latch inference
Incomplete if/case assignments in combo processes create latches. Either:
- Assign defaults at the top of
always_comb, or - Cover every branch including
default
Blocking vs non-blocking
| Context | Assignment |
|---|---|
| Combinational | blocking = |
| Sequential (flops) | non-blocking <= |
Mixing both in one process for “NBA tricks” is a common source of sim/synth mismatch — don’t.
Lint & synth loop
- Write RTL → Lint (Slang in RTL Studio)
- Simulate intent
- Synthesize (Yosys) and skim warnings
- Fix, don’t waive blindly