Chapter Twenty-Three

CPU Control Signals

An old adage commonly heard in engineering circles contends that the last 10% of a project requires 90% of the work. Regardless how distressing this idea might seem, it’s something to keep in mind. We’ve already made great progress in constructing a computer, but we’re not yet finished. What’s left isn’t quite 90% of the work, but the home stretch might be a little further away than it seems.

The central processing unit (CPU) that I’ve been designing is based on the Intel 8080 microprocessor. The arithmetic logic unit (ALU) and the register array shown in the previous two chapters constitute major parts of this CPU. The ALU performs arithmetic and logic operations on bytes. The register array contains latches for seven registers identified by the letters A, B, C, D, E, H, and L. You’ve also seen that three additional latches are required for saving the instruction byte and the one or two additional bytes that follow some instructions.

These components are connected to each other and to random access memory (RAM) through two data busses: an 8-bit data bus that ferries bytes among the components, and a 16-bit address bus used for a memory address. In the previous chapter, you’ve also seen a program counter that maintains an address for this RAM and an incrementer-decrementer that increments and decrements a 16-bit memory address.

The two busses provide the main source of connection between these components, but the components are also connected with a more complex collection of control signals, so called because they control these components to work together in executing instructions stored in memory.

Most of these control signals are of two general types:

· Signals that put a value on one of the two busses

· Signals that save a value from one of the two busses

This chapter is all about values getting on the bus and off the bus.

Signals that put a value on the bus are attached to the Enable inputs of various tri-state buffers that connect the outputs of the components to the bus. Signals that save a value from the bus usually control the Clock inputs of the various latches that connect the busses to the components on the bus. The only exception is when a value on the data bus is saved to memory using the RAM Write signal.

The synchronization of these signals is what allows the CPU to execute instructions stored in memory. This is how 8-bit and 16-bit values move among the CPU components and memory. This is the fundamental way in which codes stored in memory control the hardware of the computer. This is how hardware and software are united, as alluded to in the title of this book. You might visualize this process as a puppeteer controlling a troupe of marionettes in an exquisitely choreographed dance of arithmetic and logic. The CPU control signals are the strings.

Here are the six major components showing how they are connected to the data bus and address bus, and the control signals that they require.

The Address input of memory is connected to the 16-bit address bus. Memory is also connected to the 8-bit data bus through its Data In inputs and Data Out outputs:

A 64-by-8 array of random-access memory showing the address, data in, data out, and the write and enable control signals.

The two control signals are Write, which writes the value on the data bus into memory, and Enable, which enables the tri-state buffer on the RAM Data Out so that the contents appear on the data bus. A control panel might be attached to this memory array to allow a human being to write bytes into memory and examine them.

The most complex component is undoubtedly the register array from Chapter 22, which you’ll sometimes see abbreviated as RA:

The register array is connected to the data bus and address bus and contains many control signals.

The register array has two sets of Select inputs shown at the top. The SI signals determine which register saves the value on the data bus. The RA Clock signal at the left determines when that value is saved. The SO signals together with the RA Enable signal at the left put the value of one of registers on the data bus.

As you saw in the previous chapter, this register array is complicated in two ways. First, it must implement two additional control signals for the accumulator, which will sometimes be abbreviated Acc: The Accumulator Clock signal saves the value on the data bus in the accumulator, and the Accumulator Enable signal enables a tri-state buffer to put the value of the accumulator on the data bus.

Second, the H and L registers of the register array are also connected to the address bus in accordance with the three control signals shown at the right: HL Select selects the address bus as inputs to the H and L registers, HL Clock saves the contents of the address bus in the H and L registers, and HL Enable enables a tri-state buffer to put the contents of the H and L registers on the address bus.

The ALU from Chapter 21 has F0, F1, and F2 inputs that control whether the ALU performs an addition, subtraction, compare, or logical function:

The arithmetic logic unit is connected to both the register array and the data bus for performing arithmetic and logical operations.

