Level 59: Knight Rider RISC
Task
Goal: run the finale of the single-cycle line — the "Knight Rider" program: a running LED light through MMIO. No new instructions or schematics: the LED address 0xFFFF_F000 is built as lui x10, 0xFFFFF, and every sw x11, 0(x10) lights the runner bits and lands a line in the MMIO trace. The per-period sequence is 1,2,4,8,16,32,64,128,64,32,16,8,4,2,1 — repeat it twice and halt on LED = 1. LED is write-only (lw from it — ERR_WRITEONLY_READ), switches are read-only (sw — ERR_READONLY_WRITE). After passing the check, your level-58 core goes to the Tang Nano 9K board via the ZIP button.
The finale of the single-cycle line: the light runs across eight LEDs and back, as in the Knight Rider series. No new instructions and no schematics — this is a pure-programming level, and its program will travel to a real board.
The output goes through MMIO (memory-mapped I/O): peripherals live in the memory address space. The LED is address 0xFFFF_F000, write-only: an ordinary sw lights the runner bits, but reading from this address is forbidden (ERR_WRITEONLY_READ). The switches are 0xFFFF_F004, read-only: writing there gives ERR_READONLY_WRITE. Every sw to the LED lands a line in the MMIO trace — the check compares it pairwise.
Level tasks:
- Build the LED address.
0xFFFF_F000does not fit a 12-bit immediate — the upper half is built withlui x10, 0xFFFFF. - Lay down the header. The boundary
x13 = 128(the stop mask0x80) and the period counterx14 = 2. - Write the period. The
periodlabel: the lightx11 = 1; to the right (right) —sw,slli,bneuntil0x80; a separate0x80write; to the left (left) —srlidown to zero. The per-period sequence:1,2,4,8,16,32,64,128,64,32,16,8,4,2,1. - Repeat the period twice and halt on
.end— the LED must stay 1. - Run and compare. "Check" first asks for the number of MMIO trace writes — count it yourself: 15 per period × 2. After passing, the ZIP button packs your level-58 core into a Gowin project for the Tang Nano 9K.
Solution for self-check
First write the program yourself. The solution below gives the checkpoints.
What you should get: Knight Rider halts cleanly: 115 cycles, 30 MMIO trace records (15 per period × 2), the final LED = 1, registers x10 = 0xFFFF_F000, x11 = 1, x13 = 128, x14 = 0; after the check the core ships to the Tang Nano 9K via the ZIP button.
Step 1 — the address via lui. lui x10, 0xFFFFF: imm20 = 0xFFFFF lands in bits [31:12], the low bits are zeros. The result is exactly 0xFFFF_F000. A common mistake is assembling the address with addi — a 12-bit signed immediate cannot cover such a constant.
Step 2 — the golden program. Two periods on the x14 counter; inside a period the light x11 walks right with left shifts up to the 0x80 boundary and back with right shifts down to zero:
lui x10, 0xFFFFF # 0: LED base 0xFFFFF000
addi x13, x0, 128 # 4: 0x80, stop boundary
addi x14, x0, 2 # 8: period counter
period: addi x11, x0, 1 # 12
beq x14, x0, halt # 16
addi x14, x14, -1 # 20
right: sw x11, 0(x10) # 24
slli x11, x11, 1 # 28
bne x11, x13, right# 32 → 24
sw x11, 0(x10) # 36: 0x80
left: srli x11, x11, 1 # 40
beq x11, x0, period# 44 → 12
sw x11, 0(x10) # 48
beq x0, x0, left # 52 → 40
halt: .end # 56
Step 3 — the checkpoint numbers. The run: 115 instructions = 115 cycles; the .end halt at PC = 56 adds no cycle. The MMIO trace holds 30 writes: 15 per period (eight to the right, the 0x80 write, six to the left), two periods; the final LED = 1. The final registers: x10 = 0xFFFF_F000, x11 = 1, x13 = 128, x14 = 0. Delays (a pause between steps) are a student variant on top of the golden: an inner counting loop. The golden has no delays — for a deterministic trace length.
Step 4 — the MMIO contract. Probes on the reference runner: lw from 0xFFFF_F000 — ERR_WRITEONLY_READ (err 7) with a frozen state; sw to 0xFFFF_F004 — ERR_READONLY_WRITE (err 6); a misaligned sw to 0xFFFF_F002 — ERR_DATA_ADDRESS_MISALIGNED (err 1), the multiple-of-4 check runs before the MMIO decode. Reading the switches works: lw x6, 4(x10) with the switches at 0x01 returns 1 (a byte in the low bits, the upper bits zero).
Step 5 — the ZIP. After passing, the export button validates your saved level-58 core (parse, structural checks, schematic build) and packs an archive: 28 .v core files, the program in rtl/ROM.v, a clock divider down to ≈3 Hz, a wrapper with the clk/top_sw/top_led ports, CST pins and a Gowin project. The bitstream is not part of the archive — build it in Gowin EDA yourself. After flashing, the same code runs on a physical chip.
Check yourself
Why is sw at 0xFFFF_F002 an alignment error rather than a write to the LED?
The multiple-of-4 check runs before the MMIO decode: a misaligned address is caught as ERR_DATA_ADDRESS_MISALIGNED before the circuit even looks at which peripheral it points to. There is no such thing as a half write.