A command failed. How do you get from the message to the fix?
You type the command that worked yesterday, and the terminal answers with two lines about a missing separator. Nothing ran, nothing was tested, and the message names a file you barely remember writing. The instinct is to change something and try again. Wait for sixty seconds and read instead: the message already says where to look.
Every failure in this course happens at one of five stages. The command starts. The sources compile, which means each file is translated on its own. The design elaborates, which means the tools link the modules together and check that every referenced module exists and the named top is present. The simulation runs. The verdict appears.
The message names its stage when you read it literally. A complaint from the shell means no tool started, so the fix is never in your RTL. A complaint from Make means Make stopped first, so the fix is in the Makefile or its file name. A complaint that names a module means elaboration never finished, so the fix is in the command line or the missing file.
Three terms carry the whole lesson. PATH is the list of folders where the shell searches for programs. VCD, the value change dump, is the recording of signal changes that a waveform viewer draws. Exit status is the number a finished command reports: 0 means success and anything else means failure, and Make reports 2 when one of its steps fails.
The figure below turns the five stages into five yes-or-no questions. Start at the top and follow the yes arrows down; the first no names the case whose fix to apply before you rerun. Look at the shape of the tree first: four cases sit on the right as no branches, and only one case hides behind a yes.
Two placements surprise beginners. The Make cases sit at question 4, because Make stops before the simulator starts. Case 3 sits behind a yes, because the simulation passed and only the recording is missing.
The table below is the whole lesson on one screen: symptom, likely cause, what to check, and the fix. Each case after it quotes one real command block verbatim and walks the same four columns. All outputs below were measured on macOS unless the text names Ubuntu.
# | Symptom | Likely cause | Investigation | Fix |
|---|---|---|---|---|
1 |
| Typo, or the tool is missing or not on PATH | Retype with tab completion; run the version report | Correct the spelling; install; fix PATH |
2 |
| The design file is missing from the command | Count the files on the compile line | Add the design file |
3 | PASS verdict but no | No dump calls in the testbench | Search the testbench for the dump calls | Restore the two dump calls |
4 |
| Wrong folder or file name | List the folder contents | Correct the path |
5 |
| Spaces instead of a tab character | Open line 2 of the Makefile | Start the recipe with a tab |
6 |
| The tool reads only a subset of SystemVerilog | Check which frontend ran | Rewrite with supported constructs |
7 |
| A test fails at run time | Read the first ERROR line | Fix the design, not the test |
8 | Passes here, fails on another machine | Different tool versions | Compare the version reports | Record and match the versions |
# captured terminal output
$ iverilogg -V
bash: iverilogg: command not found
[exit status 127]The output above was measured on macOS. The shell searched PATH for iverilogg and found nothing, so no tool started and the exit status is 127. Correct the spelling to iverilog; when the spelling is right, check that the tool is installed and on PATH.
# captured terminal output
$ iverilog -g2012 -s tb_mini_controller -o build/x.vvp tb/tb_mini_controller.sv 2>&1 | head -n 5
tb/tb_mini_controller.sv:14: error: Unknown module type: mini_controller
2 error(s) during elaboration.
*** These modules were missing:
mini_controller referenced 1 times.
***The output above was measured on macOS, Icarus Verilog 13.0. Only the testbench file is on the compile line, so elaboration names the missing module. Count the files on the command, add the design file, and rerun.
# captured terminal output
$ mkdir -p build && iverilog -g2012 -s tb_mini_controller -o build/s.vvp rtl/mini_controller.sv tb/tb_mini_controller.sv && sed -i.bak '/dumpfile/d;/dumpvars/d' tb/tb_mini_controller.sv && iverilog -g2012 -s tb_mini_controller -o build/s2.vvp rtl/mini_controller.sv tb/tb_mini_controller.sv && (cd build && vvp s2.vvp | tail -n 2; ls *.vcd 2>&1 | head -n 1)
PASS: mini_controller
tb/tb_mini_controller.sv:67: $finish called at 2396000 (1ps)
ls: *.vcd: No such file or directoryThe output above was measured on macOS, Icarus Verilog 13.0. After the dump calls are deleted the PASS verdict still appears, yet no VCD file is listed. VCD exists only because the testbench asks for it, so restore the two dump calls and rerun.
# captured terminal output
$ make -f mini/Makefile 2>&1 | head -n 2
make: mini/Makefile: No such file or directory
make: *** No rule to make target `mini/Makefile'. Stop.The output above was measured on macOS, Make 3.81. Make ran and reported that the path does not exist, so no build step started. List the folder and correct the path.
# captured terminal output
$ make
Makefile:2: *** missing separator. Stop.
[exit status 2]The output above was measured on macOS, Make 3.81. Make stopped at line 2, because recipe lines must start with a tab and this one starts with spaces. Replace the leading spaces with a tab and rerun.
# captured terminal output
$ yosys -Q -T -p 'read_verilog -sv unsupported.sv' 2>&1 | tail -n 3
1. Executing Verilog-2005 frontend: unsupported.sv
unsupported.sv:1: ERROR: syntax error, unexpected TOK_INTERFACE
Parsing SystemVerilog input from `unsupported.sv' to AST representation.The output above was measured on macOS, Yosys 0.69+post. The frontend, the part of the tool that reads the language, rejects the construct, so it stops naming the unexpected token. Rewrite with constructs the tool supports.
# captured terminal output
$ make sim > /dev/null 2>&1; echo "make sim exit status with a counts_by_two bug: $?"
make sim exit status with a counts_by_two bug: 2The output above was measured on macOS, Make 3.81, with the testbench run by Icarus Verilog 13.0. Compilation succeeded and the failure arrives at run time: Make reports exit status 2 because the testbench found a mismatch. The counts-by-two bug here is the same change First Simulation makes on purpose, and that lesson shows the matching failure lines. Read the first ERROR line in the full log and fix the design, never the expected values.
# captured terminal output
$ bash scripts/check_tools.sh
iverilog Icarus Verilog version 13.0 (stable) (v13_0)
vvp Icarus Verilog runtime version 13.0 (stable) (v13_0)
verilator Verilator 5.048 2026-04-26 rev vUNKNOWN-built20260426
yosys Yosys 0.69+post (git sha1 143eb14f9cc55d6f8927e68523b0c9d2166ed02c, Release, AppleClang clang++ 21.0.0.21000101)
make GNU Make 3.81
git git version 2.54.0 (Apple Git-157)The macOS version report above lists Icarus Verilog 13.0, Verilator 5.048, Yosys 0.69+post, Make 3.81 and Git 2.54.0.
# captured terminal output
$ bash scripts/check_tools.sh
iverilog Icarus Verilog version 12.0 (stable) ()
vvp Icarus Verilog runtime version 12.0 (stable) ()
verilator Verilator 5.020 2024-01-01 rev (Debian 5.020-1)
yosys Yosys 0.33 (git sha1 2584903a060)
make GNU Make 4.3
git git version 2.43.0The Ubuntu 24.04 report above lists Icarus Verilog 12.0, Verilator 5.020, Yosys 0.33, Make 4.3 and Git 2.43.0. Same project, different tools: when a build fails on one machine and passes on another, compare the version reports first. Record the versions with every release so a future machine can match them.
make sim from an identical checkout and it fails, while yours passes. Name the first two things you compare, in order.The exact command line first, then the tool versions from the version report. Different commands mean you are not running the same flow, so align them before anything else. The same command with different versions, such as Icarus 13.0 against 12.0, points at a version difference, which is case 8.
Cause case 5 yourself so you recognize it forever. Open the working Makefile, replace the tab at the start of one recipe line with four spaces, and run make. You will see the same missing-separator stop quoted above. Restore the tab and rerun to green. The lesson is in your fingers now: when that message appears, you check line 2 before you check anything else.
Changing three things at once. Three edits and a green run teach nothing about which edit mattered, and a still-red run hides whether any edit helped. Make one change, rerun the exact command, and read the new message before the next change.
Reading the last message first. The last lines of a log report the stop; the first error reports the cause, and everything between is consequence. Scroll to the first error and fix that, because later messages often vanish once the first is fixed.
Fixing the test to match the bug. When case 7 appears, the temptation is to edit the expected value until the verdict turns green. That edit destroys the check that caught the bug. Change the design, keep the expectation, and let the test stay strict.
Rule: the message names the stage: fix one thing at that stage, then rerun.
errdemo/dut.sv:14: syntax error followed by Syntax in assignment statement l-value. Which stage failed, and what do you do?Compilation, like case 6: the tool names the file and the line, so open errdemo/dut.sv at line 14 and fix the statement. The message points at source code, so neither the Makefile nor the command line is the place to look.
error: Unable to find the root module "mini_control" with a hint that -s mini_control may be incorrect. Which case is this closest to, and what is the fix?Closest to case 2, at elaboration: the name after -s matches no module in the sources. List the module names, correct the spelling to mini_controller, and rerun.
Makefile:2: *** missing separator. Stop. Which case is it, and what exactly do you change?Case 5 exactly: line 2 of the Makefile starts with spaces instead of a tab. Replace the leading spaces on that recipe line with one tab character and rerun make. When your editor converts tabs automatically, turn that behavior off for Makefiles.
Every failure message names its stage: shell, Make, compile, elaborate, run, or verdict.
Read the first error literally, change one thing at that stage, and rerun the exact command.
A green verdict with a missing artifact, or a pass on only one machine, is still a failure: check the setup and the versions.