Notice that the B input and the Out output of the ALU are both connected to the data bus, but the A input is connected directly to the Acc output of the register array. The ALU is complicated somewhat by the necessity of saving the Carry flag (CY), the Zero flag (Z), and the Sign flag (S) that are set based on the arithmetic or logical operation being performed.

The ALU also implements a Clock signal that saves the result of the arithmetic or logic operation in a latch (and saves the flags in another latch), and an Enable signal that enables the tri-state buffer to put the ALU result on the data bus.

Another 16-bit latch holds the current value of the program counter, which is used to address bytes in memory:

The program counter is connected to the address bus and has two control signals.

The program counter is sometimes abbreviated PC. It has three control signals: The Clock signal saves the 16-bit value on the address bus in the latch. The Enable signal enables a tri-state buffer to put the contents of the latch on the address bus. The Reset signal at the left sets the contents of the latch to all zeros to begin accessing bytes from memory at the address 0000h.

Three additional 8-bit latches save up to 3 bytes of an instruction. These are packaged in the following box:

The Instruction Latch saves three bytes that make up an instruction.

Some instructions simply consist of an operation code. Others are followed by 1 or 2 additional bytes. The three Clock signals at the left save up to 3 bytes that make up an instruction.

The first byte is also the operation code, often called the opcode. If the instruction has a second byte, that byte can be enabled on the data bus with the Latch 2 Enable signal at the right. If the operation code is followed by 2 bytes, those constitute a 16-bit memory address, and it can be put on the address bus by the Latches 2 & 3 Enable signal at the right.

The final component is a circuit that can increment or decrement a 16-bit value. This will sometimes be abbreviated Inc-Dec:

The incrementer-decrementer is attached to the address bus and has one clock signal but to enable signals to provide the incremented or decremented value.

The Clock signal saves the value from the address bus in the Incrementer-Decrementer latch. The two Enable signals at the right enable either the incremented or decremented value on the address bus.

To give you a little feel for how these various control signals must be coordinated, let’s consider a little 8080 program containing just six instructions. Some of the instructions are just a single byte, while others require 1 or 2 additional bytes following the operation code:

Short program to illustrate CPU execution of instructions

This program doesn’t do much. The first instruction moves the value 27h into register A, also known as the accumulator. The MOV instruction then copies that value to register B. The value 61h is added to the accumulator, which then contains the value 88h. The value in register B is then added to that, bringing the value up to AFh. The STA instruction stores that value in memory at the address 000Ah. The HLT instruction halts the CPU because there’s nothing left to be done in this program.

Let’s ponder what the CPU needs to do to execute these instructions. The CPU uses a value called the program counter to address memory and move the instructions into the instruction latches. The program counter is initialized to the value 0000h to access the first instruction from memory. That instruction is MVI, or Move Immediate, which is intended to move the value 27h into the accumulator.

A sequence of five steps is required to process that first instruction. Each step involves putting something on the address bus and saving it elsewhere, or putting something on the data bus and saving it elsewhere, or both.

The first step is to address RAM with the program counter value of 0000h and store the value 3Eh from memory in Instruction Latch 1. This requires four control signals involving both the address bus and data bus:

· Program Counter Enable: Puts the program counter on the address bus. That value is 0000h.

· RAM Data Out Enable: Puts the value of RAM at that address on the data bus. That value is 3Eh.

· Incrementer-Decrementer Clock: Saves the value on the address bus in the incrementer-decrementer.

· Instruction Latch 1 Clock: Saves the value on the data bus in Instruction Latch 1.

The second step increments the program counter. This involves just the address bus:

· Increment Enable: Puts the incremented value of the incrementer-decrementer on the address bus. That value is now 0001h.

· Program Counter Clock: Saves that incremented value in the program counter.

Now that the first instruction byte has been saved in Instruction Latch 1, it can be used to control subsequent steps. In this case, the third and fourth steps are the same as the first and second steps except that they access the byte at memory address 0001h and save it in Instruction Latch 2.

