mastermind project report

15
Mastermind Solver EE201 project by Jacob Rodeheffer and Ethan Chan

Transcript of mastermind project report

Page 1: mastermind project report

Mastermind Solver

EE201 project by Jacob Rodeheffer and Ethan Chan

Page 2: mastermind project report

2

Table of Contents

Abstract . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

The game of Mastermind . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

Playing Mastermind on the FPGA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

Mastermind Solver’s state machine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

Mastermind Solver’s custom algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

Measures of success . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

Appendix: algorithm details . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

Appendix: hardware usage report . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

Appendix: waveforms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

Appendix: Verilog code, and code of C++ simulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

Abstract

For this project we made a Verilog program, Mastermind Solver, that lets you play the puzzle

game Mastermind against an AI player via an FPGA board. The innovative part of the program

is its AI algorithm. We came up with a new Mastermind-solving algorithm with the goal of

needing to use fewer hardware components than the Mastermind-solving algorithms already in

existence. We have established that Mastermind Solver works (it always wins the game) and

there are indications that it may require fewer hardware components.

The Game of Mastermind

Mastermind is a two-player game where one player comes up with a sequence of colors and the

other tries to guess this sequence within ten tries. The sequence is made up of four slots that can

be fill a permutation of six different colors with repetitions allowed. Order matters. The other

player then places his guesses and the player that knows the sequence will give the other player

clues for the guessed sequence with red and white pegs. A red peg is placed for each color in the

guessed sequence that is found in the correct sequence and is located in the correct slot. A white

peg is placed for each color in the guessed sequence that is found in the correct sequence but is

not located in the correct slot. The user has a total of ten guesses to correct the correct sequence.

Playing Mastermind on the FPGA

In our project we will be implementing and Artificial Intelligence onto the FPGA called

Mastermind Solver, which will be able to guess any user’s sequence within ten tries. The four

slots are represented by the four SSDs (SSD0, SSD1, SSD2, SSD3), the six colors are

Page 3: mastermind project report

3

represented by digits 0-5, switches Sw4-Sw7 each represent a red peg, switches Sw0-Sw3 each

represent a white peg, and the number of LEDs L0-L7 lit correspond with the number of guessed

sequences. Because we only have eight LEDs to work with and we can have a possible of nine

guessed sequences when we are on the 10th

guess we encoded a special pattern of LEDs, which

represents that nine sequences have been guessed.

The Reset button (BtnC) initializes the game and the SSDs display “PLAY” and waits for a user

to press the start/respond button (BtnD) to begin the game. Once the game begins the AI

produces its first guess. The user then inputs the correct amount of red and white pegs by

switching on or off the corresponding switches. When the correct number of red and white pegs

is in place the user hits the respond button (BtnD) to enter the information, which the AI uses to

produce its next guess until the correct sequence is guessed.

The AI checks for three cases when red and white pegs are placed. If only four red pegs are

placed the user is indicating that the AI has guessed his/her sequence and the SSDs display

“YAY” indicating that it has won. If the AI detects that the total number of red and white pegs

exceeds the number of slots, four in this case, the SSDs display “nono” which tells that user that

he/she has entered invalid information. Also if the AI detects, with its own logic, that it should

have guessed the user’s sequence by that guess but the user enters a combination of red and

white pegs that is not four reds, the AI tells the user that it has entered an false current or

previous combination of red and white pegs by displaying “FErr” (Fatal Error) on the SSDs.

In the top file we implemented SSD scanning and set the value of the corresponding SSDs

depending on the state the program was in.

Fig. 1

Page 4: mastermind project report

4

Mastermind Solver’s State Machine

Fig. 2 Displays the Mastermind Solver’s state machine. Reset initializes the program to begin at

state “Initial”. The arrow transitioning from “Initial” to “Guess and wait for user response” is

triggered by an active high Respond button pressed by the user. The arrow transitioning from the

“Guess and wait for user response” state to the “Check for problems” state is triggered by an

