Lab 1: Part II - Introduction to DE2 and Nios II Assembly


Description
Preparation (1 mark)
In Lab (1 mark)
Quiz (1 mark)

Description

The purpose of this lab is for you to gain familiarity with Assembly Language Programming, and the environment for programming the Altera Nios II processor at the assembly language level.

The Nios II processor is a soft processor, i.e., it is a processor implemented in the reconfigurable fabric of an FPGA. The FPGA that we use is supplied on a board called the DE2 made by Altera. You will interact with the processor using the Altera Monitor Program. As this is probably the first time you will be using the Monitor Program, please skim through its documentation (Monitor Program Tutorial). Keep it as a reference for the rest of the labs.

This lab contains a few questions and exercises for the reader: don't be afraid to experiment with the software, the debugging tools and also don't hesitate to ask your TA if you are unclear about any of the material in this lab.

Preparation (1 Mark)

Read through the Nios II Assembler section of the DESL website. Make sure you understand all the material in the commented example program and answer the following questions:

  1. What is the purpose of the .global directive?
  2. How do you specify the entry point (or beginning) of your program?
  3. There are separate "sections" for code and data, how do you specify to the assembler which section you are currently in?
  4. What directives do you use to declare a byte, half-word, word, or string?
  5. What does the .align directive do? What might go wrong, if anything, if you don't properly align variables? HINT: read the description of the ldw instruction in the Nios II Instruction Set Reference on the DESL website.
  6. In the example program (from the DESL website), how many bytes of memory are used up by the string named hellostring?
  7. How do you declare space for variables in memory without initializing them?

In Lab (1 Mark)

The in-lab part has two parts. In the first part, which is organized as a tutorial, you will use an existing assembly source file to introduce yourself to the Altera Monitor Program. Although there are no marks given for this part, the knowledge gained here is necessary for the second part (and the rest of the labs). In the second part, you will use a different assembly source file which you will have to modify in order to run it correctly and to implement additional functionality.

PART I: Compile and run an existing assembly code (0 marks)

  1. In Windows Explorer or My Computer, go to your w: drive.
  2. Create a folder to keep all your labs together (called desl for example), and then create a folder within that called lab1. Within the lab1 folder, create another folder, test1
  3. Download the program leds_7segs.s (or leds_7segs_advanced.s which accomplishes the same task but uses more advanced assembly programming), which is code for a simple test program. Save the file in the test1 directory, from above.

    DE2

  4. Power on the power supply (the box in the top-left corner of the picture above) by pressing the white button on its front side (sometimes a switch on the back) and power on the DE2 board (press the red button on its top-left corner).
  5. Open the Monitor Program and create a New Project. Choose the test1 folder you created above, and name the project test1.
  6. Choose the DE2 Media Computer as your system, and click next.
  7. Choose "Assembly Program". Click next.
  8. Click the "Add..." button, and then select the leds_7segs.s file you downloaded.
  9. Change the start symbol from _start to main.
  10. For all remaining pages, leave the default options as they are.
  11. Click "Finish".
  12. Click "Yes" when asked if you want to download the system to the board.
  13. When the system has been downloaded, select Compile from the "Actions" menu.
  14. When compilation has completed, select Load from the "Actions" menu.
  15. Select Continue from the "Actions" menu to start the program. You should see the red and green LEDs advancing from right to left, while a count (in hex) increments on 4 of the 7-segment displays.

More information on the compiling you just did

When we selected Compile and Load from the "Actions" menu, a number of commands were performed for us. The flow of commands is as follows:

Compilation process

As illustrated, there are 3 main steps. You can observe them in the "Info & Errors" window.

  1. The assembly source file is first processed by the assembler. The assembler parses your source file, checks it for syntax errors, and translates it into its equivalent binary form. We say that a file is "binary" when it contains some bytes that have values other than the ones used to represent characters that you can type on your keyboard.
  2. The linker pastes all the object files together grouping their data and code sections to form an executable program. The linker also takes care of "resolving symbols", i.e., matching by name ("symbol") the location of code or data when used in one file to their definition (usually labels made .global) in another object file. The linker thus makes it possible for you to write a function foo and call that function from a different source file by name (call foo) rather than by location (call +0x13c). In the future, if you ever encounter a compilation error stating that there is an "Unresolved symbol X", you will know that there is a reference to the X symbol in your code, but the linker cannot find the definition of that symbol in the object files that it is linking together.
  3. The executable file contains data and instructions that are encoded specifically for the Nios II processor. To execute it, we need to upload it the memory of the Nios II system on the DE2 board. Once this is done, the executable runs on the Nios II processor independently of your computer.