These steps that read instruction bytes from memory are called the instruction fetch. They have the purpose of accessing instruction bytes from memory and storing them in the instruction latches. For the instruction MVI 27h, the value 27h is now in Instruction Latch 2. That value must be moved into the accumulator. This is the fifth step, which is termed the execution of the instruction:

· Instruction Latch 2 Enable: Puts the value of that latch on the data bus.

· Accumulator Clock: Saves the value on the data bus in the accumulator.

Notice that all five of these steps involve at most just one value on the address bus and one value on the data bus. Any value put on one of the two busses is then saved elsewhere.

Now it’s on to the second instruction, which is MOV B,A. Because this instruction is only 1 byte in length, only two steps are required for the instruction fetch. The execution step is:

· Register Array Enable: Puts the value in the register array on the data bus.

· Register Array Clock: Saves the value on the data bus in the register array.

Wait a minute! The description of this execution step mentions only the register array, and not registers A and B, which is what this step requires! Why is that?

It’s simple: The bits that compose the 8080 MOV instructions are of the form

images

where DDD is the destination register and SSS is the source register. The operation code has been saved in Instruction Latch 1. The register array has two sets of 3-bit Select signals that determine which register is the source and which is the destination. As you’ll see, these signals come from the opcode stored in Instruction Latch 1, so it’s only necessary to enable the register array and latch the register array to complete the execution.

An Add Immediate instruction comes next:

ADI 61h

This is one of eight similar instructions of the form

images

where FFF refers to the function that the instruction performs: Add, Add with Carry, Subtract, Subtract with Borrow, AND, XOR, OR, or Compare. You’ll recall that the ALU has a 3-bit Function input corresponding to these values. This means that the three function bits from the opcode in Instruction Latch 1 can be directly routed to the ALU.

After the 2 bytes of the ADI instruction are fetched, the execution of the instruction requires two more steps. Here’s the first:

· Instruction Latch 2 Enable: Puts the value 61h on the data bus.

· ALU Clock: Saves the ALU result and flags in latches.

A second execution step is required to move that result into the accumulator:

· ALU Enable: Puts the ALU result on the data bus.

· Accumulator Clock: Saves that value in the accumulator.

The ADD instruction that comes next similarly requires two execution steps. The first is:

· Register Array Enable: Puts register B on the data bus.

· ALU Clock: Saves the result of the addition and the flags.

The second execution step is the same as the execution of the ADI instruction.

The STA instruction requires six steps for the instruction fetch. The 2 bytes following the STA instruction are stored in Instruction Latches 2 and 3. The execution step requires the following control signals:

· Instruction Latches 2 & 3 Enable: Puts the second and third instruction bytes on the address bus to address RAM.

· Accumulator Enable: Puts the value of the accumulator on the data bus.

· RAM Write: Writes the value on the data bus into memory.

The HLT instruction does something unique, which is stop the CPU from executing further instructions. I’ll save the implementation of that for later in this chapter.

These steps that I’ve been describing are also called cycles, much like the wash, rinse, and spin cycles of a washing machine. More technically, they are referred to as machine cycles. In the CPU that I’m building, instruction bytes are accessed from memory in one cycle that is always followed by another cycle that increments the program counter. Thus, depending on whether the instruction has 1, 2, or 3 bytes, the CPU must execute two, four, or six cycles.

Instruction execution requires one or two machine cycles, depending on the instruction being executed. Here’s a table showing what must occur during the first execution cycle of all the instructions that I’ve introduced so far:

First Execution Cycle

A table showing the first execution cycle of all the instructions introduced so far.

Notice the ellipses (…) in the first column of three rows. The rows with the ADD instruction also include ADC, SUB, SBB, ANA, XRA, ORA, and CMP; the row with ADI also includes ACI, SUI, SBI, ANI, XRI, ORI, and CPI.

The bottom four lines of that table are instructions that also require a second execution cycle. The following table shows what must occur during these second execution cycles:

Second Execution Cycle

A table showing the second execution cycle for all the instructions introduced so far that require a second execution cycle.

