2013-11-22 10:33:59 -06:00
|
|
|
|
|
|
|
\appnote{010}{Converting Verilog to BLIF}{Clifford Wolf}
|
|
|
|
|
|
|
|
\begin{appnote_abstract}
|
|
|
|
Verilog-2005 is a powerful Hardware Description Language (HDL) that can be used
|
|
|
|
to easily create complex designs from small HDL code. It is the prefered
|
|
|
|
method of design entry for many designers\footnote{The other half prefers VHDL,
|
|
|
|
a very different but -- of course -- equaly powerful language.}.
|
|
|
|
|
|
|
|
The Berkeley Logic Interchange Format (BLIF) is a simple file format for
|
|
|
|
exchanging sequential logic between programs. It is easy to generate and
|
|
|
|
easy to parse and is therefore the prefered method of design entry for
|
|
|
|
many authors of logic synthesis tools.
|
|
|
|
|
|
|
|
Yosys\footnote{\url{http://www.clifford.at/yosys/}} is a feature-rich Open-Source Verilog synthesis tool that can be used to
|
|
|
|
bridge the gap between the two file formats. It implements most of Verilog-2005
|
|
|
|
and thus can be used to import modern behavioral Verilog designs into BLIF-based
|
|
|
|
design flows without dependencies on proprietary synthesis tools.
|
|
|
|
\end{appnote_abstract}
|
|
|
|
|
|
|
|
\section{Installation}
|
|
|
|
|
|
|
|
Yosys written in C++ (using features from C++11) and is tested on modern Linux.
|
|
|
|
It should compile fine on most UNIX systems with a C++11 compiler. The README
|
|
|
|
file contains useful information on building Yosys and its prerequisites.
|
|
|
|
|
|
|
|
Yosys is a large and feature-rich program with a couple of dependencies. It is,
|
|
|
|
however, possible to deactivate some of the dependencies in the Makefile,
|
|
|
|
resulting in features in Yosys becoming unavailable. When problems with building
|
|
|
|
Yosys are encountered, a user who is only interested in the features of Yosys
|
|
|
|
that are presented in this Application Note may deactivate {\tt TCL}, {\tt Qt}
|
|
|
|
and {\tt MiniSAT} support and not build {\tt yosys-abc}.
|
|
|
|
|
|
|
|
\bigskip
|
|
|
|
|
|
|
|
This Application Note is based on GIT Rev. {\color{red} FIXME} from
|
|
|
|
{\color{red} DATE} of Yosys. The Verilog sources used for the examples
|
|
|
|
is taken from the {\it yosys-bigsim test
|
|
|
|
bench}\footnote{\url{https://github.com/cliffordwolf/yosys-bigsim}}, GIT
|
|
|
|
Rev. {\color{red} FIXME}.
|
|
|
|
|
|
|
|
\section{Getting Started}
|
|
|
|
|
|
|
|
We start with the {\tt softusb\_navre} core from {\it yosys-bigsim}. The navre
|
|
|
|
processor\footnote{\url{http://opencores.org/project,navre}} is an Open Source
|
|
|
|
AVR clone. It is a single module ({\tt softusb\_navre}) in a single design file
|
|
|
|
({\tt softusb\_navre.v}). It also is using only features that map nicely to
|
|
|
|
the BLIF format, for example it only uses synchronous resets.
|
|
|
|
|
|
|
|
Converting {\tt softusb\_navre.v} to {\tt softusb\_navre.blif} could not be
|
|
|
|
easier:
|
|
|
|
|
2013-11-22 22:46:51 -06:00
|
|
|
\begin{figure}[H]
|
2013-11-22 10:33:59 -06:00
|
|
|
\begin{lstlisting}[frame=trBL,xleftmargin=1.5em,numbers=left]
|
2013-11-22 22:46:51 -06:00
|
|
|
yosys -o softusb_navre.blif \
|
|
|
|
-S softusb_navre.v
|
2013-11-22 10:33:59 -06:00
|
|
|
\end{lstlisting}
|
2013-11-22 22:46:51 -06:00
|
|
|
\renewcommand{\figurename}{Listing}
|
|
|
|
\caption{Calling Yosys without script file}
|
|
|
|
\end{figure}
|
2013-11-22 10:33:59 -06:00
|
|
|
|
|
|
|
Behind the scenes Yosys is controlled by synthesis scripts that execute
|
|
|
|
commands that operate on Yosys' internal state. For example, the {\tt -o
|
|
|
|
softusb\_navre.blif} option just adds the command {\tt write\_blif
|
|
|
|
softusb\_navre.blif} to the end of the script. Likewise a file on the
|
|
|
|
command line -- {\tt softusb\_navre.v} in this case -- adds the command
|
|
|
|
{\tt read\_verilog softusb\_navre.v} to the beginning of the
|
|
|
|
synthesis script. In both cases the file type is detected from the
|
|
|
|
file extension.
|
|
|
|
|
|
|
|
Finally the option {\tt -S} instantiates a built-in default synthesis script.
|
|
|
|
Instead of using {\tt -S} one could also specify the synthesis commands
|
|
|
|
for the script on the command line using the {\tt -p} option, either using
|
|
|
|
individual options for each command or by passing one big command string
|
|
|
|
with semicolon-separated commands. But in most cases it is more convenient
|
|
|
|
to use an actual script file.
|
|
|
|
|
|
|
|
\section{Using a Synthesis Script}
|
|
|
|
|
|
|
|
With a script file we have better control over Yosys. The following script
|
|
|
|
file replicates what the command from the last section did:
|
|
|
|
|
2013-11-22 22:46:51 -06:00
|
|
|
\begin{figure}[H]
|
|
|
|
\begin{lstlisting}[frame=trBL,xleftmargin=1.5em,numbers=left]
|
2013-11-22 10:33:59 -06:00
|
|
|
read_verilog softusb_navre.v
|
|
|
|
hierarchy
|
|
|
|
proc; opt; memory; opt; techmap; opt
|
|
|
|
write_blif softusb_navre.blif
|
|
|
|
\end{lstlisting}
|
2013-11-22 22:46:51 -06:00
|
|
|
\renewcommand{\figurename}{Listing}
|
|
|
|
\caption{\tt softusb\_navre.ys}
|
|
|
|
\end{figure}
|
2013-11-22 10:33:59 -06:00
|
|
|
|
|
|
|
The first and last line obviously read the Verilog file and write the BLIF
|
|
|
|
file.
|
|
|
|
|
|
|
|
\medskip
|
|
|
|
|
|
|
|
The 2nd line checks the design hierarchy and instantiates parametrized
|
|
|
|
versions of the modules in the design, if necessary. In the case of this
|
|
|
|
simple design this is a no-op. However, as a general rule a synthesis script
|
|
|
|
should always contain this command as first command after reading the input
|
|
|
|
files.
|
|
|
|
|
|
|
|
\medskip
|
|
|
|
|
|
|
|
The 3rd line does most of the actual work:
|
|
|
|
|
|
|
|
\begin{itemize}
|
|
|
|
\item The command {\tt opt} is the Yosys' built-in optimizer. It can perform
|
|
|
|
some simple optimizations such as const-folding and removing unconnected parts
|
|
|
|
of the design. It is common practice to call opt after each major step in the
|
|
|
|
synthesis. In cases where too much optimization is not appreciated (for example
|
|
|
|
when analyzing a design), it is recommended to call {\tt clean} instead of {\tt
|
|
|
|
opt}.
|
|
|
|
\item The command {\tt proc} converts {\it processes} (Yosys' internal
|
|
|
|
representation of Verilog {\tt always}- and {\tt initial}-blocks) to circuits
|
|
|
|
of multiplexers and storage elements (various types of flip-flops).
|
|
|
|
\item The command {\tt memory} converts Yosys' internal representation of
|
|
|
|
arrays and array accesses to multi-port block memories, and then maps this
|
|
|
|
block memories to address decoders and flip-flops, unless the option {\tt -nomap}
|
|
|
|
is used, in which case the multi-port block memories stay in the design
|
|
|
|
and can then be mapped to architecture-specific memory primitives using
|
|
|
|
other commands.
|
|
|
|
\item The command {\tt techmap} turns a high-level circuit with coarse grain
|
|
|
|
cells such as wide adders and multipliers to a fine-grain circuit of simple
|
|
|
|
logic primitives and single-bit storage elements. The command does that by
|
|
|
|
substituting the complex cells by circuits of simpler cells. It is possible
|
|
|
|
to provide a custom set of rules for this process in the form of a Verilog
|
|
|
|
source file, as we will see in the next section.
|
|
|
|
\end{itemize}
|
|
|
|
|
2013-11-22 12:08:29 -06:00
|
|
|
Now Yosys can be run with the file of the synthesis script as argument:
|
2013-11-22 10:33:59 -06:00
|
|
|
|
2013-11-22 22:46:51 -06:00
|
|
|
\begin{figure}[H]
|
2013-11-22 12:08:29 -06:00
|
|
|
\begin{lstlisting}[frame=trBL,xleftmargin=1.5em,numbers=left]
|
2013-11-22 22:46:51 -06:00
|
|
|
yosys softusb_navre.ys
|
2013-11-22 12:08:29 -06:00
|
|
|
\end{lstlisting}
|
2013-11-22 22:46:51 -06:00
|
|
|
\renewcommand{\figurename}{Listing}
|
|
|
|
\caption{Calling Yosys with script file}
|
|
|
|
\end{figure}
|
2013-11-22 12:08:29 -06:00
|
|
|
|
|
|
|
\medskip
|
|
|
|
|
|
|
|
Now that we are using a synthesis script we can easily modify how Yosys
|
|
|
|
synthesizes the design. The first thing we should customize is the
|
|
|
|
call to the {\tt history} command:
|
|
|
|
|
|
|
|
Whenever it is known that there are no implicit blackboxes in the design, i.e.
|
|
|
|
modules that are referred to but are not defined, the {\tt hierarchy} command
|
|
|
|
should be called with the {\tt -check} option. The 2nd thing we can improve
|
|
|
|
regarding the {\tt hierarchy} command is that we can tell it the name of the
|
|
|
|
top level module of the design hierarchy. It will then automatically remove
|
|
|
|
all modules that are not referenced from this top level module.
|
|
|
|
|
|
|
|
\medskip
|
|
|
|
|
|
|
|
For many designs it is also desired to optimize the encodings for the finite
|
|
|
|
state machines (FSM) in the design. The {\tt fsm command} finds FSMs, extracts
|
|
|
|
them, performs some basic optimizations and then generate a circuit from
|
|
|
|
the extracted and optimized description. It would also be possible to tell
|
|
|
|
the FSM command to leave the FSMs in their extracted form, so they can be
|
|
|
|
processed using custom commands. But in this case we don't need that.
|
|
|
|
|
|
|
|
\medskip
|
|
|
|
|
|
|
|
So now we have the final synthesis script for generating a BLIF file
|
|
|
|
for the navre CPU:
|
|
|
|
|
2013-11-22 22:46:51 -06:00
|
|
|
\begin{figure}[H]
|
|
|
|
\begin{lstlisting}[frame=trBL,xleftmargin=1.5em,numbers=left]
|
2013-11-22 10:33:59 -06:00
|
|
|
read_verilog softusb_navre.v
|
|
|
|
hierarchy -check -top softusb_navre
|
|
|
|
proc; opt; memory; opt;
|
|
|
|
fsm; opt; techmap; opt
|
|
|
|
write_blif softusb_navre.blif
|
|
|
|
\end{lstlisting}
|
2013-11-22 22:46:51 -06:00
|
|
|
\renewcommand{\figurename}{Listing}
|
|
|
|
\caption{{\tt softusb\_navre.ys} (improved)}
|
|
|
|
\end{figure}
|
2013-11-22 10:33:59 -06:00
|
|
|
|
|
|
|
\section{Advanced Example: The Amber23 ARMv2a CPU}
|
|
|
|
|
2013-11-22 12:08:29 -06:00
|
|
|
Our 2nd example is the Amber23\footnote{\url{http://opencores.org/project,amber}}
|
|
|
|
ARMv2a CPU. Once again we base our example on the Verilog code that is included
|
|
|
|
in {\it yosys-bigsim}.
|
|
|
|
|
2013-11-22 22:46:51 -06:00
|
|
|
\begin{figure}[b!]
|
|
|
|
\begin{lstlisting}[frame=trBL,xleftmargin=1.5em,numbers=left]
|
2013-11-22 12:08:29 -06:00
|
|
|
read_verilog a23_alu.v
|
|
|
|
read_verilog a23_barrel_shift_fpga.v
|
|
|
|
read_verilog a23_barrel_shift.v
|
|
|
|
read_verilog a23_cache.v
|
|
|
|
read_verilog a23_coprocessor.v
|
|
|
|
read_verilog a23_core.v
|
|
|
|
read_verilog a23_decode.v
|
|
|
|
read_verilog a23_execute.v
|
|
|
|
read_verilog a23_fetch.v
|
|
|
|
read_verilog a23_multiply.v
|
|
|
|
read_verilog a23_ram_register_bank.v
|
|
|
|
read_verilog a23_register_bank.v
|
|
|
|
read_verilog a23_wishbone.v
|
|
|
|
read_verilog generic_sram_byte_en.v
|
|
|
|
read_verilog generic_sram_line_en.v
|
|
|
|
hierarchy -check -top a23_core
|
|
|
|
add -global_input globrst 1
|
|
|
|
proc -global_arst globrst
|
|
|
|
techmap -map adff2dff.v
|
2013-11-22 22:46:51 -06:00
|
|
|
opt; memory; opt; fsm; opt; techmap
|
2013-11-22 12:08:29 -06:00
|
|
|
write_blif amber23.blif
|
|
|
|
\end{lstlisting}
|
2013-11-22 22:46:51 -06:00
|
|
|
\renewcommand{\figurename}{Listing}
|
|
|
|
\caption{\tt amber23.ys}
|
|
|
|
\label{aber23.ys}
|
|
|
|
\end{figure}
|
|
|
|
|
|
|
|
The problem with this core is that it contains no dedicated reset signals.
|
|
|
|
Instead it is using the coding techiques shown in Listing~\ref{glob_arst} to
|
|
|
|
set reset values to be used on the global asynchronous reset in an FPGA
|
|
|
|
implementation. This design can not be expressed in BLIF as it is. Instead we
|
|
|
|
need to use a synthesis script that transforms this to synchonous resets that
|
|
|
|
can be expressed in BLIF.
|
|
|
|
|
|
|
|
\medskip
|
|
|
|
|
|
|
|
Listing~\ref{aber23.ys} shows the synthesis script for the Amber23 core. In
|
|
|
|
line 17 the {\tt add} command is used to add a 1-bit wide global input signal
|
|
|
|
with the name {\tt globrst}. That means that an input with that name is added
|
|
|
|
to each module in the design hierarchy and then all module instanciations are
|
|
|
|
altered so that this new signal is connected throughout the whole design
|
|
|
|
hierarchy.
|
|
|
|
|
|
|
|
\begin{figure}[t!]
|
|
|
|
\begin{lstlisting}[frame=trBL,xleftmargin=1.5em,numbers=left]
|
|
|
|
reg [7:0] a = 13, b;
|
|
|
|
initial b = 37;
|
|
|
|
\end{lstlisting}
|
|
|
|
\renewcommand{\figurename}{Listing}
|
|
|
|
\caption{Implicit coding of global asynchronous resets}
|
|
|
|
\label{glob_arst}
|
|
|
|
\end{figure}
|
|
|
|
|
|
|
|
\begin{figure}[b!]
|
|
|
|
\begin{lstlisting}[frame=trBL,xleftmargin=1.5em,numbers=left]
|
|
|
|
module \$adff (CLK, ARST, D, Q);
|
|
|
|
|
|
|
|
parameter WIDTH = 1;
|
|
|
|
parameter CLK_POLARITY = 1'b1;
|
|
|
|
parameter ARST_POLARITY = 1'b1;
|
|
|
|
parameter ARST_VALUE = 0;
|
|
|
|
|
|
|
|
input CLK, ARST;
|
|
|
|
input [WIDTH-1:0] D;
|
|
|
|
output reg [WIDTH-1:0] Q;
|
|
|
|
|
|
|
|
wire _TECHMAP_FAIL_ =
|
|
|
|
!CLK_POLARITY || !ARST_POLARITY;
|
|
|
|
|
|
|
|
always @(posedge CLK)
|
|
|
|
if (ARST)
|
|
|
|
Q <= ARST_VALUE;
|
|
|
|
else
|
|
|
|
Q <= D;
|
|
|
|
|
|
|
|
endmodule
|
|
|
|
\end{lstlisting}
|
|
|
|
\renewcommand{\figurename}{Listing}
|
|
|
|
\caption{\tt adff2dff.v}
|
|
|
|
\label{adff2dff.v}
|
|
|
|
\end{figure}
|
|
|
|
|
|
|
|
In line 18 the {\tt proc} command is called. But this time the newly created
|
|
|
|
reset signal is passed to the core as a global reset line to use for resetting
|
|
|
|
all registers to their initial values.
|
|
|
|
|
|
|
|
Finally in line 19 the {\tt techmap} command is used to replace all instances
|
|
|
|
of flip-flops with asynchronous resets to flip-flops with synchronous resets.
|
|
|
|
The map file used fo this is shown in Lising~\ref{adff2dff.v}.
|
2013-11-22 12:08:29 -06:00
|
|
|
|
2013-11-22 22:46:51 -06:00
|
|
|
{\color{red} FIXME}
|
2013-11-22 10:33:59 -06:00
|
|
|
|