Home | Microprocessor | Labs Index |XUP-UNM V1000 Project|Workshops | Links & Datasheets | General Educational Material


The purpose of this project is to develop a Microblaze soft processor onto a Spartan2E device.

Shown above is a Digilent Spartan2E prototyping board. It is the board/device we will be targeting for this processor. This processor project performs two simple jobs. First, it toggles the LED on the board off and on. Secondly, it continuously prints "Hello World" to the screen. The software used is ISE 5.1 (SP3) and EDK 3.1 (SP3).

Shown above is a picture of how the final project looks when it is up and running. I will now take you step-by-step through the entire process from project creation to activation where you will be observing an output like the one shown above. Here is a zip file that contains the entire completed project.


Here is a diagram of how the entire system will be interconnected and the functions of the various parts.


To begin the process, start EDK, Xilinx Platform Studio. This is a GUI based design environment. We will refer to it from now on as XPS.


Choose a directory on your hard drive where the project will reside. Choose browse to change the directory. Make sure that none of the directories in your directory path have spaces in them. For example, if you choose "my documents" you will end up with an XST 426 error when you finally get to the generate netlist section. Choose the settings shown above (the directory I have chosen is optional, you may choose one that is different). The settings come directly from the top of the FPGA device located in the center of the board. The Digilent Spartan2 and Spartan2E boards look almost identical. Make sure you double check the part number on top of the chip. Do not choose to add any additional files or parameters then click "OK." An error will come up asking if you want to start with an empty MHS file. Click "yes."


This screen shows your initial project. All it consists of is the outer frame. You can see under Project files that it has shelled out the .mhs (hardware specification file), mss (software specification file), and the .mvs (project language and simulation file).

The first thing I am going to add to the project is a UART (universal asyncronus receiver transmitter) so that my processor will be able to communicate with my hyperterminal. To add this to the project you need to go to Project, Add/Edit Cores.(dialog). If this selection isn't available you need to ensure you have upgraded to at least service pack 2. Cores (like the UART we are adding) are nothing more than packaged collections of VHDL code.

What you will see is a screen similar to the one shown above. On the right hand side of the screen select opb_uartlite and then click on "add." You will see it transition to the left hand side of the screen. Now we will need to assign the address values to the starting and ending (high) address locations. For a starting address use OxFFFF8100 and for an ending address use OxFFFF81FF. You have the entire range 0x00000000 to 0xFFFFFFFF to choose from. Since we need a minimum of one word to address the UART, as it's not a memory-type peripheral, we use a small address range. The optimal size for such an address range, in order to minimize decode logic, is 00 to FF. I have also chosen to change the instance name (see below) to "myuart" to make it easier for me to remember what I am using it for. This is also important in case you choose to use multiple instances of the same peripheral. All of these things we are selecting are called peripherals. The Microblaze system is "bus centric" which means all things must have a relationship with a bus.

While we are at this screen, it is good to bring in the rest of the necessary cores. On the left hand side of the screen you can see a column called "Peripheral." In that column you can see the real name of the cores I have added and on the "instance" and "Address' columns you can see the new names and addresses I have assigned.


 

Here are the final selections. What we have chosen in addition to myuart are as follows. We chose a Microblaze processor. This processor is the heart of the project. It is what will control all the input, output, and internal processing. We chose a block RAM (bram1) and a block RAM controller (lmb_cntlr). This will be used to store data (hello world) and instructions. In our case we don't have an external RAM chip, so we store our instructions and data in Block RAM that's internal to the FPGA instead. We included a JTAG uart (myjtaguart) to allow us to be able to interface with the JTAG device for debugging. We added the gpio (I/O) to allow us to interface with the button, LED, and clock. When you are done, click on Apply, and then OK. This will update your .mhs file.