To accomplish all this, the operation code must be decoded and turned into control signals that manipulate all these components and the RAM. These control signals enable the tri-state buffers, the Clock inputs of the various latches, the Write input of the RAM, and a few other inputs.

The remainder of this chapter will show you how this is done. It’s a process that requires several steps and a couple of different strategies.

Here’s a table of the operation codes for all these instructions:

A table showing the operation codes for all the instruction presented so far.

You’ll recall that the SSS and DDD sequences in these operation codes refer to a particular source or destination register, as shown in this table:

A table showing how three-bit source and destination codes in the operation codes refer to registers.

The bit sequence 110 is missing from this list because that sequence refers to memory addressed by the HL registers.

For the arithmetic and logic instruction, the FFF bits stand for function and refer to one of eight arithmetic or logical operations.

One easy part of the CPU control circuitry is a simple connection between Instruction Latch 1 and the Input Select and Output Select of the register array, and the Function Select of the ALU:

A circuit showing Instruction Latch 1 and how bits are used for the Input Select and Output select of the Register Array, and the Function Select of the ALU.

The C stands for “code.” The output bits C0, C1, and C2 of this latch go directly to the Input Select of the register array, while bits C3, C4, and C5 go to the Output Select of the register array and the Function Select of the ALU. This is one way to take advantage of the patterns in the operation codes.

You might see some other patterns in the opcodes: All the operation codes beginning with 01 are MOV instructions except for 76h, which is the HLT instruction. All the arithmetic and logic instructions (except for the immediate variations such as ADI, ACI, and so forth) begin with the bits 10.

A first step of decoding the opcode is to connect the output bits of Instruction Latch 1 shown previously above to three decoders: one 2-to-4 decoder and two 3-to-8 decoders. These are used to generate additional signals, some of which correspond directly to instructions, and some of which correspond to groups of instructions:

A circuit showing the preliminary steps in identifying instructions based on the operation code.

The Move Group signal at the top right corresponds to instructions that begin with the bits 01, while the Arithmetic/Logic Group signal corresponds to instructions that begin with the bits 10.

It’s important to distinguish MOV instructions that involve moving bytes between registers from those that move values between registers and memory. These memory instructions are identified with source and destination values of 110. The Memory Source and Memory Destination signals in the previous circuit indicate when the source and destination bits are 110. Finally, the Move Immediates are those instructions that begin with 00 and end with 110.

Those five signals at the top right of the circuit diagram are further decoded here:

A circuit showing how Move and Arithmetic instructions that access memory are distinguished from those that involve only registers.

Now every instruction or group of similar instructions is represented by a signal. These signals are available when the operation code is saved in Instruction Latch 1, and they can be used in additional ways to govern the processing of that instruction.

The opcode must next be used to determine how many additional instruction bytes must be fetched from memory and how many machine cycles are required for executing the instruction:

A circuit that identifies which instructions require two or three byte fetch operations, and which require two cycles for execution.

What happens if an opcode doesn’t correspond to any of these instructions? For example, I haven’t yet mentioned a peculiar 8080 instruction called NOP, pronounced “no op” for “no operation,” and which has an opcode of 00h.

You’ll notice that if none of these input signals at the left is 1, then the outputs of the OR gates are all 0, and the signals at the right indicate a 1-byte fetch and a one-cycle execute.

The basic timing of the CPU is established by an enhanced version of a little circuit you first encountered on page 296 in Chapter 20:

The basic timing circuit for the CPU includes inputs for Reset and Halt.

The oscillator at the left is a device that outputs a signal that alternates between 0 and 1, generally very quickly. This is what makes the CPU run. It’s like the CPU’s heartbeat.

The Reset signal shown at the top comes from outside the CPU. It is usually controlled by the person using the computer to start the CPU over from the beginning. Normally, the Reset signal is 0, but when it’s 1 (for example when a person presses a button labeled Reset), the CPU stops and everything goes back to the beginning.

In this circuit, the Reset signal resets the three flip-flops so that all the Q outputs are 0 and all the Q outputs are 1. When the Reset signal goes back to 0, the flip-flops are allowed to work normally, and the CPU begins running.

