5. Building State Machines with Memory



FPGAs consist of many distributed and block memory, therefore this is an abundant resource that we can capitalise upon to create a state machine. The way this functions is simple, but is usually only suitable for small state machines.

Because there are a finite number of combinations of state and inputs, there are also a finite number of next states and output combinations. When using memory to describe a state machine you create a block of memory that is deep enough to have one entry for each of the combinations of state and input. For example, our state machine has a 3-bit state, as well as three 1-bit inputs, a total of 6-bits. This equates to a memory depth of 2 to the power of 6, or 64 different combinations. The width of the memory must equal to the sum total number of bits needed to represent the next state (3-bits), and any additional output signals (none in our case). With this type of state machine, the combinatorial and sequential aspects of the previous design are merged together.

The code for this sort of state machine is extremely simple, but this is because the majority of the work is done in creating the contents of the Read Only Memory (ROM).

The key piece of code here is the '$readmemb' statement, which loads a memory configuration file into the designated memory array. The 'b' at the end of '$readmemb' means that this command expects the file to be written in binary. There is also a '$readmemh' version of the statement for hex.

The advantage of using the memory method is that it is simple to write, and forces you to consider every possibility. The downside is that it forces you to consider EVERY possibility, which for anything other than the most basic of state machines is a lot. Note that this simple puzzle requires memory 64 addresses deep. Because of this, we are not going to ask you to derive the entire memory file content, just a section of it, namely all the entries that relate to State 2. The following is the contents of the whole file, with the relevant bits that need your attention highlighted. Copy and paste this into a new text file, and fill in the gaps in the file. Then put this file in the working directory of your project. Each line corresponds to an address in the memory.

000
000
110
000
000
000
000
000
001
101
001
001
010
001
001
001
Replace me with a 3-bit value
Replace me with a 3-bit value
Replace me with a 3-bit value
Replace me with a 3-bit value
Replace me with a 3-bit value
Replace me with a 3-bit value
Replace me with a 3-bit value
Replace me with a 3-bit value
011
100
011
011
010
011
011
011
100
100
110
100
111
100
100
100
101
101
011
101
000
101
101
101
110
000
110
110
010
110
110
110
111
111
111
111
111
111
111
111

Create a new module to implement this memory-based state machine, and replace the old classic instantiation of the state machine with this new memory-based one; the interfaces should be identical. Again synthesise and implement your design. Inspect the Map report for this current solution implementation. How does it compare to the previous solution implementation?

Create a .bit file, load it into your BASYS 2 board, and test your functionality. It should be mostly the same. Differences will arise due to the fact that the previous non memory-based version did not take into account the situations when multiple buttons are being pressed at the same time. The memory-based version requires this to be considered, and so it was defined such that if multiple buttons are pressed at the same time, it will stay within its current state. In the previous version, if you held all three buttons down at the same time, depending on the order of the 'if', 'else' statements, you would transition strait through at least one state. This new memory based versions is therefore much more stable.