Assembly language

  1. Write a RISC-V assembly language program that does the following:
  • Counts the number of button-press pairs received by the system; a push of the middle-most button on the development board should generate an interrupt; the system does not react to the first interrupt, but reacts to the second interrupt. The count sequence is also dependent upon whether the right-most switch is in the up or down position.
    If the switch is up, the count increments on the second button press
  • If the switch is down, the count decrements on the second button press
  • The count clamps at 25 and 0:
  • When counting up, the count stops at 25 and then only responds to the switch in the down position.
  • When counting down, the counter stops at O and then only responds to the switch being in the up position.
  • Use lead-zero blanking on the 7-segment display when appropriate
  1. Display your working hardware implementation to your instructor (or take a video and provide a link to the video in your lab submission).

I'm saving you some grunt work by including Figure 39, which provides the active low segment data for the values in the range [0,9]. Keep in mind that the anodes are also active low.

.data sseg:

.byte 0x03,0x9F, 0x25, 0x0D, 0x99, 0x49, 0x41,0x1F, 0x01,0x09 # LUT for 7-segs

When is our assignment due ?

1 Like

In 24 hours

And when is your assignment due ?

1 Like

Monday 11:59 PM

What have you written so far ?

1 Like

and your hope is that someone will do it for you?

1 Like

no i have some code but it doesn't seem to work

.data
sseg: .byte 0x03, 0x9F, 0x25, 0x0D, 0x99, 0x49, 0x41, 0x1F, 0x01, 0x09, 0xFF

.text
.global _start

_start:
    li x8, 0x1100C008        # anodes
    li x9, 0x1100C004        # segments
    li x10, 25               # Upper count
    li x11, 0                # Lower count
    la x13, sseg             # Load address of segment LUT
    li x18, 0                # Tens digit of the count
    li x19, 0                # Units digit of the count
    li x24, 1                # Enable external interrupts
    li x25, 0                # Button press counter
    li x26, 0                # Toggle 

main_loop:
    jal display_count
    
    addi x25, x25, 1         # Simulate button press
    bne x26, x25, skip_ISR   # If toggle flag doesn't match, skip ISR
    jal ISR                  # Call ISR for second press handling
    
skip_ISR:
    j main_loop

ISR:
    xori x26, x26, 1         # Toggle button press state
    li x28, 0x11008000       # Address for switches
    lw x28, 0(x28)           # Load switch state
    andi x28, x28, 1         # Mask right-most switch (LSB)
    beqz x28, count_down     # If switch is down, decrement
    
count_up:
    addi x19, x19, 1         # Increment units
    blt x19, x10, ISR_ret    # If units < 10, return
    addi x18, x18, 1         # Increment tens
    li x19, 0                # Reset units
    bge x18, x10, clamp_up   # If tens >= 25, clamp
    j ISR_ret

count_down:
    addi x19, x19, -1        # Decrement units
    bge x19, x11, ISR_ret    # If units >= 0, return
    addi x18, x18, -1        # Decrement tens
    li x19, 9                # Set units to 9
    blt x18, x11, clamp_down # If tens < 0, clamp
    j ISR_ret

clamp_up:
    li x18, 25               # Clamp tens at 25
    li x19, 0                # Clamp units at 0
    j ISR_ret

clamp_down:
    li x18, 0                # Clamp tens at 0
    li x19, 0                # Clamp units at 0

ISR_ret:
    ret

display_count:
    add x5, x13, x18         # Offset LUT for tens digit
    lbu x5, 0(x5)            # Load segment values for tens
    sb x5, 0(x9)             # Write to SEG register
    li x5, 0xB               # Select digit 1 (tens)
    sb x5, 0(x8)             # Write to AN register
    jal delay

    add x5, x13, x19         # Offset LUT for units digit
    lbu x5, 0(x5)            # Load segment values for units
    sb x5, 0(x9)             # Write to SEG register
    li x5, 0x7               # Select digit 0 (units)
    sb x5, 0(x8)             # Write to AN register
    jal delay

    ret

delay:
    li x6, 500000            # Arbitrary delay count
delay_loop:
    addi x6, x6, -1
    bnez x6, delay_loop
    ret

.data
sseg: .byte 0x03, 0x9F, 0x25, 0x0D, 0x99, 0x49, 0x41, 0x1F, 0x01, 0x09, 0xFF

.text
.global _start

_start:
    li x8, 0x1100C008        # anodes
    li x9, 0x1100C004        # segments
    li x10, 25               # Upper count
    li x11, 0                # Lower count
    la x13, sseg             # Load address of segment LUT
    li x18, 0                # Tens digit of the count
    li x19, 0                # Units digit of the count
    li x24, 1                # Enable external interrupts
    li x25, 0                # Button press counter
    li x26, 0                # Toggle 

main_loop:
    jal display_count
    
    addi x25, x25, 1         # Simulate button press
    bne x26, x25, skip_ISR   # If toggle flag doesn't match, skip ISR
    jal ISR                  # Call ISR for second press handling
    
skip_ISR:
    j main_loop

ISR:
    xori x26, x26, 1         # Toggle button press state
    li x28, 0x11008000       # Address for switches
    lw x28, 0(x28)           # Load switch state
    andi x28, x28, 1         # Mask right-most switch (LSB)
    beqz x28, count_down     # If switch is down, decrement
    
count_up:
    addi x19, x19, 1         # Increment units
    blt x19, x10, ISR_ret    # If units < 10, return
    addi x18, x18, 1         # Increment tens
    li x19, 0                # Reset units
    bge x18, x10, clamp_up   # If tens >= 25, clamp
    j ISR_ret

count_down:
    addi x19, x19, -1        # Decrement units
    bge x19, x11, ISR_ret    # If units >= 0, return
    addi x18, x18, -1        # Decrement tens
    li x19, 9                # Set units to 9
    blt x18, x11, clamp_down # If tens < 0, clamp
    j ISR_ret

clamp_up:
    li x18, 25               # Clamp tens at 25
    li x19, 0                # Clamp units at 0
    j ISR_ret

clamp_down:
    li x18, 0                # Clamp tens at 0
    li x19, 0                # Clamp units at 0

ISR_ret:
    ret

display_count:
    add x5, x13, x18         # Offset LUT for tens digit
    lbu x5, 0(x5)            # Load segment values for tens
    sb x5, 0(x9)             # Write to SEG register
    li x5, 0xB               # Select digit 1 (tens)
    sb x5, 0(x8)             # Write to AN register
    jal delay

    add x5, x13, x19         # Offset LUT for units digit
    lbu x5, 0(x5)            # Load segment values for units
    sb x5, 0(x9)             # Write to SEG register
    li x5, 0x7               # Select digit 0 (units)
    sb x5, 0(x8)             # Write to AN register
    jal delay

    ret

delay:
    li x6, 500000            # Arbitrary delay count
delay_loop:
    addi x6, x6, -1
    bnez x6, delay_loop
    ret

Did that code work when you wrote it in C? Can you share that code so it would be easier to confirm that your logic is correct and that you have correctly expressed it in RISC-V?

I see TOTB are making you use interrupts. With buttons. Which is considerably tricky.

I won't try to figure out your code, but such a simple thing as reading a digital input can be fraught. If, for example, you read the switch when it might still be bouncing.

Can you temporarily replace the switch input with a clean digital signal? My tools include debounced pushbuttons, which can be handy if anything is being blamed on bouncing.

a7

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.