After the CPU is reset, the Q output of the flip-flop at the top is 1. It’s one of two inputs to an AND gate that allows the oscillator to control the Clock inputs of the two flip-flop toward the bottom of the diagram.

The Halt signal at the top indicates that a HLT instruction has been executed. This causes the Q output of the flip-flop at the top to become 0, which effectively stops the oscillator from controlling the CPU. The CPU can be “unhalted” with a Reset signal.

If the CPU has not been halted, the two flip-flops at the bottom of the diagram generate two signals labeled Cycle Clock and Pulse, which are shown in this timing diagram:

A timing diagram showing the relationship between the Cycle Clock and the Pulse signal.

Each cycle of the Cycle Clock corresponds to a machine cycle. Every time the Cycle Clock goes from low to high (from 0 to 1), a new machine cycle occurs.

For example, in the little example program shown earlier, the first instruction is a Move Immediate, or MVI. This instruction requires five machine cycles:

· Fetch the opcode.

· Increment the program counter.

· Fetch the byte following the opcode.

· Increment the program counter.

· Execute the instruction.

Here are those five cycles, identified with somewhat abbreviated labels:

A timing diagram showing the fetch cycles and the execute cycle for the Move Immediate instruction.

All these cycles are associated with different tri-state buffers being enabled, which causes different values to be on the address bus and data bus. During the Fetch 1 cycle, for example, the program counter is enabled on the address bus, and the RAM Data Out is enabled on the data bus. The Pulse signal is used to control the Clock input on the Instruction Byte 1 latch, and the Clock input on the incrementer-decrementer.

During the PC increment cycle, the incrementer-decrementer output is on the address bus, and the Pulse signal is used to save that incremented value in the program counter.

Earlier you saw a circuit that indicated whether an instruction consisted of 1, 2, or 3 bytes, and whether an instruction requires just one cycle to execute or two cycles.

The next step in decoding the opcode is to generate signals that indicate the type of cycle currently in effect—whether it’s the first, second, or third fetch cycle, a PC increment cycle, or the first or second execution cycle.

This job is handled by the following rather complex circuit:

A circuit that indicates the type of cycle being performed.

The inputs are on the left, and the outputs are on the right. These inputs and outputs sometimes have similar names, so this diagram might be a little confusing at first! For example, the “2-Byte Fetch” input indicates that the instruction is 2 bytes in length. The “Fetch Cycle 2” output indicates that the second byte of the instruction is currently being fetched.

The Reset signal at the top is the same as the Reset signal in the previous circuit; this is initiated by a person using the CPU to start it from the beginning. In addition, the 4-Bit Counter can also be reset from a signal at the bottom of the circuit.

The Cycle Clock advances the counter. Because this is a 4-bit counter, it can count from binary 0000 to 1111, which is decimal 0 to 15. These outputs go directly to a 4-to-16 decoder below the counter. The binary number from the counter is decoded into potentially 16 different sequential outputs, but this circuit uses only the first 9. Each of these outputs indicates a new machine cycle, whether it be a fetch cycle, a program counter increment cycle (which is abbreviated “PC Increment” in the diagram), or an execution cycle.

As the decoder outputs advance through 0, 1, 2, 3, and so forth, the following signals are generated:

1. 0. Fetch Cycle 1

2. 1. Program Counter Increment

3. 2. Fetch Cycle 2 but only if the instruction is not a 1-byte fetch

4. 3. Program Counter Increment for a 2-byte or 3-byte fetch

5. 4. Fetch Cycle 3 but only if the 3-Byte Fetch signal is 1

6. 5. Program Counter Increment for a 3-byte fetch

The Fetch Cycle 1 signal and the first Program Counter Increment signal are always generated. After that, the opcode has been fetched, loaded into Instruction Latch 1, and partially decoded, so all the input signals at the left of the diagram are available.

At most, an instruction requires three fetch cycles, each of which is followed by a PC increment cycle and two execution cycles, for a total of 8, corresponding to the decoder outputs 0 through 7.