The next step is to add and make various bus connections. The bus connections will allow us to interface the cores to each other and two the outside world of the FPGA. Launch the Add/Edit Cores.(dialog) section again and then click on the Bus Connections tab. What we need is three different busses. Two of them are identical but will have different names. They are the data and instruction lmb. Even though they are identical busses they perform different functions and so are considered different instances of the same bus with different names. The LMB is a local memory bus. It is a synchronous bus used primarily to access on-chip block RAM (bram1 in our case). The other bus we will need is the opb (on-chip peripheral bus) that we will use to interconnect the various cores. It is a general purpose synchronous bus designed for easy connection of on-chip peripheral devices. Select "opv_v.." from the upper right menu and add it once. Then select "lmb_v." and add it twice.

 

 

Next I am going to change the names of the busses to make them easier for me to remember their purposes. I do this by holding the mouse over them, right clicking and then choosing "edit name." For example, I changed the opb_v20... to "opb_bus" and the data bus from lmb_v10... to "d_lmb" and to "i_lmb. I am also going to assign them as either masters or slaves. Lastly I am going to change the connector names for the block RAM in the lower right hand corner to make the names more informative to me.


Here are the final bus configurations. Make sure yours are the same then click on apply and ok.

Next it is necessary to update and add in the ports. Ports are how we connect the various items/cores to the interconnecting buses. We don't need all the available ports that are contained in each core. We need to be specific. Go back to Add/Edit Cores..(dialog) section and click on the Ports tab. Selectively choose each of the ports required and "add" them.

The picture above shows the steps to add the various ports. I am going to change some of the names to make it clearer to me to remember what they are and what their functions are. Another important thing here is to note that this is how you decide if the ports are going to be internal or external. Internal means that they are just signals. External means that they connect outside of the design. Another thing to notice here are that the system clocks and resets are given the same names. This is important in that it shows that they are all tied together.

 

When you are done, your ports field should look like the one above. A couple of notes on side features here that we didn't use. If you wish to tie something to a high or ground you can choose "add port." This would be a handy feature if you wanted to tie voltage to an LED and have it be on all the time. Another feature is the "connect" button. From the way I have labeled a lot of the net names (sys_clk) I have tied then all together. If I had wanted to do it differently, I could have chosen all of those lines and tied them together with the connect button and given them a different name other than sys_clk.

Next it is time to click onto the Parameters tab. What all these steps are doing is to prepare our MHS (hardware specification) file. This is the file that will dictate how our Microblaze soft processor core will be pieced together and tied to a specific architecture.

There are nine separate cores involved in our processor project (so we will have to look at nine separate parameter pages). For the bulk of them there will be no changes. The right hand side of the screen shows you the parameters that can be modified. To modify them, select them, click "add" and then modify the entries on the left hand side.

First choose the lmb controller (lmb_cntlr) by selecting it in the "choose IP instance" selection in the upper right portion of the screen.


Make no changes. It is correct just the way it is. Next choose myuart.

We are making a lot of changes here. Much of this is based on the fact that the input clock on the Digilent board is a 50MHz oscillator. In the end, your choices should be the same as the screen above. Next, go onto the myjtaguart. Make no changes here and then go onto the mygpio (general purpose input/output). Here we will make some changes based on the fact that our width is only one bit (versus the default 32 bits). This design change was based on the smaller FPGA.


Here are the final settings of the gpio. Next is the Microblaze core. Make no changes here. Go onto the opb_bus, and both of the lmb busses. Make no changes to any of them. They are fine with the default settings.

Click on Apply and then OK. By doing this you are modifying your mhs (hardware specification file). What this has done is develop the hardware shell that will be our Microblaze processor. An important thing to remember here is that changes to the GUI (add/edit cores... (dialog)) will make changes to the .mhs file. This is not a reverse direction operation. Changes that are hand typed into the .mhs file are not reflected on the GUI. Next it will be necessary to add our source code. This source code is a C file that will set our LED to blink off and on and will send our "Hello World" text to the UART which will then be displayed on the screen. Click here to download the source code. Save this file into a directory called "code" within your project directory as system.c. Now return to XPS. On the left hand side find the Microblaze core (mblaze).


