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:
| Step | Transfer or signal | Effect |
|---|---|---|
| 1 | Copy PC to MAR | MAR = 16 |
| 2 | Put MAR on address bus; CU issues read on control bus | Memory location 16 selected |
| 3 | Memory returns contents on data bus to MDR | MDR = LOAD 60 |
| 4 | Copy MDR to CIR | CIR = LOAD 60 |
| 5 | Increment PC for the next sequential instruction | PC = 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.
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 instruction | PC | MAR | MDR | CIR | ACC | memory[52] |
|---|---|---|---|---|---|---|
| LOAD 50 | 11 | 50 | 3 | LOAD 50 | 3 | unchanged |
| ADD 51 | 12 | 51 | 8 | ADD 51 | 11 | unchanged |
| STORE 52 | 13 | 52 | 11 | STORE 52 | 11 | 11 |
| HALT | 14 | 13 | HALT | HALT | 11 | 11 |
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.