Digital Design & Verification (Verilog, SystemVerilog, VLSI) Module 11 – Lint, synthesis, timing, power and test
Logic synthesis with Yosys
Run a Yosys synthesis script pass by pass on an 8-bit counter, see what proc, opt, techmap and abc each do to it, and read the cell statistics.
What you will learn
- Run a Yosys synthesis script and explain each major pass
- Map one design to generic gates, FPGA LUTs and standard cells
- Read cell statistics and estimate area
- Recognise synthesis messages that point to RTL problems
Before you start
What you’ll learn · Before you start
What you will learn
- Run a Yosys synthesis script and explain each major pass
- Map one design to generic gates, FPGA LUTs and standard cells
- Read cell statistics and estimate area
- Recognise synthesis messages that point to RTL problems
Before you start
On this page
Synthesis turned this lesson’s 13-line counter into 22 gates and flip-flops, and the design passed through 101 cells on the way there. logic synthesis: The step that turns RTL into a netlist of a target's cells: standard cells for a chip, or look-up tables and flip-flops for an FPGA. More in “How chips are designed and verified” with Yosys is a script of passes, each one a command whose result you can count, so you can watch what every pass does to your design and notice when one does something you did not mean.
Here you run the main passes one at a time on an 8-bit counter, read the cell statistics after each, and check the result against Yosys’s whole default script. Then the same counter goes to three targets, with the area each costs, and two short designs show the synthesis messages that point to bugs in the RTL.
Synthesis builds cells from always blocks, one pass at a time
counter.sv is an 8-bit counter with a synchronous reset and an enable, written as one always_ff block. Yosys reads it
into RTLIL: Yosys's internal form of a design: modules made of cells, wires and processes. Every Yosys pass reads RTLIL and writes it back, so a script is a chain of rewrites of one design., its own form of a design, and every pass after that reads RTLIL and rewrites it.
Step through the passes of a typical script, with the number of cells the counter has after each:
The drawing shows the whole scene; its 8 steps are listed below.
Every step as text
- Read. read_verilog -sv parses counter.sv and turns it into RTLIL, Yosys's own form of a design. The always_ff block is still a process, a list of assignments, not yet any hardware.
- The top module. hierarchy -top counter makes counter the top of the design and checks that every module it uses is there. Modules nobody uses are dropped.
- Processes become cells. proc turns the always_ff block into four coarse cells, a $dff for the eight flip-flops, a $mux for the enable, a $mux for the reset, and an $add for q plus 1.
- Simplify. opt folds both multiplexers into the flip-flop, which becomes one $sdffe, a flip-flop with a synchronous reset and an enable. Two cells are left.
- Find structures. fsm looks for state machines to re-encode and memory for arrays to map to RAM. The counter has neither, so nothing changes here.
- Gates. techmap replaces each coarse cell with gates from Yosys's own gate library. The 8-bit adder alone becomes dozens of AND, OR and XOR gates, 101 cells in all.
- Optimise. abc, the logic optimiser that Yosys runs as a pass, rewrites the gates into fewer of them. The counter ends with 22 cells, 8 of them flip-flops.
- Count. stat lists the cells by type after any pass. Reading it after each step is how you see what each pass did, and spot a pass that did something you did not mean.
Two of those passes do the work that a person would call synthesis. proc turns processes, the always blocks, into
coarse cells: a $dff for the eight flip-flops, a $mux for the enable and one for the reset, an $add for the
increment. techmap later replaces each coarse cell with gates from Yosys’s own gate library, the step called
technology mapping: The step of synthesis that replaces generic cells with the cells of a target: gates of a library, look-up tables and flip-flops of an FPGA, or the standard cells of a chip process.. Between and after them, opt merges and removes cells, and
abc rewrites the gates into fewer ones.
Yosys’s built-in reader takes Verilog-2005 and a part of SystemVerilog with read_verilog -sv; the build used here
also has read_slang, a front end built on the slang compiler, which reads far more of SystemVerilog, as the
lesson on structs and interfaces showed on an
interface design.
Checkpoint
Check: What the main passes do
Cell statistics show what each pass did
stat counts the cells of a design by type, and tee -q -o writes its report to a file. passes.ys runs the four
passes by hand and keeps a report after each; the last command runs synth, Yosys’s default script, on the same RTL:
hdl/counter.sv
// A W-bit counter with a synchronous reset and an enable: the design that every target synthesises below.
module counter #(
parameter int W = 8
) (
input logic clk,
input logic rst, // synchronous, active high
input logic en,
output logic [W-1:0] q
);
always_ff @(posedge clk)
if (rst) q <= '0;
else if (en) q <= q + 1'b1;
endmodule hdl/passes.ys
# The main passes of a synthesis script, one at a time, with the cell statistics after each.
read_verilog -sv counter.sv
hierarchy -check -top counter
proc
tee -q -o proc.txt stat
opt
tee -q -o opt.txt stat
techmap
tee -q -o techmap.txt stat
opt
abc
opt_clean
tee -q -o abc.txt stat Commands · hdl/passes_session.py
from session import run
# passes.ys runs proc, opt, techmap and abc by hand on the 8-bit counter and keeps the statistics after each; the
# grep shows the cell counts. Then synth, the whole default script, on the same counter.
run("""
yosys -q passes.ys
grep -E "cells|[$]" proc.txt opt.txt techmap.txt abc.txt
yosys -q -p "read_verilog -sv counter.sv; synth -top counter; tee -q -o synth.txt stat"
grep -E "cells|[$]" synth.txt
""") Output
# Yosys 0.69
$ yosys -q passes.ys
$ grep -E "cells|[$]" proc.txt opt.txt techmap.txt abc.txt
proc.txt: 4 cells
proc.txt: 1 $add
proc.txt: 1 $dff
proc.txt: 2 $mux
opt.txt: 2 cells
opt.txt: 1 $add
opt.txt: 1 $sdffe
techmap.txt: 101 cells
techmap.txt: 32 $_AND_
techmap.txt: 8 $_MUX_
techmap.txt: 8 $_NOT_
techmap.txt: 20 $_OR_
techmap.txt: 8 $_SDFFE_PP0P_
techmap.txt: 25 $_XOR_
abc.txt: 22 cells
abc.txt: 5 $_AND_
abc.txt: 1 $_NAND_
abc.txt: 1 $_NOT_
abc.txt: 8 $_SDFFE_PP0P_
abc.txt: 1 $_XNOR_
abc.txt: 6 $_XOR_
$ yosys -q -p "read_verilog -sv counter.sv; synth -top counter; tee -q -o synth.txt stat"
$ grep -E "cells|[$]" synth.txt
22 cells
5 $_AND_
1 $_NAND_
1 $_NOT_
8 $_SDFFE_PP0P_
1 $_XNOR_
6 $_XOR_
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 passes_session.py
Read the four reports in order. After proc the counter is 4 cells. After opt it is 2: the two multiplexers went
into the flip-flop, now a $sdffe, a flip-flop with a synchronous reset and an enable. techmap turned those 2 cells
into 101, and abc brought them down to 22, of which 8 are the flip-flops, as $_SDFFE_PP0P_. Yosys’s cell manual
spells that name out: a rising clock edge, an active-high reset that loads 0, and an active-high enable. synth ended
at the same 22 cells as the script by hand.
A report like this is a check on the RTL. Eight flip-flops for an 8-bit counter is right; a $_DLATCH_ cell, Yosys’s
latch, in a design that should have none is a bug; and a module whose report lists no cells at all has lost its logic.
Yosys 0.69 removed four options
The 0.69 release removed -retime, -noabc9, -abc2 and -abc from its synthesis passes, so older scripts and
tutorials that pass them now stop with an error. This track pins Yosys 0.69.
The same RTL can go to three kinds of target, and each is a line of the script:
- Generic gates:
synthalone maps to Yosys’s own gates, a netlist for simulation and quick comparisons. - FPGA cells:
synth_ice40maps to an iCE40’s look-up tables, carry cells and flip-flops. - Standard cells:
dfflibmapandabcread a Liberty file: A text file, in the Liberty format, that describes the cells of a standard-cell library: each cell's function, pins, area, timing and power, at one corner of voltage and temperature. and map to the standard cell: A gate, flip-flop or other small circuit drawn once by a library's makers to a fixed height, so that place and route can line cells up in rows. A chip's logic is built from thousands or millions of them. of a real chip library.
Checkpoint
Check: Reading cell statistics
One counter on three targets, with the area each one costs Pro: opens with a Pro, Premium or Ultimate pass
The same 13 lines become different hardware on each target, and only one of the three reports has a real area. This part maps the counter three ways, reads where its 280.27 µm² go, and measures what sharing one adder saves.
In this part:
- Generic gates, iCE40 cells and SKY130 cells, measured on one counter
- Where 280.27 µm² goes, worked from the Liberty file
- Drive strengths: what the _1 at the end of every cell buys
- A list of cells the mapper must not use
- Sharing one adder, measured on all three targets
2 runnable examples (Commands, alu8.sv, alu8_shared.sv, sky130.ys) · about 5 minutes
Opening this part with your pass…
This part opens with any MySmartCoPilot pass.
- Pro pass · 1 week₹79$2.99
- 30 days₹179$5.99
- 1 year₹1,699$45
One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.
Passes can’t be bought right now, so this part can’t be opened at the moment. The free part above stands on its own. If you have a pass, enter your licence key.
It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).
Synthesis messages that point to RTL bugs, reproduced Pro: opens with a Pro, Premium or Ultimate pass
Synthesis rarely stops on a bug; it builds what the code says and writes a line in its log. This part reproduces two such lines, a latch and an undriven wire that took a whole design with it, and lists the messages worth reading in every log.
In this part:
- A latch from always @*, reported only as a warning
- An undriven wire that took a whole MAC with it
- Five messages worth reading in every log
- Turning the log into a check that a script can fail
1 runnable example (Commands, dec_latch.v, mac_typo.sv) · about 4 minutes
Opening this part with your pass…Pro part. It opens with the same pass as the part above.
Practise: summarise a stat report
The exercise turns a stat report into the numbers this lesson reads from one: cells, flip-flops, latches and the
rest. Its sample tests are the counter’s reports from the passes above:
Exercise · Easy · Python
Summarise a Yosys stat report
Yosys's stat prints a design's cells by type, under a line with their total. After proc, this lesson's counter printed, among its other lines, 4 cells, then 1 $add, 1 $dff and 2 $mux, each indented by spaces.
Write summary(report). It takes the text of one such report, for one module, and returns a dictionary with four counts:
"cells": the total;"flip_flops": the cells whose type containsdffin any case, such as$dff,$sdffeor$_SDFFE_PP0P_;"latches": the cells whose type containsdlatchin any case;"other": the rest.
A cell line is a count followed by a type that starts with $ or a letter, and every other line (wires, wire bits, ports, the module's name) is ignored. A report with no cells line, which is what a module that lost all its logic prints, gives four zeros. If the cell lines do not add up to the total, raise ValueError.
Starter code · stat_summary.py
def summary(report):
"""Cells, flip-flops, latches and other cells of one module's stat report."""
return {"cells": 0, "flip_flops": 0, "latches": 0, "other": 0} The sample tests · test_stat_summary.py
from stat_summary import summary
PROC = """=== counter ===
6 wires
28 wire bits
4 cells
1 $add
1 $dff
2 $mux
"""
ABC = """=== counter ===
4 ports
11 port bits
22 cells
5 $_AND_
1 $_NAND_
1 $_NOT_
8 $_SDFFE_PP0P_
1 $_XNOR_
6 $_XOR_
"""
def test_after_proc():
"""counts the counter's report after proc: one flip-flop cell and three others"""
assert summary(PROC) == {"cells": 4, "flip_flops": 1, "latches": 0, "other": 3}
def test_after_abc():
"""counts the eight $_SDFFE_PP0P_ cells as flip-flops"""
assert summary(ABC) == {"cells": 22, "flip_flops": 8, "latches": 0, "other": 14}
def test_latches():
"""counts $_DLATCH_ cells as latches, not flip-flops"""
report = " 5 cells\n 2 $_DLATCH_P_\n 3 $_AND_\n"
assert summary(report) == {"cells": 5, "flip_flops": 0, "latches": 2, "other": 3}
def test_no_cells():
"""gives zeros for a module whose report has wires and ports but no cells"""
report = "=== mac ===\n 6 wires\n 5 ports\n"
assert summary(report) == {"cells": 0, "flip_flops": 0, "latches": 0, "other": 0}
def test_total_must_match():
"""refuses a report whose cell lines do not add up to its total"""
try:
summary(" 3 cells\n 1 $add\n")
except ValueError:
return
raise AssertionError("no ValueError for a total of 3 with 1 cell listed") A hint
Split each line into words. A line of two words whose first word is a number is either the total (second word cells) or one cell type; match the type with type.lower() and in.
Results of the sample tests
| Test | Result | Details |
|---|
What your code printed
The sample tests run on this device, in your browser (Pyodide): nothing is sent to mysmartcopilot.com. The first run downloads Python (about 13.5 MB), which is kept for the next runs. A check in your browser is feedback for you, not proof that the code is right for every input.
Then test yourself on the passes and the statistics. The questions start where your answers have been weakest so far:
Practice that adapts to you
Practise this lesson
6 questions about 4 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.
Interview questions
What does Yosys’s proc pass do?
It turns processes, the always blocks of the RTL, into cells. Each clocked block becomes flip-flop cells such as
$dff, with multiplexers for its if and case branches, and each combinational block becomes multiplexers and logic;
a variable that some path leaves unassigned becomes a latch. In this lesson’s counter, proc made 4 cells: a $dff,
two $mux and an $add. Later passes then merge and map those cells.
Three harder questions follow, on a design that synthesised to nothing, an area over budget and comparing FPGA and chip results:
-
Fresher to mid
You synthesise a 20-bit multiply-accumulate unit and the statistics list no cells at all, while synthesis ends with status 0 and prints 16 warnings. Walk through what most likely happened, how you would confirm it, and how your flow should catch it before a netlist leaves synthesis.
-
Mid to senior
A block synthesised to SKY130 standard cells comes out 10 % over its area budget. How do you find where the area goes, what would you try first in the RTL, and how do you know a change helped?
-
Fresher to mid
The same 8-bit counter synthesises to 22 of Yosys's generic cells, and to other counts on an iCE40 and in a standard-cell library. A manager asks which number to quote for how big the design is. What do you answer, and how would you compare an FPGA cost with a chip cost?
Flashcards · 7 cards
Recall it, then check
Say the answer to yourself before you look: recalling it is what makes it stick.
-
What do the Yosys passes proc, opt, techmap and abc do?
proc turns always blocks into coarse cells; opt merges and removes cells; techmap replaces coarse cells with gates from Yosys's own library; abc rewrites the gates into fewer ones.
-
How did the 8-bit counter's cell count change pass by pass?
4 cells after proc, 2 after opt, 101 after techmap and 22 after abc, 8 of them flip-flops. The default synth script ended at the same 22.
-
What did opt do with the counter's two multiplexers?
It folded them into the flip-flop, which became a $sdffe, a flip-flop with a synchronous reset and an enable.
-
What does the Yosys cell name $_SDFFE_PP0P_ spell out?
A rising clock edge, an active-high synchronous reset that loads 0, and an active-high enable.
-
Which stat findings point to an RTL problem?
A $_DLATCH_ cell in a design that should have no latch, a flip-flop count other than you expect, and a module whose report lists no cells at all, which has lost its logic.
-
What happens to an older Yosys script that passes -retime, -noabc9, -abc2 or -abc?
It stops with an error: the 0.69 release removed those options from its synthesis passes.
-
How does one RTL file go to three kinds of target in Yosys?
synth maps to Yosys's generic gates; synth_ice40 maps to an iCE40's LUTs, carry cells and flip-flops; dfflibmap and abc read a Liberty file and map to a chip library's standard cells.
Key takeaways
- Yosys synthesises with a script of passes over RTLIL: proc turns always blocks into cells, opt merges and removes cells, techmap maps them to gates and abc rewrites the gates.
- Reading stat after each pass shows what it did: the counter went from 4 cells to 2, then 101, then 22.
- The cell statistics are a check on the RTL: the flip-flops you expect, no latch cells you did not want, and no module with no cells at all.
Terms in this lesson
- Liberty file
- A text file, in the Liberty format, that describes the cells of a standard-cell library: each cell's function, pins, area, timing and power, at one corner of voltage and temperature.
- RTLIL
- Yosys's internal form of a design: modules made of cells, wires and processes. Every Yosys pass reads RTLIL and writes it back, so a script is a chain of rewrites of one design.
- standard cell
- A gate, flip-flop or other small circuit drawn once by a library's makers to a fixed height, so that place and route can line cells up in rows. A chip's logic is built from thousands or millions of them.
- technology mapping
- The step of synthesis that replaces generic cells with the cells of a target: gates of a library, look-up tables and flip-flops of an FPGA, or the standard cells of a chip process.
References
- Yosys command reference: synth, the default synthesis script (YosysHQ)
- Yosys command reference: technology mapping (techmap, abc and its -constr sizing, dfflibmap) (YosysHQ)
- Yosys command reference: design status (stat, check) (YosysHQ)
- Yosys command reference: proc and its sub-passes (YosysHQ)
- Yosys internal cell library: flip-flop cells such as $_SDFFE_PP0P_ (YosysHQ)
- Yosys command reference: front ends (read_verilog, read_slang and others) (YosysHQ)
- Yosys CHANGELOG (0.68 to 0.69, options removed from the synthesis passes) (YosysHQ)
- SkyWater SKY130 PDK documentation: foundry-provided standard cell libraries (sky130_fd_sc_hd) (SkyWater Technology and Google (SkyWater PDK project))
- OpenROAD-flow-scripts: the sky130hd platform configuration (Liberty file, cells not to use) (The OpenROAD Project)
- yosys-slang, a SystemVerilog front end for Yosys built on slang (yosys-slang project)
Report a problem with this lesson
Kept only in this browser. Your Learn progress