Debugging decrement bugs

Posted on Thu 24 October 2024 in MUPS16

Since I added the hacked up display module, I've noticed an issue that's cropped up a few times. Since I haven't properly implemented reading the status register from the LCD controller yet, I've had to put small delay loops between character writes to avoid sending data too quickly. These are just a simple asm sequence:

.lcd_delay:
    liw   r1, 255
    addi  r1, r1, -1
    bnz   r1, .lcd_delay

This is very crude, but adds enough delay at the slow clock speed I'm running it right now. The problem is that sometimes, addi, r1, r1, -1 ends up adding some small number. I haven't worked out why.

Notes:

  • not 100% consistent, but happens often enough that we get stuck in infinite delay loops (i.e. once it starts happening it won't stop of its own accord)

  • first thought was bus contention on the data bus, but nothing obvious on the voltage levels of the data bus feeding back into the register unit

  • added collection of data, bus_a and bus_b on every step in debugger, and this shows the problem:

    0x00ea 01 3f  addi  r1, r1, -1
      Step 0  data: 0x0000 bus_a: 0x00ea bus_b: 0x0000      # Map address
      Step 1  data: 0x013f bus_a: 0x0000 bus_b: 0x0000      # Read instruction word
      Step 2  data: 0x00fb bus_a: 0x00fc bus_b: 0xffff      # r1 = r1 - 1
    0x00ec b9 fe  bnz   r1, -4
      Step 0  data: 0x0000 bus_a: 0x00ec bus_b: 0x0000      # Map address
      Step 1  data: 0xb9fe bus_a: 0x0000 bus_b: 0x0000      # Read instruction word
      Step 2  data: 0x0000 bus_a: 0x00fb bus_b: 0x0000      # Compare r1 == 0
      Step 3  data: 0x00ea bus_a: 0x00ee bus_b: 0xfffc      # Branch to 0xea if not
    0x00ea 01 3f  addi  r1, r1, -1
      Step 0  data: 0x0000 bus_a: 0x00ea bus_b: 0x0000      # Map address
      Step 1  data: 0x013f bus_a: 0x0000 bus_b: 0x0000      # Read instruction word
      Step 2  data: 0x00fd bus_a: 0x00fe bus_b: 0xffff      # r1 = r1 -1
    

    We add -1 to 0xfc and get 0xfb on the data bus (correct), and save that to r1. We then output r1 to bus_a in the bnz instruction, and that shows 0xfb (correct). We take the jump, but now when the register unit outputs r1 we see 0xfe. What happened? Somehow between step 2 of the bnz instruction and step 2 of the addi instruction we overwrote the contents of the register. At no point between those points did we see 0xfe on the data bus, so it doesn't feel like a transient set line going low or something like that.