Right click on "Sources." Go to Add Files and scan over to the code directory. You can see the multitude of different suffixes available to let you know the possibilities of different types of C and C++ code types that are acceptable.

 

Select your system.c and click open. You can see how it has added the code to the project. The next thing to verify is a quick check of the mblaze settings to make sure we have everything correct. Right click on mblaze and choose S/W settings.


Ensure that the Communication Peripherals are set as shown above. All the rest of the tabs can be left as default. Two tabs that are neat to observe here are the Details and the Optimization. Click once on the Details tab. We have left the Start Program Address blank. This means that the microblze should begin at 0x00000000. We could enter this value with no impact but you could also enter a different number if you desired your microprocessor to begin at a different location. Next click on the Optimization tab. You have a choice to choose to create the debug symbols or not. It is an accepted practice to include the symbols during the debugging phase of your project design and then to remove them when you make your final project run. This will reduce the size of your download file. Now click OK to close the S/W settings screen.


 

It is necessary to discuss the UCF (user constraint file). This file determines where my external signals/ports will connect to pins on the FPGA. Click here to download the system.ucf file. It will be different for each board and each different type of FPGA. As you can see by looking at it, it only has about five lines. This is to deal with the button, LED, etc. Copy it and paste it into your project directory into the "data" directory (if one doesn't exist, create it first). Next we will begin to compile the information we have developed. When we click on the "Generate Netlist" choice we will be launching PlatGen (Platform Generator). Three items below Generate Netlist is "Clean." If you want to delete existing Netlists, that is where you would do it. We don't need to do this since we have never compiled a Netlist. Once you launch PlatGen it will take a while for it to complete based on the power of your computer. Eventually it will come up as completed.

The next step is to translate the Netlist into something designed for downloading. In the picture above you can see a choice for Generate Bitstream. Once the Generate Netlist is completed you will need to generate a Bitstream. There is one last thing that needs to be done before you can generate the bitstream. It has to do with a design feature of the Digilent S2E board. The only button on the board (the one we are using as a reset) is tied to a global clock pin on the FPGA. This isn't a problem except it means we need to add one additional entry to the .mhs file. Here is a very important part. Every time you modify the peripherials, ports, etc. within the "Edit/Add cores . (dialog)" section and hit "OK", you are rewriting the .mhs file so each time before you generate a new bitstream you must remember to double check to make sure this entry is in the .mhs file. If it isn't there you will receive an error and the bitstream file generation will fail with an error about pin 77.



On the port line for sys_reset, at the end of the line are the words, "SIGIS = CLK". This is a work around for the board and must be in there.

Once these two things are done, you can click on "generate bitstream". It will produce (within the implementation folder) a file called system.bit. This file is used for certain items that we are not going to be using now. For us, we want a file that we can use ISE's impact tool to transfer to the FPGA. Once the generate bitstream has finished running successfully then you need to proceed to the next step. Go back to tools and then to "update bitstream" This will create another file in the implementation directory called download.bit. It is the one we will use to download to the FPGA. Once this is done you can go ahead and close XPS. It has created the file we need to download our Microblaze processor onto the FPGA.

You are now going to use a tool called "iMPACT" from within the ISE software package. I found it easiest to make a shortcut for this program onto my desktop. Disregard the small words in the picture below. I only wanted to show you the path to iMPACT.


BEFORE you launch iMPACT you will need to connect the power adapter to the board and connect the board to the computer. I choose to interface with the board through the Digilent supplied standard printer cable. Make sure the PORT/JTAG switch on the board is set to JTAG. Now launch iMPACT. You will end up with a series of three screens: Operation Mode Selection, Configure Devices, and Boundary-Scan Mode Selection. Just click "Next" through each of them - accepting the defaults. It should say that there was one device found and then prompt you for a file. Browse over to the implementation folder of your project.

Choose the download.bit file and select open. If you have s system.bit and not a download.bit file then you need to go back to XPS and run "update bitstream" from the tools menu. At this point you may receive a notice about assigning different types of devices. Just click yes.


Right click on the Xilinx device symbol and choose program. Accept the defaults and then click OK. You should be rewarded by a "programming succeeded" notice. At this point your Digilent board should have LED1 blinking on and off at a slow enough rate for you to watch it. You can close iMPACT now (no need to save anything there).

Lastly, you will want to hook up the serial port on the Digilent board to the serial port on your computer. Use a straight through cable (pin 1 on one end goes to pin 1 on the other, pin 2 on one end goes to pin 2 on the other, etc.). Under windows communications, launch HyperTerminal. Choose the following settings (that came from your programming of the UART).

If all is working you should be able to see the Hello World being repeated continuously on the screen and the LED flashing.


Now you should be able to go back in and modify the system.c file to change the text or to speed up/slow down the blinking light.

Next I will begin to show you some of the debugging tools available and how to manipulate within them. Most of the more experienced users use a command line approach whereas the tutorials more often show you a gui based operation. I will delve into both. Go back to XPS. Double click on "mblaze" to get to S/W Settings.

Change your mode selection from Executable to XmdStub. Click OK. Go to tools, clean netlist, and then back to tools and generate netlist. Once the netlist is regenerated, go back and generate the bitstream and then update bitstream. We now want to download this new debugging program down to the FPGA. Using the procedures shown previously, launch iMPACT. Proceed to download the download.bit file just like you did before. The thing you should notice first is that even though the download completed successfully, the LED is no longer flashing. If you launch the HyperTerminal you also don't have the hello world script running. Now let's return to XPS to continue with the debugging.


Proceed to tools and then to XMD. It will launch and then give you a screen like the one shown above. From here we will connect to the Microblaze core. By typing "mbconnect" you are shown a list of connection options for connecting. In my case, if I just type "mbconnect stub" the system (almost always) auto detects and finds the core. Shown below is what it looks like when it has correctly connected to the stub.


A great deal of command line entries can be made from this point. For example, if you wanted to read what was in the four registers at the uart location you could type in "mrd 0xFFFF8100 4" The 4 at the end signifies the number of words. Within the hardware reference guide section on the UART, it shows the register set and shows that register location 04 is the transmit section. To check and make sure my transmit section is working I am going to send the number one through the system to the HyperTerminal. On the XMD screen type "mwr 0xFFFF8104 0x31" and hit return. What this translates to is memory write to the 04 location the hex value 31. The hex value of 31 translates to a 1.



Here is what the resulting screens look like. Next, to check out the GPIO we will turn the LED off and on manually. To display the contents of the registers of the GPIO type in "mrd 0xA0000000 4". You will see that register 04 contains a 1. This turns the LED off. Modify the register contents to a 0 by typing mwr 0xA0000004 0x0. This turns the LED on.



By using a "0x1" you can turn the LED off again. This is a handy feature for ensuring your I/O is connected and functioning the way you think it should. Next let's go into a different debugging tool. Go back to XPS and then to Tools -> Software Debugger to open the GDB interface.


In GDB, select File -> Target Settings to display the Target Selection box. Configure the Target Selection dialog box to match the figure above and click OK.


 

A great deal of the remainder of this tutorial comes from the Xilinx EDK Microblaze Tutorial. In the GDB select File -> Open File. Select the executable.elf in the inst_Microblaze/code directory. You will end up with a screen like the one above displaying the assembly code. In GDB select File -> Exit and go back to XPS. In XPS go to Options -> Compiler Options.


 

Under the Optimization tab choose to create symbols for debugging by selecting the option as shown above and click OK. Recompile the code. You do this by clicking the compile program sources button on the XPS taskbar. Once this is finished, load the new executable.elf into GDB.


You should now be looking at your C code.


By clicking on the run symbol on the task bar you can run the program. It also has buttons for step, next, and continue. The truly great thing about his is that you can bring up the Memory and the Register windows and actually see what is going on in each one of them as you step through the code. This is an invaluable tool for being able to find out where something goes wrong.

 


alnz | UNM - XUP