| % IEEEtran howto: | |
| % http://ftp.univie.ac.at/packages/tex/macros/latex/contrib/IEEEtran/IEEEtran_HOWTO.pdf | |
| \documentclass[9pt,technote,a4paper]{IEEEtran} | |
| \usepackage[T1]{fontenc} % required for luximono! | |
| \usepackage[scaled=0.8]{luximono} % typewriter font with bold face | |
| % To install the luximono font files: | |
| % getnonfreefonts-sys --all or | |
| % getnonfreefonts-sys luximono | |
| % | |
| % when there are trouble you might need to: | |
| % - Create /etc/texmf/updmap.d/99local-luximono.cfg | |
| % containing the single line: Map ul9.map | |
| % - Run update-updmap followed by mktexlsr and updmap-sys | |
| % | |
| % This commands must be executed as root with a root environment | |
| % (i.e. run "sudo su" and then execute the commands in the root | |
| % shell, don't just prefix the commands with "sudo"). | |
| \usepackage[unicode,bookmarks=false]{hyperref} | |
| \usepackage[english]{babel} | |
| \usepackage[utf8]{inputenc} | |
| \usepackage{amssymb} | |
| \usepackage{amsmath} | |
| \usepackage{amsfonts} | |
| \usepackage{units} | |
| \usepackage{nicefrac} | |
| \usepackage{eurosym} | |
| \usepackage{graphicx} | |
| \usepackage{verbatim} | |
| \usepackage{algpseudocode} | |
| \usepackage{scalefnt} | |
| \usepackage{xspace} | |
| \usepackage{color} | |
| \usepackage{colortbl} | |
| \usepackage{multirow} | |
| \usepackage{hhline} | |
| \usepackage{listings} | |
| \usepackage{float} | |
| \usepackage{tikz} | |
| \usetikzlibrary{calc} | |
| \usetikzlibrary{arrows} | |
| \usetikzlibrary{scopes} | |
| \usetikzlibrary{through} | |
| \usetikzlibrary{shapes.geometric} | |
| \lstset{basicstyle=\ttfamily,frame=trBL,xleftmargin=2em,xrightmargin=1em,numbers=left} | |
| \begin{document} | |
| \title{Yosys Application Note 010: \\ Converting Verilog to BLIF} | |
| \author{Clifford Wolf \\ November 2013} | |
| \maketitle | |
| \begin{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 preferred | |
| method of design entry for many designers\footnote{The other half prefers VHDL, | |
| a very different but -- of course -- equally powerful language.}. | |
| The Berkeley Logic Interchange Format (BLIF) \cite{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 preferred method of design entry for | |
| many authors of logic synthesis tools. | |
| Yosys \cite{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. | |
| The scope of Yosys goes of course far beyond Verilog logic synthesis. But | |
| it is a useful and important feature and this Application Note will focus | |
| on this aspect of Yosys. | |
| \end{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 discussed in this Application Note may deactivate {\tt TCL}, {\tt Qt} | |
| and {\tt MiniSAT} support in the {\tt Makefile} and may opt against building | |
| {\tt yosys-abc}. | |
| \bigskip | |
| This Application Note is based on GIT Rev. {\tt e216e0e} from 2013-11-23 of | |
| Yosys \cite{yosys}. The Verilog sources used for the examples are taken from | |
| yosys-bigsim \cite{bigsim}, a collection of real-world designs used for | |
| regression testing Yosys. | |
| \section{Getting Started} | |
| We start our tour with the Navr\'e processor from yosys-bigsim. The Navr\'e | |
| processor \cite{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: | |
| \begin{figure}[H] | |
| \begin{lstlisting}[language=sh] | |
| yosys -o softusb_navre.blif -S softusb_navre.v | |
| \end{lstlisting} | |
| \renewcommand{\figurename}{Listing} | |
| \caption{Calling Yosys without script file} | |
| \end{figure} | |
| 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 a semicolon-separated list of 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: | |
| \begin{figure}[H] | |
| \begin{lstlisting}[language=sh] | |
| read_verilog softusb_navre.v | |
| hierarchy | |
| proc; opt; memory; opt; techmap; opt | |
| write_blif softusb_navre.blif | |
| \end{lstlisting} | |
| \renewcommand{\figurename}{Listing} | |
| \caption{\tt softusb\_navre.ys} | |
| \end{figure} | |
| 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 procedure. 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 representations 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} | |
| Now Yosys can be run with the filename of the synthesis script as argument: | |
| \begin{figure}[H] | |
| \begin{lstlisting}[language=sh] | |
| yosys softusb_navre.ys | |
| \end{lstlisting} | |
| \renewcommand{\figurename}{Listing} | |
| \caption{Calling Yosys with script file} | |
| \end{figure} | |
| \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 hierarchy} command: | |
| Whenever it is known that there are no implicit blackboxes in the design, i.e. | |
| modules that are referenced but are not defined, the {\tt hierarchy} command | |
| should be called with the {\tt -check} option. This will then cause synthesis | |
| to fail when implicit blackboxes are found in the design. | |
| 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 (FSMs) 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 {\tt fsm} command to leave the FSMs in their extracted form, so they can be | |
| further processed using custom commands. But in this case we don't want that. | |
| \medskip | |
| So now we have the final synthesis script for generating a BLIF file | |
| for the Navr\'e CPU: | |
| \begin{figure}[H] | |
| \begin{lstlisting}[language=sh] | |
| 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} | |
| \renewcommand{\figurename}{Listing} | |
| \caption{{\tt softusb\_navre.ys} (improved)} | |
| \end{figure} | |
| \section{Advanced Example: The Amber23 ARMv2a CPU} | |
| Our 2nd example is the Amber23 \cite{amber} | |
| ARMv2a CPU. Once again we base our example on the Verilog code that is included | |
| in yosys-bigsim \cite{bigsim}. | |
| \begin{figure}[b!] | |
| \begin{lstlisting}[language=sh] | |
| 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 | |
| opt; memory; opt; fsm; opt; techmap | |
| write_blif amber23.blif | |
| \end{lstlisting} | |
| \renewcommand{\figurename}{Listing} | |
| \caption{\tt amber23.ys} | |
| \label{aber23.ys} | |
| \end{figure} | |
| The problem with this core is that it contains no dedicated reset logic. | |
| Instead the coding techniques shown in Listing~\ref{glob_arst} are used to | |
| define reset values for 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 form to synchronous resets that | |
| can be expressed in BLIF. | |
| (Note that there is no problem if this coding techniques are used to model | |
| ROM, where the register is initialized using this syntax but is never updated | |
| otherwise.) | |
| \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 instantiations are | |
| altered so that this new signal is connected throughout the whole design | |
| hierarchy. | |
| \begin{figure}[t!] | |
| \begin{lstlisting}[language=Verilog] | |
| 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}[language=Verilog] | |
| (* techmap_celltype = "$adff" *) | |
| module adff2dff (CLK, ARST, D, Q); | |
| parameter WIDTH = 1; | |
| parameter CLK_POLARITY = 1; | |
| parameter ARST_POLARITY = 1; | |
| parameter ARST_VALUE = 0; | |
| input CLK, ARST; | |
| input [WIDTH-1:0] D; | |
| output reg [WIDTH-1:0] Q; | |
| wire [1023:0] _TECHMAP_DO_ = "proc"; | |
| 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 in this script the signal name | |
| {\tt globrst} is passed to the command as a global reset signal for resetting | |
| the registers to their assigned initial values. | |
| Finally in line 19 the {\tt techmap} command is used to replace all instances | |
| of flip-flops with asynchronous resets with flip-flops with synchronous resets. | |
| The map file used for this is shown in Listing~\ref{adff2dff.v}. Note how the | |
| {\tt techmap\_celltype} attribute is used in line 1 to tell the techmap command | |
| which cells to replace in the design, how the {\tt \_TECHMAP\_FAIL\_} wire in | |
| lines 15 and 16 (which evaluates to a constant value) determines if the | |
| parameter set is compatible with this replacement circuit, and how the {\tt | |
| \_TECHMAP\_DO\_} wire in line 13 provides a mini synthesis-script to be used to | |
| process this cell. | |
| \begin{figure*} | |
| \begin{lstlisting}[language=C] | |
| #include <stdint.h> | |
| #include <stdbool.h> | |
| #define BITMAP_SIZE 64 | |
| #define OUTPORT 0x10000000 | |
| static uint32_t bitmap[BITMAP_SIZE/32]; | |
| static void bitmap_set(uint32_t idx) { bitmap[idx/32] |= 1 << (idx % 32); } | |
| static bool bitmap_get(uint32_t idx) { return (bitmap[idx/32] & (1 << (idx % 32))) != 0; } | |
| static void output(uint32_t val) { *((volatile uint32_t*)OUTPORT) = val; } | |
| int main() { | |
| uint32_t i, j, k; | |
| output(2); | |
| for (i = 0; i < BITMAP_SIZE; i++) { | |
| if (bitmap_get(i)) continue; | |
| output(3+2*i); | |
| for (j = 2*(3+2*i);; j += 3+2*i) { | |
| if (j%2 == 0) continue; | |
| k = (j-3)/2; | |
| if (k >= BITMAP_SIZE) break; | |
| bitmap_set(k); | |
| } | |
| } | |
| output(0); | |
| return 0; | |
| } | |
| \end{lstlisting} | |
| \renewcommand{\figurename}{Listing} | |
| \caption{Test program for the Amber23 CPU (Sieve of Eratosthenes). Compiled using | |
| GCC 4.6.3 for ARM with {\tt -Os -marm -march=armv2a -mno-thumb-interwork | |
| -ffreestanding}, linked with {\tt -{}-fix-v4bx} set and booted with a custom | |
| setup routine written in ARM assembler.} | |
| \label{sieve} | |
| \end{figure*} | |
| \section{Verification of the Amber23 CPU} | |
| The BLIF file for the Amber23 core, generated using Listings~\ref{aber23.ys} | |
| and \ref{adff2dff.v} and the version of the Amber23 RTL source that is bundled | |
| with yosys-bigsim, was verified using the test-bench from yosys-bigsim. | |
| It successfully executed the program shown in Listing~\ref{sieve} in the | |
| test-bench. | |
| For simulation the BLIF file was converted back to Verilog using ABC | |
| \cite{ABC}. So this test includes the successful transformation of the BLIF | |
| file into ABC's internal format as well. | |
| The only thing left to write about the simulation itself is that it probably | |
| was one of the most energy inefficient and time consuming ways of successfully | |
| calculating the first 31 primes the author has ever conducted. | |
| \section{Limitations} | |
| At the time of this writing Yosys does not support multi-dimensional memories, | |
| does not support writing to individual bits of array elements, does not | |
| support initialization of arrays with {\tt \$readmemb} and {\tt \$readmemh}, | |
| and has only limited support for tristate logic, to name just a few | |
| limitations. | |
| That being said, Yosys can synthesize an overwhelming majority of real-world | |
| Verilog RTL code. The remaining cases can usually be modified to be compatible | |
| with Yosys quite easily. | |
| The various designs in yosys-bigsim are a good place to look for examples | |
| of what is within the capabilities of Yosys. | |
| \section{Conclusion} | |
| Yosys is a feature-rich Verilog-2005 synthesis tool. It has many uses, but | |
| one is to provide an easy gateway from high-level Verilog code to low-level | |
| logic circuits. | |
| The command line option {\tt -S} can be used to quickly synthesize Verilog | |
| code to BLIF files without a hassle. | |
| With custom synthesis scripts it becomes possible to easily perform high-level | |
| optimizations, such as re-encoding FSMs. In some extreme cases, such as the | |
| Amber23 ARMv2 CPU, the more advanced Yosys features can be used to change a | |
| design to fit a certain need without actually touching the RTL code. | |
| \begin{thebibliography}{9} | |
| \bibitem{yosys} | |
| Clifford Wolf. The Yosys Open SYnthesis Suite. \\ | |
| \url{http://www.clifford.at/yosys/} | |
| \bibitem{bigsim} | |
| yosys-bigsim, a collection of real-world Verilog designs for regression testing purposes. \\ | |
| \url{https://github.com/cliffordwolf/yosys-bigsim} | |
| \bibitem{navre} | |
| Sebastien Bourdeauducq. Navr\'e AVR clone (8-bit RISC). \\ | |
| \url{http://opencores.org/project,navre} | |
| \bibitem{amber} | |
| Conor Santifort. Amber ARM-compatible core. \\ | |
| \url{http://opencores.org/project,amber} | |
| \bibitem{ABC} | |
| Berkeley Logic Synthesis and Verification Group. ABC: A System for Sequential Synthesis and Verification. \\ | |
| \url{http://www.eecs.berkeley.edu/~alanmi/abc/} | |
| \bibitem{blif} | |
| Berkeley Logic Interchange Format (BLIF) \\ | |
| \url{http://vlsi.colorado.edu/~vis/blif.ps} | |
| \end{thebibliography} | |
| \end{document} |