The logic is messy to account for combinations of multibyte fetches and multiple execution cycles. For example, the Execution Cycle 1 signal at the right can be the third cycle for instructions that require a 1-byte fetch, or the fifth cycle for instructions that require a 2-byte fetch, or the seventh cycle for instructions that require a 3-byte fetch.

The reset logic at the bottom is the most complex. It can occur as early as the fourth cycle for an instruction that requires one fetch cycle and one execution cycle, or the ninth cycle for an instruction that requires three fetch cycles and two execution cycles.

During the three fetch cycles, the program counter is enabled on the 16-bit bus, and the RAM Data Out is enabled on the 8-bit bus. The Pulse signal stores the value on the address bus in the incrementer-decrementer and the value on the data bus in one of the three instruction latches. This is the purpose of the following circuit, which generates all the signals for instruction fetch cycles (but not PC increment cycles):

A circuit to generate all the signals for instruction fetch cycles and Program Counter increment cycles.

Regardless whether it’s the first, second, or third fetch, the program counter is enabled on the address bus and the RAM Data Out on the data bus. In all three cases, the Pulse signal always controls the Clock input on the Incrementer-Decrementer latch. For the three fetch cycles, the Pulse signal also controls the clock on the corresponding instruction latch.

Notice the tri-state buffers on two of these signals. That’s because other circuits (coming up) might also be controlling the Enable signal on the RAM Data Out tri-state buffer, and the Clock signal on the Incrementer-Decrementer latch. The signal at the left of the tri-state buffer is both the input and the Enable signal.

The signals required for the PC increment cycle are handled entirely by this circuit:

A circuit to generate the two signals required for Program Counter increment cycles.

All the signals for the instruction fetch cycles, and the PC increment cycles have now been created. All that’s left are the signals for the execution cycles. These are more complex because they depend on the particular instruction being executed.

The big circuit on page 370 has two output signals labeled Exec. Cycle 1 and Exec. Cycle 2. These two execute cycles can be abbreviated EC1 and EC2, as shown in the following circuit:

A circuit that combines the Pulse signal with the two Execution Cycle signals to generate two Execution Pulse signals.

These two signals are combined with the Pulse signal for two additional Execute Pulse signals that are abbreviated EP1 and EP2.

One instruction is handled rather simply. This is the HLT instruction, which halts the CPU:

A circuit to generate a Halt signal.

The HLT signal at the left comes from the instruction decoder on page 367; the Halt signal at the right goes to the circuit with the oscillator on page 368.

The relationship between the other instructions and the corresponding signals that must be generated is rather complex, so it’s best to avoid a lot of messy logic gates and instead handle them with a few diode ROM matrices, such as those that you saw in Chapter 18.

This first diode ROM matrix handles all the Enable and Clock signals in connection with the 16-bit address bus, for both the first and second execution cycles:

Diode ROM Matrix for all the control signals for the address bus.

Keep in mind that the signals at the bottom are for the address bus only. You’ll see the signals for the 8-bit data bus shortly. This diagram corresponds to the 16-Bit Address Bus heading in the tables on pages 363 and 364.

That tri-state buffer on the bottom left of the diagram is enabled by the Execution Cycle 1 signal. This governs the value on the address bus during the first execution cycle. For all the MOV, MVI, and arithmetic instructions involving memory addressed with the HL registers, that’s the HL register.

In addition, the HL register is enabled for the INX and DCX instructions. These are the instructions that increment and decrement the HL register. For the LDA and STA instructions, however, the memory address for loading or storing a byte is obtained from Instruction Latches 2 and 3.

In the case of the INX and DCX instructions, the Execution Pulse 1 signal saves the value of the HL registers in the incrementer-decrementer latch.

The INX and DCX instructions are the only two instructions that involve the address bus during the second execution cycle. These two instructions cause the incremented or decremented value of the HL register to be on the address bus. The Execution Pulse 2 signal then causes the new value of HL to be saved in the H and L registers.

The diode ROM matrix for the 8-bit data bus is a little more complicated. I’ve divided it into two diagrams corresponding to the two instruction cycles. Here’s the first instruction cycle:

