ECAD and Architecture Practical Classes
This this lab you will be implementing Conway's Game of Life on the DE2 board. The DE2 board will be running a prebuilt MIPS soft-core processor together with renderer code that you will write. You will also produce the MIPS assembler to implement the Game of Life cellular automaton.
Begin by downloading the Quartus Archive file from the Tiger "MIPS" page. When you open this file in Quartus you will be asked where you'd like to place the project, so select a suitable directory (e.g. U:\game_of_life on the PWF). Note that this project has incremental compilation enabled which works just fine on the PWF, but is not licensed on the web edition of the tools. If you turn off incremental compilation, then it should compile just find on the web edition.
This contains a working Quartus project that will form the basis of this lab. Open the project in Quartus by double-clicking on life.qpf. If you explore the project using the Files tab in the Project Navigator you will find several Verilog files. The files located within the directory Tiger make up the processor. The files mouse.v and mouse_logic.v form the code that talks to the mouse and returns movement data. The only signals that you will need to use are the x, y and left output signals from the mouse_logic module. The x and y values give the position of the cursor on the screen, with the origin at the top-left. The "left" signal changes state each time the left mouse button is pressed. Important:it does NOT go high when the button is pressed, and low otherwise, it is a two-phase signal that changes state each time the button is pressed life.v is the top-level module in this project, and the renderer has the same basic layout as the previous lab. The majority of the other Verilog files have been auto-generated using SOPC Builder (see the description below). The only other file that may be of interest at this point is the initial.mif file, this contains the data to be loaded into the frame buffer when the chip is programmed.
N.B. when you open up the programmer, you may find the programming file is set to something like "Z:\...\life.sof" if this happens, change this to the life.sof file in the working directory by double-clicking on it and selecting the correct file from the dialog.
For those who are interested, download the shell file from the Tiger "MIPS" page instead. This contains the project without the SOPC component or incremental compilation set up. To set these up you will have to follow the respective tutorials. This will take slightly more time, but would serve as a good introduction to some of the tools available. Ensure you complete the SOPC tutorial first, followed by incremental compilation.
SOPC Builder (System On a Programmable Chip) is a tool that is provided as part of Quartus to assist in producing larger systems consisting of several components sharing a common bus. It is accessable via Tools | SOPC Builder. You will not be required to use this in order to gain the tick, since the component has already been created for you. For those of you who are interested, there is a brief introduction to SOPC Builder here.
A full compilation of this project takes roughly 10-15 minutes to complete. In order to reduce the time you spend sitting around twiddling your thumbs waiting for it to compile, this project has been set up to make use of the incremental compilation feature available in Quartus. This essentially involves splitting the project into several logical partitions, and assigning each of these a specific region of the FPGA to use (called a LogicLock region). A full compile is performed, and then subsequent compiles will only re-synthesise and fit those partitions that contain changed source code. The project currently has 2 partitions, one for the entire project, the other holding the processor only. Thus, if no changes are made to the processor, then this will not be re-compiled each time, significantly shortening the compile time. Those who are interested further in incremental compilation and its uses will find Altera's documentation helpful.
Additionally, the physical synthesis setting is set to "fast". This reduces the compile time to a few minutes, at the expense of producing less efficient designs. The design currently is set up to run off a 25MHz clock, since a 50MHz one gives a few timing warnings when it is compiled. After the labs have been completed, you may wish to try changing it back to a 50MHz clock and sorting out the timing issues. Note you will have to change a few parameters in the mouse module that relate to wait states. If you decide to have a go at a 50MHz clock then it is best to set the physical synthesis setting back to "normal" or even "extra" to allow for more optimisation during compilation. To do this, go to Assignments | Settings and on the left hand tree view, select Fitter Settings | Physical Synthesis Optimizations. At the bottom, under Physical Synthesis Effort select Normal and click OK. Only change this if you need to, as it will push the compilation time up. Once you have the project set up, compile it once to check that it is working, then proceed to the next step.
MIPS assembler - getting started
Together with the project files, you will also need to download and extract the toolset onto your local machine. Once this is done, proceed as follows:
- Program the board with the project. N.B. you will not see anything displayed on the monitor yet since the renderer code has not been written.
- Run the MIPS Communication Server within the toolset directory first using the short cut to it (since this setups path information specific to the PWF configuration). You should select the USB connection from the drop-down box; then select the DE2 board from the list box and click Connect. The program can then be minimised to the system tray.
- Run IDE.exe. This will be the development environment for working with the MIPS assembler.
- Open up test.S from the toolset directory. N.B. if you decide to experiment with the MIPS
further by creating your own assembler files, you will need
regdef.h to be present in the same directory as your assembler
file. This can be copied from the toolset directory. The assembly
files should also have a capital - S extension.
Also note that the registers in the code do not start with the $ symbol. This is due to the interface used to the GNU assembler. The $'s are added automatically.
- Click Tools | Compile. The output is shown in the console window. Any assembler errors will be reported here. This is not a fully-functioning command prompt, but it does support basic commands. Warning: when you come to write your own assembler, you may find strange errors mentioning the c pre-processor. This can occur if you start a comment with a pre-processor keyword such as "# if". To get around these errors, it is recommended to start all comments with "##".
- Click Tools | Run. If all is working correctly, you should see "DEADBEEF" displayed on the 7-segment displays.
If you experience any problems, see the troubleshooting page for more details.
Also included in the toolset is a file serialio.S. This
contains various routines for reading from and writing to the JTAG
port on the processor, allowing you to output information that may be
useful for debugging. Each function is commented in the file, together
with what registers each uses. The file is included via a c-type
"#include" statement, which has already been added to the main
assembly file that you will be using (life.S). The functions
are called via the standard
In order to view the output, you need to start the JTAGTerminal
program from a command line (this will not work from within the
IDE). The JTAG Terminal takes 1 argument which is the cable name you
will be connecting to. This can be found in the drop-down box in the
MIPS Communication Server, and looks something like "USB-Blaster
[USB-0]". I.e. you would start the program up using a command of the
JTAGTerminal "USB-Blaster [USB-0]". Note that the
quotes are important. When receiving data, data is not sent from the
terminal until it receives a carriage return character.
GDB is also available for debugging. In order to start a debugging session with GDB you can use the debug.bat batch file. On the command line (not in the IDE), while in the Toolset directory, run debug.bat prog.elf (once you've built your program). You will be presented with a GDB prompt. Type help to get a full list of possible commands. The ones of particular interest will be:
- continue - Continues running the program until a breakpoint is hit.
- stepi - Steps the program a single instruction. When stepping over a branch instruction this will step over both the branch and the delay slot. This actually steps a single assembler instruction, so for some instructions such as li which actually expand to two instructions you will need to execute stepi twice to step to the next instruction in the file. step can be used which will step over psuedo-instructions such as li in one step, however sometimes it exhibits strange behaviour with branches and the step effectively continues instead, so the use of stepi is recomended instead.
- print x - Prints out the value of x, where x is something like a register name, e.g. to print t0 you would use the command print $t0. If you wish to output in hex use print/x instead, for an unsigned decimal integer output use print/u.
- info reg - Prints out the contents of all registers.
- break position - Sets a breakpoint at a certain position, to specify a breakpoint at a line x use life.S:x where life.S is the name of your assembly file. So to set a breakpoint at line 10 you would use the command break life.S:10. When execution reaches a breakpoint, execution will be paused and you will be able to use the debugger to examine state (i.e. register and memory contents), and single step execution. Breakpoints should not be placed in branch delay slots
- clear position - Clears a breakpoint, so to remove a breakpoint in life.S at line 10 you would use the command clear life.S:10.
- x/mbx (char*)(&store_data) + n - Examine m bytes starting from byte n of store_data. So for example if you wish to examine the first line of your newly computed state (which is 40 cells long) you would use the command x/40bx (char*)(&store_data) if you wished to examine the second row you would use the command x/40bx (char*)(&store_data) + 40 and so on.
- quit - Quits GDB
If you quit GDB while you are not in the debugger (i.e. there is no gdb prompt waiting for a command, this may happen after you continue and have not yet hit a breakpoint), in order to continue running and debugging programs you may need to disconnect and the connect again with the MIPS Communication Server.