EE354 Project: Minesweeper in Verilog
Finished a project a few days ago for EE354 at USC: Introduction to Digital Circuits. The final project for the class requires us to write a program in verilog to implement whatever we want, as far as it’s not too trivial. So I took a few days and finished this minesweeper game. The source code, with the compiled programming file, can be downloaded here. It’s not too difficult; in case you are going to work on one as well, here are a few remarks.
Hardware/Software Specifications
This project is created for the Nexys 3 board using Xilinx ISE 14.7, and programming is done using the software Diligent Adept. If you want to try it out, you can program the bit file: ms_top.bit onto your board. To play, connect the board to a VGA monitor. Control is done with the 5 buttons on the board and a switch, and obviously you look at the monitor to play. Additional debugging output on the LEDs.
How To Play
Up, down, left, right buttons to move your current selected grid, and press the center button to click on the grid. There is no support for flagging a mine, because there are only 5 buttons and I don’t wanna complicate things further. Keep the switch 0 turned off. On the left is a game board with 16 x 16 grids and 40 hidden mines, on the right you can see a smiley face to indicate the status of the game: playing, lost or won, just like the game on a Windows machine. There is also a timer that counts in seconds.
Remarks
Compiling the project takes about ten minutes each time, so during that time I usually play the old version “to find bugs”.
To display the digits, I created a 30 x 30 bitmap for each digit, as well as the explosive. That takes a while.
The smiley face, however, is done by equations (or inequalities) and not bitmaps, since the bitmaps would be huge otherwise.
The VGA display code is modified from a code template. The timing generator should be the same across all Verilog VGA projects for this class of FPGA boards.
Once I encountered an error saying “your design does not fit in this device”, so I pulled a combinational block of code out of the display module and made a separate small module for it, and instantiated it in the display module. That worked, I have no idea why.
Randomization is done by first creating a pseudorandom sequence. Here I did a x1 = a * x0 + b approach to generate this sequence. Then each time I initialize 40 mines on the top left corner, and randomly swap the states of 2 grids 1000 times. That gives a satisfactory result.
Last but not least, the effect that opens up an entire connected empty area is done naively. In a normal CS approach, I would have created a BFS or DFS walk to flood the neighbors, but such a thing is more complicated in an EE approach, since instead of data structures like vectors or recursive functions, we only have wires, registers and modules. The way I did it was that during each clock, I would go through all the grids, and check whether the grid should be cleared based on its neighbors. The trick here is that this looping over all grids is done in parallel, so doing it once takes the same amount of time as doing 256 times.
Some other groups in the past have done some pretty awesome work, like one group did a maze that presented the walls and the ground in 3D perspectives, and another did a 2 player bomberman. If you try hard enough, this final project could be a lot of fun.