Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • How to Use This Course
  • Reading Paths
  • Quick Start: Your First Green Build
  • Part 1: How Chips Get Made6
  • Part 2: Your Workstation5
  • Part 3: Specify and Architect3
  • Part 4: The Design Loop6
    • Compile, Elaborate, Simulate, Synthesize, Lint
    • First Simulation
    • Waveforms with GTKWave
    • Lint with Verilator
    • First Synthesis Check
    • Simulation Code vs Synthesizable Code
  • Part 5: The Verification Ladder6
  • Part 6: Automation and Reproducibility5
  • Part 7: Hand-Off to the Back-End3
  • Part 8: When Things Go Wrong3
  • Part 9: Project and Next Steps3
  • Reference4
Loading lesson

‹Part 4: The Design Loop
  1. Topics
  2. Start Here: RTL and Verification
  3. Part 4: The Design Loop
  4. First Synthesis Check

Part 4 · The Design Loop · Working (W)

First Synthesis Check

Run the first synthesis check on mini_controller with Yosys: what a structural check with generic cells tells you, and why area, speed and power need a mapped netlist.

On this page

    Note

    Level: Working (W) · Answers: What does synthesis tell you at this stage, and what does it not?

    Before this: Lint with Verilator

    You linted the code and the simulation passes. What does synthesis tell you at this stage, and what does it not?

    The counter counts, the testbench reports its verdict, and Verilator is quiet. Before you trust the code further, you ask the next tool in the loop a narrower question: does this code describe hardware that a tool can build from? The answer comes from Yosys, an open-source synthesis tool, and it is smaller than you might expect.

    Synthesis first asks whether the code describes hardware

    Synthesis means translation from a description of behavior into gates. The full version of that translation maps your code onto a real factory library and answers hard questions about area, speed, and power. This lesson runs only the first part of that journey, on purpose.

    The check reads the design, confirms the hierarchy, turns the clocked process into registers and logic, simplifies the result, looks for obvious problems, and counts what it found. Each of those jobs is one Yosys command, and the project Makefile runs them in order: read_verilog reads the code as SystemVerilog, hierarchy confirms the top module and its connections, proc turns the always block into registers and logic, opt simplifies, check looks for obvious problems, and stat reports the counts.

    The cells in the report are generic, which means placeholders no factory built. The report names four of them, measured on Yosys 0.69+post on macOS: $add is an adder of some width, $not is an inverter, $reduce_or collapses many bits into one decision, and $sdffe is a flip-flop that holds one bit across each clock edge. Other Yosys versions report different names and counts for the same design. Any technology could implement these placeholders, which is exactly why this check cannot answer area, speed, or power. Those answers need a mapped netlist built from a real library, plus timing constraints, and that work belongs to the synthesis course.

    So the check answers one question well: the code describes hardware with no structural surprise. It leaves the rest alone. Whether the hardware does the right thing is the testbench's job. How big it is, how fast it runs, and how much power it burns are questions for a mapped flow. A passing synthesis check next to a failing simulation is still a broken design.

    Four generic cells, not a chip

    The figure below draws the middle of the report as four boxes between the inputs and the count register. Look at the middle column first: one box per generic cell, with the job each one does inside the counter. Nothing in the picture comes from a factory library, so nothing in it has an area or a delay.

    What Yosys found in the counter: four generic cells between the inputs and the count register. Look at the middle column first; each box is a placeholder, not a mapped gate.

    Run the check and read every line

    The listing below is the synth target from the project Makefile. It is the whole check in one command.

    Diagram
    SHELL := /bin/bash
    IVERILOG ?= iverilog
    VVP      ?= vvp
    YOSYS    ?= yosys
    VERILATOR ?= verilator
    RTL := rtl/mini_controller.sv
    TB  := tb/tb_mini_controller.sv
    BUILD := build
    
    .PHONY: help sim lint synth all clean check-tools
    .DEFAULT_GOAL := all
    help:
    	@echo "Targets: sim lint synth all check-tools clean"
    
    all: lint sim synth
    
    $(BUILD):
    	mkdir -p $(BUILD)
    
    sim: | $(BUILD)
    	$(IVERILOG) -g2012 -Wall -s tb_mini_controller -o $(BUILD)/sim.vvp $(RTL) $(TB)
    	set -o pipefail; cd $(BUILD) && $(VVP) sim.vvp | tee sim.log
    	@grep -c "^PASS:" $(BUILD)/sim.log | grep -qx 1
    
    lint:
    	$(VERILATOR) --lint-only -Wall --top-module mini_controller $(RTL)
    
    synth: | $(BUILD)
    	$(YOSYS) -Q -T -p 'read_verilog -sv $(RTL); hierarchy -check -top mini_controller; proc; opt; check -assert; stat' > $(BUILD)/synth.log
    
    check-tools:
    	@bash scripts/check_tools.sh
    
    clean:
    	rm -rf $(BUILD)

    This listing is the project's synth target: one Yosys command over the design file, with its output saved to the build log.

    Diagram
    # captured terminal output
    $ make synth && tail -n 22 build/synth.log
    mkdir -p build
    yosys -Q -T -p 'read_verilog -sv rtl/mini_controller.sv; hierarchy -check -top mini_controller; proc; opt; check -assert; stat' > build/synth.log
    5. Executing CHECK pass (checking for obvious problems).
    Checking module mini_controller...
    Found and reported 0 problems.
    
    6. Printing statistics.
    
    === mini_controller ===
    
            +----------Local Count, excluding submodules.
            | 
            8 wires
           14 wire bits
            5 public wires
            8 public wire bits
            5 ports
            8 port bits
            4 cells
            1   $add
            1   $not
            1   $reduce_or
            1   $sdffe

    This output came from Yosys 0.69+post on macOS. The first line creates the build folder, the second runs the six jobs and saves the log, and the third prints the tail of that log.

    • Read the code. read_verilog -sv parses the design file as SystemVerilog. Note what is missing: the testbench is never read, so none of its simulation-only code can confuse this check.

    • Confirm the structure. hierarchy -check -top mini_controller names the top module and verifies that every connection resolves.

    • Build and simplify. proc turns the clocked process into registers and logic, and opt removes what the translation left redundant.

    • Check for problems. The CHECK pass reports 0 problems, measured on Yosys 0.69+post on macOS. That number means no obvious structural defect, not a correct design.

    • Count the result. The stat block lists 4 cells, measured on Yosys 0.69+post on macOS: one $add, one $not, one $reduce_or, one $sdffe. Other Yosys versions report different names and counts, so treat the exact list as illustrative of this version.

    Predict first The next section runs plain check, without -assert, on a design with an undriven wire. What exit status do you expect: 0 or nonzero?

    You might expect a nonzero status, since the design has a real defect. It exits 0. The warning is real but the status says success, which is why the Makefile uses check -assert instead.

    Break it on purpose: a wire with no driver

    The module below is small and almost right. Output y follows input a, and output z follows wire w, but nothing ever drives w.

    bad.sv
    1
    2
    3
    4
    5
    module bad (input logic a, output logic y, output logic z);
        logic w;
        assign y = a;
        assign z = w;
    endmodule

    This listing is the bad design the transcripts below check: a complete module with one wire that has no driver.

    Diagram
    # captured terminal output
    $ yosys -Q -T -p 'read_verilog -sv yodemo/bad.sv; hierarchy -check -top bad; proc; opt; check -assert' | tail -n 4
    ERROR: Found 1 problems in 'check -assert'.
    5. Executing CHECK pass (checking for obvious problems).
    Checking module bad...
    Warning: Wire bad.\z is used but has no driver.
    Found and reported 1 problems.

    This output came from Yosys 0.69+post on macOS. The last line names the defect: wire w inside module bad is used but has no driver. In hardware that wire floats, so z is unknown.

    Diagram
    # captured terminal output
    $ yosys -Q -T -p 'read_verilog -sv yodemo/bad.sv; hierarchy -check -top bad; proc; opt; check; stat' > /dev/null; echo "without -assert: exit status $?"
    without -assert: exit status 0

    Without -assert the same design exits with status 0, measured on Yosys 0.69+post on macOS. The warning printed, but the status says success, so a scripted loop would march on.

    Diagram
    # captured terminal output
    $ yosys -Q -T -p 'read_verilog -sv yodemo/bad.sv; hierarchy -check -top bad; proc; opt; check -assert; stat' > /dev/null 2>&1; echo "with -assert: exit status $?"
    with -assert: exit status 1

    With -assert the same design exits with status 1, measured on Yosys 0.69+post on macOS. That one flag is why the Makefile uses check -assert: a warning you could miss becomes a failure you cannot. The fix is ordinary hardware thinking: drive w from a real source, or remove the output that needs it, then re-run until the report returns to 0 problems.

    Three ways this step fools beginners

    • Reading stat as area. Four generic cells say the structure is small and regular. They say nothing about square microns, because no library was involved. Wait for the mapped flow before any area claim.

    • Ignoring a warning because the run exited 0. Plain check warns about the undriven wire and still reports success. Treat every Yosys warning as a defect until you understand it, and keep -assert in the command so the exit status agrees.

    • Calling a synthesized design a verified design. Synthesis never runs your testbench, so it cannot catch a wrong priority or a missed wrap. A green check plus a red simulation is a broken design; Tests That Can Fail shows how to earn trust in behavior.

    Rule: a passing synthesis check means the code describes hardware; it says nothing about correct behavior, area, speed, or power.

    Check yourself stat reports 4 cells. Does that tell you the chip area?

    No. The cells are generic placeholders counted before any mapping to a real library, measured on Yosys 0.69+post on macOS, and other versions report different names and counts. Area needs a mapped netlist plus library data, which this check never touches.

    Check yourself Why does the Makefile use check -assert instead of plain check?

    Plain check exits 0 on a design with an undriven wire, so a real defect looks like success. With -assert the same design exits 1, so the loop stops and the warning gets fixed instead of filed away.

    Interview

    Asked: "What does a successful synthesis run tell you?"

    Weak answer: That the design is correct and ready for the back end.

    Strong answer: That the code describes hardware with no structural surprise: it parses, its hierarchy resolves, its processes become registers and logic, and check found 0 problems, measured on Yosys 0.69+post on macOS. It says nothing about behavior, which the testbench owns, and nothing about area, speed, or power, which need a mapped netlist and constraints.

    Follow-ups: (1) What would you add to learn about area? (2) Why does this check run before any timing constraint exists?

    Key takeaways

    • A first synthesis check asks whether the code describes hardware; generic cells are placeholders, not silicon.

    • Read every line of the report: 0 problems from check and the cell list from stat, measured on your tool version.

    • Use check -assert so a warning becomes a failure; plain check exits 0 on a real defect.

    Keep going

    Next: Lesson 4.6, Simulation Code vs Synthesizable Code. The check reads only the design file. Next you learn why: some testbench code could never become hardware.

    Related topics

    • Synthesis: Flow Overview

    Previous

    22 / 47

    Next: Simulation Code vs Synthesizable Code

    Up next

    Up nextSimulation Code vs Synthesizable Code

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Compile, Elaborate, Simulate, Synthesize, Lint
    • First Simulation
    • Waveforms with GTKWave