mirror of https://github.com/YosysHQ/yosys.git
411 lines
13 KiB
ReStructuredText
411 lines
13 KiB
ReStructuredText
|
.. _chapter:sota:
|
|||
|
|
|||
|
Evaluation of other OSS Verilog Synthesis Tools
|
|||
|
===============================================
|
|||
|
|
|||
|
In this appendix [1]_ the existing FOSS Verilog synthesis tools [2]_ are
|
|||
|
evaluated. Extremely limited or application specific tools (e.g. pure
|
|||
|
Verilog Netlist parsers) as well as Verilog simulators are not included.
|
|||
|
These existing solutions are tested using a set of representative
|
|||
|
Verilog code snippets. It is shown that no existing FOSS tool implements
|
|||
|
even close to a sufficient subset of Verilog to be usable as synthesis
|
|||
|
tool for a wide range existing Verilog code.
|
|||
|
|
|||
|
The packages evaluated are:
|
|||
|
|
|||
|
- Icarus Verilog [3]_
|
|||
|
|
|||
|
- Verilog-to-Routing (VTR) / Odin-II
|
|||
|
:cite:p:`vtr2012}`:raw-latex:`\cite{Odin`
|
|||
|
|
|||
|
- HDL Analyzer and Netlist Architect (HANA)
|
|||
|
|
|||
|
- Verilog front-end to VIS (vl2mv) :cite:p:`Cheng93vl2mv:a`
|
|||
|
|
|||
|
In each of the following sections Verilog modules that test a certain
|
|||
|
Verilog language feature are presented and the support for these
|
|||
|
features is tested in all the tools mentioned above. It is evaluated
|
|||
|
whether the tools under test successfully generate netlists for the
|
|||
|
Verilog input and whether these netlists match the simulation behavior
|
|||
|
of the designs using testbenches.
|
|||
|
|
|||
|
All test cases are verified to be synthesizeable using Xilinx XST from
|
|||
|
the Xilinx WebPACK suite.
|
|||
|
|
|||
|
Trivial features such as support for simple structural Verilog are not
|
|||
|
explicitly tested.
|
|||
|
|
|||
|
Vl2mv and Odin-II generate output in the BLIF (Berkeley Logic
|
|||
|
Interchange Format) and BLIF-MV (an extended version of BLIF) formats
|
|||
|
respectively. ABC is used to convert this output to Verilog for
|
|||
|
verification using testbenches.
|
|||
|
|
|||
|
Icarus Verilog generates EDIF (Electronic Design Interchange Format)
|
|||
|
output utilizing LPM (Library of Parameterized Modules) cells. The EDIF
|
|||
|
files are converted to Verilog using edif2ngd and netgen from Xilinx
|
|||
|
WebPACK. A hand-written implementation of the LPM cells utilized by the
|
|||
|
generated netlists is used for verification.
|
|||
|
|
|||
|
Following these functional tests, a quick analysis of the extensibility
|
|||
|
of the tools under test is provided in a separate section.
|
|||
|
|
|||
|
The last section of this chapter finally concludes these series of
|
|||
|
evaluations with a summary of the results.
|
|||
|
|
|||
|
.. code:: verilog
|
|||
|
:number-lines:
|
|||
|
|
|||
|
module uut_always01(clock,
|
|||
|
reset, count);
|
|||
|
|
|||
|
input clock, reset;
|
|||
|
output [3:0] count;
|
|||
|
reg [3:0] count;
|
|||
|
|
|||
|
always @(posedge clock)
|
|||
|
count <= reset ?
|
|||
|
0 : count + 1;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
endmodule
|
|||
|
|
|||
|
.. code:: verilog
|
|||
|
|
|||
|
module uut_always02(clock,
|
|||
|
reset, count);
|
|||
|
|
|||
|
input clock, reset;
|
|||
|
output [3:0] count;
|
|||
|
reg [3:0] count;
|
|||
|
|
|||
|
always @(posedge clock) begin
|
|||
|
count <= count + 1;
|
|||
|
if (reset)
|
|||
|
count <= 0;
|
|||
|
end
|
|||
|
|
|||
|
endmodule
|
|||
|
|
|||
|
[fig:StateOfTheArt_always12]
|
|||
|
|
|||
|
.. code:: verilog
|
|||
|
:number-lines:
|
|||
|
|
|||
|
module uut_always03(clock, in1, in2, in3, in4, in5, in6, in7,
|
|||
|
out1, out2, out3);
|
|||
|
|
|||
|
input clock, in1, in2, in3, in4, in5, in6, in7;
|
|||
|
output out1, out2, out3;
|
|||
|
reg out1, out2, out3;
|
|||
|
|
|||
|
always @(posedge clock) begin
|
|||
|
out1 = in1;
|
|||
|
if (in2)
|
|||
|
out1 = !out1;
|
|||
|
out2 <= out1;
|
|||
|
if (in3)
|
|||
|
out2 <= out2;
|
|||
|
if (in4)
|
|||
|
if (in5)
|
|||
|
out3 <= in6;
|
|||
|
else
|
|||
|
out3 <= in7;
|
|||
|
out1 = out1 ^ out2;
|
|||
|
end
|
|||
|
|
|||
|
endmodule
|
|||
|
|
|||
|
[fig:StateOfTheArt_always3]
|
|||
|
|
|||
|
.. _sec:blocking_nonblocking:
|
|||
|
|
|||
|
Always blocks and blocking vs. nonblocking assignments
|
|||
|
------------------------------------------------------
|
|||
|
|
|||
|
The "always"-block is one of the most fundamental non-trivial Verilog
|
|||
|
language features. It can be used to model a combinatorial path (with
|
|||
|
optional registers on the outputs) in a way that mimics a regular
|
|||
|
programming language.
|
|||
|
|
|||
|
Within an always block, if- and case-statements can be used to model
|
|||
|
multiplexers. Blocking assignments (:math:`=`) and nonblocking
|
|||
|
assignments (:math:`<=`) are used to populate the leaf-nodes of these
|
|||
|
multiplexer trees. Unassigned leaf-nodes default to feedback paths that
|
|||
|
cause the output register to hold the previous value. More advanced
|
|||
|
synthesis tools often convert these feedback paths to register enable
|
|||
|
signals or even generate circuits with clock gating.
|
|||
|
|
|||
|
Registers assigned with nonblocking assignments (:math:`<=`) behave
|
|||
|
differently from variables in regular programming languages: In a
|
|||
|
simulation they are not updated immediately after being assigned.
|
|||
|
Instead the right-hand sides are evaluated and the results stored in
|
|||
|
temporary memory locations. After all pending updates have been prepared
|
|||
|
in this way they are executed, thus yielding semi-parallel execution of
|
|||
|
all nonblocking assignments.
|
|||
|
|
|||
|
For synthesis this means that every occurrence of that register in an
|
|||
|
expression addresses the output port of the corresponding register
|
|||
|
regardless of the question whether the register has been assigned a new
|
|||
|
value in an earlier command in the same always block. Therefore with
|
|||
|
nonblocking assignments the order of the assignments has no effect on
|
|||
|
the resulting circuit as long as the left-hand sides of the assignments
|
|||
|
are unique.
|
|||
|
|
|||
|
The three example codes in
|
|||
|
:numref:`Fig. %s <fig:StateOfTheArt_always12>`
|
|||
|
and :numref:`Fig. %s <fig:StateOfTheArt_always3>`
|
|||
|
use all these features and can thus be used to test the synthesis tools
|
|||
|
capabilities to synthesize always blocks correctly.
|
|||
|
|
|||
|
The first example is only using the most fundamental Verilog features.
|
|||
|
All tools under test were able to successfully synthesize this design.
|
|||
|
|
|||
|
.. code:: verilog
|
|||
|
:number-lines:
|
|||
|
|
|||
|
module uut_arrays01(clock, we, addr, wr_data, rd_data);
|
|||
|
|
|||
|
input clock, we;
|
|||
|
input [3:0] addr, wr_data;
|
|||
|
output [3:0] rd_data;
|
|||
|
reg [3:0] rd_data;
|
|||
|
|
|||
|
reg [3:0] memory [15:0];
|
|||
|
|
|||
|
always @(posedge clock) begin
|
|||
|
if (we)
|
|||
|
memory[addr] <= wr_data;
|
|||
|
rd_data <= memory[addr];
|
|||
|
end
|
|||
|
|
|||
|
endmodule
|
|||
|
|
|||
|
[fig:StateOfTheArt_arrays]
|
|||
|
|
|||
|
The 2nd example is functionally identical to the 1st one but is using an
|
|||
|
if-statement inside the always block. Odin-II fails to synthesize it and
|
|||
|
instead produces the following error message:
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
ERROR: (File: always02.v) (Line number: 13)
|
|||
|
You've defined the driver "count~0" twice
|
|||
|
|
|||
|
Vl2mv does not produce an error message but outputs an invalid synthesis
|
|||
|
result that is not using the reset input at all.
|
|||
|
|
|||
|
Icarus Verilog also doesn't produce an error message but generates an
|
|||
|
invalid output for this 2nd example. The code generated by Icarus
|
|||
|
Verilog only implements the reset path for the count register,
|
|||
|
effectively setting the output to constant 0.
|
|||
|
|
|||
|
So of all tools under test only HANA was able to create correct
|
|||
|
synthesis results for the 2nd example.
|
|||
|
|
|||
|
The 3rd example is using blocking and nonblocking assignments and many
|
|||
|
if statements. Odin also fails to synthesize this example:
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
ERROR: (File: always03.v) (Line number: 8)
|
|||
|
ODIN doesn't handle blocking statements in Sequential blocks
|
|||
|
|
|||
|
HANA, Icarus Verilog and vl2mv create invalid synthesis results for the
|
|||
|
3rd example.
|
|||
|
|
|||
|
So unfortunately none of the tools under test provide a complete and
|
|||
|
correct implementation of blocking and nonblocking assignments.
|
|||
|
|
|||
|
Arrays for memory modelling
|
|||
|
---------------------------
|
|||
|
|
|||
|
Verilog arrays are part of the synthesizeable subset of Verilog and are
|
|||
|
commonly used to model addressable memory. The Verilog code in
|
|||
|
:numref:`Fig. %s <fig:StateOfTheArt_arrays>`
|
|||
|
demonstrates this by implementing a single port memory.
|
|||
|
|
|||
|
For this design HANA, vl2m and ODIN-II generate error messages
|
|||
|
indicating that arrays are not supported.
|
|||
|
|
|||
|
.. code:: verilog
|
|||
|
:number-lines:
|
|||
|
|
|||
|
module uut_forgen01(a, y);
|
|||
|
|
|||
|
input [4:0] a;
|
|||
|
output y;
|
|||
|
|
|||
|
integer i, j;
|
|||
|
reg [31:0] lut;
|
|||
|
|
|||
|
initial begin
|
|||
|
for (i = 0; i < 32; i = i+1) begin
|
|||
|
lut[i] = i > 1;
|
|||
|
for (j = 2; j*j <= i; j = j+1)
|
|||
|
if (i % j == 0)
|
|||
|
lut[i] = 0;
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
assign y = lut[a];
|
|||
|
|
|||
|
endmodule
|
|||
|
|
|||
|
[fig:StateOfTheArt_for]
|
|||
|
|
|||
|
Icarus Verilog produces an invalid output that is using the address only
|
|||
|
for reads. Instead of using the address input for writes, the generated
|
|||
|
design simply loads the data to all memory locations whenever the
|
|||
|
write-enable input is active, effectively turning the design into a
|
|||
|
single 4-bit D-Flip-Flop with enable input.
|
|||
|
|
|||
|
As all tools under test already fail this simple test, there is nothing
|
|||
|
to gain by continuing tests on this aspect of Verilog synthesis such as
|
|||
|
synthesis of dual port memories, correct handling of write collisions,
|
|||
|
and so forth.
|
|||
|
|
|||
|
.. code:: verilog
|
|||
|
:number-lines:
|
|||
|
|
|||
|
module uut_forgen02(a, b, cin, y, cout);
|
|||
|
|
|||
|
parameter WIDTH = 8;
|
|||
|
|
|||
|
input [WIDTH-1:0] a, b;
|
|||
|
input cin;
|
|||
|
|
|||
|
output [WIDTH-1:0] y;
|
|||
|
output cout;
|
|||
|
|
|||
|
genvar i;
|
|||
|
wire [WIDTH-1:0] carry;
|
|||
|
|
|||
|
generate
|
|||
|
for (i = 0; i < WIDTH; i=i+1) begin:adder
|
|||
|
wire [2:0] D;
|
|||
|
assign D[1:0] = { a[i], b[i] };
|
|||
|
if (i == 0) begin:chain
|
|||
|
assign D[2] = cin;
|
|||
|
end else begin:chain
|
|||
|
assign D[2] = carry[i-1];
|
|||
|
end
|
|||
|
assign y[i] = ^D;
|
|||
|
assign carry[i] = &D[1:0] | (^D[1:0] & D[2]);
|
|||
|
end
|
|||
|
endgenerate
|
|||
|
|
|||
|
assign cout = carry[WIDTH-1];
|
|||
|
|
|||
|
endmodule
|
|||
|
|
|||
|
[fig:StateOfTheArt_gen]
|
|||
|
|
|||
|
For-loops and generate blocks
|
|||
|
-----------------------------
|
|||
|
|
|||
|
For-loops and generate blocks are more advanced Verilog features. These
|
|||
|
features allow the circuit designer to add program code to her design
|
|||
|
that is evaluated during synthesis to generate (parts of) the circuits
|
|||
|
description; something that could only be done using a code generator
|
|||
|
otherwise.
|
|||
|
|
|||
|
For-loops are only allowed in synthesizeable Verilog if they can be
|
|||
|
completely unrolled. Then they can be a powerful tool to generate array
|
|||
|
logic or static lookup tables. The code in
|
|||
|
:numref:`Fig. %s <fig:StateOfTheArt_for>` generates a
|
|||
|
circuit that tests a 5 bit value for being a prime number using a static
|
|||
|
lookup table.
|
|||
|
|
|||
|
Generate blocks can be used to model array logic in complex parametric
|
|||
|
designs. The code in
|
|||
|
:numref:`Fig. %s <fig:StateOfTheArt_gen>` implements a
|
|||
|
ripple-carry adder with parametric width from simple assign-statements
|
|||
|
and logic operations using a Verilog generate block.
|
|||
|
|
|||
|
All tools under test failed to synthesize both test cases. HANA creates
|
|||
|
invalid output in both cases. Icarus Verilog creates invalid output for
|
|||
|
the first test and fails with an error for the second case. The other
|
|||
|
two tools fail with error messages for both tests.
|
|||
|
|
|||
|
Extensibility
|
|||
|
-------------
|
|||
|
|
|||
|
This section briefly discusses the extensibility of the tools under test
|
|||
|
and their internal data- and control-flow. As all tools under test
|
|||
|
already failed to synthesize simple Verilog always-blocks correctly, not
|
|||
|
much resources have been spent on evaluating the extensibility of these
|
|||
|
tools and therefore only a very brief discussion of the topic is
|
|||
|
provided here.
|
|||
|
|
|||
|
HANA synthesizes for a built-in library of standard cells using two
|
|||
|
passes over an AST representation of the Verilog input. This approach
|
|||
|
executes fast but limits the extensibility as everything happens in only
|
|||
|
two comparable complex AST walks and there is no universal intermediate
|
|||
|
representation that is flexible enough to be used in arbitrary
|
|||
|
optimizations.
|
|||
|
|
|||
|
Odin-II and vl2m are both front ends to existing synthesis flows. As
|
|||
|
such they only try to quickly convert the Verilog input into the
|
|||
|
internal representation of their respective flows (BLIF). So
|
|||
|
extensibility is less of an issue here as potential extensions would
|
|||
|
likely be implemented in other components of the flow.
|
|||
|
|
|||
|
Icarus Verilog is clearly designed to be a simulation tool rather than a
|
|||
|
synthesis tool. The synthesis part of Icarus Verilog is an ad-hoc add-on
|
|||
|
to Icarus Verilog that aims at converting an internal representation
|
|||
|
that is meant for generation of a virtual machine based simulation code
|
|||
|
to netlists.
|
|||
|
|
|||
|
Summary and Outlook
|
|||
|
-------------------
|
|||
|
|
|||
|
Table \ :numref:`tab:StateOfTheArt_sum` summarizes
|
|||
|
the tests performed. Clearly none of the tools under test make a serious
|
|||
|
attempt at providing a feature-complete implementation of Verilog. It
|
|||
|
can be argued that Odin-II performed best in the test as it never
|
|||
|
generated incorrect code but instead produced error messages indicating
|
|||
|
that unsupported Verilog features where used in the Verilog input.
|
|||
|
|
|||
|
In conclusion, to the best knowledge of the author, there is no FOSS
|
|||
|
Verilog synthesis tool other than Yosys that is anywhere near feature
|
|||
|
completeness and therefore there is no other candidate for a generic
|
|||
|
Verilog front end and/or synthesis framework to be used as a basis for
|
|||
|
custom synthesis tools.
|
|||
|
|
|||
|
Yosys could also replace vl2m and/or Odin-II in their respective flows
|
|||
|
or function as a pre-compiler that can translate full-featured Verilog
|
|||
|
code to the simple subset of Verilog that is understood by vl2m and
|
|||
|
Odin-II.
|
|||
|
|
|||
|
Yosys is designed for extensibility. It can be used as-is to synthesize
|
|||
|
Verilog code to netlists, but its main purpose is to be used as basis
|
|||
|
for custom tools. Yosys is structured in a language dependent Verilog
|
|||
|
front end and language independent synthesis code (which is in itself
|
|||
|
structured in independent passes). This architecture will simplify
|
|||
|
implementing additional HDL front ends and/or additional synthesis
|
|||
|
passes.
|
|||
|
|
|||
|
Chapter \ :numref:`<CHAPTER_eval>` contains a more detailed
|
|||
|
evaluation of Yosys using real-world designs that are far out of reach
|
|||
|
for any of the other tools discussed in this appendix.
|
|||
|
|
|||
|
…passed 2em …produced error 2em :math:`\skull` …incorrect output
|
|||
|
|
|||
|
[tab:StateOfTheArt_sum]
|
|||
|
|
|||
|
.. [1]
|
|||
|
This appendix is an updated version of an unpublished student
|
|||
|
research paper. :cite:p:`VerilogFossEval`
|
|||
|
|
|||
|
.. [2]
|
|||
|
To the author's best knowledge, all relevant tools that existed at
|
|||
|
the time of this writing are included. But as there is no formal
|
|||
|
channel through which such tools are published it is hard to give any
|
|||
|
guarantees in that matter.
|
|||
|
|
|||
|
.. [3]
|
|||
|
Icarus Verilog is mainly a simulation tool but also supported
|
|||
|
synthesis up to version 0.8. Therefore version 0.8.7 is used for this
|
|||
|
evaluation.)
|