active high Response button pressed by the user. Here we can see a problem. Because our

Response button is used to begin the game and enter a guess, the Response button must be

debounced to active for only one cycle else we would transition straight to the “Check for

problems” state without processing data in the “Guess and wait for user response” state. Even if

we did not use the Respond button to begin the game and enter a guess we would still need to

debounce the signal to prevent it from being high for multiple clock cycles and looping among

the “Guess and wait for user response”, “Check for problems”, and “Algorithm” state. Therefore

we must make sure the Response button has only a single-clock pulse with the SCEN signal the

debouncer module offers.

The “Check for problems” state checks for three cases when pegs are placed. This was

mentioned earlier. If the AI guesses correctly or if there is a Fatal Error, we transition to the

“Initial” state. If there is a non fatal error where the user enters a total of more than four pegs we

return to the “Guess and wait for user response” state and the user is given another try to give

correct information. Else we transition to the Algorithm state.

In the “Algorithm” state the AI uses the information given to it to formulate the next guess. This

algorithm will be discussed in depth later on. The “Algorithm” state always transitions to the

Guess and wait for response” state.

Page 5: mastermind project report

5

Fig. 2

As noted there is a lot of logic in the Algorithm state which is the bulk of the code. This created a

bug in our implementation on the FPGA board where our debouncer didn’t work half the time

and state machine skipped states half the time. Both these problems were related to tremendous

amount of logic implemented into these two modules. With help from the TA, we realized that

our clock was too fast and the logic it took to carry out operations was not fast enough to keep up

to finish before transitioning to the next state. This was simply fixed by slowing down to clock to

give the computer more time to “think” in each state.

Mastermind Solver’s Custom Algorithm

Deciding on an algorithm

At first we researched online for an algorithm we could use for this project. We discovered

several candidates. The most promising one, the Five-Guess Algorithm, can always solve the

code in five guesses or less. To do this, the algorithm requires maintaining a list of all 1296 (64)

possible solution codes, so that as each clue is received the codes that are incompatible with the

clue’s information can be struck off the list, leaving a reduced number of possible codes.

However, we wanted to make a new contribution instead of simply implementing someone else’s

algorithm. We did not attempt to design an algorithm that takes less guesses than the Five-Guess

Page 6: mastermind project report

6

Algorithm, since much professional research has already been done on that problem. Instead, we

chose to optimize a variable other than the number of guesses taken: the number of hardware

components needed to implement the solver on an FPGA. This idea came to us because the Five-

Guess Algorithm would need 1296 flip-flops right off the bat to record its possible-solutions list,

and that seemed like a large number that we had some chance of beating.

So the algorithm we came up with does not try to minimize the number of guesses taken to solve

the code. The only constraint we put on the algorithm regarding number of guesses was that it

must always win (use ten guesses or less). In fact, taking more guesses lets the algorithm’s logic

be “lazier”, using less hardware; decreased guess-efficiency can allow for increased hardware-

efficiency.

Structure of the algorithm

The first five guesses always made by Mastermind Solver are the following: 0000, 1111, 2222,

3333, 4444. The purpose of these guesses is to determine which numbers the solution code

contain, without yet finding their ordering. For example, if the user were to declare two matches

for the guess 0000, then the program knows that the solutions code contains two 0s. Mastermind

Solver always makes these first five guesses, even if all numbers contained in the code are found

before the fifth guess. We chose to have this guess-inefficiency for the purpose of greater

hardware-efficiency: checking after each guess for whether all numbers have been found would

require more hardware, probably muxes for if-statements.

At first we also had a sixth guess of 5555. This guess would have been “lazy”, because the

program can figure out the number of 5s in the code by process of elimination, without having to

use an additional guess. Having this lazy guess would have saved hardware. However, we had to

go with the logic-intensive method (process of elimination) instead, because at the time our

algorithm was requiring eleven guesses for some code sequences; we needed the algorithm to be

more efficient by one guess in order to always win.

At this point, the algorithm has greatly reduced the number of possible solutions. In the worst

