Nios II is a 32-bit RISC instruction set designed by Altera (now Intel) for soft-core processors that run on FPGAs. It’s the running example in Computer Architecture because it’s clean, simple, and small enough to learn end-to-end while still being a real architecture used in industry.

Every Nios II instruction is 32 bits wide, and memory is byte-addressable, so each instruction occupies 4 consecutive byte addresses. The PC increments by 4 between instructions in straight-line code.

Register file

32 general-purpose registers, each 32 bits wide:

RegisterConventionUse
r0zeroAlways reads as 0; writes ignored
r1atAssembler temporary (don’t use in hand-written code)
r2, r3return valuesReturn value(s) from subroutines
r4r7argumentsFirst four subroutine arguments
r8r15caller-savedFree for use; not preserved across calls
r16r23callee-savedFree, but must be preserved if used
r24etException temporary
r25btBreak temporary
r26gpGlobal pointer
r27spStack pointer
r28fpFrame pointer (optional)
r29eaException return address
r30baBreak return address
r31raReturn address (link register)

Plus a small set of control registers (status, estatus, ienable, ipending, etc.) for interrupts and processor state.

Notation

In Nios II’s Register transfer notation descriptions, the convention is uppercase R (so R2 ← [LOC] reads as “load contents of memory at LOC into r2”). In actual Nios II assembly source, registers are written lowercase: r2, r3, etc. This vault uses lowercase r0..r31 for Nios II–specific examples and uppercase R0..R31 for generic textbook RTN descriptions.

In assembly source, the operand order is dest, src1, src2:

add r3, r4, r5      # r3 ← r4 + r5
ldw r2, 0(r5)       # r2 ← memory[r5 + 0]

Comments start with # and run to end of line.

Instruction categories

For Computer Architecture the practical instruction subset breaks into:

Logical and shift instructions (and, or, xor, srli, etc.) round out the set but the four categories above cover most Computer Architecture work.

Assembly source structure

A typical Nios II program looks like:

.text                  # code section
.global _start

_start:
    movia r2, LIST     # load address of LIST
    ldw   r3, 0(r2)    # load first element
    addi  r3, r3, 1    # increment
    stw   r3, 0(r2)    # store back
    
    br _start          # loop forever (placeholder)

.data                  # data section
LIST: .word 10, 20, 30, 40

.text and .data are assembler directives — they tell the assembler what to do but don’t generate executable instructions themselves. .word reserves a 4-byte word with a given initial value.

For the design process behind a non-trivial program — partitioning into subroutines, choosing data structures, writing pseudocode first — see Subroutine design process.