Refactor of State Machines
Martin Schoeberl
Technical University of DenmarkEmbedded Systems Engineering
March 26, 2020
1 / 40
Outline
I Today one hour lecture planned, but probably longerI Repeat finite-state machine with datapathI Factoring of finite-state machinesI Talk on todays (and next week) lab exercise
2 / 40
Show Example on “Whiteboard”
3 / 40
FSM with Datapath
I A type of computing machineI Consists of a finite-state machine (FSM) and a datapathI The FSM is the master (the controller) of the datapathI The datapath has computing elements
I E.g., adder, incrementer, constants, multiplexers, ...I The datapath has storage elements (registers)
I E.g., sum of money payed, count of something, ...
4 / 40
FSM-Datapath Interaction
I The FSM controls the datapathI For example, add 2 to the sum
I By controlling multiplexersI For example, select how much to addI Not adding means selecting 0 to add
I Which value goes whereI The FSM logic also depends on datapath output
I Is there enough money payed to release a can of soda?I FSM and datapath interact
5 / 40
Popcount Example
I An FSMD that computes the popcountI Also called the Hamming weightI Compute the number of ‘1’s in a wordI Input is the data wordI Output is the countI Code available at PopCount.scala
6 / 40
Popcount Block Diagram
dinValid popCntValid
FSM
din popCnt
popCntReadydinReady
Datapath
7 / 40
Popcount Connection
I Input din and output popCountI Both connected to the datapathI We need some handshakingI For data input and for count
output
dinValid popCntValid
FSM
din popCnt
popCntReadydinReady
Datapath
8 / 40
Popcount Handshake
I We use a ready-valid handshakeI When data is available valid is
assertedI When the receiver can accept
data ready is assertedI Transfer takes place when both
are asserted
dinValid popCntValid
FSM
din popCnt
popCntReadydinReady
Datapath
9 / 40
The FSM
Count
Idle
Done
Valid
Finished
Result read
I A Very Simple FSMI Two transitions depend on input/output handshakeI One transition on the datapath output
10 / 40
The Datapath
+
shfdin
00 cnt
count
11 / 40
Let’s Explore the Code
I In PopCount.scala
12 / 40
Usage of an FSMD
I Maybe the main part your vending machine is an FSMD?
13 / 40
Working Break
I Build your own “camera” standI 20 minutesI Show your solution to the others at the end of the break
I Don’t expose it too early too early ;-)
14 / 40
Factoring FSMs
I Divide a big problem into several smaller problemsI Splitting a FSM into two or more
I Simplify the designI FSMs communicate via logic signals
I FSM provides input controls signals to anotherI FSM senses output from another
15 / 40
Specification Of a Light Flasher
I Inputs: startI Outputs: lightI Operation:
I When in = 1, FSM goes through 5 sequences:I On-Off-On-Off-On
I Each On sequence (flash):I out = 1I 6 cycles long
I Each Off sequence (space):I out = 0I 4 cycles long
I After 5 sequences, FSM goes back to off state to wait fornew input
16 / 40
Light Flasher State Diagram
I Example from Dally, Chapter 17I Copyright figure, so show it from older slides
17 / 40
Specification Change
I We have a flat FSM with 27 statesI 27 is(state) statements
I If we change the specification toI 12 cycles for each flashI 4 flashesI 7 cycles between flashesI Complete change of switch statementI Now 70 is statements!
I This does not scale
18 / 40
Factor Light Flasher
I Factor out counting on and off intervalsI Into a timerI Reduces 6 and 4 states sequences into two single states
I Results inI a master FSM andI a timer FSM
I Simplifies FSMsI Allows easier change of interval lengths
19 / 40
Factored Light Flasher
start
timer
Load
lightMaster FSM
Timertim
erSe
lect
timer
Don
e
I Time loads value 5 or 3, based in timerLoad
20 / 40
Timer Specification
I Two inputsI timerLoad to load the down counterI timerSelect to select between 6 and 4 cycles counting
I OutputI timerDone is 1 when counter has completed the countdownI Remains asserted until counter reloaded
I Counter can be (re)loaded in any stateI When not loaded it counts down to zero
I Similar to the timer we looked at last week
21 / 40
The Timer FSM
val timerReg = RegInit(0.U)
timerDone := timerReg === 0.U
// Timer FSM (down counter)
when(!timerDone) {
timerReg := timerReg - 1.U
}
when (timerLoad) {
when (timerSelect) {
timerReg := 5.U
} .otherwise {
timerReg := 3.U
}
}
22 / 40
The Master FSM
I Show in IntelliJI Run test and show waveform
23 / 40
Result of Refactoring
I State of original flat FSM has been separatedI The part of cycle counting in the counterI Part flash or space in master FSMI Represent original 27 states in just two 6 states FSMsI
I BTW: the master FSM is a Mealy FSM
24 / 40
Still Redundancy in FSM
I flash1, flash2, and flash3 same functionI space1 and space2 same functionI Refactor number of remaining flashesI Master FSM states: off, flash, and space
25 / 40
Factor out “flash number”
start
timer
Load
lightMaster FSM
Timer
timer
Sele
ct
timer
Don
e
cntL
oad
Counter
cntD
ecr
cntD
one
26 / 40
Counter
val cntReg = RegInit(0.U)
cntDone := cntReg === 0.U
// Down counter FSM
when(cntLoad) { cntReg := 2.U }
when(cntDecr) { cntReg := cntReg - 1.U }
I Loaded with 2 for 3 flashesI Counts the remaining flashes
27 / 40
Code of Flasher2
I Show in IntelliJI Run test and show waveform
28 / 40
Benefits of Refactored Solution
I Master FSM has just three states: off, flash, and spaceI Change of intervals or number of flashes needs no change
in the FSMI Smaller components are easier to read and simpler to test
individually
29 / 40
Usage in your VM
I Maybe factor out the edge detection for the button(s)I Use a timer for more advanced user interface
I Blinking LED on some errorI Write text as a banner in the 7-segment displayI ...
30 / 40
Functions
I Circuits can be encapsulated in functionsI Each function call generates hardwareI A function is defined with def nameI Similar to a method in JavaI Simple functions can be a single line
def adder(v1: UInt, v2: UInt) = v1 + v2
val add1 = adder(a, b)
val add2 = adder(c, d)
31 / 40
More Function Examples
I Functions can also contain registers
def addSub(add: Bool, a: UInt, b: UInt) =
Mux(add, a + b, a - b)
val res = addSub(cond, a, b)
def rising(d: Bool) = d && !RegNext(d)
val edge = rising(cond)
32 / 40
The Counter as a Function
I Longer functions in curly bracketsI Last value is the return value
def counter(n: UInt) = {
val cntReg = RegInit(0.U(8.W))
cntReg := cntReg + 1.U
when(cntReg === n) {
cntReg := 0.U
}
cntReg
}
val counter100 = counter(100.U)
33 / 40
Functional Abstraction
I Functions for repeated pieces of logicI May contain stateI Functions may return hardwareI More lightweight than a Module
34 / 40
Parameterization
class ParamChannel(n: Int) extends Bundle {
val data = Input(UInt(n.W))
val ready = Output(Bool())
val valid = Input(Bool())
}
val ch32 = new ParamChannel(32)
I Bundles and modules can be parametrizedI Pass a parameter in the constructor
35 / 40
A Module with a Parameter
class ParamAdder(n: Int) extends Module {
val io = IO(new Bundle{
val a = Input(UInt(n.W))
val b = Input(UInt(n.W))
val c = Output(UInt(n.W))
})
io.c := io.a + io.b
}
I Parameter can also be a Chisel type
36 / 40
Use the Parameter
val add8 = Module(new ParamAdder(8))
val add16 = Module(new ParamAdder(16))
I Can be used for the display multiplexing configuration
37 / 40
Today Lab
I Display multiplexingI Described in Vending Machine Specification (show)I This and next weekI Can also be developed in simulation
38 / 40
Display Multiplexing
I Saving of pins in the FPGAI Switch between the four digits at around 1 kHzI Switch faster in simulationI Show codeI Sketch needed hardware
39 / 40
Summary
I Divide a bigger problem into smaller onesI Easier to designI Easier to testI Sometimes only feasible solution
I Factoring state machinesI Separate state into multiple ‘orthogonal’ state variablesI Each is simpler to handle (fewer states)I “Factors out” repetitive sequencesI Hierarchical structure
40 / 40