case, when none of the code’s numbers are repeats, there are 24 (4!) remaining possibilities,

down from the original 1296 (64). Here is a table listing out all remaining possible forms of the

solution, depending on the form of repetition exhibited by the numbers found to be in the code.

(A, B, C, and D are variables containing distinct numbers.)

Repetition (form of the sixth guess)

AAAB AABB AABC ABCD

Remaining possible solution forms

AABA BBAA ABAB BCAA ACAB AACB BADC ADBC ABDC

ABAA BABA CBAA ABCA ACBA BCDA ACDB ADCB

BAAA ABBA CAAB ABAC BDAC DBAC ACBD

BAAB BACA CABA CADB CBDA DBCA

BAAC CDAB DACB CBAD

Page 7: mastermind project report

7

CDBA BDCA BACD

DABC CABD

DCAB BCAD

DCBA

The sixth guess is an arbitrary ordering of all the numbers that the program found to be contained

in the code during the previous guesses. For example, if one 0, one 3, one 4, and one 5 were

found to be in the code, then the sixth guess would be 5430. The clue provided by the user in

response to this sixth guess, specifically, the number of strong matches (i.e., how many numbers

in the guess are correct and in the correct location), is then used to narrow down the possible

solutions even more. In the worst case, 9 possible solutions remain.

Repetition (form of the sixth guess)

AAAB AABB AABC ABCD

Strong matches for sixth guess

2 0 2 0 1 2 0 1 2

Remaining possible solution forms

AABA BBAA ABAB BCAA ACAB AACB BADC ADBC ABDC

ABAA BABA CBAA ABCA ACBA BCDA ACDB ADCB

BAAA ABBA CAAB ABAC BDAC DBAC ACBD

BAAB BACA CABA CADB CBDA DBCA

BAAC CDAB DACB CBAD

CDBA BDCA BACD

DABC CABD

DCAB BCAD

DCBA

The logic to use from the seventh guess onwards depends on which column of the above table

the solution code belongs to. If the solution is somewhere in the five left-most columns, then the

algorithm simply iterates through the remaining solutions. This works because there are four

remaining guesses, and these columns have four or less remaining possibilities. Also, it is the

desirable method, even though it is not the most guess-efficient procedure: it is hardware-

efficient, because the program does not need to spend hardware on checking the user’s clues

after each guess.

Solving codes that fall into the four right-most columns requires logic that is smarter than dumb

iteration, since these columns have more possible solutions (five or more) than the number of

Page 8: mastermind project report

8

remaining guesses (four). Each of these four columns has its own sub-algorithm. Please refer to

the appendix if you are interested in the details.

Implementing the algorithm in Verilog

There were two challenges to implementing the algorithm in Verilog. The first was that Verilog

apparently does not support nested for-loops (there was always an error unless the nested for-

loops were removed). Fortunately we were only planning on using two sets of nested loops, and

these did not have large iteration intervals, so it was not too hard to explicitly write out each

iteration of the inner loops.

The second challenge was the question of how to fit the algorithm into the state machine – put it

all into one state, or spread it out over multiple states? We are still not sure which design would

result in less hardware used. We opted for the one-state design because that one was easier to

implement, but the other design might use less hardware because it might be able to do loops

more efficiently. If we had more time, we could have tried both designs and compared their

synthesis hardware usage reports.

Measures of Success

We have two primary goals for Mastermind Solver: that it always wins Mastermind, and that it

minimizes hardware usage. The first goal, at least, has been met. We made sure by simulating the

algorithm’s performance in all 1296 possible games, using a C++ program. (The C++ simulator

code can be found in the appendix.) It was a good thing we used the simulator, because it

revealed an error in our algorithm: the algorithm could not solve certain codes of the form

AABC, contrary to our expectations. We fixed that bug, and subsequent C++ simulations

indicated a flawless algorithm. We have also done several dozen tests on the FPGA to verify that

the algorithm was correctly translated into Verilog. In the appendix is a waveform depicting

