Simon

6.195 ViewLogic VHDL project
William Moyne
12/11/1997
 

OVERVIEW:

Simon is a VHDL version of the popular toy where the user attempts to mimic the sequence of lights displayed by the toy. If the use succeeds, the sequence is increased by one and the game continues.  The game ends when the player presses the wrong button (i.e. doesn't correctly replay the sequence).

The goal of the game is to get as long a sequence as possible.

Figure 1. Simon Game
(Note: Colors (4) are Buttons)
 

DESIGN:

To manage the complexity of the design, Simon was divided into a number of sub-components each performing its own simple task. The module interactions are shown below with descriptions of each following.
Figure 2: Simon Hierarchy

Simon:

The Simon module controls the overall flow of the hardware. It acts as a connector for information between the various modules. In addition to connections, Simon also handles system-wide reset and initialization as well as keeping track of sequence length and the player's current position within the sequence (when they are trying to play it back).

The goal of the Simon module is to keep track of all sequence-related information, enabling the other modules to be written for one-event tasks (such as one button press, one button check, playing one light in the sequence).

All other modules in the system are designed to be asynchronous with an enable line and a done line. This simplifies the design of the Simon module by making all operations a simple invoke/wait procedure.  Timing issues are essentially eliminated.

Random

Random uses a feedback shift register to generate a pseudo-random number sequence. This sequence is essential for the functionality of the Simon system. The reason is that the goal of the game is to play a sequence of some length then check a user-provided sequence against this one. Pseudo-random numbers are ideal for this because they require storage of only one item, the seed, all other members of the sequence can be computed serially given the seed.

For the purpose of debugging the system, a simple 8 bit seed was used with feedback from bits 0,4,7.  Clearly this sequence has at most 256 random starting locations and has a maximum unique length of 256.  The length of the seed does not change the fundamental interfaces to this module, so more complex sequences can be generated as needed. Matlab was used to ensure that the initial seed and feedback locations shown did not lead to a degenerate sequence of 0, 1, or some small period repetition.
 

Random2:

Random2 is a simple wrapper for the random class that generates 2-bit random numbers asynchronously to the system.  When the newnum line of Random2 is driven high, Random2 queries Random for 2 bits which are concatenated and sent out the rndbits line. Once the computation is done, the done line is asserted. The reason for the asynchronous behavior was to enable different implementations of the random2 interface to use the same entity.  The extension of Random2 to more than 2 bits is trivial since timing of the computation is not critical.

Play:

The play module is responsible for driving the four colored lights (and optionally buzzers) to indicate to the user which "note" is next in the random sequence. Play's main function is to hold the light/note for a human-readable length of time. This is accomplished by running a large counter to slow down the system clock to a more reasonable level (1 Hz or so).

When the playnote line of the Play module is driven high, Play queries Random2 for the next random number (2 bits) and then drives the corresponding light. When done, Play asserts the done line.

Button:

The Button module receives the input from the user (in the form of four buttons underneath the four colors).  In order to eliminate possible switch bouncing, Button latches in the button information and holds it until it is reset.  This behavior makes it insensitive to bounce. The Button module also encodes the one-hot button sequence (0100,1000, ...) into 2 bits (10,11,...).  In addition, an additional signal is provided which notifies the system when any button is pressed.

The Button module also ignores buttons that are pressed prior to reset and held.  This prevents double sampling of user input do to the speed of the system clock (resets). Illegal button combinations are also ignored (1100,1001, ...).

Check:

The Check module checks one user input against the next digit in the random sequence. When the check enable line of Check is driven high, Check queries Random2 for the next random number and compares it against the number provided by the user.  If they are not the same, the checkbad line is driven high, otherwise it is driven low. Once the process is complete, the checkdone line is asserted.

Note: Check and Play use separate instanciations of the Random2 class.  The reason for this was the control lines for Random2 were being driven by both modules simultaneously. This gave logic levels of 'X' rather than '1' or '0'. Another way to remedy this problem would be to put Random2 on a bus and selectively drive signals from Play and Check. The former approach was taken due to ease of programming and debugging.
 

Other Modules (Not implemented):

In addition to the core modules implemented, there are a number of modules that would be necessary to move Simon from the debug phase into the playable phase.  A few of these are listed below:

SIMULATION:

The modules where each designed and simulated in isolation to make sure that they worked before the final integration was performed. The Viewlogic tools were used to first analyze (compile) and then test (simulate) the design. Project 1 shows a simple example of how to use the analyzer and simulation tool.

In order to simplify the testing of modules, command (.cmd) files were written that provide interesting stimulus to each module to ensure that it exhibits correct behavior. The source-files along with their associated test files are shown below:
 
MODULE COMMAND FILE
Random randomtest.cmd
Random2 random2test.cmd
Play playtest.cmd
Check checktest.cmd
Button buttontest.cmd
Simon simontest.cmd
Simon modules and their respective test command files.
 
 These tests can be performed by first analyzing the VHDL code with the viewlogic analyzer, then loading the entity into the fusion/speedwave tool.  At the speedwave prompt, type: execute testfilename.cmd and the test file with bring up the viewtrace window with the results of the simulation.
 
 In addition to the file itself, Random2 and Simon require use of the user library because they include other modules.  In order to simulate Simon a user library called "simon" must be created with the library manager (see proj 1) and all other source files must be analyzed. To compile Random2 follow the same procedure, but only Random needs to be compiled into the "simon" library.

NOTE: It was discovered (after much work) that naming an entity with the same name as the library causes strange errors.  For this reason, the main module is actually called asimon so that it does not conflict with the "simon" library.

A typical trace of the main simon module is shown (here). The important signals on this line are:

User Inputs:

Output

 All other signals are shown for debugging only. The length of time that the lights are held to non-zero values is much shorter than would happen in a real game.  The reason for the short time is that simulating events that occur over large cycle times are difficult.
 
The game shown in the traces goes for three rounds.  Using the following color key, a play-by-play account is given:
KEY:  BLUE=1000    RED=0100    GREEN=0010    YELLOW=0001
  1. RESET/IDLE
  2. User presses any key to start game: RED
  3. Game Plays sequence length one: BLUE
  4. User Pushes BLUE
  5. Game increases sequence by one and plays both: BLUE BLUE
  6. User repeats sequence: BLUE BLUE
  7. Game increments sequence to three: BLUE BLUE GREEN
  8. User messes up: GREEN
  9. User Loses and game starts over

 SYNTHESIS:

Unfortunately, the synthesis of the VHDL was not as successful as the simulation.  Ideally one code base can be used to both simulate and synthesize a design.  Unfortunately, the simulator accepts syntax that may or may not lead to correctly synthesized code.  The use of Variables can also lead to unexpected results.

Starting from the bottom, random was compiled using the WARP synthesis tool to see whether modification were needed. 1 error was encountered which was caused by a " 'event" operator.  Apparently, the only " 'event" reliably supported in synthesis is "clk".

After completely removing the " 'event" and rewriting the procedures accordingly, it was found that the component compiled but oscillated during simulation. There was no clear reason for this, but there was a variable in use so this was marked as the culprit.

Once again random was completely rewritten.  This time eliminating the variable completely and changing most of the other code to compensate. This synthesized and simulated fine with the following utilization using a 371 CPLD:

Results were not as promising when Random2 was compiled with random1.  Although in simulation random2 works fine and random works fine even in sythesis/simulation. When they are put together, an unexplained oscillation occurs.  The utilization (for what it's worth) is shown here.

The check module showed similar utilization. The Play module has an interesting property. Because it uses an integer to count for the delay, WARP extends that variable out to 32 bits (and all the product terms that go with them) even though currently the variable only counts to 10. The utilization of play could easily be brought down to similar levels of random and check if this integer was changed to a bit vector.

From the utilization numbers obtained from these modules it seems clear that Simon could easily fit in a small FPGA and maybe a CPLD. One of the reasons it may fit in a CPLD even though each module takes over 30% of the 371 is that they share many of the same signals, this would lead to a savings of macrocells within the chip.

If the design could not fit on a single device or if only small PLD's are available, the boundaries used in the simon simulation are fairly good to chop up the design in that they have few signals between them and each do specific tasks.
 

CONCLUSION:

VHDL is a very powerful language to design digital systems without actually having to hook them up.  Ideally a designer could write some VHDL code, simulate it using a fast behavioral simulator, then synthesize the same code into actual hardware.

The reality of the current tools is not quite this easy.  First,  the libraries (such as ieee) used seem to differ between manufacturers so there are incompatibilities moving code between tools.  Also, the simulators seem to support syntax that cannot be synthesized.  It would be nice if the simulator still simulated non-synthesizable code but warned the user.

Given the current state of the tools, the best path may be to design each module with VHDL in a behavioral model to get the fast simulation times, but then synthesize each module before moving on. This will ensure that if drastic changes are needed within a module (possibly changing its timing profile) then the user will not have to propagate these changes all the way up the design hierarchy.