always @(posedge clk) for sequential logicassign or always @(*) for combinational logicBefore simulation, run static syntax checking using slang:
# Check Verilog/SystemVerilog syntax
slang <module_name>.v
# Or for SystemVerilog files
slang <module_name>.sv
What slang checks:
If slang reports errors:
Before simulation, verify:
if/case branches assign in combinational blocks)default case branch=) in sequential always blocks<=) in combinational always blockstimescale directive present in all source filesalways #5 clk = ~clk; for 10ns period)$display() or $monitor() for pass/fail reporting$finish() after all tests complete_tb.v The skill automatically detects and uses available simulators in priority order:
vcs command available)xrun command available)# Priority order: VCS → Xrun → Icarus
which vcs && use_vcs
which xrun && use_xrun
fallback to iverilog
vcs -full64 -debug_acc+all -l sim.log -R <module_name>.v <module_name>_tb.v
vcs -full64 -debug_acc+all -sverilog -l sim.log -R <module_name>.sv <module_name>_tb.sv
xrun -64bit -access rwc -l sim.log <module_name>.v <module_name>_tb.v
xrun -64bit -access rwc -sv -l sim.log -R <module_name>.sv <module_name>_tb.sv
iverilog -o <module_name>.vvp <module_name>.v <module_name>_tb.v
vvp <module_name>.vvp
⚠️ Important: Always use VCD format for waveform dumping to ensure compatibility:
initial begin
$dumpfile("<module_name>.vcd");
$dumpvars(0, <module_name>_tb);
end
$dumpfile()/$dumpvars()gtkwave ORpython3 /scripts/check_vcd.py .vcd `timescale 1ns/1ps
module <module>_tb;
// Parameters
parameter CLK_PERIOD = 10;
// Signals
reg clk;
reg rst_n;
// ... add inputs/outputs
// Instantiate DUT
<module> dut (
.clk(clk),
.rst_n(rst_n),
// ... ports
);
// Clock generation
initial begin
clk = 0;
forever #(CLK_PERIOD/2) clk = ~clk;
end
// VCD dump
initial begin
$dumpfile("<module>.vcd");
$dumpvars(0, <module>_tb);
end
// Test stimulus
initial begin
// Initialize
rst_n = 0;
// ... init inputs
// Release reset
#(CLK_PERIOD * 2);
rst_n = 1;
// Apply test vectors
// ... stimulus code
// Check results
// ... self-checking assertions
#(CLK_PERIOD * 10);
$finish();
end
// Monitor
initial begin
$monitor("Time=%0t: signals=...", $time);
end
endmodule
For automated waveform checking, use Python VCD parsing.
Reference: references/vcd-analysis.md
memory/verilog_specs/_spec.md .v _tb.v .vvp (Icarus), sim.log, and .vcd filesUse the provided helper script to automatically select and run the best available simulator:
# The script checks for VCS → Xrun → Icarus in order
bash <skill_dir>/scripts/simulate.sh <module_name>
Example workflow:
# 1. Detect simulator and run
bash scripts/simulate.sh counter
# 2. Check simulation log
cat sim.log
# 3. Analyze VCD waveforms
python3 scripts/check_vcd.py counter.vcd
| Tool | Command | Purpose |
|---|---|---|
| ------ | --------- | --------- |
| Synopsys VCS | vcs -full64 -debug_acc+all -l sim.log -R file.v | Compile & Simulate Verilog |
| Synopsys VCS (SV) | vcs -full64 -debug_acc+all -sverilog -l sim.log -R file.sv | Compile & Simulate SystemVerilog |
| Cadence Xrun | xrun -64bit -access rwc -l sim.log file.v | Compile & Simulate Verilog |
| Cadence Xrun (SV) | xrun -64bit -access rwc -sv -l sim.log -R file.sv | Compile & Simulate SystemVerilog |
| Icarus Verilog | iverilog -o out.vvp file.v | Compile Verilog (fallback) |
| VVP | vvp out.vvp | Run simulation |
| GTKWave | gtkwave dump.vcd | View waveforms (optional) |
| Issue | Fix |
|---|---|
| ------- | ----- |
| Multiple drivers | Ensure one-always-one-signal: each signal assigned in exactly one always block |
| Latch inference | Ensure all if/case branches assign in combinational always |
| Missing reset | Include explicit reset in sequential always blocks |
| Race conditions | Use non-blocking <= in sequential logic only |
| Simulation mismatch | Check timescale and delays |
| VCD not generated | Ensure $dumpfile() called before $dumpvars() |
| Symptom | Cause | Solution |
|---|---|---|
| --------- | ------- | ---------- |
| No output, simulation stuck | Combinational loop | Check for circular logic in combinational always blocks |
| Infinite loop warning | Zero-delay feedback | Add delay elements or check async feedback paths |
| Division by zero | Runtime calculation error | Check divisor is never zero |
| Array out of bounds | Invalid index | Verify index range before array access |
| Symptom | Cause | Solution |
|---|---|---|
| --------- | ------- | ---------- |
| Specific signal is X | Uninitialized register | Add explicit reset value |
| Wide bus partially X | Mixed width assignment | Check vector width consistency |
| After reset release | Reset deassertion timing | Ensure reset held long enough |
| Random X propagation | X propagation from input | Trace back to source of X |
| Symptom | Cause | Solution |
|---|---|---|
| --------- | ------- | ---------- |
| Output one cycle late | Blocking vs non-blocking | Use <= in sequential always blocks |
| Glitches on output | Combinational logic hazard | Add register stage or use synchronous output |
| Setup/hold violations (ASIC) | Clock/data skew | Check synthesis timing reports |
| Error | Cause | Solution |
|---|---|---|
| ------- | ------- | ---------- |
| "Not synthesizable" | Unsupported Verilog construct | Replace with synthesizable equivalent |
| "Multiple drivers" | Signal assigned in multiple always | Merge logic or use intermediate signals |
| "Latch inferred" | Incomplete if/case in combinational | Add default assignment or use else |
| "Undriven signal" | Output declared but not assigned | Connect to logic or tie to constant |
Every Verilog file should include:
/**
* Module: <module_name>
* Description: <brief description>
* Author: <name>
* Date: <YYYY-MM-DD>
* Version: <major>.<minor>.<patch>
*
* Changelog:
* v1.0.0 - <date> - Initial release
* v1.1.0 - <date> - <description of changes>
* v2.0.0 - <date> - <breaking changes>
*
* Parameters:
* - PARAM1: <description> (default: <value>)
* - PARAM2: <description> (default: <value>)
*
* Ports:
* - clk: <description>
* - rst_n: <description>
* ...
*/
# Before starting new feature
git checkout -b feature/new-functionality
# After completing and testing
git add <files>
git commit -m "feat: add <feature> to <module>"
git checkout main
git merge feature/new-functionality
共 1 个版本