Yosys
Yosys
CONTENTS 1
YosysHQ Yosys, Version 0.48-dev
Note
This documentation recently went through a major restructure. If you’re looking for something from the
previous version and can’t find it here, please let us know. Documentation from before the restructure can still
be found by switching to version 0.36 or earlier. Note that the previous theme does not include a version
switcher.
Yosys is an open source framework for RTL synthesis. To learn more about Yosys, see What
is Yosys. For a quick guide on how to get started using Yosys, check out Getting started with
Yosys. For the complete list of commands available, go to commandindex.
CONTENTS 1
CHAPTER
ONE
WHAT IS YOSYS
Yosys began as a BSc thesis project by Claire Wolf intended to support synthesis for a CGRA
(coarse-grained reconfigurable architecture). It then expanded into more general infrastructure
for research on synthesis.
Modern Yosys has full support for the synthesizable subset of Verilog-2005 and has been
described as “the GCC of hardware synthesis.” Freely available and open source, Yosys finds
use across hobbyist and commercial applications as well as academic.
Note
A permissive license lets people do anything with your code with proper attribution and without warranty. The
ISC license is functionally equivalent to the BSD 2-Clause and MIT licenses, removing some language that is no
longer necessary.
Together with the place and route tool nextpnr, Yosys can be used to program some FPGAs
with a fully end-to-end open source flow (Lattice iCE40 and ECP5). It also does the synthesis
portion for the OpenLane flow, targeting the SkyWater 130nm open source PDK for fully open
source ASIC design. Yosys can also do formal verification with backends for solver formats like
SMT2.
Yosys, and the accompanying Open Source EDA ecosystem, is currently maintained by Yosys
Headquarters, with many of the core developers employed by YosysHQ GmbH. A commercial
extension, Tabby CAD Suite, includes the Verific frontend for industry-grade SystemVerilog
and VHDL support, formal verification with SVA, and formal apps.
CONTENTS 1
1.1 What you can do with Yosys
• Read and process (most of) modern Verilog-2005 code
• Perform all kinds of operations on netlist (RTL, Logic, Gate)
• Perform logic optimizations and gate mapping with ABC
CONTENTS 1
YosysHQ Yosys, Version 0.48-dev
In special cases such as synthesis for coarse-grain cell libraries or when testing
new synthesis algorithms it might be necessary to write a custom HDL synthesis
tool or add new features to an existing one. In these cases the availability of a
Free and Open Source (FOSS) synthesis tool that can be used as basis for custom
tools would be helpful.
In the absence of such a tool, the Yosys Open SYnthesis Suite (Yosys) was
developed. This document covers the design and implementation of this tool.
At the moment the main focus of Yosys lies on the high-level aspects of
digital synthesis. The pre-existing FOSS logic-synthesis tool ABC is used by
Yosys to perform advanced gate-level optimizations.
An evaluation of Yosys based on real-world designs is included. It is shown that
Yosys can be used as-is to synthesize such designs. The results produced by
Yosys in this tests where successfully verified using formal verification and are
comparable in quality to the results produced by a commercial synthesis tool.
Yosys is a Verilog HDL synthesis tool. This means that it takes a behavioural design
description as input and generates an RTL, logical gate or physical gate level description of the
design as output. Yosys’ main strengths are behavioural and RTL synthesis. A wide range of
commands (synthesis passes) exist within Yosys that can be used to perform a wide range of
synthesis tasks within the domain of behavioural, rtl and logic synthesis. Yosys is designed to be
extensible and therefore is a good basis for implementing custom synthesis tools for specialised
tasks.
System Level
System Design
High Level
High Level Synthesis (HLS)
Switch Level
1 A quick investigation into FOSS VHDL tools yielded similar grim results for FOSS VHDL
synthesis tools.
This section covers how to get started with Yosys, from installation to a guided walkthrough of
synthesizing a design for hardware, and finishing with an introduction to writing re-usable
Yosys scripts.
2.1 Installation
This document will guide you through the process of installing Yosys.
Targeted architectures
The OSS CAD Suite releases nightly builds for the following architectures:
7
git clone --recurse-submodules https://github.com/YosysHQ/yosys.git # ..or..
git clone https://github.com/YosysHQ/yosys.git
cd yosys
7
YosysHQ Yosys, Version 0.48-dev
Note
As of Yosys v0.47, releases include a yosys.tar.gz file which includes all source code and all sub-modules in a
single archive. This can be used as an alternative which does not rely on git.
Supported platforms
The following platforms are supported and regularly tested:
• Linux
• macOS
Other platforms which may work, but instructions may not be up to date and are not regularly
tested:
• FreeBSD
• WSL
• Windows with (e.g.) Cygwin
Build prerequisites
A C++ compiler with C++17 support is required as well as some standard tools such as
GNU Flex, GNU Bison, Make and Python. Some additional tools: readline, libffi, Tcl and zlib;
are optional but enabled by default (see ENABLE_* settings in Makefile). Graphviz and Xdot
are used by the show command to display schematics.
Installing all prerequisites for Ubuntu 20.04:
sudo apt-get install gperf build-essential bison flex \
libreadline-dev gawk tcl-dev libffi-dev git graphviz \
xdot pkg-config python3 libboost-system-dev \
or MacPorts:
sudo port install bison flex readline gawk libffi graphviz \
pkgconfig python311 boost zlib tcl
Note
On FreeBSD system use gmake instead of make. To run tests use: MAKE=gmake CXX=cxx CC=cc gmake 7
test
YosysHQ Yosys, Version 0.48-dev
For Cygwin use the following command to install all prerequisites, or select these additional
packages:
7
YosysHQ Yosys, Version 0.48-dev
setup-x86_64.exe -q --packages=bison,flex,gcc-core,gcc-g++,git,libffi-devel,libreadline-
˓→devel,make,pkg-config,python3,tcl-devel,boost-build,zlib-devel
Warning
As of this writing, Cygwin only supports up to Python 3.9.16 while the minimum required
version of Python is 3.11. This means that Cygwin is not compatible with many of the
Python-based frontends. While this does not currently prevent Yosys itself from working,
no guarantees are made for contin- ued support. It is instead recommended to use Windows
Subsystem for Linux (WSL) and follow the instructions for Ubuntu.
Build configuration
The Yosys build is based solely on Makefiles, and uses a number of variables which influence
the build process. The recommended method for configuring builds is with a Makefile.conf file
in the root yosys directory. The following commands will clean the directory and provide an
initial configuration file:
make config-clang # ..or..
make config-gcc
Check the root Makefile to see what other configuration targets are available. Other variables can
then be added to the Makefile.conf as needed, for example:
echo "ENABLE_ZLIB := 0" >> Makefile.conf
Using one of these targets will set the CONFIG variable to something other than none, and will
override the environment variable for CXX. To use a different compiler than the default when
building, use:
make CXX=$CXX # ..or..
make CXX="g++-
11"
Note
Setting the compiler in this way will prevent some other options such as ENABLE_CCACHE from working as
expected.
If you have clang, and (a compatible version of) ld.lld available in PATH, it’s recommended to
speed up incremental builds with lld by enabling LTO with ENABLE_LTO=1. On macOS,
LTO requires using clang from homebrew rather than clang from xcode. For example:
make ENABLE_LTO=1 CXX=$(brew --prefix)/opt/llvm/bin/clang++
By default, building (and installing) yosys will build (and install) ABC, using yosys-abc as the
executable name. To use an existing ABC executable instead, set the ABCEXTERNAL make
2.1. Installation 9
YosysHQ Yosys, Version 0.48-dev
variable to point to the desired executable.
2.1. Installation 9
YosysHQ Yosys, Version 0.48-dev
See also
Refer to Testing Yosys for details on testing Yosys once compiled.
2.1. Installation 9
YosysHQ Yosys, Version 0.48-dev
Good starting points for reading example source code to learn how to write passes are
passes/opt/opt_dff. cc and passes/opt/opt_merge.cc.
Users of the Qt Creator IDE can generate a QT Creator project file using make qtcreator.
Users of the Eclipse IDE can use the “Makefile Project with Existing Code” project type in
the Eclipse “New Project” dialog (only available after the CDT plugin has been installed) to
create an Eclipse project in order to programming extensions to Yosys or just browse the Yosys
code base.
See also
Advanced usage docs for Synth commands
2 #( parameter MAX_DATA=256,
localparam AWIDTH = $clog2(MAX_DATA)
3 ) ( input en, clk, rst,
output reg [AWIDTH-1:0] addr
4 );
initial addr = 0;
5
// async reset
7 if (rst)
addr <= 0;
8 else if (en) begin
if ({'0, addr} == MAX_DATA-1)
2.2. Synthesis starter 11
YosysHQ Yosys, Version 0.48-dev
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
(continues on next page)
While the open source read_verilog frontend generally does a pretty good job at processing
valid Verilog input, it does not provide very good error handling or reporting. Using an
external tool such as verilator before running Yosys is highly recommended. We can
quickly check the Verilog syntax of our design by calling verilator --lint-only fifo.v.
See also
Advanced usage docs for Loading a design
2.1.6 Elaboration
Now that we are in the interactive shell, we can call Yosys commands directly. Our overall
goal is to call synth_ice40 -top fifo, but for now we can run each of the commands
individually for a better sense of how each part contributes to the flow. We will also start
with just a single module; addr_gen.
At the bottom of the help output for synth_ice40 is the complete list of commands called
by this script. Let’s start with the section labeled begin:
read_verilog -D ICE40_HX -lib -specify +/ice40/cells_sim.v loads the iCE40 cell models
which al- lows us to include platform specific IP blocks in our design. PLLs are a common
example of this, where we might need to reference SB_PLL40_CORE directly rather than
being able to rely on mapping passes later. Since our simple design doesn’t use any of these IP
blocks, we can skip this command for now. Because these
cell models will also be needed once we start mapping to hardware we will still need to load them
later.
Note
// async reset
6
// increment address when enabled
if (rst)
8 addr <= 0;
11
12
13
14
15
16
17
18
19
20
21
Note
hierarchy should always be the first command after the design has been read. By specifying the top
module, hierarchy will also set the (* top *) attribute on it. This is used by other commands that need
to know which module is the top.
3. Executing AST frontend in derive mode using pre-parsed AST for module `\
addr_gen'. Generating RTLIL representation for module `\addr_gen'.
A $2
Y
B $eq
0 -> 31:8
7:0 - 7:0
255
rst
clk
PROC $1
en
o.v:12.2-20
fif .6
PROC $4
addr
fo.v:0.0-0.
fi 0
A $3
Y 7:0 - 7:0
1
B $add
To handle these, let us now introduce the next command: proc - translate processes to
netlists. proc is a macro command like synth_ice40 . Rather than modifying the design
directly, it instead calls a series of other commands. In the case of proc , these sub-commands
work to convert the behavioral logic of processes into multiplexers and registers. Let’s see
what happens when we run it. For now, we will call proc -noopt to prevent some automatic
optimizations which would normally happen.
clk
8'00000000 $1╲addr[7:0]
A $10 Y
rst
$0╲addr[7:0]
A
R $1
S
T 2
C
L $a
df Q
K f
A
D
A A
$3 A $2
Y Y $6 $8
B $add B $eq B Y B Y
addr $mux $mux
S S
7:0 - 7:0
1
8'00000000
0 -> 31:8
en
255
rst
clk AR
$12
ST $ad
CL ff Q
K
D
A A
$6 Y $8 Y
B B
$mux $mux
S S
A $2 Y
B $eq
8'11111111 en
YosysHQ Yosys, Version 0.48-dev
Note
clean - remove unused cells and wires can also be called with two semicolons after any
command, for example we could have called opt_expr;; instead of opt_expr; clean. You may notice some
scripts will end each line with ;;. It is beneficial to run clean before inspecting intermediate products to
remove disconnected parts of the circuit which have been left over, and in some cases can reduce the
processing
See also
Advanced usage docs for
• Converting process blocks
• Optimization passes
12.2. Executing AST frontend in derive mode using pre-parsed AST for module `\
addr_gen'. Parameter \MAX_DATA = 256
Generating RTLIL representation for module `$paramod\addr_gen\MAX_DATA=s32
˓→ '00000000000000000000000100000000'.
˓→ '00000000000000000000000100000000'.
Note
The number before a command’s output increments with each command run. Don’t worry if your numbers
don’t match ours! The output you are seeing comes from the same script that was used to generate the
images in this document, included in the source as fifo.ys. There are extra commands being run which
you don’t see, but feel free to try them yourself, or play around with different commands. You can always
start over with a clean slate by calling exit or hitting ctrl+d (i.e. EOF) and re-launching the Yosys interactive
terminal. ctrl+c (i.e. SIGINT) will also end the terminal session but will return an error code rather than
exiting gracefully.
We can also run proc now to finish off the full begin section. Because the design schematic is
quite large, we will be showing just the data path for the rdata output. If you would like to see
the entire design for yourself, you can do so with show - generate schematics using graphviz.
Note that the show command only works with a single module, so you may need to call it with
show fifo. Displaying schematics section in Scripting in Yosys has more on how to use show .
clk
rdata
raddr
CLK $60
clk Q
fifo_reader D $dff
en addr
rst $paramod╲addr_gen╲MAX_DATA=s32'00000000000000000000000100000000 1'x ADDR
rst $25
CLK DATA
$memrd
EN
1'x
The other highlighted block is a $memrd cell. At this stage of synthesis we don’t yet know
what type of memory is going to be implemented, but we do know that rdata <= data[raddr];
could be implemented as a read from memory. Note that the $memrd cell here is
asynchronous, with both the clock and enable signal undefined; shown with the 1'x inputs.
See also
Advanced usage docs for Converting process blocks
2.1.7 Flattening
At this stage of a synthesis flow there are a few other commands we could run. In
synth_ice40 we get these:
First off is flatten . Flattening the design like this can allow for optimizations between modules
which would otherwise be missed. Let’s run flatten;; on our design.
yosys> flatten
˓→ '00000000000000000000000100000000.
<suppressed ~2 debug messages>
yosys> clean
rst A
RS
T $6
C 6 Q fifo_reader.add
L $a
dff r
KD A $3 7:0 - 7:0 A
6
B $a Y
dd $55
1 A B $m Y
ux
$5 S
A$3
5 8'0000000 3 Y
B$m
clk $e Y 0 ux
8'11111111 q
B S
The pieces have moved around a bit, but we can see addr_gen module after proc -noopt from
earlier has replaced the fifo_reader block in rdata output after proc. We can also see that the
addr output has been
renamed to fifo_reader.addr and merged with the raddr wire feeding into the $memrd cell. This
wire merging happened during the call to clean which we can see in the output of flatten;;.
Note
flatten and clean would normally be combined into a single yosys> flatten;; output, but they
appear separately here as a side effect of using echo for generating the terminal style output.
Depending on the target architecture, this stage of synthesis might also see commands such as
tribuf with the -logic option and deminout . These remove tristate and inout constructs
respectively, replacing them with logic suitable for mapping to an FPGA. Since we do not
have any such constructs in our example running these commands does not change our
design.
Note
While the iCE40 flow had a flatten section and put proc in the begin section, some synthesis scripts will
instead include these in this section.
Part 1
In the iCE40 flow, we start with the following commands:
We’ve already come across opt_expr , and opt_clean is the same as clean but with more
verbose output. The check pass identifies a few obvious problems which will cause errors
later. Calling it here lets us fail faster rather than wasting time on something we know is
impossible.
Next up is opt -nodffe -nosdff performing a set of simple optimizations on the design. This
command also ensures that only a specific subset of FF types are included, in preparation for
the next command: fsm
2.2. Synthesis starter 28
YosysHQ Yosys, Version 0.48-dev
- extract and optimize finite state machines. Both opt and fsm are macro commands which are
explored in more detail in Optimization passes and FSM handling respectively.
Up until now, the data path for rdata has remained the same since rdata output after
flatten;;. However the next call to opt does cause a change. Specifically, the call to opt_dff
without the -nodffe -nosdff options is able to fold one of the $mux cells into the $adff to
form an $adffe cell; highlighted below:
yosys> opt_dff
A $3
B6 Y
$a
dd
A $5
B 3
S $m Y
ux
1 7:0 - 7:0
A $3
rst B5 Y
ARST
$e
CLK
D
fifo_reader.addr q 8'00000000
$74
EN
ren Q
$adffe 8'11111111 CLK $60 Q
ADDR D $dff
clk $25 DATA
CLK
$memrd
EN
rdata
1'x
1'x
See also
Advanced usage docs for
• FSM handling
• Optimization passes
Part 2
The next group of commands performs a series of optimizations:
A $3
B6 Y
$a
dd
A $5
B3
S $m
ux Y
A $3
B5 Y
$e
1'1 q 7:0 - 7:0 7:0 - 7:0
rst ARS
T $74 AD $25
Q fifo_reader.addr
DR $me 8'00000000
CLK CL mrd
ren
D 8'11111111 K D
EN
clk A
T CLK
D
$60 Q rdata
1'x
A $dff
1'x
Our next command to run is memory_dff - merge input/output DFFs into memory read ports.
7:0 - 7:0 7:0 - 7:0
yosys> memory_dff
A $3
B6 Y
$a
dd
A
$53 Y
B
$mux
A $35 S
Y
B $eq
AD
DR
AR
ST
CL $25
K
2.2. Synthesis starter 33
rst
ARST fifo_reader.addr
CLK
clk D $74
EN
Q
YosysHQ Yosys, Version 0.48-dev
$adffe 8'11111111 EN $memr D 8'00000000
SR d_v2
1'0
ST A
T rdata
1'1
A
1'0
As the title suggests, memory_dff has merged the output $dff into the $memrd cell and
converted it to a
$memrd_v2 (highlighted). This has also connected the CLK port to the clk input as it is now a
synchronous memory read with appropriate enable (EN=1'1) and reset (ARST=1'0 and SRST=1'0)
inputs.
See also
Advanced usage docs for
• Optimization passes
• Technology mapping
• Memory handling
Part 3
The third part of the synth_ice40 flow is a series of commands for mapping to DSPs. By
default, the iCE40 flow will not map to the hardware DSP blocks and will only be
performed if called with the -dsp flag: synth_ice40 -dsp. While our example has nothing
that could be mapped to DSPs we can still take a quick look at the commands here and
describe what they do.
See also
Advanced usage docs for Technology mapping
Part 4
That brings us to the fourth and final part for the iCE40 synthesis
flow:
2.2. Synthesis starter 35
YosysHQ Yosys, Version 0.48-dev
Listing 2.14: coarse section (part 4)
(continues on next page)
alumacc
opt
yosys> alumacc
1'1
$92
A CO
$90
BI X $91
$alu
1'0 Y
clk $$74 Q
adffe
CLK A
$53
D Y
ren A $35 8'00000000
8'11111111 Y B
B
$eq
1'0 ADDR
$25
ARST DATA rdata
emrd
CLK
1'1 EN
Once these cells have been inserted, the call to opt can combine cells which are now identical
but may have been missed due to e.g. the difference between $add and $sub .
The other new command in this part is memory - translate memories to basic cells. memory is
another
macro command which we examine in more detail in Memory handling. For this document,
let us focus just on the step most relevant to our example: memory_collect . Up until this
point, our memory reads and our memory writes have been totally disjoint cells; operating on
the same memory only in the abstract. memory_collect combines all of the reads and writes
for a memory block into a single cell.
1'1
$92
A CO
$90
BI X $91
$alu
1'0 Y
7:0 - 7:0
7:0 - 7:0
rst ARST fifo_reader.addr
$74
Q
CLK A
$53
ren D Y
8'11111111 A $35 8'00000000
Y B
B
$eq
1'0
clk
RD_ADDR
1'1
RD_ARS
T
data
1'0 RD_SRST $mem_ v2 rdata
RD_DATA
WR_ADD
R
$19 WR_CLK
WR_DATA
$20
Looking at the schematic after running memory_collect we see that our $memrd_v2 cell has
been replaced with a $mem_v2 cell named data, the same name that we used in fifo.v. Where
before we had a single set of signals for address and enable, we now have one set for reading
(RD_*) and one for writing (WR_*), as well as both WR_DATA input and RD_DATA output.
See also
Advanced usage docs for
• Optimization passes
• Memory handling
Final note
Having now reached the end of the the coarse-grain representation, we could also have gotten
here by running synth_ice40 -top fifo -run : map_ram after loading the design. The -run
<from_label>: <to_label> option with an empty <from_label> starts from the begin section,
while the <to_label> runs up to but including the map_ram section.
Memory blocks
Mapping to hard memory blocks uses a combination of memory_libmap and techmap .
$techmap601╲data.0.0.MASK
MASK
0 -> 10:9 14:14 - 7:7
RADDR
0:0 - 8:8 RCLK 6:6 - 6:6
RCLKE
data.0.0
RE RDATA
WADDR SB_RAM40_4K
A
$techmap601╲data.0.0.WADDR 10:10 - 5:5
B $561 Y
$552 rdata
$mux
WCLK S
clk 2:2 - 4:4
WCLKE
WDATA $559
$548 WE
rst ARST
fifo_reader.addr $techmap601╲data.0.0.WDATA
D $adffe
ren
1'1
1'1 $530
A CO
1'0 B $528 $529
X
BI $alu
Y
1'0 7:0 - 7:0 7:0 - 7:0
A
B $465 Y
$mux
8'00000000 S
A $403 Y
8'11111111 B $eq
The map_ram section converts the generic $mem_v2 into the iCE40 SB_RAM40_4K
(highlighted). We can also see the memory address has been remapped, and the data bits have
been reordered (or swizzled). There is also now a $mux cell controlling the value of rdata. In
fifo.v we wrote our memory as read-before-write, however the SB_RAM40_4K has undefined
behaviour when reading from and writing to the same address in the same cycle. As a result,
extra logic is added so that the generated circuit matches the behaviour of the
verilog. Synchronous SDP with undefined collision behavior describes how we could change our
verilog to match our hardware instead.
If we run memory_libmap under the debug command we can see candidates which were
identified for mapping, along with the costs of each and what logic requires emulation.
2.2. Synthesis starter 40
YosysHQ Yosys, Version 0.48-dev
- cost: 2048.000000
$546
[6] 0:0
- 0:0 0:
00:0-
6:6 0:0 - 0:0
$546 X ->-- 6:6
2:2 5:5
4:4
[2]
X -> 3:3
$546
[4] 4:4 - 2:2
X -> 1:1
$546 0:0 - 0:0
[0]
$547 00:0
->-10:9
8:8
[0]
0 -> 7:7
$547 7:1 - 6:0
[7:1]
$548
1'1
Note
The visual clutter on the RDATA output port (highlighted) is an unfortunate side effect of opt_clean on the
swizzled data bits. In connecting the $mux input port directly to RDATA to reduce the number of wires, the
$techmap579\data.0.0.RDATA wire becomes more visually complex.
See also
Arithmetic
Uses techmap to map basic arithmetic logic to hardware. This sees somewhat of an
explosion in cells as multi-bit $mux and $adffe are replaced with single-bit $_MUX_ and
$_DFFE_PP0P_ cells, while the $alu is replaced with primitive $_OR_ and $_NOT_ gates
and a $lut cell.
ice40_wrapcarry
techmap -map +/techmap.v -map +/ice40/arith_map.v
opt -fast
abc -dff -D 1 ( only if -retime)
ice40_opt
See also
Advanced usage docs for Technology mapping
Flip-flops
Convert FFs to the types supported in hardware with dfflegalize , and then use techmap
to map them. In our example, this converts the $_DFFE_PP0P_ cells to SB_DFFER.
We also run simplemap here to convert any remaining cells which could not be mapped to
hardware into gate-level primitives. This includes optimizing $_MUX_ cells where one of the
inputs is a constant 1'0, replacing it instead with an $_AND_ cell.
See also
Advanced usage docs for Technology mapping
LUTs
abc and techmap are used to map LUTs; converting primitive cell types to use $lut and
SB_CARRY cells. Note that the iCE40 flow uses abc9 rather than abc . For more on what these
2.2. Synthesis starter 46
YosysHQ Yosys, Version 0.48-dev
do, and what the difference between these two commands are, refer to The ABC toolbox.
C 0:0 - 2:2
D $717
Q
rst
2:2 - 0:0
0:0 - 3:3
C
D $718
Q
3:3 - 0:0
1'0
C 0:0 - 5:5
D $720
A Q
1:1 - 0:0 B $771 E $_DFFE_PP0P_
$_MU X_
Y
S
1'0
0:0 - 1:1
0:0 - 0:0
4:4 - 0:0 A
B $774
$_MU X_
S
Y
1'0
0:0 - 4:4
A
2:2 - 0:0
$772
0:0 - 2:2
0 -> 3:3
A
$lut 5:5 - 0:0
B Y
7:1 - 6:0 6:0 - 7:1 2'10 1:0 - 1:0 $_MUX_
S 0:0 - 6:6
1'0
A $870 Y
0:0 - 0:0 $_NOT_ 0:0 - 0:0 0:0 - 0:0
A
A $791 B $773 Y 0:0 - 3:3
B Y 3:3 - 0:0 $_MUX_
$871 $_OR_
1:1 - 0:0 A Y
$_NOT_ 2:2 - 0:0 0:0 - 0:0 A $799
0:0 - 0:0
B $_OR_ Y
A $970 Y A $797
Y A 0:0 - 5:5
6:6 - 0:0 $_NOT_ 3:3 - 0:0 $_OR_ 0:0 - 1:1 1'0
B 1:1 - 0:0 B Y
A $775
$794 $_MUX_
Y S
A $972 Y 0:0 - 3:3
B
7:7 - 0:0 $_NOT_ 5:5 - 0:0
0:0 - 0:0 A $796 0:0 - 0:0
C Y 0:0 - 7:7
B $_OR_ A
D $715
Q 0:0 - 0:0 fifo_reader.addr 2:2 - 0:0 A $964 Y A $792 B $777 Y
$ _NOT _ B Y 0:0 - 1:1 1'0 $ _MUX _
E $_DFFE_PP0P_ $_OR_ 1:1 - 0:0
S
6:6 - 0:0
C
D $719
Q
0:0 - 6:6
7:7 - 0:0
ren
C
D $721
Q
1:1 - 0:0
clk
0:0 - 7:7
C
D $722
Q 0:0 - 1:1
C
D $716
Q
16'x
1:1 - 0:0
0 -> 10:9 A
$552 [1]
B Y
$_MUX_
S
$559
1'1
15:15 - 15:15 0:0 - 1:1
1'1
$546 [7]
MASK
14:14 - 7:7
$546 [3]
7:7 - 7:7 7:7 - 14:14
X -> 15:15 RE
RADDR data.0.0
$546 [5]
WADDR SB_RAM40_4K 13:13 - 13:13
$techmap601╲data.0.0.RDATA
12:12 - 3:3
$546 [6]
$546 [4]
X -> 7:7
$552 [2] A
0 -> 10:9
$547 [0] B $812 Y
$ _MUX _
S
$559
$547 [7:1]
A
$552 [3]
1'1 B Y
$_MUX_
S
$559
A
$552 [4]
B Y
$_MUX_
S
$559 0:0 - 4:4
rdata
5:5 - 0:0
A 0:0 - 5:5
B $815
$_MU X_
$552 [5]
S
Y
$559
0:0 - 6:6
6:6 - 0:0
A
B $816
$_MU X_
$552 [6] Y
S
0:0 - 7:7
$559
A
B $817
$_MU X_
Y 0:0 - 0:0
$552 [7] S
$559 A
B $810
$_MU X_
Y
$552 [0] S
C 0:0 - 2:2
D $717
Q
rst
2:2 - 0:0
0:0 - 7:7
C
D $722
Q
7:7 - 0:0
A $772
2:2 $_AND_ Y 0:0 - 1:1
$964 B C
A Y - 0:0 0:0 - 2:2
2:2 - 0:0 D
$_NOT_ $716
Q
A $792 A $773 E SB_DFFER
$962 Y Y
3:3 - 0:0 A Y B $_OR_ 0:0 - 1:1 B $_AND_ 0:0 - 3:3 R
$_NOT_ 0:0 - 0:0 3:3 - 0:0
0:0 - 0:0
A $796 A
$871 $774
1:1 - 0:0 A Y Y Y
$_NOT_ 1:1 - 0:0 B $_OR_ 0:0 - 0:0 4:4 - 0:0 $_AND_ 0:0 - 4:4
B
A 0:0 - 0:0
B $791 Y A $799
$968 0:0 - 0:0 $_OR_ 0:0 - 0:0 Y
4:4 - 0:0 A Y A $775
$ _NOT _ 2:2 - 0:0 A
B $_OR_ Y 0:0 - 5:5 1:1 - 0:0
B $797 Y 0:0 - 1:1 B _AND_
A $_OR_ 1:1 - 0:0
$ $793 5:5 - 0:0
A $_OR_ Y 0:0 - 2:2
5:5 - 0:0 $ N O T __ B
3:3 - 0:0 A $776
966 Y 0:0 - 6:6
Y
C $970 A $794
6:6 - 0:0 A Y 0:0 - 3:3
D $715 $ _NOT _ B $_OR_
Y
A 0:0 - 7:7
0:0 - 0:0 $777
Q 0:0 - 0:0 fifo_reader.addr Y
E SB_DFFER 7:7 - 0:0 B $_AND_
A $972 Y
R 7:7 - 0:0 $_NOT_
0:0 - 1:1
A $771
$1076 0:0 - 0:0
0:0 - 0:0 A Y 0:0 - 0:0
$_NOT_
0:0 - 0:0
A $770
0:0 - 0:0
Y
7:1 - 6:0 6:0 - 7:1 B $_AND_
5:5 - 0:0
0:0 - 5:5
3:3 - 0:0
C
D $720
Q
0:0 - 3:3
4:4 - 0:0
ren
C
D $718
Q
0:0 - 4:4
6:6 - 0:0
clk
C
D $719 Q 0:0 - 6:6
C
D $721
Q
0 -> 10:9 A
$552 [4]
B Y
$_MUX_
S
$559
0:0 - 8:8
$546 [1]
X -> 11:11
WCLKE
10:10 - 5:5
5:5 - 5:5 5:5 - 10:10
6:6 - 0:0
0 -> 10:9
$552 [6] A
$816
1'1 B
$_MU X_
S
Y
$559
0:0 - 6:6
7:7 - 0:0
A
$817
$552 [7] B
$_MU X_
S
Y
0:0 - 7:7
$559
rdata
0:0 - 0:0
A $810 0:0 - 0:0
B
$_MU X_
$552 [0] Y
S
0:0 - 1:1
1:1 - 0:0
A $811
B
$_MU X_
$552 [1] Y
S
0:0 - 2:2
$559
A $812
B
$_MU X_
$552 [2] Y
S
0:0 - 3:3
3:3 - 0:0
A $813
B
$_MU X_
$552 [3] Y
S
C
D $720
Q
5:5 - 0:0
0:0 - 5:5
0:0 - 1:1
$2202
0:0 - 3:3 A Y
$lut 0:0 - 6:6
$2210
A Y
0:0 - 3:3
1'0 CI
$528.slice[5].carry
I0 CO
SB_CARRY A $2200 Y
I1 $lut
$80
A Y 0:0 - 0:0
CI 0:0 - 3:3 0:0 - 2:2 CI
1'0 A $2208 Y
I0 $528.slice[1].carry CO $lut 1'0 I0 $528.slice[4].carry CO
SB_CARRY SB_CARRY
1:1 - 0:0 I1 I1
CI
$528.slice[2].carry CI
D 1'0 I0 CO 1'0
$716 SB_CARRY I0 CO
E Q SB_CARRY 0:0 - 3:3 0:0 - 7:7
SB_DFFER I1
3:3 - 0:0
$2168
0:0 - 4:4 A Y
0:0 - 3:3 $2204 $lut
0:0 - 0:0 A Y
$lut
rst C
D $715
0:0 - 3:3 $2206 0:0 - 3:3
A Y
CI
C $528.slice[6].carry
1'0 I0 CO 0:0 - 3:3
$717 SB_CARRY
Q
E SB_DFFER
C
D $718 16'0000000000000000
Q
4:4 - 0:0 E SB_DFFER
0 -> 10:9
ren
C
D $719
Q
0:0 - 8:8
clk
C
D $721
Q
C
D $722
Q
15:15 - 15:15
1'1
MASK
7:7 - 7:7 7:7 - 14:14
1'1 14:14 - 7:7
$1276
$techmap2134╲data.0.0.RDATA
0 -> 15:15 RE data.0.0
$1268 RDATA 3:3 - 6:6 6:6 - 12:12
WADDR SB_RAM40_4K 13:13 - 13:13
0 -> 13:13
$1270 $lut╲rdata[5]
$552 [5] A Y
$1262
$559 6:6 - 2:2 0:0 - 5:5
$lut╲rdata[6]
A Y
$552 [6] $lut
$1376
0:0 - 6:6
0 -> 10:9
$559 7:7 - 2:2
$1380 $lut╲rdata[7]
A Y
$552 [7]
0:0 - 7:7
$1382 0:0 - 8:8
0:0 - 2:2
$559
$lut╲rdata[0]
$1384 A Y
$lut 0:0 - 0:0
$552 [0] rdata
0 -> 7:7
$1386
1:1 - 2:2 $lut╲rdata[1]
$559 A Y 0:0 - 1:1
$lut
$1388 $techmap2134╲data.0.0.WCLKE
$552 [1] 0:0 - 2:2
$1390 $lut╲rdata[2]
1'1 2:2 - 2:2 A Y
$lut
$559
$1392
$559
Finally we use techmap to map the generic $lut cells to iCE40 SB_LUT4 cells.
CI
1'0 0:0 - I0 data.0.0_RADDR_7
data.0.0_RADDR_7_S 2:2 _SB_CARRY_I1
SB_CARRY
B_CARRY_I1_CO I0
0:0 - 1'0 I1 CO
1'0 I1
2:2 data.0.0_RADDR_6_SB_LUT4
I2
CI
1'0 I0 data.0.0_RAD SB_LUT4
I1 CI 0.0_RADDR_2_S 0:0 - 2:2 -
1'0 I0 B_CARRY_I1 2:2 0:0
SB_CA
data.0.0_RADDR_2_S 2:2 - 0:0 -
RRY
B_CARRY_I1 0:0 1'0 1:1
CO 2:2 -
1'0 I0 data.0.0_RADDR I0
3:3 2:2 - 0:0 1'0 I1
I1
data.0.0_RADDR_1_
I2 SB_LUT4 0:0 - data.0.0_RADDR_7_SB
I2
1'0 2:2
O SB_LUT4
I3 C 0:0 - 2:2 - 1'0
D ata.0.0_R ata.0.0_R 2:2 -
ADD 2:2 3:3 ADDR 0:0 I0
data.0.0_RADDR_6_S
E rdata_SB_L
2:2 - SB_DFFER 16'000000000 UT4_O
0:0 0:0 - 0000000 O
2:2 I2
C
D
0:0 - 0:0data.0.0_RADDR_S 2:2 -
E 3:3 2:2 -
data.0.0_R 0:0 0 -> 1'0 0:0 -
0:0 - Q ADDR 7:7
7:7 SB_DFFER 0:0 - 10:9
2:2
D
R 0:0 - 0:0
data.0.0_RADDR_7_S 2:2 - I0 I1
E 0:0
SB_DFFER ta.0.0_RD rdata_SB_LUT
15:15 - ATA_1 4_O_4
15:15 2:2 - O
7:7 - 0:0 D 0:0
0:0 -
data.0.0_RADDR_1_SB_DFFER
E 0:0 MA
SB_DFFER SK 0:0 -
1'1 3:3
ren D RA
RE 8:8 - 1'0
data.0.0_RADDR_ data.0.0_RADDR_2_SB_DFFER_Q
E data.0.0_RA 1'1 data.0.0SB_RAM40_4K 2:2
WADDR
SB_LUT4_I3_O Q DDR_2 RDATA
SB_DFFER 2:2 - 7:7 - 7:7 6:6 - I0
WC I1
3:3 1'1
I0 LK 2:2 SB_LU
rdata_SB_LUT4_
1' I2 T4
3:3 - 0:0 D 0 I2 SB_LUT4 0:0 - WC 1:1 - 0:0
E O
SB_DFFER I3 3:3 0:0 -
1'0 I0 0:0 - 1:1
I1 1:1
data.0.0_RADDR_5_ data.0.0_RADDR_SB_LUT data.0.0_
1'0 1'0 WDATA 0 ->
Q 4_I3 15:15
E data.0.0_W
SB_DFFER_Q 1'0 DATA_4 1:1 - 0:0
SB_DFFER Q 0:0 - 1:1
4:4 - 2:2 - data.0.0_
0:0 0:0 data.0.0_W RDATA
C 0:0 - DATA_2 1:1 - 7:7 -
2:2 0:0
data.0.0_RA data.0.0_W 14:14
E DDR_5 DATA_6
SB_DFFER
2:2 - data.0.0_W 1:1 - 0:0
DATA_1 0:0 - 0:0 - 1:1
3:3
data.0.0_W 14:14
DATA_5 1:1 -
0:0
1'0 data.0.0_W
data.0.0_RADDR_6_S DATA_3
B_CARRY_I1_CO 0:0 - 1'0
0.0_RADDR_3_S 2:2 1'0 data.0.0_W 0:0 -
B_CARRY_I1 DATA_7 I0 0:0
0:0 - 0:0 - 1'0
2:2 rdat
2:2 2:2 - I2 a
2:2 - 0:0 ata.0.0_RDATA_ I0
data.0.0_R I0 0:0 - SB_LUT 0:0 -
CI ADDR 6:6 1:1 - 0:0 O 5:5
3:3 2:2 - 0:0 I1
1'0 I0 SB_CA data.0.0_RADDR_2_SB_LUT4_I2
I2 SB_LUT4 2:2 - I3
data.0.0_RADDR_3_SB_ 0:0 - 0:0 - ta.0.0_RDATA_2
I1 RRY 2:2 0:0 2:2 - 0:0
O 1:1
I3 1:1 - 0:0 -
0:0 2:2
1:1 -
1'0 0:0 1'0
0:0 -
I0 5:5 I0 rdata_SB_LUT4
1'0 I1 1:1 - 0:0
0:0 - 1:1
0:0 - data.0.0_RADDR_3_SB_LUT4
I2 I2 _O_5 O
2:2 SB_LUT4 2:2 - SB_LUT
.0.0_RADDR_4_S 0:0 0:0 -
B_CARRY_I1 1:1 - 6:6
CI 0:0
SB_CA 1:1 -
I1 RRY 0:0 1'0
CI 0:0 -
1:1 I0
SB_CA .0.0_RADDR_5_ 0:0 - 2:2 - data.0.0_RADDR_4
I1 RRY SB_CARRY_I 2:2 - 0:0 SB_LUT4
2:2 3:3 0:0 - 1:1 - I2
0:0 O
1'0 4:4
I0
1'0 I1 0:0 -
1:1
data.0.0_RADDR_4_SB_LUT4
_I2 1'0 0:0 -
O 4:4
ta.0.0_RD I0
ATA_6 0:0 - 0:0 I1
rdata_SB_LUT
4_O_3
1:1 - O
0:0
data.0.0_WADDR_3 [0]
0 -> 10:9
See also
Advanced usage docs for
• Technology mapping
• The ABC toolbox
Other cells
The following commands may also be used for mapping other cells:
hilomap
Some architectures require special driver cells for driving a constant hi or lo value. This
command replaces simple constants with instances of such driver cells.
iopadmap
Top-level input/outputs must usually be implemented using special I/O-pad cells. This
command inserts such cells to the design.
These commands tend to either be in the map_cells section or after the check section depending on
the flow.
blackbox =A:whitebox
YosysHQ Yosys, Version 0.48-dev
The new commands here are:
Number of wires: 95
Number of wire bits: 262
Number of public wires: 95
Number of public wire bits: 262
Number of ports: 7
Number of port bits: 29
Number of memories: 0
Number of memory bits: 0
Number of processes: 0
Number of cells: 138
$scopeinfo 2
SB_CARRY 26
SB_DFF 26
SB_DFFER 25
SB_LUT4 58
SB_RAM40_4K 1
Note that the -top fifo here is optional. stat will automatically use the module with the
top attribute set, which fifo was when we called hierarchy . If no module is marked top,
then stats will be shown for each module selected.
The stat output is also useful as a kind of sanity-check: Since we have already run proc ,
we wouldn’t expect there to be any processes. We also expect data to use hard memory; if
instead of an SB_RAM40_4K saw a high number of flip-flops being used we might suspect
something was wrong.
If we instead called stat immediately after read_verilog fifo.v we would see something very
different:
Number of wires: 28
Number of wire bits: 219
Number of public wires: 9
Number of public wire bits: 45
2.2. Synthesis starter 53
YosysHQ Yosys, Version 0.48-dev
Number of ports: 7
Number of port bits: 29
Number of memories: 1
(continues on next page)
Number of wires: 8
Number of wire bits: 60
Number of public wires: 4
Number of public wire bits: 11
Number of ports: 4
Number of port bits: 11
Number of memories: 0
Number of memory bits: 0
Number of processes: 2
Number of cells: 2
$add 1
$eq 1
Notice how fifo and addr_gen are listed separately, and the statistics for fifo show 2 addr_gen
modules. Because this is before the memory has been mapped, we also see that there is 1
memory with 2048 memory bits; matching our 8-bit wide data memory with 256 values (8 *
256 = 2048).
Synthesis output
The iCE40 synthesis flow has the following output modes available:
• write_blif - write design to BLIF file,
• write_edif - write design to EDIF netlist file, and
• write_json - write design to a JSON file.
As an example, if we called synth_ice40 -top fifo -json fifo.json, our synthesized fifo
design will be output as fifo.json. We can then read the design back into Yosys with
read_json , but make sure you use design -reset or open a new interactive terminal first.
The JSON output we get can also be loaded into nextpnr to do place and route; but that is
beyond the scope of this documentation.
See also
synth_ice40 - synthesis for iCE40 FPGAs
Yosys script files typically use the .ys extension and contain a set of commands for Yosys to run
sequentially. These commands are the same ones we were using on the previous page like
read_verilog and hierarchy .
Warning
The space after the semicolon is required for correct parsing. log a;log b; for example will
display
a;log b instead of a and b as might be expected.
Another special character that can be used in Yosys scripts is the bang !. Anything after the bang
will be executed as a shell command. This can only be terminated with a new line. Any
semicolons, hashes, or other special characters will be passed to the shell. If an error code is
returned from the shell it will be raised by
Yosys. exec provides a much more flexible way of executing commands, allowing the output
to be logged and more control over when to generate errors.
12
13
14
1
0
15
1
1 16
1
8
echo on
1 hierarchy -top addr_gen
select -module addr_gen
9 select -list
select t:*
2 select -list
0 select -set new_cells %
select -clear
show -format dot -prefix addr_gen_show addr_gen
show -format dot -prefix new_cells_show -notitle @new_cells
21 show -color maroon3 @new_cells -color cornflowerblue p:* -notitle -format dot -prefix␣
˓→ addr_gen_hier
22
23
(continues on next page)
# ========================================================
25
opt_expr; clean
28
29
30
31
32
The first command there, echo on, uses echo to enable command echoes on. This is how we
generated the code listing for hierarchy -top addr_gen output. Turning command echoes on prints
the yosys> hierarchy
-top addr_gen line, making the output look the same as if it were an interactive terminal.
hierarchy -top addr_gen is of course the command we were demonstrating, including the output
text and an image of the design schematic after running it.
We briefly touched on select when it came up in synth_ice40 , but let’s look at it more now.
Selections intro
The select command is used to modify and view the list of selected objects:
yosys> select -module addr_gen
yosys [addr_gen]> select -list
addr_gen
addr_gen/$1\addr[7:0]
addr_gen/$add$fifo.v:19$3_Y
addr_gen/$eq$fifo.v:16$2_Y
addr_gen/$0\addr[7:0]
addr_gen/addr
addr_gen/rst
addr_gen/clk
2.3. Scripting in Yosys 39
YosysHQ Yosys, Version 0.48-dev
addr_gen/en
addr_gen/$add$fifo.v:19$3
addr_gen/$eq$fifo.v:16$2
addr_gen/$proc$fifo.v:0$4
addr_gen/$proc$fifo.v:12$1
yosys [addr_gen]> select t:*
yosys [addr_gen]*> select -
list addr_gen/$add$fifo.v:19$3
addr_gen/$eq$fifo.v:16$2
yosys [addr_gen]*> select -set new_cells %
yosys [addr_gen]*> select -clear
When we call select -module addr_gen we are changing the currently active selection from the
whole design, to just the addr_gen module. Notice how this changes the yosys at the start of
each command to yosys [addr_gen]? This indicates that any commands we run at this point will
only operate on the addr_gen module. When we then call select -list we get a list of all objects
in the addr_gen module, including the module itself, as well as all of the wires, inputs,
outputs, processes, and cells.
Next we perform another selection, select t:* . The t: part signifies we are matching on
the cell type, and the * means to match anything. For this (very simple) selection, we are
trying to find all of the cells, regardless of their type. The active selection is now shown as
[addr_gen]*, indicating some sub-selection of the addr_gen module. This gives us the $add
and $eq cells, which we want to highlight for the addr_gen module after hierarchy image.
We can assign a name to a selection with select -set. In our case we are using the name
new_cells, and telling it to use the current selection, indicated by the % symbol. We can then
use this named selection by referring to it as @new_cells, which we will see later. Then we
clear the selection so that the following commands can operate on the full design. While we
split that out for this document, we could have done the same thing in a single line by
calling select -set new_cells addr_gen/t:* . If we know we only have the one module in our
design, we can even skip the addr_gen/ part. Looking further down the fifo.ys code we can see
this with select -set new_cells t:$mux t:* dff. We can also see in that command that
selections don’t have to be limited to a single statement.
Many commands also support an optional [selection] argument which can be used to override the
currently selected objects. We could, for example, call clean addr_gen to have clean operate on
just the addr_gen module.
Detailed documentation of the select framework can be found under Selections or in the
command reference at select - modify and view the list of selected objects.
Displaying schematics
While the select command is very useful, sometimes nothing beats being able to see a design for
yourself. This is where show comes in. Note that this document is just an introduction to the
show command, only covering the basics. For more information, including a guide on what the
different symbols represent, see A look at the show command and the Interactive design
investigation page.
Note
The show command requires a working installation of GraphViz and xdot for displaying the actual circuit
diagrams.
This is the first show command we called in fifo.ys, as we saw above. If we look at the log
output for this image we see the following:
yosys> show -format dot -prefix addr_gen_show addr_gen
Calling show with -format dot tells it we want to output a .dot file rather than opening it for
display. The
-prefix addr_gen_show option indicates we want the file to be called addr_gen_show.* .
Remember, we do this in fifo.ys because we need to store the image for displaying in the
documentation you’re reading. But if you just want to display the images locally you can
skip these two options. The -format option internally calls the dot command line program
from GraphViz to convert to formats other than .dot. Check GraphViz output docs for more
on available formats.
2.3. Scripting in Yosys 41
YosysHQ Yosys, Version 0.48-dev
Note
If you are using a POSIX based version of Yosys (such as for Mac or Linux), xdot will be opened in the
background and Yosys can continue to be used. If it it still open, future calls to show will use the same
A $2
Y
0 -> 31:8
B $eq
7:0 - 7:0
255
rst
clk
PROC $1
en
o.v:12.2-20
fif .6
PROC $4
addr
fo.v:0.0-0.
fi 0
A $3 7:0 - 7:0
Y
1 B $add
addr_gen
xdot instance.
The addr_gen at the end tells it we only want the addr_gen module, just like when we called
select
-module addr_gen in Selections intro. That last parameter doesn’t have to be a module name, it
can be any valid selection string. Remember when we assigned a name to a selection and called
it new_cells? We saw in the select -list output that it contained two cells, an $add and an $eq .
We can call show on that selection just as easily:
0 -> 31:8
addr 7:0 - 7:0
$2_Y
255 A $2 Y
B $eq
addr
A $3 Y
B $add $3_Y
1
See also
A look at the show command on the Interactive design investigation page.
A $2
Y
B $eq
0 -> 31:8
7:0 - 7:0
255
rst
clk
PROC $1
en
o.v:12.2-20
fif .6
PROC $4
addr
fo.v:0.0-0.
fi 0
A $3
Y 7:0 - 7:0
1
B $add