Assembly Language Code
Assembly Language Code
AIMS/OBJECTIVES:
The purpose of this exercise is to learn how to connect simple input and output devices to
an FPGA chip and implement a circuit via AMP and Nios2 assembly codes to instruct
these devices. We will use the 50 MHz on board clock and push buttons on the DE2-
series board as inputs and we will use light emitting diodes (LEDs) and 7-segment
2. THEORY:
The DE2-115 Media Computer includes a timer that can be used to measure various time
intervals. The interval timer is loaded with a preset value, and then counts down to zero using
the 50-MHz clock signal provided on the DE2-115 board. The programming interface for the
timer includes six 16-bit registers. The 16-bit register at address 0x10002000 provides status
information about the timer, and the register at address 0x10002004 allows control settings to be
The TO (timeout) bit is set to 1 when the internal counter reaches zero.
Once set by a timeout event, the TO bit stays set until explicitly cleared by a master
RUN is set to 1 by the timer whenever it is currently counting. Write operations to the
ITO is used for generating Nios II interrupts, which are discussed in section 3.
CONT affects the continuous operation of the timer. When the timer reaches a count
value of zero it automatically reloads the specified starting count value. If CONT is
set to 1, then the timer will continue counting down automatically. But if CONT = 0,
then the timer will stop after it has reached a count value of 0.
The two 16-bit registers at addresses 0x10002008 and 0x1000200C allow the period of the
timer to be changed by setting the starting count value. The default setting provided in the
DE2-115 Media Computer gives a timer period of 125 msec. To achieve this period, the
starting value of the count is 50 MHz x 125 msec = 6.25x106. It is possible to capture a
snapshot of the counter value at any time by performing a write to address 0x10002010. This
write operation causes the current 32-bit counter value to be stored into the two 16-bit timer
registers at addresses 0x10002010 and 0x10002014. These registers can then be read to
Push button work base upon a pulse, hence the button/s are program so that when they are
push they perform a specific task. There are 4 push buttons labelled KEY[0] through KEY[3] on
the board, but in the DE2 Media and Basic Computers, only three of them are usable. KEY[0] is
used as a reset for the Nios II processor, and thus not available to user programs. KEY[1]
through KEY[3] can be simultaneously read as the bits 1 to 3 of a memory-mapped register, and
corresponding bits in the Interrupt Mask Register and Edge Capture Register support the use of
interrupts. They are active high, so when a button is pressed its value is 1, and it is 0 otherwise.
The push buttons are relatively clean but still require debouncing.
The LEDs are use as indicators in this case, there are 18 red LEDs which can be set by
writing directly to the 18 least significant bits of the red LED register at 0x10000000, and
similarly there are 9 green LEDs at 0x10000010. Both of those locations are in fact 32-bits wide,
The next indictor that was used in this lab is the 7- segment display. The 7-segment displays
are configured as a two 32-bit registers. Each byte of each register directly controls the segments
of the corresponding displays, turning them on and off. Thus, it is necessary to provide some
decoding to display hexadecimal values on the displays. A1 is used to turn on a segment; 0 turns
it off.
3. EQUIPMENT:
Power cable
USB cable
4. METHOD:
Task 1
The program below starts counting from 0 up to 232 – 1, when a pushbutton (except KEY0) is
pressed. The count is advanced every one hundredth of a second (1/100 sec) via the use of the
internal 50 MHz onboard clock. The count is displayed on the 18 red LEDs, LEDR0-17.
.global _start
_start:
movia r23, 0x10002000 /* interval timer (onboard 50 MHz clock) base address */
movui r10, 10
/* monitor timeout signal to identify when the timer countdown ends (reach 0) */
WAIT_FOR_TO_SIGNAL:
br WAIT_FOR_TO_SIGNAL
1. Modify the code so that the counter starts counting only when KEY3 is pressed.
2. Modify the code so that the green LED directly above each pushbutton illuminates
3. Modify the code so that the counter advances every one second.
Task 2
1. Replace the instruction stwio r4, 0(r18) with the following lines of code and observe what
2. Modify the code so that output displayed on the red LEDs in 2.1 is also displayed on
HEX0.
3. Modify the code so that the count advances by one every second starting from 0000 up to
Task 3
Use the pushbuttons to add control to the operation of the counter as described below:
KEY3 - This button is used to trigger (start) the counter from an initial state of 0000,
resume counting after the counter has been paused and to restart the counter after a reset.
KEY2 - This button is used to stop/pause the counter holding the count currently being
pressed, your counter is reset to zero, irrespective of its current state, and should hold this
5. Observations:
When any of the push button are pressed the green LEDs directly above lit up.
The greater the count value the longer the timer value and the slower the red leds
transition.
When stwio r4, 0(r18) was replaced it was observed that a binary count of
6. CONCLUSION :
In this lab exercise the 50Mhz on the DE2-115 board was utilized. In manipulating the
clock on the board, the two 16-bit registers at addresses 0x10002008 and 0x1000200C
allow the period of the timer to be changed by setting the starting count value. The
starting count was calculated by finding the product of 50Mhz and 1sec which resulted in
a count of 50M
This value was then converted to two pairs of hexadecimal 02FA and F080 which
resulting in a 1 second transition of the timer. This count was then modified to counting
from 0-9 in binary which was then decoded to display on the hex display. This could then
be integrated to create so what of a stopwatch. This lab was a successful exercise as a full
understanding of how to utilize the 50Mhz on the DE2-115 board was obtain.
Appendix
1.1
.global _start
_start:
movia r23, 0x10002000 /* interval timer (onboard 50 MHz clock) base address */
movui r10, 10
stwio r2, 0(r19) #store what is in register r2 to r19 and which displays
/* monitor timeout signal to identify when the timer countdown ends (reach 0) */
WAIT_FOR_TO_SIGNAL:
beq r3, r0, WAIT_FOR_TO_SIGNAL /* wait until timer timeout (TO is set to 1) */
br WAIT_FOR_TO_SIGNAL
1.2
.global _start
_start:
movia r23, 0x10002000 /* interval timer (onboard 50 MHz clock) base address */
movui r10, 10
stwio r2, 0(r19) #store what is in register r2 to r19 and which displays
/* monitor timeout signal to identify when the timer countdown ends (reach 0) */
WAIT_FOR_TO_SIGNAL:
beq r3, r0, WAIT_FOR_TO_SIGNAL /* wait until timer timeout (TO is set to 1) */
br WAIT_FOR_TO_SIGNAL
1.3
ADDR_SSEGNUMS: .word 0x4F5B063F, 0x077D6D66, 0x6F7F
.global _start
_start:
/* monitor timeout signal to identify when the timer countdown ends (reach 0) */
WAIT_FOR_TO_SIGNAL:
ldhio r3, 0(r23) /* load status register */
andi r3, r3, 1 /* load timeout (TO) bit */
beq r3, r0, WAIT_FOR_TO_SIGNAL /* wait until timer timeout (TO is set to 1) */
/* monitor timeout signal to identify when the timer countdown ends (reach 0) */
WAIT_FOR_TO_SIGNAL:
ldhio r3, 0(r23) /* load status register */
andi r3, r3, 1 /* load timeout (TO) bit */
beq r3, r0, WAIT_FOR_TO_SIGNAL /* wait until timer timeout (TO is set to 1) */
.global _start
_start:
/* monitor timeout signal to identify when the timer countdown ends (reach 0) */
WAIT_FOR_TO_SIGNAL:
ldhio r3, 0(r23) /* load status register */
andi r3, r3, 1 /* load timeout (TO) bit */
beq r3, r0, WAIT_FOR_TO_SIGNAL /* wait until timer timeout (TO is set to 1) */
dis:
addi r7,r7,1
add r4, r4, r3 /* count number of timeouts */
divu r5, r4, r10 # register r10 is dividing register r4 and the result is stored in r5
mul r5, r5, r10 # register r10 is multiplying register r5 and the result stored in
r5
sub r5, r4, r5 # register r5 is now subtracting from r5 and result stored in r5
stwio r5, 0(r18) # this results in a binary count which is stored in the red LEDs
ldw r5,0(r17) #the content of register r17 which are word is loaded into r5
stwio r5, 0(r20) #the content of register r5 is being displayed in the hex0-3 display
addi r17, r17,4 #this shift between the pair of hexadecimals that should be
displayed on hex0-3
stwio r0, 0(r23) /* reset TO bit in status register */
beq r7,r11,reset
br WAIT_FOR_TO_SIGNAL
reset:
movia r17,ADDR_SSEGNUMS
movia r7,0
br dis
2.3
ADDR_SSEGNUMS: .word 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x67
Hex_2: .word
0x3f00,0x0600,0x5b00,0x4f00,0x6600,0x6d00,0x7d00,0x0700,0x7f00,0x06700,0x3f00
Hex_3: .word
0x3f0000,0x060000,0x5b0000,0x4f0000,0x660000,0x6d0000,0x7d0000,0x070000,0x7f0000,0x
670000,0x3f0000
Hex_4: .word
0x3f000000,0x06000000,0x5b000000,0x4f000000,0x66000000,0x6d000000,0x7d000000,0x07
000000,0x7f000000,0x67000000,0x3f000000
.global _start
_start:
/* monitor timeout signal to identify when the timer countdown ends (reach 0) */
WAIT_FOR_TO_SIGNAL:
ldhio r3, 0(r23) /* load status register */
andi r3, r3, 1 /* load timeout (TO) bit */
beq r3, r0, WAIT_FOR_TO_SIGNAL /* wait until timer timeout (TO is set to 1) */
dis:
movia r9,0
movia r12,0
ldw r9,0(r17)
or r12,r12,r9
ldw r9,0(r16)
or r12,r12,r9
ldw r9,0(r15)
or r12,r12,r9
ldw r9,0(r14)
or r12,r12,r9
stwio r12, 0(r20)
reset:
addi r24,r24,1
addi r16,r16,4
movia r17,ADDR_SSEGNUMS
movia r7,0
beq r24,r13,billz
br dis
billz:
addi r25,r25,1
movia r17,ADDR_SSEGNUMS
movia r16,Hex_2
movia r7,0
movia r24,0
addi r15,r15,4
beq r25,r13,gran
br dis
gran:
addi r26,r26,1
movia r17,ADDR_SSEGNUMS
movia r16,Hex_2
movia r15,Hex_3
movia r7,0
movia r24,0
movia r25,0
addi r14,r14,4
beq r26,r13,_start
br dis
3
ADDR_SSEGNUMS: .word 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x67
Hex_2: .word
0x3f00,0x0600,0x5b00,0x4f00,0x6600,0x6d00,0x7d00,0x0700,0x7f00,0x06700,0x3f00
Hex_3: .word
0x3f0000,0x060000,0x5b0000,0x4f0000,0x660000,0x6d0000,0x7d0000,0x070000,0x7f0000,0x
670000,0x3f0000
Hex_4: .word
0x3f000000,0x06000000,0x5b000000,0x4f000000,0x66000000,0x6d000000,0x7d000000,0x07
000000,0x7f000000,0x67000000,0x3f000000
.global _start
_start:
movia r28,0x04
movia r29,0x02
/* monitor timeout signal to identify when the timer countdown ends (reach 0) */
WAIT_FOR_TO_SIGNAL:
ldhio r3, 0(r23) /* load status register */
andi r3, r3, 1 /* load timeout (TO) bit */
beq r3, r0, WAIT_FOR_TO_SIGNAL /* wait until timer timeout (TO is set to 1) */
dis:
ldwio r2, 0(r22) /* load input from pushbuttons */
beq r2,r29,Key1
beq r2,r28,Key2
movia r2,0
movia r9,0
movia r12,0
ldw r9,0(r17)
or r12,r12,r9
ldw r9,0(r16)
or r12,r12,r9
ldw r9,0(r15)
or r12,r12,r9
ldw r9,0(r14)
or r12,r12,r9
stwio r12, 0(r20)
reset:
addi r24,r24,1
addi r16,r16,4
movia r17,ADDR_SSEGNUMS
movia r7,0
beq r24,r13,billz
br dis
billz:
addi r25,r25,1
movia r17,ADDR_SSEGNUMS
movia r16,Hex_2
movia r7,0
movia r24,0
addi r15,r15,4
beq r25,r13,gran
br dis
gran:
addi r26,r26,1
movia r17,ADDR_SSEGNUMS
movia r16,Hex_2
movia r15,Hex_3
movia r7,0
movia r24,0
movia r25,0
addi r14,r14,4
beq r26,r13,_start
br dis
Key1:
movia r2,0
br PRESS_A_KEY_TO_START
Key2:
movia r5,0x3f3f3f3f
stwio r5,0(r20)
movia r2,0
br _start