The diode ROM matrix for the 8-bit data bus during the first execution cycle.

This circuit is the realization of the 8-Bit Data Bus column in the table on page 363. The two tri-state buffers at the bottom are enabled by the Execution Cycle 1 and Execution Pulse 1 signals. The first tri-state buffer controls what’s on the data bus; the second tri-state buffer controls where that value is stored.

The three types of MOV instructions at the top are followed by a destination and a source. These destinations and sources can be any one of the registers, or they can be memory addressed by the HL registers. When the source is a register, the register array (abbreviated RA in the diagram) is enabled on the data bus; when the source is memory, the Data Out of the RAM is enabled. (Keep in mind that the RAM is addressed by the 16-bit bus during this time, and the diode ROM matrix for the address bus sets that value to the HL registers.) When the destination is a register, the second tri-state buffer controls the Clock input for the register array. When the destination is memory, the RAM Write signal saves that value in memory.

For the two types of MVI (“move immediate”) instructions, the contents of Instruction Latch 2 are enabled on the data bus; that value is either stored in the register array or saved in memory.

All the arithmetic and logic instructions are represented in this diagram by the ADD and ADI (“add immediate”) instructions. The value enabled on the data bus is either the register array, RAM Data Out, or Instruction Latch 2, depending on the instruction. In all cases, that value is latched in the arithmetic logic unit. These instructions require additional work during the second execution cycle, which you’ll see shortly.

For the LDA (“load accumulator”) and STA (“store accumulator”) instructions, the diode ROM matrix for the address bus ensures that the RAM is addressed by the contents of Instruction Latches 2 and 3. For LDA, the RAM Data Out is enabled on the data bus, and that value is stored in the accumulator. For the STA instruction, the accumulator is enabled on the data bus, and that value is stored in memory.

The arithmetic and logic instructions require a second execution cycle involving the data bus. The diode ROM matrix for these cases is much simpler than the others:

The diode ROM matrix for the 8-bit data bus during the second execution cycle.

For these instructions, the value from the ALU is enabled on the data bus, and that value must be saved in the accumulator, as also shown in the 8-Bit Data Bus column in the table on page 364.

Images

With that, the subset of the 8080 microprocessor that I’ve been constructing over the past three chapters is complete, and a working simulation is available on the CodeHiddenLanguage.com website.

Engineers who design computers often spend a great deal of time trying to make those computers as fast as possible. Different designs of the digital logic circuits might be faster or slower than others. It is very often the case that making a digital circuit faster requires adding more logic gates.

If I wanted to speed up the CPU that I’ve been describing, I would first focus on the instruction fetches. Each instruction fetch requires a second machine cycle that has the sole purpose of incrementing the program counter. I would try to incorporate that logic in the instruction fetch cycle itself to do these two things simultaneously. It probably involves a dedicated incrementer. This improvement would reduce the time required for loading instructions from memory by half!

Even little changes have great benefits. If you were designing a CPU that might be used in millions of computers, each of which is potentially executing millions of instructions every second, eliminating machine cycles would be of enormous benefit to every user.

Let’s look at a simple program that might be executed by this CPU. Suppose you have 5 bytes stored in memory beginning at address 1000h and you want a program that adds them up. Here it is:

A program that adds up five bytes stored in memory.

The first two instructions set the values of the H and L registers. Then the program uses HL to access the bytes and accumulate the sum, incrementing HL after each memory access.

As you can see, there’s some repetition here. An INX instruction is followed by an ADD instruction four times. That’s not too bad for this particular program, but what if you wanted to add up 20 values? Or a hundred? And what if these weren’t bytes you wanted to add but 16-bit or 32-bit values requiring more instructions to accumulate the sum?

Can repetition like this be avoided? Can there be an instruction that causes other sequences of instructions to be repeated? But what does that look like? And how does it work?

This topic is so important that an entire chapter is devoted to it!

If you find an error or have any questions, please email us at admin@erenow.org. Thank you!