†† The Verilog® Hardware Description Language, Donald E. Thomas (Author), Philip R. Moorby (Author) ISBN:9781402070891 Amazon Link
Examples for rescheduling
Slide Audience
This presentation includes slides for both a graduate and undergraduate course, but with very different delivery, emphasis, and expectation. The slides marked in title with a superscript circle ∘ are only for the graduate course and should be ignored for the presentation to undergradaute students.
Finite State Machine (FSM)
Characterized by
A set of states
A set of inputs and outputs
A state transition function
An output function
Finite State Machine with Datapath
A very common framework being described and implemented is a Finite State Machine with a Datapath: a designated data path controlled by signals designated FSM circuitry
Book’s FSM Hardware Implementation
†Shaumont
suitable for implementation of algorithm with input and local variables stored in datapath register
Hardware Implementation:
Current State held in a register
Any additional status information held in status register
Next-State and State Control Logic Determines next state and control signals based on registers
Datapath implements operations on data under control of sate control logic
Components of a modeling/description language for FSM ∘
Wires and registers with specified precision and sign
Arithmetic and bitwise operations
Comparison Operations
Bitvector Operations (selecting multiple bits from a vector)
Selection
Indexed Storage
Organization and Precedence
Modules (Hardware)
Software and Hardware ∘
If available customizable hardware is fast, and control logic is difficult to describe, a good mix can be software for control and hardware for calculations. We will see later approaches that use a general purpose processor for control.
4 Rules of Proper FSMD ∘
The relate to describing a piece of hardware (or software) in a modeling language which is software.
1 Neither registers nor signals can be assigned more than once during a clock cycle (covered in our Verilog code rules by the one-block assignment rule)
2 No circular definitions exist between wires (i.e. no combinatorial logic loops)
3 If a signal is used as an operand of an expression, it must have a known value in the same clock cycle
4 All datapath outputs must be defined (assigned) during all clock cycles (in some cases a DontCare may be allowed)
Hardware/Software Partitioning ∘
For a general application, hardware is best for timing-critical (especially simultaneous processes and triggering events) while software is flexible and good for implementing algorithms with high complexity – in the sense of Kolmogorov complexity, the length of the code to implement the algorithm to produce some output given some inputs.
Remember, timing-critical can refer to predictability of timing, not just how fast it can go (a real-time system is a system with timing guarantees)
Control and Datapath Partitioning
Datapath operations can be encoded in the state machine description or can be build separately.
If pre-built modules are used, as is common, the datapath is necessarily a separate description.
Often the datapath represents the algorithm calculations, separating the datapath code makes the code more readable
Coding datapath separately can allow more explicit influence over and insight into the resources used for computation while separating details of control code
Can sometimes think of datapath as implementing instructions for the controller to invoke/call
Separating the datapath code can allow better reuse under a different scheduling of operations (implementing a different algorithm)
In general, designing the datapath first and then the control is a good strategy
Temporal Processes of statemachine
Just after clock edge, state variables are updated. For controller this means that a state-transition is complete and state registers holds the new current state. For the data path, this means that the register variables are updated as a result of assigning (algebraic, boolean, logical, etc…) expressions to them.
Controller FSM Combines the control state and the data-path state to evaluate the new next state for the, at the same time it will also select what instructions should be executed by the datapath
The datapath FSM will evaluate the next-state for the state variables in the datapath, using the updated datapath state as well as the instructions received from the control FSM
Just before the next clock edge, both the control FSM and the datapath FSM have evaluated and prepared the next-state value for the control state as well as the datapath state
†Shaumont
Controller FSM vs Datapath
Controller FSM
IrregularStructure
Very well-suited for FSM-style description, difficult to describe with (boolean) expression-based
Registers represent the familiar sense of the state of the system
Datapath
Regular Structure
Often easy to describe with expressions or structurally build with blocks
Registers represent algorithmic states (intermediate or partial results)
Partition-and-Conquer Design
Datapath operations can be encoded within the same procedural code as the state machine description or can be built separately.
First consider partitioning.
Identify elements in the datapath from experience with traditional digital systems (e.g. communications modules, arithmetic modules, multiplexer’s and demultiplexers, registers and multi-word buffers, FIFOs, IP Cores etc…).
Identify the control signals required and the status/condition information required to make decisions on the control.
State Machine with High Amounts of Branching and Merging
example find borg|car|cat|bot|bet|bit and output done flag where done is a registered output
done flag logic cannot be coded directly based on CS and with the final states
registered outputs in general must coded once per transistion, though the existance of one common default may save some lines of code
Encoding datapath operations WITHIN in the statemachine description with the controller instead of coding them in a separate block is sometimes better.
It is common to see “algorithmic” statemachines described with control and computation embedded in the same procedural block. These are modules which perform complex computations over multiple cycles and require internal registers/memory.
We’ll first focus on control state machines first, with an emphasis on timing and external status and control signals then discuss computational statemachines
Data-Flow Graph
Data-Flow Graphs represents dependencies among operations in the process of an arithmetic algorithm (more compact than a full state diagram).
A algorithmic state machine performs one or more operations in a state (i.e. clock cycle) while satisfying the required order dependencies from the graph
Ex: Draw the Datapath and Identify Status and Control as well as Pre-Register data names
I strongly support not using single-always-block implementations of statemachines, though the compactness of coding for presentation is one reason I used single-always-blocks in the code herein
Note that most moderately complex logic coded within single edge-triggered always block is essentially the same as a single-always-block FSM, even if not formalized as a case-statement-based FSM description. Therefore I find it is useful to study the single-always-block style to understand what is being implemented in such code.
Extended State Registers
At times we’ll want to include an extra register to store information that we don’t want to code as part of our primary state register.
Examples:
partial results in the process of a multi-cycle computation
saved results to provide at the output ports at a later time
status flags for events that should be remembered and used in later processing and state decisions
event counters
timing counters, to control timing without creating additional states
These extended state registers are not necessarily represented by the number of drawn states state transition diagram or the primary coded state register, but formally they ARE part of the state of the system
note the explicit state register and the additional extended state registers
Note that the output and status can be based one or more of the input, NS, and other state registers.
Logic based on only the current state groups updates based on the current/source state, e.g. describes all output independently of transition away from the current state
case(CS)
S0:begin flag=0;end//unconditional, combinational output in S0
S1:begin flag=1;end
Including the input signals makes the output/update also input-dependant
case(CS)
S0:beginif(in==0)
flag=0;//conditional, combinational output while in S0,// updates immediately with input changeelse
flag=1;//conditional, combinational output while in S0,// updates immediately with input changeend
S1:begin flag=1;end
Including NS as a dependency selects edges based on the destination state. Note that NS itself may depend on the input. This is useful if complex parts of the output logic have already been capture in the NS logic description.
case(CS)
S0:beginif(NS==S3)
flag=0;//conditional, combinational output while in S0,// updates immediately with input change through immediate NS changeelse
flag=1;//conditional, combinational output while in S0,// updates immediately with input change through immediate NS changeend
S1:begin flag=1;end
Using a root case statement based on NS tends to organize updates based on the destination state (transitions into state). This is useful for registered output logic.
case(NS)
S0:begin flag=0;end// combinational output, update seen immediately// with input update that selects destination state S0
S1:begin flag=1;end
case(NS)
S0:beginif(CS==S3)
flag=0;// combinational output, update applied immediately// with input update that selects destination state S0// applies only if current state is S3 else
flag=1;end
S1:begin flag=1;end
Using NS useful for registered output logic.
always @(posedge clk)begincase(NS)
S0:begin flag<=0;end//glitch-free update when CS becomes S0
S1:begin flag<=1;end//glitch-free update when CS becomes S1
Registered Output for Partitioning and Timing
One of the advantages of registered output design is in design partitioning and addressing the timing of a design within each partition.
Registered Ouput Modules:
Assembled Registered Ouput Modules:
Length of Combinatorial Paths are matched to those in the partitions
Irregular Modules:
Assembled Irregular Modules:
Length of paths is determined by factors accross partitions
Logic Optimizer and designer therefore have different perspectives of the design
Output path has underspecified timing constraint that may need to account for delays of output
Control FSM Cycle Timing
Control FSM are commonly required to implement timing based on cycles, reading of status signals in particular cycles, and generating control signals at the appropriate time
Fast and Slow Systems
Many issues will arise in using systems that operate at different speeds, or don’t operate in a predetermined fixed timing
Most generally
the master may assert a request until it is acknowledged
commonly, if a request and an ack are asserted in the same cycle, then it is assume that the data is consumed
for reading (e.g. results) the master may wait until a result is ready to read a response
a separate flag like done or data valid (presented for consumption) is common for this
Waiting – Conditional and Unconditional
It is common to require one or both of
conditional waiting
unconditional waiting
These can be used to implement
Fixed waiting – unconditionally wait a predetermined number of cycles
Minimum wait (Fixed followed by Conditional)
fix delay then wait for a condition based on external input to be satisfied. This is useful when interfacing with external “slow” entities that need time after being signaled to send back a response.
Implementation of Waits
Some Options:
Add “top” level wait states to state machine in each place needed
Use a counter
a) Use external counter ( implement as an external state machine) and interface to it
b) embed something like a counter in the coding of the state machine, thus creating substates using the counter as an extended state register.
Create a single programmable wait state to jump to and return to from multiple states using a “jump” register extended state register
Unconditional Delay Using Extra States
Unconditional Delay Using Extended State Register Variable : Counter
Minimal Pause: Delay + Conditional Exit Using An Extra Final Wait State (unconditional delay +conditional exit)
Another Varient:
Minimum Wait: Delay + Conditional Exit Using Extended State Register Variable Counter
Programmable Wait State
Explicit Top-Level States vs Programmable State
Explicit
Programmable
Thought Question
Is it better to grow the state register or use a separate counter variable?
no simple universal answer
“For Loop” State Machine
Extended-state registers can help implement loop behaviors
Example: create outer loop with 10 iterations and inner loop with 5 iterations
Drawing Possible Hardware
Realizations of i,j registers and support hardware
After examination of the state diagram, three required behaviors are desired: Hold, Increment , Load0
A primary FSM will generate the control signals
Note i would be the output of the register, the output from the register could be called (i_next , _i, i_comb, i_int, i_prereg)
class discussion: timing diagram
Combinatorial vs Sequential Pitfalls
Wrongly using the output of a register instead of the input can be a pitfall when using single-always-block (registered outputs) and extended state registers
Wrong Code State D
SA:
i<=0;...
SD:
i <= i+1;if(i<10)
CS<=SA;else
CS<=SE;
….
Correct Code State D
SD:
next_i = i+1;if(next_i<10)
CS<=SA;else
CS<=SE;
i <= next_i;
….
Tweaking Question ( a question asked in class)
Could one just change i<10 to i<9?
Wrong Code State D
SA:
i<=0;...
SD:
i <= i+1;if(i<10) CS<=SA;else CS<=SE;
….
Tweaked / “Hacked”
SA:
i<=0;...
SD:
i <= i+1;if(i<9) CS<=SA;else CS<=SE;
….
Perhaps yes, but the reasoning is important.
Lets say you are working on a class HW project – if you make the wrong version, run a simulation or debug in FPGA hardware, notice that one extra loop is performed and “tweak” the code to “just make it work” without understand the options, than that would not be a good reason. You want to be cognizant of and understand the different choices, then you have the knowledge and understanding to select the most appropriate implementation. Furthermore, at some point your code will be very large and systems will be complex – expecting to make many tweaks is not a reliable approach. You want to learn to get as much right the first time as possible.
I’d argue that the tweaked version is less readable, but I could not say it is wrong.
Detecting Signal Change in Single-Clock-Domain Synchronous Logic
When looking for a change on an signal, avoid a careless temptation to “detect” edges using edge specifiers if it is not warranted to create a new clock domain. Ex:
always @(posedge e)
e_counter <= e_counter +1;
Consider saving a previous version of the signal in a register, and using both present and previous input values to detect a transition:
A slave device commonly starts processes based on a start signal from a master. A slave process may be fast or slow compared to a master. For instance, an instruction processor acting as a master controlling a slave through general I/O ports. Driven by software, it the processor may require many clock cycles to respond (software bit-banging and handshaking can be slow).
Considering a slow master applying a command signal, yet requiring many clock cycles to respond to a handshaking signal from a slave. The slave might falsely initiate a second round of activity if the command is asserted too long.
Transition detection condition for statemachines
To alter the behavior, a slave state machine can instead look for a change in the signal in two consecutive clock cycles
Saving the previous input value:
always @(posedge clk) go_prev<=go;
using a fresh high as a condition within a statemachine
(go==1&& go_prev==0)
Limitations of FSM
FSM typically lack any hierarchy. There is no way to connect details of state-machines leading to state explosion. Otherwise, a hierarchy of states is quite useful for organizing an algorithm.
State Machine State Explosion
†Shaumont
Consider two state machines. Maybe one captures user input like desired temperature, it has states, inputs and outputs appropriate to perform that task. Perhaps the other controls a heating element based on measured and desired temperature. Separated, they may be fairly simple, but what happens when they are described as a single, flat state machine?
A multiplicative effect in the number of states. Two three-state FSMs became one nine-state FSM
This motivates partitioning into multiple state machines in hardware design
Global Exceptions
Now, see what happens if a single new condition, a universal exception must be added.
A dramatic result from only one new condition. Readability and perhaps feasibility of mentally managing the FSM is severely impacted.
†Shaumont
†Shaumont
Global exception in software
A single if statement can be added, taking advantage of the hierarchy of logic embedded in code.
switch(current_state){case A: …
case B: …
case C: …
case D: …
}
if(exception){do this
}else{switch(current_state){case A: …
case B:case C:case D:}
Delay/Pause/Waiting with Extended State Register
Think about the delay examples given earlier using a counter. The counter was implementing one form of hierarchical states.
Consider waiting for an acknowledgment signal for 220 clock cycles. This would require ~1 Millon states with the condition to move to the next state or proceed to end state if acknowledge was received.
Runtime Flexibility ∘
The rigid implementation of hardware and the limited representation of FSMs do not make it very flexible model, especially if one considers run-time flexibility
Microprogrammed Control ∘
Rigid next-state logic is replaced by a rigid next-address logic with a programmable control store.
Complex designs make require using/creating some form of compiler and a custom language
†Shaumont
General Processor Control ∘
Next step towards generalization is to use a general purpose processor
A number of models exist for doing that, from implementing custom hardware as a slave coprocessor that implements hardware-accelerated instructions (or functions) to treating the custom hardware modules and processor as cooperative peer components.
Interfacing is another issue and choices depend on rigidness of interfaces and which should be the master or slave.
Common choices:
Confirm hardware design to be able attach to processor bus
Write a hardware wrapper to attach hardware to system bus
Use general IO to interface processor to hardware
With respect to the processor, need to decide on interrupt or polling interface. Platforms should provide options for both for all the choices above
Multi-Cycle Computations as FSMs
In the following slides, we will consider examples of algorithmic FSMs. These are used to describe and synthesize multi-cycle computations. The number of state transitions defined are typically less than with a complex controller FSM.
A more regular, forward, orderly progression through the states is typical, and the designer’s thought processes may be focused on the computation being performed in each state and the resulting partial results (in registers), as opposed to the output during the state.
Thus, it becomes more reasonable to use a single edge-triggered always block in the design. The fewer number of transition decisions (branches) makes the concern of code bloat negligible.
Algorithmic State Machine Diagram
An introduction to informal ASM Diagrams
ASM Chart Elements
State Box
State Name (required)
State Encoding (optional)
Register Updates (denoted with <=)
Moore Machine Output Updates (combinational logic)
Multi-cycle computation:
Note, the single-block style here was used since the state transition sequence is straightforward. Also, the data path is combined with the controller.
We are not worried about “code bloat” from having to code each output on every transition.
Instead of concentrating on timing coincidence of state and outputs
vs coding coincidence of state and outputs,
we are focused on the coincidence of states and computations. In this single block style the computation performed and resources required for each each are clear, though the corresponding output of each computation is seen and can be used on the cycle following the corresponding state indicated in the state register. In other words, we are interested in what update to registers is being computed and prepared in each state.
In this specific case we can provided a relaxed timing constraint for the paths from the output of the registers for i,j,k to the input of f. We will later learn about manipulation constraints for the synthesizer to allow for multi-cycle paths, but for now we assume that all combinational chains must complete work within a clock cycle.
Explicitly coding the rescheduling so that only one multiply is performed per cycle is simple and seen in the next code. However, this doesn’t ensure resource sharing as shown in the figure with one a single multiplier.
Suggesting Resource Sharing guides the synthesizer to reuse hardware for operations at multiple places in the code
The coding method depends on the synthesizer tool: the following code is more likely interpreted as resource sharing since the multiplier result is always written to the same variable
← * mux multiplier input from i
← save multiplier output for output f
← reveal new f
← * mux multiplier input from k
← save multiplier output for g
Another option is to manually extract the multiplier out of the edge-triggered code and write datapath logic explicitly for the multiplier paired with a mux along with a state machine to change the inputs
Multiplier input controlled using an explicit mux in the datapath:
Invalid rearrangement for i+j+k consuming input k in state S_1 instead of S_2 and vice versa for input j unless the optimizer tool or designer can otherwise determine that i and j do not change in those time cycles. Input timing must be maintained just like output updates.
Auto: In this mode, XST tries to select the best suited encoding algorithm for each FSM.
One-Hot: One-hot encoding is the default encoding scheme. Its principle is to associate one code bit and also one flip-flop to each state. At a given clock cycle during operation, one and only one bit of the state variable is asserted. Only two bits toggle during a transition between two states. One-hot encoding is very appropriate with most FPGA targets where a large number of flip-flops are available. It is also a good alternative when trying to optimize speed or to reduce power dissipation. 00000001 00000010 00000100
… 01000000 10000000
Gray: Gray encoding guarantees that only one bit switches between two consecutive states. It is appropriate for controllers exhibiting long paths without branching. In addition, this coding technique minimizes hazards and glitches. Very good results can be obtained when implementing the state register with T flip-flops. 00000000 00000001 00000011 00000010 00000110
…
Compact: Compact encoding consists of minimizing the number of bits in the state variables and flip-flops. This technique is based on hypercube immersion. Compact encoding is appropriate when trying to optimize area.
Johnson: Like Gray, Johnson encoding shows benefits with state machines containing long paths with no branching. 00000000 00000001 00000011 00000111
… 11111111 11111110 11111100 11111000
… 10000000 rollover to all zeros
Sequential: Sequential encoding consists of identifying long paths and applying successive radix two codes to the states on these paths. Next state equations are minimized.
Speed1: Speed1 encoding is oriented for speed optimization. The number of bits for a state register depends on the particular FSM, but generally it is greater than the number of FSM states.
User: In this mode, XST uses original encoding, specified in the HDL file. For example, if you use enumerated types for a state register, then in addition you can use the ENUM_ENCODING constraint to assign a specific binary value to each state. Please refer to “Design Constraints” chapter for more details.
RAM-Based Finite State Machine (FSM) Synthesis: Large Finite State Machine (FSM) components can be made more compact and faster by implementing them in the block RAM resources provided in Virtex® devices and later technologies. FSM Style (FSM_STYLE) directs XST to use block RAM resources for FSMs.
Unreachable States
One of the benefits of extracting FSMs, is that additional analysis and design checks are available:
“XST can detect unreachable states in an FSM. It lists them in the log file in the HDL Synthesis step.”
Safe Finite State Machine (FSM) Implementation
XST can add logic to your Finite State Machine (FSM) implementation that will let your state machine recover from an invalid state. If during its execution, a state machine enters an invalid state, the logic added by XST will bring it back to a known state, called a recovery state. This is known as Safe Implementation mode.
By default, XST automatically selects a reset state as the recovery state. …
This feature is useful in system susceptible to corruption or as a way to handle undefined power-on initialization
Encoding Review
One-hot encoding is good for speed and simplicity of state decoding logic and state incrementing.
More compact codes such as standard binary encoding generally require a smaller state state register than one-hot encoding at the possible cost of size and speed.
But this depends on the density of combinatorial logic vs. registers the supporting HW platform and in the design.
FPGAs have many registers and so the cost of additional combinatorial logic may large compared to the savings from needing less registers.
Codes where only one or two bits change at a time in the state register may be beneficial.
Less transitions may lead to less power depending on overall design, e.g. if stage register output connects to a high-capacitance load (high-fanout)
Can minimize the chance of metastability errors (such as systems with tight timing, or radiation vulnerability).
These codes may also minimize logic glitches.
FSM Log File
The XST log file reports the full information of recognized Finite State Machine (FSM) components during the Macro Recognition step. Moreover, if you allow XST to choose the best encoding algorithm for your FSMs, it reports the one it chose for each FSM. \ As soon as encoding is selected, XST reports the original and final FSM encoding. If the target is an FPGA device, XST reports this encoding at the HDL Synthesis step. If the target is a CPLD device, then XST reports this encoding at the Low Level Optimization step.
Log File Example
Synthesizing Unit <fsm_1>.
Related source file is "/state_machines_1.vhd".
Found finite state machine <FSM_0> for signal <state>.
------------------------------------------------------
| States | 4 |
| Transitions | 5 |
| Inputs | 1 |
| Outputs | 4 |
| Clock | clk (rising_edge) |
| Reset | reset (positive) |
| Reset type | asynchronous |
| Reset State | s1 |
| Power Up State | s1 |
| Encoding | automatic |
| Implementation | LUT |
------------------------------------------------------
Found 1-bit register for signal <outp>.
Summary:
inferred 1 Finite State Machine(s).
inferred 1 D-type flip-flop(s).
Unit <fsm_1> synthesized.
========================================================
Explicit States are stored in the state register, but other registers for variables can exist serving as extended state variables
In-class example given
Technically, every register in a digital system is a part of the state. What variables you decide to think of as state in your state diagram and what is coded in the CS register and used in the case statement is up to you.
When there are many similar states, sometimes combining them in code and adding a register for a variable makes sense. This can reduce the state decoding and state logic and may make the code more maintainable and easier to read.