1.1.1 - The fetch-decode-execute cycle

1.1.1 - The fetch-decode-execute cycle

Stored instructions cannot act until the processor retrieves and interprets them. You will trace the fetch-decode-execute cycle using addresses, register contents and bus transfers. Following a complete small program also shows why a branch can change which instruction is fetched next.

Fetching the next instruction

The fetch-decode-execute cycle is the repeating process through which a CPU obtains an instruction, determines its meaning and carries out its operation. The PC identifies the next instruction's address. Fetch copies the instruction from memory into the CIR so it remains available while the processor works on it.

We use a simple memory model in which each instruction occupies one address. Thus incrementing PC advances it by 1. On a byte-addressed processor with longer instructions the increment depends on instruction length; do not transfer the “plus 1” assumption to every machine.

Suppose PC = 16 and memory[16] contains LOAD 60. The fetch proceeds as follows:

StepTransfer or signalEffect
1Copy PC to MARMAR = 16
2Put MAR on address bus; CU issues read on control busMemory location 16 selected
3Memory returns contents on data bus to MDRMDR = LOAD 60
4Copy MDR to CIRCIR = LOAD 60
5Increment PC for the next sequential instructionPC = 17

Step 5 may be coordinated earlier during fetch in a stated implementation; its essential effect here is that the next sequential address is ready. Fetch does not yet load the contents of location 60 into ACC. It has obtained the instruction LOAD 60; the operand's memory access belongs to execution.

The distinction between instruction and data explains the two possible uses of MDR. During fetch it holds the instruction at address 16. Later, during execution, it may hold the data at address 60. Copying the instruction to CIR protects it from that reuse of MDR.

Decoding and executing an instruction

During decode, the control unit interprets the opcode and operand in CIR. It determines which operation and transfers the instruction requires. During execute, it issues the signals that cause those actions. The exact execution steps depend on the instruction; “execute” does not mean that every instruction uses the same register transfers.

Continue the fetched LOAD 60 example with memory[60] = 11. Decoding identifies a load from direct address 60. Execution places 60 in MAR, sends it on the address bus and requests a read on the control bus. The data bus returns 11 into MDR, then 11 is copied to ACC. CIR still holds LOAD 60, and PC remains 17. PC does not become 60 because 60 is a data address, not the next instruction address.

For ADD 61, with ACC = 11 and memory[61] = 4, execution reads location 61 through MAR and MDR. The ALU adds MDR's 4 to ACC's 11 and writes result 15 into ACC. For STORE 62, execution instead copies ACC's 15 to MDR, places 62 in MAR and requests a memory write. The data bus carries 15 towards memory. The result is memory[62] = 15; ACC can remain 15 in this model.

Register-transfer notation is a compact description of movement. MAR ← PC means “copy the contents of PC into MAR”; it does not erase PC. ACC ← ACC + MDR means that an addition produces the new ACC value. This is notation for the model's behaviour, not an instruction to execute in Python.

Tracing successive cycles

A reliable trace records the requested state at an explicit point in the cycle. “After fetch” and “after execution” can produce different MAR and MDR contents, even for the same instruction. Always state the convention before filling a table.

This complete original program starts at PC = 10, with ACC = 0. Each instruction occupies one address. Data are memory[50] = 3 and memory[51] = 8. LOAD, ADD and STORE have the direct-address meanings explained above. HALT stops processing and makes no additional data access.

Plain text
Address  Instruction
10       LOAD 50
11       ADD 51
12       STORE 52
13       HALT

The following table records state after execution of each instruction, including the PC increment that occurred during its fetch:

Executed instructionPCMARMDRCIRACCmemory[52]
LOAD 5011503LOAD 503unchanged
ADD 5112518ADD 5111unchanged
STORE 52135211STORE 521111
HALT1413HALTHALT1111

The first row's MAR is 50 because execution reused it for data. Immediately after that instruction's fetch it was 10. On the HALT row, MAR and MDR still show the final fetch: this instruction made no subsequent data access. Another machine could specify different HALT behaviour; the table is correct for the explicit model here.

Notice that PC points ahead while CIR identifies the current instruction. Replacing PC with the address of CIR in every row would hide the progression to the next fetch.

When execution changes the next address

A branch instruction changes the sequence by putting a target instruction address into PC. An unconditional branch always takes its target; a conditional branch does so only if its stated condition is met. It changes the next fetch, rather than moving the target instruction directly into CIR.

For this model, BRZ a branches to address a if ACC is zero and otherwise leaves the sequential PC unchanged. BRA a always branches to a. Neither instruction accesses data memory during execution. If instruction 20 is BRZ 28, fetch leaves CIR = BRZ 28 and PC = 21. With ACC = 0, execution replaces PC with 28; the next cycle copies 28 to MAR and fetches memory[28]. With ACC = 5, execution leaves PC = 21; the next cycle fetches memory[21]. The target 28 is an instruction address, unlike the data address in LOAD 28.

This reasoning also applies to a loop: a taken backward branch makes PC revisit an earlier instruction address. Without a changing state and an eventual exit condition the processor could repeat indefinitely. We do not need to run the code to trace the two possible outcomes; the complete condition determines them.