several successful tests of the program.

As for the second goal, minimizing hardware usage, we cannot claim to have definitely

accomplished it, although there are reasons to believe we have. We did observe the Xilinx

hardware usage report for our custom-algorithm implementation, and it is encouraging. Only 265

flip-flops were needed, as compared to the 1296 expected to be the minimum number needed for

the Five-Guess Algorithm implementation. However, all of 524 muxes were needed for our

implementation, and that sounds large. (For the complete hardware report, see the appendix.)

Ideally we would have done a duplicate project in parallel that used the Five-Guess Algorithm,

and then compared the Xilinx hardware usage reports of the two.

Page 9: mastermind project report

9

Appendix: Algorithm Details

Sub-algorithm for AABC, with 2 strong matches

guess AEEE // where E is distinct from A, B, and C

if (0 strong matches for AEEE) {

guess BAAC

guess CABA

}

else {

// 1 strong match for AEEE

guess ABAC

guess ACBA

guess AACB

}

Sub-algorithm for ABCD, with 0 strong matches

guess BACD

if (0 strong matches for BACD) {

guess CDAB

if (0 strong matches for CDAB) {

guess DCBA

}

else {

guess DCAB

guess CDBA

}

}

else if (1 strong match for BACD) {

guess AACD

if (0 strong matches for AACD) {

guess BCCD

if (1 strong match for BCCD) {

guess BDAC

}

else {

// 2 strong matches for BCCD

guess BCDA

}

}

else {

// 1 strong match for AACD

guess CACD

if (1 strong match for CACD) {

guess DABC

}

Page 10: mastermind project report

10

else {

// 2 strong matches for CACD

guess CADB

}

}

}

else {

// 2 strong matches for BACD

guess BADC

}

Sub-algorithm for ABCD, with 1 strong match

guess ABEE // where E is distinct from A, B, C, and D

if (0 strong matches for ABEE) {

guess EECE

if (0 strong matches for EECE) {

guess CABD

guess BCAD

}

else {

// 1 strong match for EECE

guess DACB

guess BDCA

}

}

else {

// 1 strong match for ABEE

guess AEEE

if (0 strong matches for AEEE) {

guess DBAC

guess CBDA

}

else {

// 1 strong match for AEEE

guess ADBC

guess ACDB

}

}

Sub-algorithm for ABCD, with 2 strong matches

guess AEEE // where E is distinct from A, B, C, and D

if (0 strong matches for AEEE) {

guess BACD

guess CBAD

guess DBCA

Page 11: mastermind project report

11

}

else {

// 1 strong match for AEEE

guess ABDC

guess ACBD

guess ADCB

}

Appendix: Hardware Usage Report

Advanced HDL Synthesis Report

Macro Statistics

# Adders/Subtractors 14

2-bit adder 1

21-bit adder 1

3-bit adder 1

3-bit adder carry in 2

32-bit adder 4

4-bit adder 4

5-bit adder 1

# Counters 1

27-bit up counter 1

# Registers 265

Flip-Flops 265

# Comparators 44

3-bit comparator equal 10

32-bit comparator lessequal 20

4-bit comparator greater 6

4-bit comparator lessequal 8

# Multiplexers 524

1-bit 2-to-1 multiplexer 136

1-bit 4-to-1 multiplexer 6

12-bit 2-to-1 multiplexer 39

12-bit 4-to-1 multiplexer 2

2-bit 2-to-1 multiplexer 12

21-bit 2-to-1 multiplexer 1

3-bit 2-to-1 multiplexer 160

3-bit 4-to-1 multiplexer 4

32-bit 2-to-1 multiplexer 164

# FSMs 3

Page 12: mastermind project report

12

Appendix: Waveforms

Note: in the following three test games, the delay in transitioning between certain message-

displaying states (such as the Fatal Error state) has been abbreviated to make the waveform

layout friendlier.

Page 13: mastermind project report

13

Page 14: mastermind project report

14

Page 15: mastermind project report

15