digiwleeaLearn
Open the lab →

Processor

Composing everything into a working 8-bit CPU: buses, multiplexers, decoders, registers, an ALU, RAM, a program counter, and the control unit that runs the fetch-decode-execute loop.

BusesMoving a whole byteA bus is just several wires carrying one bit each, grouped so they move a whole multi-bit number together. It is the notation and plumbing the rest of the CPU is built on.The multiplexerChoosing a signalA multiplexer is a data selector: a SEL input picks which of several data inputs is passed to the output. It is the switch that decides what travels on a bus, and you have already built one.DecodersOne-hot addressingA decoder turns a small binary address into one-hot select lines: exactly one output goes high, the one named by the address. It is how an address picks a single register or memory cell.Encoders and demultiplexersThe duals of the decoder and muxAn encoder is the reverse of a decoder: it turns a one-hot set of lines back into a binary address. A demultiplexer is the reverse of a multiplexer: it routes one input to one of several outputs chosen by a select code. Together with the decoder and mux they complete the data-routing toolkit.The priority encoderHighest request winsA priority encoder outputs the binary index of the highest-numbered active input even when several inputs are high at once, plus a 'valid' output that is 1 whenever any input is active. It fixes the wrong answer a plain encoder gives on non-one-hot inputs, which is why interrupt controllers use it.The seven-segment display decoderTurning a 4-bit digit into a numeralA seven-segment display decoder maps a 4-bit BCD digit (0 to 9) to seven segment outputs a to g, each lighting one bar of the numeral. It is a decoder built as seven boolean functions of the same four input bits, one per segment.An 8-bit registerStoring a whole byteAn 8-bit register is eight register bits sharing one clock and one write-enable. It loads a byte off the bus when enabled and holds it otherwise. It is the basic storage box of the CPU.Adding 8-bit numbersThe ripple-carry adderChain eight full adders, each carry feeding the next, and you can add two 8-bit numbers in one shot. This ripple-carry adder is the arithmetic core the ALU is built around.Negative numbers and subtractionTwo's complement, and one block that does bothTwo's complement lets the same 8 wires represent negatives, and makes subtraction into addition: to compute A - B, add A to the bit-flipped B and carry in 1. One XOR per bit turns the adder into an adder/subtractor.Overflow and the carry flagWhen the answer does not fitFixed-width arithmetic can produce a result too big for its bits. The carry flag catches that for unsigned numbers; the separate overflow flag catches it for signed two's-complement numbers, where adding two positives can wrongly land on a negative.The ALUThe arithmetic and logic coreAn ALU performs one of several operations on two bytes, chosen by a function code, and reports a zero flag. It bundles the adder/subtractor with bitwise logic behind a multiplexer: the CPU's compute unit.The accumulatorThe one register the machine computes intoThe accumulator is the single working register an accumulator-machine CPU (like the one this course builds) keeps its running result in, so ADD means add memory to the accumulator.Tri-state buffers and the shared busMany drivers, one wire, one at a timeA tri-state buffer can drive a wire high, drive it low, or let go entirely (high-Z). That third state is what lets many components take turns driving one shared bus, which is how a CPU moves data between blocks.The program counterCounting through addresses, and the counters behind itA counter steps through values on each clock. Ripple counters chain toggle flip-flops (simple, but the count settles with a cumulative delay); synchronous counters clock every bit together (bit k toggles when all lower bits are 1); a mod-N counter wraps after N states; and a program counter is a synchronous up-counter with a load path so it can also jump.The program counterThe register that points at the next instructionThe program counter is a register holding the address of the next instruction, incrementing each cycle so the CPU walks through memory in order, and loadable so a jump can redirect it.Synchronous countersOne shared clock, a count-enable chain, and clean cascadingA synchronous counter clocks every flip-flop from one common clock so all bits update on the same edge, and a count-enable AND chain toggles bit k only when the enable and every lower bit are 1. A ripple-carry-out cascades counters, a direction line makes it count up or down, and a decoded synchronous clear or load makes it count modulo N.Finite state machinesA circuit that steps through statesA finite state machine is a state register plus next-state logic: it sits in one of a fixed set of states and, each clock edge, moves to the next state decided by the current state and inputs. It is the pattern behind any controller, including the CPU's control unit.Designing a sequence detectorFSM design from a spec: Moore vs MealyDesigning a finite state machine from a word specification means drawing a state diagram, filling a state-transition and output table, encoding the states in flip-flops, and reading the next-state and output equations off the table. A Moore machine's output depends on the state alone; a Mealy machine's depends on the state and the current input.Algorithmic state machines (ASM charts)A flowchart notation for state machinesAn ASM chart is a flowchart-style notation for a finite state machine, built from a rectangular state box, a diamond decision box, and a rounded conditional-output box, where one ASM block is everything that happens in a single clock cycle. It is the bridge from a state diagram toward register-transfer-level coding.State minimization and encodingFewer states, and the codes you give themTwo refinements turn a rough state diagram into efficient hardware. Merging equivalent states (states no observer can tell apart) cuts the number of flip-flops, and the state assignment (the binary code you give each state) sets the cost of the next-state and output logic, where one-hot, binary, and Gray encodings trade flip-flop count against speed and glitches.Analyzing a sequential circuitReverse engineering: from an unknown netlist back to behaviorSequential analysis recovers an unknown clocked circuit's behavior: read each flip-flop's input equations off the gates, substitute them into the flip-flop's characteristic equation to get the next-state bits, build the state table, draw the state diagram, and describe what the machine does. It is finite-state-machine synthesis run backwards, the skill for reverse-engineering or verifying a design.Memory: RAMAddressable storage on a busRAM is a bank of registers plus an address decoder. The address selects one cell; a write stores the data bus into it, a read drives that cell's value back onto the bus through a tri-state. It is where a program and its data live.The register fileThe CPU's fast scratch storageA register file is a small array of registers with addressed read and write ports, so a datapath can read two source operands and write one result in the same clock cycle. It is built from registers, a decoder for the write port, and a multiplexer per read port, and it is the fast working storage a CPU computes on.Caches and the memory hierarchyKeeping the data you need within reachMain memory is far slower than the CPU, so processors keep a small, fast cache of recently and nearby-used data. The memory hierarchy stacks registers, cache levels, DRAM, and disk so that most accesses are served by a fast copy near the top, and locality is what makes that bet pay off.The instruction registerHolding and splitting an instructionThe instruction register latches the byte fetched from memory and holds it steady while the CPU acts on it, exposing it split into an opcode (what to do) and an operand (what to do it to).Machine codeInstructions as numbersA program is just bytes in memory. Each instruction byte splits into an opcode (what to do) and an operand (what to do it to). Defining that mapping is defining the instruction set.An opcode becomes control linesHow an instruction turns into actionThe control unit is a lookup table from opcode to the exact enable, load, and function lines to raise, so decoding an instruction just means picking the right row of signals.The control unitThe sequencer that pulls the leversThe control unit steps through micro-operations and raises the control lines that gate values onto the bus and enable loads. A ring counter provides the steps; the opcode chooses which lines fire on each step.Wiring blocks into a data pathFrom parts to a working circuitA datapath is registers and an ALU connected by a shared bus, where control lines decide which block drives the bus and which reads it each cycle.The datapathHanging the blocks on a shared busThe datapath is every storage and compute block wired to one shared bus, each gated on by a control line. Data flows from a source, through the ALU if needed, into a destination, one transfer per step.The control signal matrixOne row per instruction, one column per leverA control matrix is a table with one row per instruction and one column per control line; a 1 marks each line the instruction asserts, and filling it in completely specifies a hardwired control unit.FetchReading the next instruction from memoryThe fetch phase reads the byte at the program counter's address out of RAM into the instruction register, then increments the program counter, the first step of every instruction.DecodeSplitting the instruction and choosing what to doThe decode phase splits the fetched instruction into its opcode and operand and looks up which control lines that opcode needs, choosing what the execute phase will do.ExecuteDoing what the instruction saysThe execute phase raises the decoded control lines so the datapath actually performs the operation (load, add, or store) and the result lands where the opcode dictates.Fetch, decode, executeThe whole machine, running a programA CPU repeats one loop forever: fetch the next instruction from memory, decode its opcode, and execute it on the datapath. Those three steps, driven by the control unit's clock, are a working computer.MicrocodeControl lines stored as firmware, not gatesMicrocode replaces hardwired control logic with a small ROM whose words are the control-line settings, so the instruction set becomes reprogrammable firmware instead of fixed gates.Von Neumann vs HarvardOne memory or two?A von Neumann machine keeps instructions and data in one memory (simple, but they compete for one bus) while a Harvard machine splits them into two (faster, used in DSPs and caches).Virtual memoryGiving each program its own address spaceVirtual memory gives each program its own large address space that a page table maps onto the smaller physical RAM, with a TLB caching recent translations, so programs need not know where they really live.Memory-mapped I/OTalking to devices with LOAD and STOREMemory-mapped I/O wires a peripheral's registers to specific memory addresses, so the same LOAD and STORE instructions that touch RAM also read a sensor or drive an output.PipeliningOverlapping instructions for throughputA pipeline splits the datapath into stages separated by registers, so several instructions are in flight at once: while one decodes, the next is fetched. Throughput rises toward one instruction per cycle even though each instruction still takes several cycles end to end, as long as hazards between instructions are handled.Measuring CPU performanceThe iron law and Amdahl's lawA processor's runtime is the instruction count times the average cycles per instruction times the clock period. Every design choice moves one of those three terms, often at the expense of another, so clock speed alone is a poor measure, and Amdahl's law caps how much speeding up one part can help.Tracing a programFour instructions, step by stepHand-execute a tiny LOAD / ADD / STORE / HALT program on the accumulator CPU, following fetch-decode-execute and watching the registers change until it computes a sum.Assembly languageHuman-readable machine codeWriting programs as raw hex bytes is error-prone. Assembly language replaces each instruction byte with a short mnemonic (LOAD, ADD, STORE, HALT), and an assembler translates the mnemonics one-to-one back into the opcode bytes the CPU runs.Labels and dataNaming addresses so you don't count bytesHardcoding memory addresses is fragile: insert one instruction and every address shifts. A label names an address, and the assembler's symbol table fills in the real number, so you write LOAD x and reserve data with x: .byte 5.Writing a programA complete program, and the limit that grows the ISAPutting it together: a straight-line program that sums three numbers, assembled to bytes and traced to the answer. Then the honest limit, with only LOAD/ADD/STORE/HALT the machine runs top to bottom once and cannot loop or choose, which is exactly what a jump instruction adds.Addressing modesHow an instruction names its operandOur LOAD, ADD, and STORE always mean 'the operand is a memory address, read the value there,' which is called direct addressing. Real instruction sets add more rules: immediate (the value is in the instruction), indirect (the operand points to the address), and indexed (a base plus an offset, for arrays and loops). This lesson names our machine's single mode and honestly contrasts it with the modes x86, ARM, and RISC-V provide.