CummingsSNUG2019SV FSM1
CummingsSNUG2019SV FSM1
Silicon Valley, CA
Voted Best Presentation
1st Place
World Class SystemVerilog & UVM Training
Clifford E. Cummings Heath Chambers
Sunburst Design, Inc. HMC Design Verification, Inc.
Provo, UT, USA Albuquerque, NM, USA
www.sunburst‐design.com
ABSTRACT
There are at least seven different Finite State Machine (FSM) design techniques that are
commonly taught, one with combinatorial outputs and six with registered outputs. This paper
will describe four of the FSM design techniques: (1) 1‐Always Block Style with registered
outputs, (2) 2‐Always Block Style with combinatorial outputs, (3) 3‐Always Block Style with
registered outputs, and (4) 4‐Always Block Style with registered outputs
This paper establishes measurement techniques to determine good coding styles and also shows
synthesis results for ASIC designs.
Multiple benchmark FSM designs are used to measure coding style and synthesis efficiency.
The other three FSM design styles will be described in follow‐on papers.
SNUG 2019
Table of Contents
Finite State Machine (FSM) Design & Synthesis using SystemVerilog ‐ Part I ................................................. 1
1. Introduction ............................................................................................................................................................................. 6
2. Important design goals ........................................................................................................................................................ 7
2.1 More code = more bugs ......................................................................................................................................... 7
3. FSM Coding Style Metrics ................................................................................................................................................... 8
4. State machine types .............................................................................................................................................................. 8
4.1 Moore ‐vs‐ Mealy ...................................................................................................................................................... 8
4.2 Binary ‐vs‐ OneHot encoding .............................................................................................................................. 9
5. ASIC ‐vs‐ FPGA Synthesis .................................................................................................................................................... 9
6. SystemVerilog FSM coding styles ................................................................................................................................ 10
6.1 One Always Block FSM coding style ‐ registered outputs ................................................................... 10
6.2 Two Always Block FSM coding style ‐ combinatorial outputs .......................................................... 10
6.3 Three Always Block FSM coding style ‐ registered outputs ............................................................... 11
6.4 Four Always Block FSM coding style ‐ registered outputs ................................................................. 12
7. SystemVerilog FSM Coding Tips & Tricks ................................................................................................................ 13
7.1 Logic data type ....................................................................................................................................................... 13
7.2 Assignments using '0 / '1 / 'x ‐vs‐ 1'b0 / 1'b1 / 1'bx ............................................................................ 13
7.3 FSM module header & port list ....................................................................................................................... 15
7.4 Enumerated state types ..................................................................................................................................... 15
7.5 FMS RTL code should use SystemVerilog always_ff and always_comb procedures ................ 17
7.6 FSM State Register ................................................................................................................................................ 17
7.7 Default next='x ‐vs‐ default next=state ....................................................................................................... 18
7.8 Next state naming convention ......................................................................................................................... 19
7.9 Next assignments placed in a column .......................................................................................................... 20
7.10 Loopback next state assignments ............................................................................................................... 21
7.11 Default output assignments ........................................................................................................................... 21
7.12 Nonblocking Assignment race conditions? ............................................................................................. 22
8. Benchmark FSM designs .................................................................................................................................................. 23
8.1 FSM1 with 4 states, 2 outputs and 2 inputs .............................................................................................. 25
8.2 FSM7 with 10 states, 1 output and 2 inputs .............................................................................................. 27
8.3 FSM8 with 10 states, 3 outputs and 2 inputs ............................................................................................ 33
8.4 Prep4 FSM design with 16 states, 8‐bit output and 8‐bit input ....................................................... 35
9. Comparisons & Summary ................................................................................................................................................ 38
Figure 8 ‐ DesignVision error messages from bad usage of always_ff begin‐end statements ............... 18
Figure 9 ‐ FSM loopback state assignment styles ...................................................................................................... 21
Figure 10 ‐ FSM1 state diagram ........................................................................................................................................ 25
Figure 11 ‐ fsm1 ‐ Coding styles effort comparison ................................................................................................. 25
Figure 12 ‐ fsm1 ‐ Lines of code ........................................................................................................................................ 26
Figure 13 ‐ fsm1 ‐ Coding goals summary .................................................................................................................... 27
Figure 14 ‐ FSM7 state diagram ........................................................................................................................................ 27
Figure 15 ‐ fsm7 ‐ Coding styles effort comparison ................................................................................................. 28
Figure 16 ‐ fsm7 ‐ Lines of code ........................................................................................................................................ 29
Figure 17 ‐ fsm7 ‐ Coding goals summary .................................................................................................................... 29
Figure 18 ‐ FSM7 state diagram ‐ why is the 1‐always block style so verbose? .......................................... 30
Figure 19 ‐ FSM8 state diagram ........................................................................................................................................ 33
Figure 20 ‐ fsm8 ‐ Coding styles effort comparison ................................................................................................. 33
Figure 21 ‐ fsm8 ‐ Lines of code ........................................................................................................................................ 34
Figure 22 ‐ fsm8 ‐ Coding goals summary .................................................................................................................... 35
Figure 23 ‐ Prep4 state diagram ....................................................................................................................................... 35
Figure 24 ‐ prep4 ‐ Coding styles effort comparison ............................................................................................... 36
Figure 25 ‐ prep4 ‐ Lines of code ...................................................................................................................................... 37
Figure 26 ‐ prep4 ‐ Coding goals summary .................................................................................................................. 37
Table of Examples
Example 1 ‐ FSM1 module header and port list example ...................................................................................... 15
Example 2 ‐ FSM1: fsm1_pkg_a.sv with abstract enumerated state_e typedef ............................................. 16
Example 3 ‐ FSM1: fs1_pkg_b.sv encoded state_e typedef w/logic data type and bit‐range .................. 16
Example 4 ‐ FSM1: importing fsm1_pkg::*; (abstract or binary) with state/next declaration .............. 16
Example 5 ‐ FSM state register declaration ................................................................................................................. 17
Example 6 ‐ Bad usage of always_ff begin‐end statements ................................................................................... 18
Example 7 ‐ Default next='x combinatorial always_comb procedure for FSM designs ............................ 19
Example 8 ‐ always_comb next assignments in a neat column ‐ Recommended ........................................ 20
Example 9 ‐ always_comb next assignments following contour of the code ‐ NOT Recommended ... 20
Example 10 ‐ FSM registered output assignments using an always_ff procedure ...................................... 22
Example 11 ‐ fsm7_1 ‐ 1‐always block style output assignments for each transition arc ....................... 32
Example 12 ‐ File: fsm1_pkg_a.sv ‐ fsm1_pkg enumerated typedef .................................................................. 43
Example 13 ‐ File: fsm1_pkg_b.sv ‐ fsm1_pkg enumerated typedef .................................................................. 43
1. Introduction
What could possibly be new about Finite State Machine (FSM) design? Hasn't this topic been
completely covered by existing publications?
Sunburst Design has been teaching six different FSM coding styles, plus a few minor variants, for
more than two decades and the last paper that Cliff did on this topic was presented in 2003. Cliff &
Heath have made many new observations and refinements to the FSM coding techniques and we have
observed synthesis improvements using FSM coding styles. Also, FSM synthesis can have interesting
differences when synthesizing for ASICs and FPGAs. This paper shares fundamental FSM coding
styles along with newer FSM design techniques that we have refined in the 15 years since Cliff's last
FSM conference paper.
FSM design is actually a very large topic. The seven major FSM coding styles include one FSM coding
style with combinatorial outputs and six FSM coding styles with registered outputs. Registering
module outputs is typically recommended by synthesis tool vendors as it helps meet timing goals
more easily without using multiple different input and output timing design constraints. Registered
outputs are also glitch‐free. There is nothing inherently wrong with FSM combinatorial outputs when
glitching outputs are used internally to an ASIC or FPGA design and settle before the next active clock
edge to meet register setup times, which can be proven with Static Timing Analysis (STA) tools, so
we do show one reasonable FSM coding style with combinatorial outputs.
Heath and Cliff generally recommend doing FSM design with registered outputs and there are
multiple FSM coding styles that achieve that goal.
The seven different coding styles that we commonly teach are:
2‐always block coding style with combinatorial outputs.
1‐always block coding style with registered outputs.
3‐always block coding style with registered outputs.
4‐always block coding style with registered outputs (new style not previously shown).
Indexed OneHot coding style with registered outputs.
Parameter OneHot coding style with registered outputs.
Output encoded coding style with registered outputs.
This topic is large enough that it is our intent to break documentation on these styles into three
papers with this being the first. This paper will cover the first four coding styles listed above with the
remaining three coding styles and sub‐variations to be covered in subsequent papers.
In the process of writing this paper, we discovered that the 1‐always block coding style typically
infers a design that is somewhat smaller and faster than our preferred 3‐always block coding style.
We found that creating a 4‐always block FSM design could achieve the same synthesis results as the
1‐always block style while still being a much more concise coding style than the 1‐always block style.
The reasons for these claims and the 4‐always block coding style are included in this paper.
Table 1 - Average time verification engineers spend in various tasks
The Wilson Research Group Studies from 2010[6], 2012[7], 2014[8][9], 2016[10][11] and 2018[12]
all showed that debug time consistently consumed the most verification engineering time. Since 2014
as shown in Table 1, debugging has taken on average ~95% more effort than any other verification
task.
It is clear from these studies that any coding habit that helps to minimize debug time is an important
habit to develop. The RTL coding guidelines shared in this paper help to reduce debug time.
Figure 1 - Moore & Mealy State Machine block diagram
Moore state machines are favored in industry because the outputs have a full cycle to settle through
the combinatorial logic and are therefore easier to meet required cycle times. Mealy outputs allow
an input to appear after the cycle has started, and the input must still traverse the combinatorial logic
and meet setup time for the Mealy output. If the design absolutely requires an input to make it on‐
chip after the active clock edge, pass through logic and appear on the output all within one cycle,
those are the designs that typically use a Mealy output.
Using a play on words, it is said that, "Moore is Less" meaning that Moore state machines are only
dependent on the current state while Mealy State Machines are dependent on the current state and
one or more inputs.
In general, we avoid Mealy FSM designs unless absolutely necessary.
Figure 2 - Binary -vs- OneHot state diagrams
FPGA synthesis tools frequently have a special setting (typically a GUI switch) to turn off the
automatic creation of OneHot FSM designs. OneHot FPGA designs will be described in the Part II FSM
paper.
Figure 3 - Block diagram for 1-always block coding style
code) followed by an always_comb procedure to represent the combined next state logic and
combinatorial output logic. Optionally, the outputs can be separated from the always_comb
procedure and placed into a separate always_comb procedure or into one or more continuous
assignment statements.
Figure 4 - Block diagram for 2-always block coding style
Figure 5 - Block diagram for 3-always block coding style
The trick used in this coding style is to recognize that the output assignments are the "next" output
assignments and not the output assignments for the current state, so the final always_ff procedure
will use a case statement to test the next state, not the current state. Since the outputs are calculated
from the next state logic, this can add extra logic when synthesized as the next state was already
calculated from input conditions. This means that there is one block of combinatorial logic that
calculates the next state and that feeds a second block of combinatorial logic to calculate the next
outputs, which can create larger and slower combinatorial logic. In the 1‐always block coding style,
the inputs and state variables are used to calculate both the next state and next outputs in parallel,
which can reduce the size and delay through the combinatorial next output logic. This inefficiency
will be addressed in the 4‐always block coding style described in the next section.
Figure 6 - Block diagram for 4-always block coding style
Figure 7 - FSM1 state diagram - used for example code
7.2 Assignments using '0 / '1 / 'x -vs- 1'b0 / 1'b1 / 1'bx
SystemVerilog introduced a very convenient shorthand to assign all 0's, all 1's or all X's to a scalar
signal or a vector bus. The notation is to assign '0 (all zeros), '1 (all ones) and 'x (all X's). Although
There were too many opportunities for confusion by adding '0 / '1 / 'x / 'z to concatenation, so
the SystemVerilog Standards Group decided that when this shorthand notation was used in
concatenation that the notation would only expand to a single bit each. In the above examples, the
values expand as shown below.
data[15:0] = {'1, 4'hA, '0};
// is equal to 16'b0000_0000_0011_0100 or 16'h0034
data[15:0] = {'0, '1, '0};
// is equal to 16'b0000_0000_0000_0010 or 16'h0002
Many engineers list each port on a separate line and there is nothing specifically wrong with that
practice, but we prefer to group multiple signals into each output and input declaration as shown
in Example 1, to reduce the number of lines of code in the FSM design and to allow more of the FSM
design to be visible per page when examining the code.
Checklist item: Use the Verilog‐2001 concise port declaration style and declare all ports to be of type
logic. Extra points for listing outputs followed by inputs followed by control inputs. Extra points for
grouping multiple signals into each output and input port list declaration.
(2) By maintaining pkg_a and pkg_b files, we could easily switch from abstract to binary
encoded enum typedef[s] without maintaining two copies of each FSM file.
(3) Simulation of either abstract or binary‐encoded enum[s] was as easy as selecting and
compiling the appropriate package before compiling the other simulation files since each
package had the same identical package name. This gave us much easier code maintenance.
(4) Similarly, synthesis of either abstract or binary‐encoded enum[s] was as easy as compiling the
appropriate package before compiling the other synthesis files since each package had the
same identical package name. Again, much easier code maintenance.
(5) If we wanted to try different enumerated assignments, we only had to change the pkg_b file
and all styles would use the exact same new encodings. We did not have to touch the FSM files
themselves.
(6) The testbench could easily use the same state_e typedef to implement reference models
to track expected FSM states, if desired.
(7) The testbench could easily use bind ‐files for assertions or covergroups by using the typedef
to input the state and next variables from the FSM design.
After we implemented the separate package files, we were able to cut the number of FSM benchmark
files in half and ensured a more error‐free coding style.
The enumerated declarations for the state_e typedef can either be made using abstract state
encodings as shown in
Example 2, or can be made using the logic data type, specifying the number of state bits as a range,
and include user‐defined encodings for each state as shown in Example 3.
package fsm1_pkg;
typedef enum {IDLE,
READ,
DLY,
DONE,
XXX } state_e;
endpackage
Example 2 - FSM1: fsm1_pkg_a.sv with abstract enumerated state_e typedef
package fsm1_pkg;
typedef enum logic [1:0] {IDLE = 2'b00,
READ = 2'b01,
DLY = 2'b11,
DONE = 2'b10,
XXX = 'x } state_e;
endpackage
Example 3 - FSM1: fs1_pkg_b.sv encoded state_e typedef w/logic data type and bit-range
import fsm1_pkg::*;
state_e state, next;
Example 4 - FSM1: importing fsm1_pkg::*; (abstract or binary) with state/next declaration
It is typical for RTL coders to start with the abstract state and next declarations and to later add
state encodings if desired. Since the state names are used throughout the FSM RTL code, adding state
encodings later does not require any additional RTL modifications to the FSM design.
The enumerated state names also show up automatically in a waveform display to help track state
transitions and to help debug the state machine. It is often useful to show two copies of the
enumerated names in the waveform display, the first showing the state names (which is the default
mode for all waveform viewers) and the second copy with the radix changed to be binary, decimal or
hex to see the state encodings (often useful for debugging). There is nothing in the IEEE
SystemVerilog Standard[15] that requires a waveform viewer to show the state names by default,
but all waveform viewers that we have used from all of the major EDA vendors show the state names
by default.
It is a good practice to include an extra XX or XXX state in the list of declared state names as shown in
both Example 2 and Example 3. This extra XXX state will be used to code the always_comb procedure
and this practice can help quickly debug an FSM design, plus if one chooses to include state encodings,
the XXX state will be set to all X's, which are treated as "don't cares" by the synthesis tool to help
optimize the synthesized design.
Checklist item: Declare the state and next variables using enumerated types. Add an XX or XXX
state to help debug the design and to help optimize the synthesized result.
7.5 FMS RTL code should use SystemVerilog always_ff and always_comb procedures
The RTL code for the FSM design should use always_ff and always_comb procedures to infer
clocked and combinatorial logic. Do not use the older Verilog always procedures. The always_ff
and always_comb procedures show designer intent and include built‐in checking for bad RTL coding
styles as described in the paper "SystemVerilog Logic Specific Processes for Synthesis ‐ Benefits and
Proper Usage[3]."
Checklist item: Use always_ff and always_comb procedures to infer clocked and combinatorial
logic. Do not use the older Verilog always procedures.
There is no need to put the if‐statement and the state assignment on separate lines and there is no
need to put begin ‐ end on the always_ff procedure. Also, we place the reset state assignment and
next state assignment into a nice, neat column for easy scanning and reading.
Note that adding begin ‐ end to the always_ff procedure is not only unnecessary, but introduces
the opportunity to add code before the first if (!rst_n) statement, which violates coding
requirements for some synthesis tools including Design Compiler. In short, the always_ff begin ‐
end allows an RTL designer to code and simulate something that might not be synthesizable and as
such, we consider this to be a poor coding practice.
Consider the legal RTL code in Example 6.
always_ff @(posedge clk, negedge rst_n) begin
testbad <= go;
if (!rst_n) state <= IDLE;
else state <= next;
end
Example 6 - Bad usage of always_ff begin-end statements
This example code is legal SystemVerilog code and will simulate without error, but once this design
is read into the DesignVision GUI, the following error messages are reported in a pop‐up window:
1: Error:
<filename><line number>:
The statements in this 'always' block are outside the scope of the
synthesis policy. Only an 'if' statement is allowed at the top level in
this always block. (ELAB-302)
In short, the begin ‐ end is unnecessary, needlessly verbose and introduces the opportunity to add
bad code that might not be discovered until the design is read for synthesis.
Checklist item: Declare the state register using just 3 lines of code and place it at the top of the design
after the enumerated type declaration.
Anyone who has done extensive RTL coding and simulation recognizes that, when it comes to RTL
debugging, catastrophic RTL coding failures are the easiest to find, identify and fix. Conversely, subtle
RTL coding errors can often be very time consuming to find and frequently require the RTL coder to
add numerous debug printing messages to finally discover the subtle problem in the code. Making X‐
assignments can help cause catastrophic simulation failures when there is an RTL design problem,
while implied loopback errors can often allow an FSM design to appear to be working for multiple
clock cycles before the simulation reports an FSM simulation error.
So how does this work and what procedure do we recommend?
We strongly encourage engineers to make the pre‐default next='x assignment in the FSM design.
The pre‐default X‐assignments have two RTL simulation debug advantages and one RTL synthesis
advantage.
The RTL simulation advantage is that assigning X's frequently causes the simulation to fail
catastrophically if there is a missing next assignment. At the point where there is a missing next
assignment, we say that the waveform display "starts to bleed red!" Wherever the next state
assignment is missing, the waveform display will show that next is all X's and that is typically the
exact point where the next‐assignment is missing. This is a catastrophic simulation error that quickly
identifies the missing assignment and, from our experience, is fixed very quickly.
The second RTL simulation advantage is that making a pre‐default‐X assignment requires the RTL
coder to code an equation for each transition arc from each state. After completing the FSM design, a
designer can double‐check the code by counting the number of transition equations for each state in
the RTL code and match that to the number of transition arcs in the state diagram. There is a one‐to‐
one correspondence between the number of transition equations and transition arcs. Using the
next=state default assignment allows designers to remove loopback transition assignments from
the RTL code wherever there is a feedback loop on that state so there will be fewer RTL equations
than transition arcs in the state diagram.
The RTL synthesis advantage is that making X‐assignments is like putting X's into a K‐Map for unused
states and all digital design engineers recognize that adding X's to a K‐Map allows engineers or tools
to make larger groupings, enabling smaller sums‐of‐products, which can infer smaller combinatorial
logic (at least in theory).
Making a next=state pre‐default assignment only has one minor advantage over the next='x pre‐
default assignment. Any state with a loopback transition can be omitted from the RTL code since that
state will not take another transition branch and will remain in the same state; thus potentially
removing a few lines of code.
Since debug time is a primary concern in RTL design, we recommend using the pre‐default next='x
assignment style.
Checklist item: Use the pre‐default next='x assignment at the top of the always_comb procedure.
with using nextstate except that it is a needlessly long identifier that lengthens the code on all of
the next assignments in the combinatorial always_comb procedure.
We know that next is a keyword in VHDL so those with a VHDL background tend to gravitate towards
using the nextstate identifier, but next is not a keyword in SystemVerilog and SystemVerilog
coders can make their designs more concise by using the next identifier instead of using nextstate.
As previously mentioned, we prefer concise code.
Checklist item: Extra points for using next instead of using nextstate in the FSM design, but both
work fine.
always_comb begin
next = XXX;
case (state)
IDLE : if (go) next = READ;
else next = IDLE; //@ loopback
READ : next = DLY;
DLY : if (!ws) next = DONE;
else next = READ;
DONE : next = IDLE;
default: next = XXX;
endcase
end
Example 9 - always_comb next assignments following contour of the code - NOT Recommended
Of course the simulation and synthesis of both of the above examples will be identical. The column
alignment is used to quickly understand and debug the always_comb next assignments.
Checklist item: Extra points for placing the next assignments in a neat column in the FSM RTL code.
If the pre‐default next=state is used, the loopback assignment can be omitted from the if-else-
if statement since the next state is already assigned to stay in the current state.
The reason for using the //@ loopback comment and placing the loopback into the final else ‐
clause is that it makes it very easy to convert from the next='x pre‐default to the next=state pre‐
default style of always_comb procedure (although we do not recommend the latter). The RTL coder
simply replaces next='x with next=state and then deletes all lines that have the //@ loopback
comment.
must not change for that state and that will infer a latch when synthesized.
Listing all of the outputs for each state causes the FSM RTL design code to grow in size very quickly.
Listing all of the outputs for each state makes it confusing for an engineer to determine which outputs
have changed in which states. Engineers often try to examine the output assignments for the
preceding and next states in an attempt to try to figure out what has changed in this state.
A better coding practice is to place default output assignments before the output‐assignment case
statement and then to update the appropriate outputs for each state where the outputs change as
shown in Example 10.
always_ff @(posedge clk, negedge rst_n)
if (!rst_n) begin
rd <= '0;
ds <= '0;
end
else begin
rd <= '0;
ds <= '0;
case (next)
IDLE : ;
READ : rd <= '1;
DLY : rd <= '1;
DONE : ds <= '1;
default: {rd,ds} <= 'x;
endcase
end
endmodule
Example 10 - FSM registered output assignments using an always_ff procedure
This coding style offers two significant advantages over making all output assignments for each state.
First, the code becomes more concise. Second an engineer can plainly see which outputs change for
each state, thus making the code more readable, easier to understand and easier to debug.
This style requires less code (one of our goals) and makes the design easier to debug (also one of our
goals).
Checklist item: Place pre‐default output assignments before the output‐assignment case statement
and then update the appropriate outputs for each state where the outputs change.
The 2001 Verilog Standard[14] fixed the example in section 9.2.2 to have parallel execution of the
two assignments, which indeed is a race condition; thus, Section 5.4.1 clearly governs the behavior
of two sequentially executed nonblocking assignments and last assignment wins.
There is no race condition in Example 10.
None of the designs up to this point used case‐default values set to all X's ( case-default‐X). In
the tables for each FSM design, these are referred to as the "No case‐default‐X" values.
Since adding default X's to a case statement is similar adding X's to a K‐Map, default X‐values were
assigned to next states and outputs in the case statements and the previous synthesis exercises were
repeated. These are referred to as the "Default X" values in the tables.
The next synthesis iteration was to change the next = 'x assignments to next = state and to
remove all of the loopback code from the case statements. The theory being tested is that synthesis
might improve if the state does not transition and if the extra code is removed from each design. Then
the synthesis runs were executed again. These are referred to as the "Default X ‐ No Loopback" values
in the tables.
Figure 10 - FSM1 state diagram
There is one loopback state in the FSM1 design and that is in the IDLE state.
The coding effort for small FSM designs using the different styles does not differ significantly, but
it will differ dramatically as the number of states and outputs increases.
Figure 11 - fsm1 - Coding styles effort comparison
Figure 11 shows the relative coding difference between the four coding styles. The full fsm1 RTL code
for all four coding styles used in Figure 11 are shown in Appendix 2.2 ‐ Appendix 2.5. The fsm1_pkg
files with both abstract and binary encoded typedef[s] that were used by all of the fsm1 designs are
shown in Appendix 2.1.
Design Compiler O‐2018.06‐SP4 LSI 10K Library ‐ lsk_10k
No case‐default‐X / Explicit loopback case‐default‐X / Explicit loopback case‐default‐X / Implicit loopback
RTL No Clock Goal Clock Goal 7.5 RTL No Clock Goal Clock Goal 7.5 RTL No Clock Goal Clock Goal 7.5
Enums LOC* Area Slack Area Slack LOC* Area Slack Area Slack LOC* Area Slack Area Slack
fsm1_1 Abstract 39 52 ‐5.57 52 0.04 44 50 ‐5.19 49 0.04 42 50 ‐5.36 51 0.04
fsm1_2 Abstract 34 32 ‐4.89 38 (1.68) 39 31 ‐4.94 35 (1.37) 38 28 ‐5.18 35 (1.37)
fsm1_3 Abstract 38 49 ‐6.37 49 0.03 41 49 ‐6.37 49 0.03 40 49 ‐6.37 57 0.04
fsm1_4 Abstract 48 52 ‐5.57 52 0.04 50 52 ‐5.57 52 0.04 49 53 ‐5.10 52 0.04
Design Compiler O‐2018.06‐SP4 SAED Library ‐ saed32rvt_ss0p95v125c.db
No case‐default‐X / Explicit loopback case‐default‐X / Explicit loopback case‐default‐X / Implicit loopback
RTL No Clock Goal Clock Goal 0.65 RTL No Clock Goal Clock Goal 0.65 RTL No Clock Goal Clock Goal 0.65
Abstract LOC* Area Slack Area Slack LOC* Area Slack Area Slack LOC* Area Slack Area Slack
fsm1_1 Abstract 39 51 ‐0.42 54 0.00 44 51 ‐0.40 52 0.00 42 52 ‐0.39 54 0.00
fsm1_2 Abstract 34 34 ‐0.38 54 (0.12) 39 34 ‐0.40 42 (0.09) 38 32 ‐0.40 43 (0.09)
fsm1_3 Abstract 38 48 ‐0.50 49 0.00 41 48 ‐0.50 49 0.00 40 48 ‐0.50 48 0.00
fsm1_4 Abstract 48 51 ‐0.42 54 0.00 50 51 ‐0.42 54 0.00 49 50 ‐0.40 52 0.00
When the fsm1 design was synthesized, there were almost no differences when state encodings and
pre‐default‐X values were added. Also there was no noticeable difference when the loopback code
was deleted. In this design, the 1‐always block coding style had slightly better synthesis results than
the 3‐always block style, and the 4‐always block style synthesis results matched the 1‐always block
synthesis results. Since this FSM design has four states and since two bits were used to create all
possible unique encodings for each state, it is not surprising that adding default‐X assignments did
not noticeably improve the synthesis results. We expect pre‐default‐X assignments will prove more
useful when the number of states is not a power of 2.
Figure 12 - fsm1 - Lines of code
Figure 13 - fsm1 - Coding goals summary
It is apparent from Figure 12 that the coding styles are rather equal.
Figure 14 - FSM7 state diagram
As can be seen from the fsm7 design, the 1‐always block coding style required 46% more code than
the equivalent 3‐always block coding style.
Page 27 Finite State Machine (FSM) Design & Synthesis
Rev 1.0 using SystemVerilog ‐ Part I
SNUG 2019
Figure 15 - fsm7 - Coding styles effort comparison
When the fsm7 design was synthesized, there was some area and performance advantage using the
1‐always block coding style over the 3‐always block coding style as shown in Table 3. This is
presumably due to the fact that the registered outputs for the 3‐always block coding style are
calculated from the next state values as opposed to using the same inputs tests to calculate the
clocked outputs for the 1‐always block style. Noteworthy is the fact that the 4‐always block style
synthesis results were actually slightly better than the 3‐always block synthesis results. The full fsm7
RTL code for the coding styles used in Figure 15 are shown in Appendix 2.7 ‐ Appendix 2.10. The
fsm7_pkg files with both abstract and binary encoded typedef[s] that were used by all of the fsm7
designs are shown in Appendix 2.6.
Design Compiler O‐2018.06‐SP4 LSI 10K Library ‐ lsk_10k
No case‐default‐X / Explicit loopback case‐default‐X / Explicit loopback case‐default‐X / Implicit loopback
RTL No Clock Goal Clock Goal 8.5 RTL No Clock Goal Clock Goal 8.5 RTL No Clock Goal Clock Goal 8.5
Enums LOC* Area Slack Area Slack LOC* Area Slack Area Slack LOC* Area Slack Area Slack
fsm7_1 Abstract 69 100 ‐7.60 153 0.00 73 94 ‐7.48 105 0.11 70 89 ‐7.42 97 0.06
fsm7_2 Abstract 41 76 ‐8.10 118 (1.48) 45 78 ‐6.87 112 (1.15) 43 78 ‐8.90 95 (1.15)
fsm7_3 Abstract 46 93 ‐8.92 164 (0.91) 47 89 ‐8.14 145 0.01 45 87 ‐7.82 127 0.02
fsm7_4 Abstract 57 95 ‐8.38 139 0.07 59 91 ‐7.79 118 0.03 57 87 ‐7.96 88 0.12
Design Compiler O‐2018.06‐SP4 SAED Library ‐ saed32rvt_ss0p95v125c.db
No case‐default‐X / Explicit loopback case‐default‐X / Explicit loopback case‐default‐X / Implicit loopback
RTL No Clock Goal Clock Goal 0.65 RTL No Clock Goal Clock Goal 0.65 RTL No Clock Goal Clock Goal 0.65
Enums LOC* Area Slack Area Slack LOC* Area Slack Area Slack LOC* Area Slack Area Slack
fsm7_1 Abstract 69 122 ‐0.77 126 0.00 73 101 ‐0.63 107 0.00 70 96 ‐0.68 102 0.00
fsm7_2 Abstract 41 80 ‐0.68 108 (0.11) 45 87 ‐0.61 109 (0.07) 43 82 ‐0.71 95 (0.07)
fsm7_3 Abstract 46 100 ‐0.73 113 0.00 47 95 ‐0.65 101 (0.01) 45 92 ‐0.62 122 0.00
fsm7_4 Abstract 57 105 ‐0.70 125 0.00 59 103 ‐0.65 107 0.00 57 96 ‐0.68 107 0.00
Figure 16 - fsm7 - Lines of code
Figure 17 - fsm7 - Coding goals summary
It is apparent from Figure 16 that the 1‐always block coding style is significantly more verbose than
the 3‐always block coding style and that the 1‐always block code is getting harder to follow all of the
next‐output assignments.
We have again noted that the 1‐always block coding style might not be so easy to change due to FSM
changes.
8.2.1 Why is 1 always block more verbose than 3 always block?
When we originally examined different FSM coding styles more than 15 years ago, we were
surprised to observe that larger 1‐always block FSM RTL coded examples were significantly more
verbose than 3‐always block coded examples. Based on the names of the styles, this seemed
counter intuitive. After all, which sounds bigger? 1‐always block or 3‐always blocks?
Upon closer examination we noted that the 2‐always block and 3‐always block RTL coding styles
assign the outputs once per state, while the 1‐always block style assigned the outputs once per
transition arc to each state.
Figure 18 - FSM7 state diagram - why is the 1-always block style so verbose?
In the FSM7 design, as shown in Figure 18, the worst case state is S3. Every state in this FSM design
that transitions to state S3 must set state <= S3 and also change the output assignment by setting
y1 <= '1. These two assignments must be encapsulated within begin ‐ end statements. This means
that each transition arc to state S3 must include these four lines of code. This contributes to the rapid
code‐explosion that is so common when using the 1‐always block coding style.
In the RTL code shown in Example 11, it can be seen that there are four lines of code for each state in
the case statement that are nearly identical. For each transition to state S3, the assignment y1 <=
'1 is required and the state <= S3 assignment is also required. These two assignments must also
be surrounded by begin ‐ end. These four lines of code, added to each case item, quickly add many
lines of code to the case statement.
end
endmodule
Example 11 - fsm7_1 - 1-always block style output assignments for each transition arc
The difference becomes more pronounced when there are more states, multiple output assignments
and more transition arcs as shown in the FSM8 design of Section 8.3 .
Figure 19 - FSM8 state diagram
As can be seen from the fsm8 design, the 1‐always block coding style required 84% more code than
the equivalent 3‐always block coding style.
Figure 20 - fsm8 - Coding styles effort comparison
Design Compiler O‐2018.06‐SP4 LSI 10K Library ‐ lsk_10k
No case‐default‐X / Explicit loopback case‐default‐X / Explicit loopback case‐default‐X / Implicit loopback
RTL No Clock Goal Clock Goal 9.0 RTL No Clock Goal Clock Goal 9.0 RTL No Clock Goal Clock Goal 9.0
Enums LOC* Area Slack Area Slack LOC* Area Slack Area Slack LOC* Area Slack Area Slack
fsm8_1 Abstract 136 147 ‐10.66 220 0.03 142 163 ‐8.63 207 0.00 138 149 ‐8.37 179 0.15
fsm8_2 Abstract 70 105 ‐10.57 190 (2.99) 76 100 ‐7.88 150 (1.95) 73 98 ‐8.62 141 (1.87)
fsm8_3 Abstract 72 140 ‐14.81 284 (0.72) 73 133 ‐11.50 229 (1.38) 70 139 ‐12.62 246 (1.39)
fsm8_4 Abstract 98 155 ‐10.11 261 (0.03) 100 157 ‐9.02 190 0.02 97 162 ‐10.45 210 0.01
fsm8_1 Encoded 136 140 ‐11.38 213 (0.09) 142 164 ‐7.85 195 0.02 138 175 ‐8.73 198 0.03
fsm8_2 Encoded 70 94 ‐7.95 154 (2.70) 76 85 ‐7.19 130 (2.16) 73 95 ‐9.57 141 (1.69)
fsm8_3 Encoded 72 128 ‐11.55 224 0.01 73 128 ‐11.55 224 0.01 70 146 ‐11.90 270 (0.95)
fsm8_4 Encoded 98 143 ‐8.64 180 0.01 100 164 ‐7.85 195 0.02 97 174 ‐8.02 220 0.00
LOC* ‐ Lines Of Code (not including imported enums)
Design Compiler O‐2018.06‐SP4 SAED Library ‐ saed32rvt_ss0p95v125c.db
No case‐default‐X / Explicit loopback case‐default‐X / Explicit loopback case‐default‐X / Implicit loopback
RTL No Clock Goal Clock Goal 0.8 RTL No Clock Goal Clock Goal 0.8 RTL No Clock Goal Clock Goal 0.8
Enums LOC* Area Slack Area Slack LOC* Area Slack Area Slack LOC* Area Slack Area Slack
fsm8_1 Abstract 136 170 ‐0.84 185 0.00 142 180 ‐0.75 195 0.00 138 177 ‐0.90 186 0.00
fsm8_2 Abstract 70 119 ‐0.80 166 (0.17) 76 120 ‐0.74 142 (0.12) 73 124 ‐0.66 148 (0.09)
fsm8_3 Abstract 72 154 ‐1.15 210 (0.05) 73 150 ‐1.07 173 (0.01) 70 152 ‐1.19 177 0.00
fsm8_4 Abstract 98 178 ‐0.84 199 0.00 100 177 ‐0.84 187 0.00 97 185 ‐0.82 181 0.00
fsm8_1 Encoded 136 160 ‐0.86 177 0.00 142 193 ‐0.69 197 0.00 138 212 ‐0.71 211 0.00
fsm8_2 Encoded 70 116 ‐0.72 145 (0.16) 76 97 ‐0.53 150 (0.15) 73 116 ‐0.85 141 (0.11)
fsm8_3 Encoded 72 140 ‐0.93 176 0.00 73 140 ‐0.93 176 0.00 70 171 ‐0.97 243 (0.01)
fsm8_4 Encoded 98 164 ‐0.74 172 0.00 100 193 ‐0.69 197 0.00 97 220 ‐0.69 222 0.00
LOC* ‐ Lines Of Code (not including imported enums)
Table 4 - fsm8 - Synthesis efficiency comparison table
Surprisingly, when the fsm8 design was synthesized, there was some area and performance
advantage using the 3‐always block coding style over the 1‐always block and 4‐always block coding
styles as shown inTable 4. This observation suggests that first coding FSM designs using the concise
and efficient 3‐always block style and then copying the code to incorporate the 4‐always block
modifications is a good strategy. The copied 4‐always block style typically will have better synthesis
results than the 3‐always block style, but not always.
The full fsm8 RTL code for the coding styles used in Figure 20 are shown in Appendix 2.11 ‐ Appendix
2.11. The fsm8_pkg files with both abstract and binary encoded typedef[s] that were used by all of
the fsm8 designs are shown in Appendix 2.11.
Figure 21 - fsm8 - Lines of code
Figure 22 - fsm8 - Coding goals summary
We see in Figure 21 and Figure 22 that the 1‐always block coding style is significantly more verbose
than the 3‐always block coding style and that the 1‐always block code is getting even harder to
understand all of the next‐output assignments, while again noting that the 1‐always block and 4‐
always block coding styles were not necessarily more efficient when synthesized.
We have also noted that the 1‐always block coding style might not be very easy to change due to FSM
changes.
8.4 Prep4 FSM design with 16 states, 8-bit output and 8-bit input
The Prep4 design has an asynchronous low‐true rst_n, one 8‐bit input i, and one 8‐bit output o.
Figure 23 - Prep4 state diagram
As can be seen in Figure 24 for the prep4 design, the 1‐always block coding style required more than
twice as much code (114% more code) than the equivalent 3‐always block coding style.
Figure 24 - prep4 - Coding styles effort comparison
Design Compiler O‐2018.06‐SP4 LSI 10K Library ‐ lsk_10k
No case‐default‐X / Explicit loopback case‐default‐X / Explicit loopback case‐default‐X / Implicit loopback
RTL No Clock Goal Clock Goal 11 RTL No Clock Goal Clock Goal 11 RTL No Clock Goal Clock Goal 11
Enums LOC* Area Slack Area Slack LOC* Area Slack Area Slack LOC* Area Slack Area Slack
prep4_1 Abstract 188 304 ‐10.96 421 0.00 192 303 ‐11.17 353 0.04 182 334 ‐11.03 451 0.00
prep4_2 Abstract 115 201 ‐9.44 345 (4.65) 119 199 ‐9.06 312 (4.91) 110 222 ‐13.57 360 (2.54)
prep4_3 Abstract 90 285 ‐16.32 476 (1.58) 92 281 ‐14.27 511 (0.62) 83 297 ‐16.30 497 (2.09)
prep4_4 Abstract 126 328 ‐12.09 453 (0.34) 128 304 ‐11.49 419 0.02 118 340 ‐12.64 487 0.00
prep4_1 Encoded 188 297 ‐10.69 363 0.01 192 297 ‐12.32 353 0.00 182 355 ‐14.89 423 0.02
prep4_2 Encoded 115 198 ‐9.01 357 (4.84) 119 202 ‐10.11 310 (5.08) 110 222 ‐13.22 360 (3.10)
prep4_3 Encoded 90 278 ‐15.89 491 (1.61) 92 291 ‐15.37 580 (1.14) 83 293 ‐17.42 491 (2.68)
prep4_4 Encoded 126 302 ‐11.61 346 0.04 128 297 ‐11.11 361 0.01 118 350 ‐11.62 458 0.01
LOC* ‐ Lines Of Code (not including imported enums)
Design Compiler O‐2018.06‐SP4 SAED Library ‐ saed32rvt_ss0p95v125c.db
No case‐default‐X / Explicit loopback case‐default‐X / Explicit loopback case‐default‐X / Implicit loopback
RTL No Clock Goal Clock Goal 0.8 RTL No Clock Goal Clock Goal 0.8 RTL No Clock Goal Clock Goal 0.8
Enums LOC* Area Slack Area Slack LOC* Area Slack Area Slack LOC* Area Slack Area Slack
prep4_1 Abstract 188 369 ‐0.85 373 0.00 192 398 ‐0.78 395 0.00 182 441 ‐0.90 494 (0.01)
prep4_2 Abstract 115 276 ‐0.66 345 (0.34) 119 275 ‐0.69 327 (0.29) 110 314 ‐0.95 355 (0.20)
prep4_3 Abstract 90 354 ‐1.19 448 (0.09) 92 367 ‐1.21 408 (0.08) 83 377 ‐1.40 526 (0.11)
prep4_4 Abstract 126 409 ‐0.79 400 0.00 128 399 ‐0.81 401 0.00 118 438 ‐1.02 478 (0.08)
prep4_1 Encoded 188 383 ‐0.73 386 0.00 192 379 ‐0.87 368 0.00 182 456 ‐0.92 488 0.00
prep4_2 Encoded 115 267 ‐0.65 376 (0.33) 119 272 ‐0.69 339 (0.32) 110 315 ‐0.83 368 (0.26)
prep4_3 Encoded 90 358 ‐1.14 469 (0.14) 92 355 ‐1.19 426 (0.05) 83 368 ‐1.34 529 (0.09)
prep4_4 Encoded 126 383 ‐0.86 371 (0.01) 128 379 ‐0.87 399 0.00 118 463 ‐0.98 493 (0.01)
LOC* ‐ Lines Of Code (not including imported enums)
Table 5 - prep4 - Synthesis efficiency comparison table
It should be noted that the outputs in this prep4 design are shown in vector form for each state, so
the easiest way to code the outputs in this FSM design was to assign the output vector for each state
and not make default‐X output assignments. Since the outputs are calculated from each next state,
the area increased significantly when synthesized. The full prep4 RTL code for the coding styles used
in Figure 24 are shown in Appendix 2.17 ‐ Appendix 2.20. The prep4_pkg files with both abstract
and binary encoded typedef[s] that were used by all of the prep4 designs are shown in Appendix
2.16.
Figure 25 - prep4 - Lines of code
Figure 26 - prep4 - Coding goals summary
As seen in Figure 25, the 1‐always block coding style is more than twice as verbose as the 3‐always
block coding style and the 1‐always block code is getting much harder to follow when examining the
next‐output assignments.
We have again noted in Figure 26 that the 1‐always block coding style is not so easy to change due to
FSM changes.
10. Acknowledgements
We are grateful to good friend and colleague Paul Zimmer, creator of the FizZim FSM diagram and
code generation tool[16], for his review and valuable suggestions to help improve this paper.
We also thank our good friend and colleague, Steve Golson, for his recommendations to use newer
technology libraries and to use input and output design constraints with our FSM designs.
WE also thank Jing Zhan, Robert Lombardi and Benny Widen for their valuable feedback and
suggestions regarding the paper and presentation.
We thank Will Cummings of Synopsys for his help with using the Synplify Pro and Synplify Premier
FPGA synthesis tools.
11. References
[1] Armenia Educational Programs ‐ SAED: Synopsys Armenia Educational Department
https://www.synopsys.com/company/contact‐synopsys/office‐locations/armenia/armenia‐
educational‐program.html
[2] Clifford E. Cummings, "Synthesizable Finite State Machine Design Techniques Using the New
SystemVerilog 3.0 Enhancements," SNUG
http://www.sunburst‐design.com/papers/CummingsSNUG2003SJ_SystemVerilogFSM.pdf
[3] Clifford E. Cummings, “SystemVerilog Assertions ‐ Bindfiles & Best Known Practices for Simple SVA
Usage,” SNUG 2016 (Silicon Valley).
http://www.sunburst‐design.com/papers/CummingsSNUG2016SV_SVA_Best_Practices.pdf
[4] Clifford E. Cummings, "SystemVerilog Logic Specific Processes for Synthesis ‐ Benefits and Proper Usage,"
SNUG
http://www.sunburst‐design.com/papers/CummingsSNUG2016SV_SVLogicProcs.pdf
[5] Dejan Marković, "Logic Synthesis ‐ Lecture 11," EEM216A Lecture Slides, Fall 2012
http://icslwebs.ee.ucla.edu/dejan/researchwiki/images/0/0c/F2012‐Lec‐11_Logic‐Synthesis.pdf
[6] Harry Foster, "Part 5: The 2010 Wilson Research Group Functional Verification Study,"
(See Figure 2 ‐ 32% Debug)
https://blogs.mentor.com/verificationhorizons/blog/2011/04/04/part‐5‐the‐2010‐wilson‐research‐
group‐functional‐verification‐study/
[7] Harry Foster, "Part 6: The 2012 Wilson Research Group Functional Verification Study,"
(See Figure 2 ‐ 36% Debug)
https://blogs.mentor.com/verificationhorizons/blog/2013/07/22/part‐6‐the‐2012‐wilson‐research‐
group‐functional‐verification‐study/
[8] Harry Foster, "Part 3: The 2014 Wilson Research Group Functional Verification Study,"
(See Figure 2 ‐ 43% Debug)
https://blogs.mentor.com/verificationhorizons/blog/2015/04/01/part‐3‐the‐2014‐wilson‐research‐
group‐functional‐verification‐study/
[9] Harry Foster, "Part 8: The 2014 Wilson Research Group Functional Verification Study,"
(See Figure 5 ‐ 37% Debug)
https://blogs.mentor.com/verificationhorizons/blog/2015/07/13/part‐8‐the‐2014‐wilson‐research‐
group‐functional‐verification‐study/
[10] Harry Foster, "Part 3: The 2016 Wilson Research Group Functional Verification Study,"
(See Figure 2 ‐ 43% Debug)
https://blogs.mentor.com/verificationhorizons/blog/2016/08/29/part‐3‐the‐2016‐wilson‐research‐
group‐functional‐verification‐study/
[11] Harry Foster, "Part 8: The 2016 Wilson Research Group Functional Verification Study,"
(See Figure 5 ‐ 39% Debug)
https://blogs.mentor.com/verificationhorizons/blog/2016/10/04/part‐8‐the‐2016‐wilson‐research‐
group‐functional‐verification‐study/
[12] Harry Foster, "Part 4: The 2018 Wilson Research Group Functional Verification Study,"
(See Figure 4‐2 ‐ 42% Debug)
https://blogs.mentor.com/verificationhorizons/blog/2019/01/02/part‐4‐the‐2018‐wilson‐research‐
group‐functional‐verification‐study/
[13] IEEE Standard Hardware Description Language Based on the Verilog Hardware Description Language,
IEEE Computer Society, IEEE, New York, NY, IEEE Std 1364‐1995
[14] IEEE Standard Verilog Hardware Description Language, IEEE Computer Society, IEEE, New York, NY,
IEEE Std 1364‐2001
[15] "IEEE Standard For SystemVerilog ‐ Unified Hardware Design, Specification and Verification Language,"
IEEE Computer Society and the IEEE Standards Association Corporate Advisory Group, IEEE, New York,
NY, IEEE Std 1800™‐2017
[16] Paul Zimmer, Michael Zimmer, Brian Zimmer, "FizZim ‐ an open‐source FSM design environment,"
http://www.fizzim.com/mydownloads/fizzim_tutorial_20160423.pdf
[17] SAED Technology Libraries ‐ SolvNet, "Bitcoin Low Power Case Study," (download Technology
Libraries)
https://solvnet.synopsys.com/retrieve/2630223.html
[18] Steve Golson, "State Machine Design Techniques for Verilog and VHDL," Synopsys Journal of High‐Level
Design,
September 1994, pp. 1‐48.
Lines of Code Web References:
[19] Amy Bowersox, "How true is the following: "Every line of code is a bug"?,"
https://www.quora.com/How‐true‐is‐the‐following‐Every‐line‐of‐code‐is‐a‐bug
[20] Chad Perrin, "The danger of complexity: More code, more bugs," https://www.techrepublic.com/blog/it‐
security/the‐danger‐of‐complexity‐more‐code‐more‐bugs/
[21] Charles Brian Quinn, "Less Code is Better," https://www.bignerdranch.com/blog/less‐code‐is‐better/
[22] Clifford E. Cummings, "The Sunburst Design ‐ "Where's Waldo" Principle of Verilog Coding,"
http://www.sunburst‐design.com/papers/Wheres_Waldo_Coding.pdf
[23] Jack Ganssle, "Keep It Small," http://www.ganssle.com/articles/keepsmall.htm
[24] Quora, "Is there a correlation between the number of lines of code and the number of bugs in software?,"
https://www.quora.com/Is‐there‐a‐correlation‐between‐the‐number‐of‐lines‐of‐code‐and‐the‐
number‐of‐bugs‐in‐software
[25] Software Engineering, "More code = more bugs,"
https://softwareengineering.stackexchange.com/questions/41949/more‐code‐more‐bugs
[26] Steve Baker, "What is the average ratio of bugs to a line of code?," https://www.quora.com/What‐is‐the‐
average‐ratio‐of‐bugs‐to‐a‐line‐of‐code
The [b]inary encoded enumerated types package file is named fsm1_pkg_b.sv but the package
name is still fsm1_pkg.
package fsm1_pkg;
typedef enum logic [1:0] {IDLE = 2'b00,
READ = 2'b01,
DLY = 2'b11,
DONE = 2'b10,
XXX = 'x } state_e;
endpackage
Example 13 - File: fsm1_pkg_b.sv - fsm1_pkg enumerated typedef
These packages include a typedef for the state_e type that is used by all of the fsm1 designs.
Using the same package name makes it possible to read the separate package files first in a simulation
and first in synthesis compilation to selectively choose abstract or binary encoded enumerated types
without touching the fsm1 files.
import fsm1_pkg::*;
state_e state;
import fsm1_pkg::*;
state_e state, next;
always_comb begin
next = XXX; //@LB next = state;
rd = '0;
ds = '0;
case (state)
IDLE : if (go) next = READ;
else next = IDLE; //@ LB
READ : begin
rd = '1;
next = DLY;
end
DLY : begin
rd = '1;
if (!ws) next = DONE;
else next = READ;
end
DONE : begin
ds = '1;
next = IDLE;
end
default: begin
ds = 'x;
rd = 'x;
next = XXX;
end
endcase
end
endmodule
Example 15 - fsm1_2x - 2-always block with combinatorial outputs
import fsm1_pkg::*;
state_e state, next;
always_comb begin
next = XXX; //@LB next = state;
case (state)
IDLE : if (go) next = READ;
else next = IDLE; //@ LB
READ : next = DLY;
DLY : if (!ws) next = DONE;
else next = READ;
DONE : next = IDLE;
default: next = XXX;
endcase
end
import fsm1_pkg::*;
state_e state, next;
always_comb begin
next = XXX; //@LB next = state;
case (state)
IDLE : if (go) next = READ;
else next = IDLE; //@ LB
READ : next = DLY;
DLY : if (!ws) next = DONE;
else next = READ;
DONE : next = IDLE;
default: next = XXX;
endcase
end
always_comb begin
n_rd = '0;
n_ds = '0;
case (state)
IDLE : if ( go) n_rd = '1; // READ
else ; // IDLE
READ : n_rd = '1; // DLY
DLY : if ( ws) n_rd = '1; // READ
else n_ds = '1; // DONE
DONE : ; // IDLE
default: {n_rd,n_ds} = 'x;
endcase
end
The [b]inary encoded enumerated types package file is named fsm7_pkg_b.sv but the package
name is still fsm7_pkg.
package fsm7_pkg;
typedef enum logic [3:0] {S0 = 4'b0000,
S1 = 4'b0001,
S2 = 4'b0011,
S3 = 4'b0010,
S4 = 4'b0110,
S5 = 4'b0111,
S6 = 4'b0101,
S7 = 4'b0100,
S8 = 4'b1100,
S9 = 4'b1000,
XX = 'x } state_e;
endpackage
Example 19 - File: fsm7_pkg_b.sv - fsm7_pkg enumerated typedef
These packages include a typedef for the state_e type that is used by all of the fsm7 designs.
Using the same package name makes it possible to read the separate package files first in a simulation
and first in synthesis compilation to selectively choose abstract or binary encoded enumerated types
without touching the fsm7 files.
import fsm7_pkg::*;
state_e state;
import fsm7_pkg::*;
state_e state, next;
always_comb begin
next = XX; //@LB next = state;
y1 = '0;
case (state)
S0 : if (go && jmp) next = S3;
else if (go && !jmp) next = S1;
else next = S0; //@ LB
S1 : if (jmp) next = S3;
else next = S2;
S2 : next = S3;
S3 : begin
y1 = '1;
if (!jmp) next = S4;
else next = S3; //@ LB
end
S4 : if (jmp) next = S3;
else next = S5;
S5 : if (jmp) next = S3;
else next = S6;
S6 : if (jmp) next = S3;
else next = S7;
S7 : if (jmp) next = S3;
else next = S8;
S8 : if (jmp) next = S3;
else next = S9;
S9 : if (jmp) next = S3;
else next = S0;
default: begin
y1 = 'x;
next = XX;
end
endcase
end
endmodule
Example 21 - fsm7_2x - 2-always block style with combinatorial outputs
import fsm7_pkg::*;
state_e state, next;
always_comb begin
next = XX; //@LB next = state;
case (state)
S0 : if (go && jmp) next = S3;
else if (go && !jmp) next = S1;
else next = S0; //@ LB
S1 : if (jmp) next = S3;
else next = S2;
S2 : next = S3;
S3 : if (!jmp) next = S4;
else next = S3; //@ LB
S4 : if (jmp) next = S3;
else next = S5;
S5 : if (jmp) next = S3;
else next = S6;
S6 : if (jmp) next = S3;
else next = S7;
S7 : if (jmp) next = S3;
else next = S8;
S8 : if (jmp) next = S3;
else next = S9;
S9 : if (jmp) next = S3;
else next = S0;
default: next = XX;
endcase
end
always_comb begin
n_y1 = '0;
case (state)
S0 : if (go && jmp) n_y1 = '1; // S3
else ; // S0, S1
S2 : n_y1 = '1; // S3
S3 : if (!jmp) ; // S4
else n_y1 = '1; // S3
S1, S4, S5, S6, S7, S8, S9:
if (jmp) n_y1 = '1; // S3
else ; // S2, S5, S6, S7, S8, S9, S0
default: n_y1 = 'x;
endcase
end
The [b]inary encoded enumerated types package file is named fsm8_pkg_b.sv but the package
name is still fsm8_pkg.
package fsm8_pkg;
typedef enum logic [3:0] {S0 = 4'b0000,
S1 = 4'b0001,
S2 = 4'b0011,
S3 = 4'b0010,
S4 = 4'b0110,
S5 = 4'b0111,
S6 = 4'b0101,
S7 = 4'b0100,
S8 = 4'b1100,
S9 = 4'b1000,
XX = 'x } state_e;
endpackage
Example 25 - File: fsm8_pkg_b.sv - fsm8_pkg enumerated typedef
These packages include a typedef for the state_e type that is used by all of the fsm8 designs.
Using the same package name makes it possible to read the separate package files first in a simulation
and first in synthesis compilation to selectively choose abstract or binary encoded enumerated types
without touching the fsm8 files.
import fsm8_pkg::*;
state_e state;
y2 <= '1;
state <= S3;
end
else if (sk0 && !jmp) begin
y1 <= '1;
y2 <= '1;
y3 <= '1;
state <= S6;
end
else state <= S5;
S5 : if (jmp) begin
y1 <= '1;
y2 <= '1;
state <= S3;
end
else if (!sk1 && !sk0 && !jmp) begin
y1 <= '1;
y2 <= '1;
y3 <= '1;
state <= S6;
end
else if (!sk1 && sk0 && !jmp) begin
y3 <= '1;
state <= S7;
end
else if (sk1 && !sk0 && !jmp) begin
y2 <= '1;
y3 <= '1;
state <= S8;
end
else begin
y1 <= '1;
y2 <= '1;
y3 <= '1;
state <= S9;
end
S6 : if (jmp) begin
y1 <= '1;
y2 <= '1;
state <= S3;
end
else if (go && !jmp) begin
y3 <= '1;
state <= S7;
end
else begin
y1 <= '1;
y2 <= '1;
y3 <= '1;
state <= S6; //@ LB
end
S7 : if (jmp) begin
y1 <= '1;
y2 <= '1;
state <= S3;
end
else begin
y2 <= '1;
y3 <= '1;
state <= S8;
end
S8 : if (jmp) begin
y1 <= '1;
y2 <= '1;
state <= S3;
end
else begin
y1 <= '1;
y2 <= '1;
y3 <= '1;
state <= S9;
end
S9 : if (jmp) begin
y1 <= '1;
y2 <= '1;
state <= S3;
end
else state <= S0;
default: begin
y1 <= 'x;
y2 <= 'x;
y3 <= 'x;
state <= XX;
end
endcase
end
endmodule
Example 26 - fsm8_1x - 1-always block style with registered outputs
import fsm8_pkg::*;
state_e state, next;
always_comb begin
next = XX; //@LB next = state;
y1 = '0;
y2 = '0;
y3 = '0;
case (state)
S0: if ( go && jmp) next = S3;
else if ( go && !jmp) next = S1;
else next = S0; //@ LB
S1 : begin
y2 = '1;
if (jmp) next = S3;
else next = S2;
end
S2 : if (jmp) next = S3;
else next = S9;
S3 : begin
y1 = '1;
y2 = '1;
if (!jmp) next = S4;
else next = S3; //@ LB
end
S4 : if (jmp) next = S3;
else if (sk0 && !jmp) next = S6;
else next = S5;
S5 : if (jmp) next = S3;
else if (!sk1 && !sk0 && !jmp) next = S6;
else if (!sk1 && sk0 && !jmp) next = S7;
else if ( sk1 && !sk0 && !jmp) next = S8;
else next = S9;
S6 : begin
y1 = '1;
y2 = '1;
y3 = '1;
if (jmp) next = S3;
else if (go && !jmp) next = S7;
else next = S6; //@ LB
end
S7 : begin
y3 = '1;
if (jmp) next = S3;
else next = S8;
end
S8 : begin
y2 = '1;
y3 = '1;
if (jmp) next = S3;
else next = S9;
end
S9 : begin
y1 = '1;
y2 = '1;
y3 = '1;
if (jmp) next = S3;
else next = S0;
end
default: begin
y1 = 'x;
y2 = 'x;
y3 = 'x;
next = XX;
end
endcase
end
endmodule
Example 27 - fsm8_2x - 2-always block style with combinatorial outputs
import fsm8_pkg::*;
state_e state, next;
always_comb begin
next = XX; //@LB next = state;
case (state)
S0: if ( go && jmp) next = S3;
else if ( go && !jmp) next = S1;
else next = S0; //@ LB
S1 : if ( jmp) next = S3;
else next = S2;
S2 : if ( jmp) next = S3;
else next = S9;
S3 : if (!jmp) next = S4;
else next = S3; //@ LB
S4 : if (jmp) next = S3;
else if (sk0 && !jmp) next = S6;
else next = S5;
S5 : if (jmp) next = S3;
else if (!sk1 && !sk0 && !jmp) next = S6;
else if (!sk1 && sk0 && !jmp) next = S7;
else if ( sk1 && !sk0 && !jmp) next = S8;
else next = S9;
S6 : if (jmp) next = S3;
else if (go && !jmp) next = S7;
else next = S6; //@ LB
S7 : if ( jmp) next = S3;
else next = S8;
S8 : if ( jmp) next = S3;
else next = S9;
S9 : if ( jmp) next = S3;
else next = S0;
default: next = XX;
endcase
end
S7 : y3 <= '1;
S1 : y2 <= '1;
S3 : begin
y1 <= '1;
y2 <= '1;
end
S8 : begin
y2 <= '1;
y3 <= '1;
end
S6, S9 : begin
y1 <= '1;
y2 <= '1;
y3 <= '1;
end
endcase
end
endmodule
Example 28 - fsm8_3x - 3-always block style with registered outputs
import fsm8_pkg::*;
state_e state, next;
always_comb begin
next = XX; //@LB next = state;
case (state)
S0: if ( go && jmp) next = S3;
else if ( go && !jmp) next = S1;
else next = S0; //@ LB
S1 : if ( jmp) next = S3;
else next = S2;
S2 : if ( jmp) next = S3;
else next = S9;
S3 : if (!jmp) next = S4;
else next = S3; //@ LB
S4 : if (jmp) next = S3;
else if (sk0 && !jmp) next = S6;
else next = S5;
S5 : if (jmp) next = S3;
else if (!sk1 && !sk0 && !jmp) next = S6;
else if (!sk1 && sk0 && !jmp) next = S7;
else if ( sk1 && !sk0 && !jmp) next = S8;
else next = S9;
S6 : if (jmp) next = S3;
else if (go && !jmp) next = S7;
else next = S6; //@ LB
S7 : if ( jmp) next = S3;
else next = S8;
S8 : if ( jmp) next = S3;
else next = S9;
S9 : if ( jmp) next = S3;
else next = S0;
default: next = XX;
endcase
end
always_comb begin
{a3,a2,a1} = '0;
case (state)
S0 : if (go && jmp) { a2,a1} = '1; // S3
else if (go && !jmp) { a2 } = '1; // S1
else ; // S0
S3 : if (!jmp) ; // S4
else { a2,a1} = '1; // S3
The [b]inary encoded enumerated types package file is named prep4_pkg_b.sv but the package
name is still prep4_pkg.
package prep4_pkg;
typedef enum logic [3:0] {S0 = 4'b0000,
S1 = 4'b0100,
S2 = 4'b0101,
S3 = 4'b0001,
S4 = 4'b1011,
S5 = 4'b1001,
S6 = 4'b0010,
S7 = 4'b0011,
S8 = 4'b0110,
S9 = 4'b1111,
S10 = 4'b1101,
S11 = 4'b0111,
S12 = 4'b1010,
S13 = 4'b1000,
S14 = 4'b1110,
S15 = 4'b1100,
XX = 'x } state_e;
endpackage
Example 31 - File: prep4_pkg_b.sv - prep4_pkg enumerated typedef
These packages include a typedef for the state_e type that is used by all of the prep4 designs.
Using the same package name makes it possible to read the separate package files first in a simulation
and first in synthesis compilation to selectively choose abstract or binary encoded enumerated types
without touching the prep4 files.
import prep4_pkg::*;
state_e state;
end
S9 : if (in[0]) begin
out <= 8'hFF;
state <= S11;
end
else begin
out <= 8'hFF;
state <= S9; //@ LB
end
S10: begin
out <= 8'h06;
state <= S1;
end
S11: if (in == 64) begin
out <= 8'h7F;
state <= S15;
end
else begin
out <= 8'h7F;
state <= S8;
end
S12: if (in == 255) begin
out <= 8'h00;
state <= S0;
end
else begin
out <= 8'hFD;
state <= S12; //@ LB
end
S13: if (in[1] ^ in[3] ^ in[5]) begin
out <= 8'hFD;
state <= S12;
end
else begin
out <= 8'hDF;
state <= S14;
end
S14: if (in) begin
if (in < 64) begin
out <= 8'hFD;
state <= S12;
end
else begin
out <= 8'hFF;
state <= S10;
end
end
else begin
out <= 8'hDF;
state <= S14; //@ LB
end
S15: if (in[7]) begin
case (in[1:0])
2'b00: begin
out <= 8'hDF;
state <= S14;
end
2'b01: begin
import prep4_pkg::*;
state_e state, next;
always_comb begin
next = XX; //@LB next = state;
out = 'x;
case (state)
S0 : begin
out = 8'h00;
if (in) begin
if (in < 4) next = S1;
else if (in < 32) next = S2;
else if (in < 64) next = S3;
else next = S4;
end
else next = S0; //@ LB
end
S1 : begin
out = 8'h06;
if (in[0] && in[1]) next = S0;
else next = S3;
end
S2 : begin
out = 8'h18;
next = S3;
end
S3 : begin
out = 8'h60;
next = S5;
end
S4 : begin
out = 8'h80;
if (in[0] || in[2] || in[4]) next = S5;
else next = S6;
end
S5 : begin
out = 8'hF0;
if (in[0]) next = S7;
else next = S5; //@ LB
end
S6: begin
out = 8'h1F;
if ( in[6] & in[7]) next = S1;
else if (!in[6] & in[7]) next = S9;
else if ( in[6] & !in[7]) next = S8;
else next = S6; //@ LB
end
S7 : begin
out = 8'h3F;
if ( in[6] & in[7]) next = S4;
else if (!in[6] & !in[7]) next = S3;
else next = S7; //@ LB
end
S8 : begin
out = 8'h7F;
if (in[4] ^ in[5]) next = S11;
else if (in[7]) next = S1;
else next = S8; //@ LB
end
S9 : begin
out = 8'hFF;
if (in[0]) next = S11;
else next = S9; //@ LB
end
S10: begin
out = 8'hFF;
next = S1;
end
S11: begin
out = 8'hFF;
if (in == 64) next = S15;
else next = S8;
end
S12: begin
out = 8'hFD;
if (in == 255) next = S0;
else next = S12; //@ LB
end
S13: begin
out = 8'hF7;
if (in[5] ^ in[3] ^ in[1]) next = S12;
else next = S14;
end
S14: begin
out = 8'hDF;
if (in) begin
if (in < 64) next = S12;
else next = S10;
end
else next = S14; //@ LB
end
S15: begin
out = 8'h7F;
if (in[7]) begin
case (in[1:0])
2'b00: next = S14;
2'b01: next = S10;
2'b10: next = S13;
2'b11: next = S0;
endcase
end
else next = S15; //@ LB
end
default : begin
out = 'x;
next = XX;
end
endcase
end
endmodule
Example 33 - prep4_2x - 2-always block style with combinatorial outputs
import prep4_pkg::*;
state_e state, next;
always_comb begin
next = XX; //@LB next = state;
case (state)
S0 : if (in) begin
if (in < 4) next = S1;
else if (in < 32) next = S2;
else if (in < 64) next = S3;
else next = S4;
end
else next = S0; //@ LB
S1 : if (in[0] && in[1]) next = S0;
else next = S3;
S2 : next = S3;
S3 : next = S5;
S4 : if (in[0] || in[2] || in[4]) next = S5;
else next = S6;
S5 : if (in[0]) next = S7;
else next = S5; //@ LB
S6: if ( in[6] & in[7]) next = S1;
else if (!in[6] & in[7]) next = S9;
else if ( in[6] & !in[7]) next = S8;
else next = S6; //@ LB
S7 : if ( in[6] & in[7]) next = S4;
else if (!in[6] & !in[7]) next = S3;
else next = S7; //@ LB
S8 : if (in[4] ^ in[5]) next = S11;
else if (in[7]) next = S1;
else next = S8; //@ LB
S9 : if (in[0]) next = S11;
else next = S9; //@ LB
S10: next = S1;
S11: if (in == 64) next = S15;
else next = S8;
S12: if (in == 255) next = S0;
else next = S12; //@ LB
S13: if (in[5] ^ in[3] ^ in[1]) next = S12;
else next = S14;
S14: if (in) begin
if (in < 64) next = S12;
else next = S10;
end
else next = S14; //@ LB
S15: if (in[7]) begin
case (in[1:0])
2'b00: next = S14;
2'b01: next = S10;
2'b10: next = S13;
2'b11: next = S0;
endcase
end
else next = S15; //@ LB
default : next = XX;
endcase
end
import prep4_pkg::*;
state_e state, next;
always_comb begin
next = XX; //@LB next = state;
case (state)
S0 : if (in) begin
if (in < 4) next = S1;
else if (in < 32) next = S2;
else if (in < 64) next = S3;
else next = S4;
end
else next = S0; //@ LB
S1 : if (in[0] && in[1]) next = S0;
else next = S3;
S2 : next = S3;
S3 : next = S5;
S4 : if (in[0] || in[2] || in[4]) next = S5;
else next = S6;
S5 : if (in[0]) next = S7;
else next = S5; //@ LB
S6: if ( in[6] & in[7]) next = S1;
else if (!in[6] & in[7]) next = S9;
else if ( in[6] & !in[7]) next = S8;
else next = S6; //@ LB
S7 : if ( in[6] & in[7]) next = S4;
else if (!in[6] & !in[7]) next = S3;
else next = S7; //@ LB
S8 : if (in[4] ^ in[5]) next = S11;
else if (in[7]) next = S1;
else next = S8; //@ LB
S9 : if (in[0]) next = S11;
else next = S9; //@ LB
S10: next = S1;
S11: if (in == 64) next = S15;
else next = S8;
S12: if (in == 255) next = S0;
else next = S12; //@ LB
S13: if (in[5] ^ in[3] ^ in[1]) next = S12;
else next = S14;
S14: if (in) begin
if (in < 64) next = S12;
else next = S10;
end
always_comb begin
n_out = 8'h00;
case (state)
S0 : if (in) begin
if (in < 4) n_out = 8'h06; // S1
else if (in < 32) n_out = 8'h18; // S2
else if (in < 64) n_out = 8'h60; // S3
else n_out = 8'h80; // S4
end
else n_out = 8'h00; //@ LB
S1 : if (in[0] && in[1]) n_out = 8'h00; // S0
else n_out = 8'h60; // S3
S2 : n_out = 8'h60; // S3
S3 : n_out = 8'hF0; // S5
S4 : if (in[0] || in[2] || in[4]) n_out = 8'hF0; // S5
else n_out = 8'h1F; // S6
S5 : if (in[0]) n_out = 8'h3F; // S7
else n_out = 8'hF0; // S5
S6: if ( in[6] & in[7]) n_out = 8'h06; // S1
else if (!in[6] & in[7]) n_out = 8'hFF; // S9
else if ( in[6] & !in[7]) n_out = 8'h7F; // S8
else n_out = 8'h1F; // S6
S7 : if ( in[6] & in[7]) n_out = 8'h80; // S4
else if (!in[6] & !in[7]) n_out = 8'h60; // S3
else n_out = 8'h3F; // S7
S8 : if (in[4] ^ in[5]) n_out = 8'hFF; // S11
else if (in[7]) n_out = 8'h06; // S1
else n_out = 8'h7F; // S8
S9 : if (in[0]) n_out = 8'hFF; // S11
else n_out = 8'hFF; // S9
S10: n_out = 8'h06; // S1
S11: if (in == 64) n_out = 8'h7F; // S15
else n_out = 8'h7F; // S8
S12: if (in == 255) n_out = 8'h00; // S0
else n_out = 8'hFD; // S12
S13: if (in[5] ^ in[3] ^ in[1]) n_out = 8'hFD; // S12
else n_out = 8'hDF; // S14
S14: if (in) begin
if (in < 64) n_out = 8'hFD; // S12
else n_out = 8'hFF; // S10
end
else n_out = 8'hDF; // S14
S15: if (in[7]) begin
case (in[1:0])