The previous section already talked about Qibec's only instruction. This instruction works by inverting a data-bit, and branching (jumping) to a specific location if the bit is zero after inverting.
Or in short, Invert, and Branch if Clear ("IBC") - hence the somewhat contrived project-name.
This section shows the CPU's subsystems and how they cooperate. Each subsystem is then discussed in more detail.
For the sake of simplicity, logic-blocks used in this section are deliberately drawn differently than their corresponding standard symbols.
Overview of subsystems
The I/O-channels introduced in the previous section are used to pass information into and out of the CPU. They form the electrical interface between the CPU and the outside world.
Note that I/O-channels are not physical entities. An I/O-channel is merely a name given to the place where a binary number enters or exits the CPU.
From the outside, changes on I/O-channels are the only visible aspects of instruction-execution.
The following figure gives a better idea of what goes on inside the CPU.
The topmost 3 fields show the 3 I/O-channels: program-counter output, branch-input and data-channel.
In following drawings as well as this one, thick arrows represent binary numbers containing multiple bits (for instance, a 16-bit address-value). Thin arrows represent single-bit values and signals (for instance, the value of the data-channel).
The CPU contains 4 subsystems worth mentioning in more detail:
- data-latch (the block on the right labeled "D" and "Q")
- multiplexer (the trapezoid-shaped block)
- address-increment unit (the block labeled "+1")
- address-latch (the blocks labeled "L")
In a nutshell, the data-latch inverts and reads the value on the data-channel. The multiplexer uses this value to select between the next program-address and an arbitrary branch-address. The next program-address is formed by the address-increment unit, by adding 1 to the current address.
(Address-latches only serve to stabilise the address-value before it's being output on the program-counter - more about this later, when discussing clock-phases.)
This block is named "latch", because its function resembles a latch on a door: a bit can pass through, until it is "latched" (locked).
The type of latch used here has a data-input (D) and 2 data-outputs (Q and its opposite, Q-overline).
Furthermore, there's an "enable"-input. As long as the enable-input is high (1), output Q will follow input D - a change of D will immediately be seen at Q.
When the enable-input goes low (0), the value of D at that exact moment will be "latched" (remembered). Output Q will then show the latched value - regardless of what happens at D during that time - until the enable-input goes high again.
Therefore, this type of latch can be used to take a snapshot of a signal. In the context of this CPU, it latches the value of the data-channel at a given moment.
Furthermore, once the data-channel has been latched, the opposite of the original value is present at output Q-overline.
By connecting a resistor between this inverted output and the data-channel, the opposite of the original signal becomes available to the outside world.
(The following sections will show how this is useful.)
The non-inverted latch-output Q is also used within the CPU. Recall that this output will show the original value of the data-channel at the time it was latched.
This output-signal will be used to select 1 out of 2 multiplexer-inputs, discussed next.
A multiplexer is a block that has 2 inputs (A and B, say), and a single output. Furthermore, it has a single-bit "select"-input that determines which one of the 2 input-values it will output.
If the select-input is low, the output will mimic input A, otherwise B.
The output and both inputs are equal in width - that is, they have the same number of bits.
By using binary number representation, a multiplexer can select between 2 binary numbers - in the case of this CPU, between 2 16-bit addresses.
(A 16-bit multiplexer basically consists of 16 single-bit multiplexers in parallel, each selecting 1 out of 2 input-bits.)
The next program-address (a 16-bit value) is made available at multiplexer-input A. A branch-address (a 16-bit value as well, coming in on the CPU's branch-channel) is made available at multiplexer-input B.
Recall from the previous paragraph that the original value of the data-channel (before inversion) was used as select-signal for the multiplexer.
Therefore, if the original value of the data-channel was low (and the new, inverted value is high), the multiplexer-output will mimic its input A - the next program address, else it will choose the branch-address as output.
In the section about binary numbers, an addition of 2 numbers in binary representation was given.
The function of the address-increment unit resembles an addition, except one of the operands if a fixed "1" (one).
Using this block, the value of the program-counter is incremented, and fed back into the multiplexer as candidate for "next program-counter", to be used during the next instruction-cycle.
Interface-wise, the address-increment is quite simple - it only has one input and one output, both 16 bits wide. The output, when seen as a binary number, is simply the incremented input.
Last and least: address-latch
An address-latch is very similar to a wide version of the data-latch, discussed earlier.
Compared to the data-latch, this block has no inverted output, and instead of a single bit, 16 bits are latched simultaneously.
In other words, a address-latch can latch a 16-bit address. The CPU has 2 of these latches, one behind the other.
To understand why two address-latches (instead of one, or none at all) are needed, take a look at the figure displaying the CPU's subsystem-overview.
In case no address-latch was present, the multiplexer-output would be connected directly to the address-increment unit, whose output would be connected back to multiplexer-input A.
In case the multiplexer's input A was selected, this would cause the program-counter to be incremented again and again, as fast as the hardware would allow, causing an unstable and undefined value at the program-counter channel.
In case just one address-latch was present, the problem would persist: as soon as this single address-latch was enabled, the program-counter value would spin around again.
The value of the program-counter would eventually become stable as soon as the address would be latched (i.e. when the enable-input of the latch would go low), but this value would still be undefined.
With two address-latches, the multiplexer-output can be latched in 2 steps: first latch the bottom-most address-latch, then the other. In this situation, there is no chance for the program-counter value to spin around.
Thus, the address-latches solve a practical problem, but are not really part of the CPU's "core functionality".