The process we just described to generate executables is very similar to the one you can find on a GNU/Linux system, as Altera modified the GNU utilities to create their own. For this reason, most utilities will be very similar in both systems. Since the GNU tool-chain is well documented on the web, you can find a lot of relevant information by searching, for example, for the GNU Linker.

More information on the program you just ran

In this section, we examine the difference between the assembly source code and the machine code.

Listing of a program

Take a look at the source code of the program you just ran by opening leds_7segs.s in Notepad++ or another text editor. You will obtain an output in the following format:

Sample code

This program, typed by a human, is meant to be converted to an executable program by the assembler software. The components of a program as shown in the figure above are:

You will find an extensive description of the supported syntax of assembly in the "Syntax" section of the the GNU Assembler guide. In particular, it will be useful for you to know in the future that you can enter constants in assembly in their decimal, binary, octal or hexadecimal representation.

Disassembly of a program

The Nios II processor executes instruction one by one in the order specified in the program. The program is a binary file consisting of machine code representing instructions and some metadata. The assembler will convert each instruction of the source code into one machine-executable instruction, except for movia, the only pseudo-instruction that the assembler converts into two machine-executable instructions. Except movia, there is a one-to-one correspondence between the machine code and the source code, so it is possible to "disassemble" a machine code instruction into its corresponding assembly code. The Monitor Program displays the disassembly of leds_7segs.s in its disassembly window, with the following format:

Altera Monitor Disassembly

Notice how the label has no address of its own; it refers to the address of the immediately following instruction in the executable. The addresses and machine codes are given in hexadecimal. In the Nios II instruction set, all instructions are 32 bits in length. This explains why addresses of consecutive instructions are separated by a distance of 4 bytes (32 bits). Compare this output with the original source program. Observe how the movia pseudo-instruction is converted into a orhi and a ori and observe the one-to-one matching of some other instructions. Notice also how the constants defined with an .equ directive (such as ADDR_GREENLEDS) have been replaced by their numerical value in the machine code. Finally, notice that there are instructions in the disassembly that were not in the source code. The Monitor Program tries to disassemble the contents of memory, whether the values came from your source code, your data, or even random values.

PART II: Modify an existing assembly program (1 mark)

Create a new directory in your lab1 folder, called test2. Create a text file called test.s in that folder and copy the following assembly code into it:

.equ RED_LEDS, 0x10000000

/* List of registers utilized:
r2: pointer in array                 r6: index in the array
r3: value displayed                  r7: temporary register
r4: address of LEDs                  r9: counter in delay loop
r5: length of the array                                        */

array:
.byte 1
.byte 2
.byte 3
.byte 4

.global main
main:
movia r4,RED_LEDS  /* Get address of LED device */
movia r2,array     /* Get address of array */
movi r3,0          /* initialize value displayed */
movi r6,0          /* initialize counter */
movi r5,4          /* set length of the array */

LOOP:
bge r6,r5,amin     /* test for end of array */

ldb r7,0(r2)       /* load digit from array */
or r3,r3,r7        /* insert character in string of digits */
stwio r3,0(r4)     /* write to the red LEDs /
addi r2,r2,1       /* increment address */
slli r3,r3,4       /* shift string to the left */

addi r6,r6,1

movia r99,10000000 /* set starting point for delay counter */

DELAY:
subi r9,r9,1       # subtract 1 from delay
bne r9,r0, DELAY   # continue subtracting if delay has not elapsed
br LOOP            # delay elapsed, redo the LOOP

This program should light up the binary representation of numbers (1, 2, 3, and 4) on the red LEDs (using 4 LEDs per digit), then scrolls to the left until the first digit reaches the 4th position. The process then repeats.

  1. Create a new project with this file in the Monitor Program, and compile it.
  2. The assembler will report errors; try to fix all of them until your program is successfully assembled. Make sure you fix any warnings as well (this code should not produce any warnings). Do this on your own and try to understand the compiler's error messages. ONLY IF YOU GET STUCK click below to see how to fix the above code (but again, you are highly discouraged from doing so - try it on your own). After it compiles, there is still a bug in the program! Compare your code to the disassembly output (see above). Also, try to use the single step functionality of the Monitor Program to find the bug. If you can't, click here :(
  3. Modify your code to use only 3 bits to represent each digit, and then extend the array with digits 5 and 6. Scroll all 6 digits across the 18 red LEDs.
  4. Enhance the previous step so that, rather than setting the LEDs back to all zeros, they keep going. When the 1 digit reaches the far left, it reappears on the right, but 2 through 6 continue shifting normally, so that 2 moves to the far left, and so on.

Quiz (1 Mark)

Be prepared to answer questions about the Altera Monitor Program, about the compilation process that happens underneath, and about the assembly language basics. The following are some of the things that you should know by the end of this lab: