Project 1 Getting Started with the ARM

Introduction to Vitis and the ARM assembly language



This initial project is intended to familiarize you with Xilinx’s Vitis design tool, the ARM Assembly language, and programming your Blackboard. Vitis is a full-featured integrated design environment (IDE) tool that contains an editor, assembler/compiler, linker, loader, debugger, and programmer – everything needed to create, process, download and analyze software for ZYNQ’s ARM processor. In the project requirements, you will write several small assembly programs that access some of Blackboard’s I/O devices, like switches and LEDs. Then in the challenges, you can test your knowledge, and solve some related problems.

After completing the project requirements and challenges, you must demonstrate your work to the lab assistant to receive credit. The assistant will assign points during your demo using the project submission form, and then the submission form must be turned in for credit. Take a few moments to familiarize yourself with the submissions policy, and print out the submission form before demonstrating your work to the assistant.

Before you begin, you should:

  • Have the Blackboard;
  • Have a recent PC with internet access;
  • Have an hour or two to get your design environment up and running.

After you’re done, you should:

  • Have the Xilinx Vitis tool installed and running;
  • Know how to set up a program in Vitis;
  • Know how to create an ARM aseembly language program;
  • Have a basic understanding of the ARM microprocessor.


This project introduces the ARM processing environment, the tools you will use to create ARM programs, and assembly language programming.

The ARM processor core used on the ZYNQ was designed by the ARM Corporation, but ARM does not produce chips – rather, they design and sell the “Intellection Property” (IP) that specifies the exact structural design of the processor. Manufacturing companies that make chips, like Apple, TI, AMD and many others purchase ARM’s IP and include it in their chip along with other IP blocks. ARM sells many different processor circuits – Xilinx uses the ARMv7-A processor on the ZYNQ device used on the Blackboard.

AMD’s ZYNQ device also includes an FPGA, and it is directly connected to the ARM using a high-speed AXI bus (more on the AXI bus later). In the Digital Logic course, we ignored the ARM and used AMD’s Vivado tool to design custom logic circuits for the FPGA; in this microprocessors course, we will use AMD’s Vitis tool to create custom software for the ARM.

Ideally, we’d like to ignore the FPGA in this class and only use the ARM. But many of the devices on the Blackboard are connected to FPGA I/O pins (and not to the ARM directly). For the ARM to access those devices, their signals must be passed through the FPGA, and so the FPGA must be configured every time the board is powered on. Further, the ARM must support a wide variety of external memory technologies that all have different signals, different timings, and different drivers, and the ARM system must be configurable so that it can work with any of them. Chip manufacturers (like Xilinx) include mechanisms to allow board designers (like Real Digital) to configure/program the ARM to work with the devices they choose. This ARM setup information is typically contained in an initialization file that must be written into internal registers each time the device is powered on. Real Digital has produced a setup file for the Blackboard, and this project demonstrates its use.

This project also introduces ARM assembly language programming. The ARM processor includes a large number of instructions, but most of them are variations of a relatively small number of “core” instructions. The topic documents provide some background on commonly used instructions and the ARM architecture. After working with these basic instructions, you can extend your knowledge by working directly with the ARM Architecture Reference Manual (see link below). Section A-8 provides detailed information for all possible ARM instructions. You will note that for every “core” instruction (for example, “ADD”), there are many sub-instructions (12 for ADD) that define different instruction encodings or other options. And further, each of these 12 sub-instructions have many conditional and addressing mode variations, so that many dozens of ADD instructions can be encoded. But they are all related, and once you understand a little about how the instructions are formed, you will come to realize the instruction set is actually straight-forward.


1. Setup Vitis, and verify the demo project

Follow the tutorial to create your first Vitis project:

TUTORIAL: Creating a new Vitis project

After successfully loading the tutorial’s demo project and verifying that the switches control the LEDs, you are ready to move on.

2. Negate the Signal from the Switches

Modify your program to turn the LEDs off when the switches are a 1, and on when they are a 0.


After loading the data from the switches, you will need to modify it (invert it) before writing the LED register. Examine the ARM instructions, and see if you can find an efficient instruction to do the inversion (there are several ways it can be done). Experiment a little, and try to find the best way!

3. Use Pushbuttons to Illuminate LEDs

Create a program to turn on the LEDs when pushbuttons are pressed.


Like the slide switches, the pushbuttons are also connected to the ARM through the FPGA, but they are accessed at a different address. Refer to the GPIO reference manual section to find the address of the correct register, and the bits within that register that must be modified. GPIO Programmers Reference

4.Use comparisons and branches to light an LED

By using branch and compare instructions, you can write programs that act differently under different conditions. The following program illuminates one of Blackboard’s LEDs if the value of the switches is less then 4. If the value is greater or equal to 4, the LED is turned off.

.global main

.equ LED_CTL, 0x41210000
.set SW_DATA, 0x41220000

	ldr r1,=SW_DATA	
	ldr r2,=LED_CTL	
	ldr r0,[r1]	@load switch value, (*r1) ->r0
	cmp r0,#4	@compare switch value with 4
	blt led_light	@branch to 'led_light' if sw val is less than 4
	mov r0,#0
	str r0,[r2]
	b loop		@go back to start of loop
	mov r0,#1
	str r0,[r2]	
	b loop		


Write a program that will illuminate the first LED if the value of the switches is equal to your age, and the second LED if all switches are ‘1’.

5.Use comparisons to control multiple LEDs

Treat the values from the first 4 switches as a binary number, and light up the first 4 LED’s individually if the number falls in a certain range: Light LED0 if the value of the switches is from 0 to 3; LED 1 if the value is between 4 and 7; LED 2 if the value is between 8 and 11; and LED 3 if the value is between 12 and 15. Only one LED should be lit at any time.

Hint: Reading the switch register returns the value of all 12 switches, but you are only interested in the first four switches. You need a way to check the binary value of only the first four switches. You could simply require that the upper eight switches are all set to 0, but requiring certain input states like this is generally considered bad practice, particularly when you can remove that requirment with some simple processing. In this case, you can simply “mask out” the higher switch values by ANDing the value in the switch regsiter with 0x0000000F. Is it clear why this works?


1. Control LED’s using both switches and buttons.

Treat the first four LED’s as a function of the first 4 switches and the four buttons, and light an LEDs when its corresponding switch or button is activated, but not when both are activated.

2. Use buttons to latch a binary value

Treat the first 8 switches as an 8-bit binary value, and ‘latch’ the value of the switches to an internal memory location when one of the buttons is pressed. Show the latched value on the first eight LEDs, and demonstrate that changing the switches does not change the LED value until the latch button is pressed again. Clear the value (set the value to zero) when a different button is pressed.

3. Have an LED toggle with a button press.

Make the first green LED turn on when the first button is pressed and turn off when the button is pressed again. The LED should not change state when the button is released or if the button is held down.

All done with the first module!

Print the submission form and demonstrate your work to the TA.