The Science of Everything Podcast - Episode 93: How Computers Work Part III - Logic Gates and Components
Episode Date: January 19, 2018In this third part of the series on computers I begin with an overview of Boolean algebra, including a discussion of key logic functions such as NOT, AND, and OR, and also discuss how CMOS logic gates... implementing these functions are fabricated from transistors. I then survey the wide variety of logic components used in electronic circuits, including the multiplexor, adder, tristate buffer, flip-flops, comparator, and clock generator, and discuss the functions fulfilled by these devices in modern computers.
Transcript
Discussion (0)
You're listening to The Science of Everything podcast episode 93.
How Computers Work Part 3.
Logic gates and components.
I'm your host, James Fodor.
So in this episode, we're going to continue on from where we left off in the previous episode
and explain how we can use transistors to build logic gates
and, in turn, how we can use logic gates to implement different logical circuitry components
that are used in processes in modern computers.
Before we get to that, however, we need to talk about Boolean, Algebra and Logic to explain why these logic gates are so important.
Recommended pre-listening for this episode should fairly obviously be the previous episode, How Computers Work Part 2,
in order to give you the background about how transistors work and how they're relevant to gate design.
So, let's jump in and start talking about Boolean, algebra, and logic.
Bullion algebra is a branch of algebra in which the values of the variables can only be true or false,
donated as 1 and 0. In elementary algebra, which you would have learned at high school,
the main operations are the usual arithmetic operations of plus, minus, division, multiplication,
and the variables just at any old number. In Boolean algebra, the variables can only be zeros and
ones. The key operations are the logical operations of awe and and negation. It is a useful
formalism for describing logical relations in the same way that ordinary algebra describes
numerical relations between different quantities. Now, as noted in the previous episode,
modern digital computers operate under the digital abstraction, which essentially only
considers two possible states of affairs in a circuit, low voltage or high voltage. And there's
a threshold. Anything below this counts as low voltage, anything above it counts as high voltage.
In principle, you could try to distinguish as many voltages you like. You could try
distinguish three, four, 20 different levels of voltages in a wire and correspond each of those
to a particular type of signal. The trouble is that the constraints of trying to operate these
devices at very high speed and very small size and low power make noise a big factor. So if you're
not waiting a long time for these devices to reach equilibrium, that's the high speed part. If they're
small so there aren't large numbers of electrons present and if they're low power, so again there
aren't very large numbers of electrons actually transferring the currents or transferring voltages,
there's going to be quite a bit of noise built into the system, and so it's going to be
hard to distinguish fine distinctions between different voltages. So recognizing large
numbers of different voltage levels is difficult. It's much easier to just try to make it
as simple as possible and only distinguish between two possibilities, low voltage or high
voltage. That's why binary works so well in digital computers, because it's much easier to build
devices that work on that basis. Because we have devices that work on binary inputs and outputs,
zeros or ones, we need an algebra, we need an abstract formal way of describing how to perform
operations on binary inputs and binary outputs, and that's what Boolean algebra does.
Now, it's been proved that any logical expression can be represented, any expression in Boolean
algebra can be represented using either only NAND gates or only Norg gates. So these are sometimes
called universal gates because basically we can build anything we like using only NAND or only
nor gates. Now I haven't defined NAND or NORN nor gates, so I'll jump to that in a moment.
But there are a number of main different types of logic gates that perform different
Boolean operations and that the most important of them are the NAND and the NOR gates,
because as I said, those are logically universal. If you have any one of those, you can
build any of the other gates and therefore make any circuits that you like.
Now, you might be wondering why we have logic gates in circuits. The answer is that, remember,
point of a computer is to try to automate the process of calculating the results of formal,
logical, arithmetic operation, to compute the values of functions, in other words. Because we've decided
to go with the binary route, we need to have a straightforward way of instantiating carrying out
these formal operations on binary units in hardware. And logic gates are a very convenient way of doing
that. It builds the logic into the hardware itself so that we can easily construct more
complex devices and have a handle on what we're actually computing and what we're doing in a
given circuit. So this is why we use logic gates. It's a way of connecting up the abstract
mathematical or logical operations that we're trying to get our computer to perform with the
real hardware. Finally, designers also generally want to reduce the number of gates they use. And to
compute any moderately complex function, there are usually many equivalent ways of doing it. So there
are complicated procedures that are followed to try to reduce the number of gates that are used
to perform any given operation or computer-given function in Boolean algebra.
And these use formalisms called DeMorgan's Laws and other heuristics and algorithms
that you can study in the textbooks, but we won't really cover here.
I just want to emphasize that there's usually not only one way of doing something in a logic circuit.
There are many ways that you can achieve the same ends, and generally you want to do it in the
few as gates as possible because it reduces the cost and often the time taken as well.
The more gates, the more logic gates and therefore the more transistors the currents have
as to flow through the longer it takes for the computation to be performed.
All that being said, let's have a tour of the main logic gates, and each of these corresponds
effectively to one of the main operations in Boolean algebra.
Logic gates almost always have two inputs and one output.
The one exception to that is the not gate, which is the simplest type of gate.
it takes in one input and gives one output.
Each input and output you can think of as corresponding to a single electrical wire,
which carries a voltage of either high or low, so a bit, zero or one.
In the knot gate, you have a one input,
and the output is just always the opposite of whatever the input is.
So it's an inverter, it just inverts whatever your bit is.
So when the input is zero, the output is one,
and when the input is one, the output is zero.
That's very simple.
Useful, but simple.
Now the other gates, the other six gates that we're going to talk about, have two inputs and one output.
So they perform some operation depending upon the voltages or the values of the two input wires.
Probably the easiest to understand is the and gate.
That takes two inputs and outputs the result.
The result is zero in all cases unless both of the input wires are one, in which case the output is also one.
So that's just a logical and.
That's very easy to understand.
The output is only a one if the inputs, A and B they're often called,
if both A and B are both one.
If only one of them is one, it's still zero,
and if they're both zero, the output is also zero.
Notice when I'm describing these logic gates that for a logic gate that takes two inputs
and gives one output, there are only ever four possibilities.
Either both inputs could be zero or both inputs could be one.
Those are two possibilities.
The other two possibilities is that A is 1 and B is 0, or B is 1, and A is 0.
So there are only four possible outputs that you have to define in order to completely define the operation of one of these logic gates.
So we've just defined and.
It's always 0 unless both the inputs are 1, and that corresponds to our notion of and.
Now, the gate that I mentioned before, anand gate is a not-and gate.
It's the same as if you had an and gate and then put a knot on the output.
So in other words, it's always one unless both of the inputs A and B are 1, in which case it's a 0.
So it's just the opposite of an and gate.
Orgate works a little bit differently to how you might expect.
So if either one of its inputs or both of its inputs are 1, then the output is 1.
The only time the output is 0 is when both of the inputs are 0.
Now that works in accordance with what we think of as inclusive or, that is one or the other, or both.
So you just have to have at least one of the inputs being one, and then the output is one.
Nor is similar to and nor is one of the other universal gates that I mentioned.
It's just again the exact opposite of or, like putting an or gate than through a knot gate.
It's one when B and A, both of the inputs are zero and zero in all of the other cases.
The two most difficult gates to understand are X-Or and X-NOR gates.
An X-Or gate stands for exclusive or.
It's actually generally what we think about when we think of as or.
That is one or the other but not both.
So its output is one if exactly one of the inputs is one,
but it's zero if both of them are zero or both of them are one.
X-Nor is the opposite of X-Or.
It is one when both of the inputs are zero,
or when both of the inputs are 1, but 0 when 1 is 0 and 1 is 1.
Another way of thinking about an X-Nor gate is that it tells you if both the inputs are the same.
So it's 1 when they're either both 0 or both 1s and 0 if they're different.
So you can think of it as a matcher if you like.
It'll only be 1 if they're both the same.
So to help understand that, I've compiled this little table here
to sort of translate the formal definition of the functions computed by each of these logic gates into English.
So a knot gate is just not. It's just inverted. That's easy to understand. And an and gate is, again, just and. That's easy to understand. An example would be if you had two requirements that simultaneously must be met. So to be eligible for the job, you must have a degree and five years of experience. If you only have one of those things, or if you don't have any of them, then you won't be able to apply for the job. NAND basically means anything but both. So an example of this would be you can have either dessert, you know, in one of those fancy meals where you can,
pick either of the desserts. You can have one or the other of the ice cream or the custard, say,
or you can skip dessert entirely so you can have neither of them, but you can't have both of them
because that's greedy, you know. So that's what NAND is, just not both of them.
Or the or gate is at least one of. So, for example, if you have to show your identification,
you might say that you have to show a driver's license or a passport. You could also show both,
that would be fine, but you have to show at least one. If you don't show at least one, then
you won't be able to prove your identity.
A Norgate effectively corresponds in English to none.
That is, you can't have, or you mustn't have, any of the possibilities,
the possible inputs being one.
So an example would be that you cannot go in this ride if you are under 12 years old,
or if you are less than a certain height.
You must have none of those properties pertaining
in order for the output to be one, in other words,
in order for you to be able to go on the ride.
XOR is exclusive, also.
one or the other but not both. An example would be that you're doing a degree and you have to pick
an academic major. You can pick computer science or electrical engineering. You can't not pick
either because you have to have a major, but you can't pick both of them either because you can't
have two. You can have one or the other but not both. And X nor is the opposite of XOR. It just means
effectively neither or both. So this is probably less common in practice. But again, the easy way
of thinking about this is that it just tests if both of the inputs are the same or. It just tests if both of the inputs are the same
not. So now that we've talked about the logical operations in Lulian algebra and each of
these has a corresponding gate, a physical device that you can build to implement that
logical operation, let's discuss how you can actually build this physical device using
transistors. All of these can be built using transistors connected up by wires. We will
focus on the most important logic gates for computers, so these are
inverters, so knot gates and NAND gates. Most electrical devices these days are made
from NAND gates, remember, because they're logically universal. It turns that to be easier
potentially to have a few more NAND gates rather than having, if you need an exor gate,
say, just make it using NAND gates, than having a specialized exor gate, which you then have
to manufacture, sort of separately. It's easy just to make a whole bunch of the same thing,
and then connect them up in the way that you need. So that's why logically universal gates
are so useful in producing electronic devices. So a single logic gate will usually be made
from somewhere between two to four CMOS transistors. So a single transistor,
there is not enough to produce a logic gate, but you need a couple of them, but not too many.
And the logic gate is defined by its logical behavior.
So that depends only on its input and output relationships, as I've described in the Boolean
algebra section.
Now, an important thing to understand is that when logic gates are drawn in digital system
circuits, if you look at diagrams or textbooks and so on, you'll only generally see input
and output wires. These are the ones that carry the logic symbols, the zeros and the ones,
of the inputs and the outputs. In practice, however, there are always at least two additional
lines, electrical currents, lines carrying electrical current, that are not shown, one of which
connects to a high voltage source, so five volts, and one connected to the ground, zero volts.
So, in fact, usually for every logic gate there will be four wires, at least four wires, sometimes
more. In the case of an inverter, for example, there'll be the single input and a single output,
but also then the high voltage source and the low voltage source, and those are crucial to get the thing to work.
They're not, however, part of the logical operation of the circuit.
They don't define the zero or one's inputs or outputs.
They serve a physical implementation purpose, not a logical purpose,
and that's why they're not drawn on the logic diagrams,
but it's important to realize that they are implicitly there
because you need them to implement the logic gate in the actual real physical device.
Now, it's tempting to think, and this confused me for a while studying this,
It's tempting to think that we form circuits with logic gates by just connecting the outputs of gates to the inputs of other gates and the outputs of gates together and everything just gets wide up together in one big complicated circuit.
You put the inputs through and the operations pass through all the logic gates and it's outputed in terms of the output signal on some wire on the other side of the circuit.
That's not exactly what happens.
And in fact, if you tried to do that, it wouldn't work.
the reason is because you can't simply connect up the outputs of two different CMOS transistors together
because if one transistor was on while the other one was off there'd be the voltage on the wire would be undefined
one one transistor would be trying to turn the wire on or put a high voltage on it and the other would be trying to turn it off to put a low voltage on it
and so the result would be undefined they'd be competing for control of the wire likely that would lead to overheating and other problems
and undefined logical outputs in the intermediate forbidden zone that I talked about so all sorts of potential issues there if you try to
to do that. So that's not the way that logic gates are implemented or circuits are implemented
in practice. In fact, what happens is that logic gates are constructed according to the following
principle. Input wires, so that's the logical inputs that go into the logic gates, always
connect up to the gate region of transistors, while output wires connect up, directly or indirectly,
to either the ground or the high voltage wires. Now, this way input and
output wires and never actually directly wide up to each other in a single circuit. That is,
current can never flow from the input of a logic gate through to the output of the logic gate,
because they're not electrically connected to each other. The input of the logic gate is always
connected up to the gate, which, remember, is separated from the other regions of the
semiconductor regions by the insulator region. That's the oxide part of the metal oxide
semiconductor in MOSFET.
The oxide
electrically separates the
gate region from the rest
of the device. And thus,
there's always an electrical separation between the
input wires of a logic gate
which connect up to the gates and
the output wires which connect up to the sources
and both the source and the sink
actually of the transistors.
So the way
that a logic gate works therefore is that
the input determines the gate voltages
on all of the transistors
which in turn flip on or off the transistors,
which then determines whether the output connects to the high or the low voltages.
So input and output are never directly connected to each other.
The input is actually a control voltage,
which determines whether the output gets connected to the high voltage wire
or the low voltage wire, but both of which are always there.
It's just which do you connect to as the output wire.
So hopefully that's sort of clear.
It's an important distinction that you don't have just a single circuit flowing
from the input to the output. The input is the control voltage, which connects up to the gate
on the transistors, and determines whether the switches go on and off, and therefore whether
the output connects up to the positive voltage or the zero voltage. So the upshot of this is
that when you're following the logic through a digital circuit from input to output, following
input through the logic device through the output is correct when you're talking about the
flow of logical information, or the bit flow in other words, but it's not correct if you think
that that represents the flow of current through a circuit, because the current is not flowing
through the device from input to output in that way. In fact, very little current is flowing in a
CMOS device because largely it's affected by just changes in the bits of the inputs and outputs
is affected by changing the voltages. But even ignoring that, the inputs and outputs are not
connected up in the same circuit, so there wouldn't be current flowing anyways. Now, with that
background we can explain how to implement CMOS logic gates using MOSFETs. Remember, CMOS is
a complementary metal oxide semiconductors, complementary meaning that it uses P-Mosses and N-Mosses in conjunction.
So a given logic gate will always include at least one of each of these types of transistors.
Let's start with the simplest case, which is a knot gate or an inverter, and you can make an inverter
in CMOS using just two transistors, so it's a fairly simple circuit. One is a P-Moss, and one is an N-Moss.
Now, as usual, as I discussed in the previous episode, we connect up our N-MOS source to the ground,
and the P-Moss source to the high voltage.
So the sources in each one are connected up to different voltages.
Now that that's done, all we have to do is connect up the input to the gate of both of the gates.
Now, at this point we have to pause and say that there are two sensors in which we're using the word gate here,
which gets very confusing.
One is a logic gate.
So that's an electronic device, like a knot gate or a NAND gate,
that's made up of a bunch of transistors, and it has inputs and outputs.
It performs a Boolean operation.
The other sense in which we use the word gate is that the conductor region
that sits between the source and the drain regions of a transistor
and forms the region in which we apply the external voltage
that allows us to turn on or off the circuit.
So gate can mean a bunch of transistors performing a logical function in a logic gate,
or it can mean that particular region or component of a transistor.
I will try to be clear in which one I'm referring to.
So in this case, we connect up the input of the logic gate,
the overall input to the gate as a whole.
That is connected up to the gate regions of both of the transistors
that make up the logic gate.
So input actually goes to both of the gates of the transistors
without any difference.
It just goes straight to both of them.
We then take the output of the logger gate as whole
from the drains of both of the transistors.
So the input goes to the gates of both transistors and the output comes from both of the drains.
The only real difference between whether the P-Moss transistor and the N-Moss transistor is that, in the case of the N-Moss transistor,
the source is connected up to zero voltage, whereas in the P-Moss transistor, the source is connected up to high voltage,
and that's, again, always the way we do it in CMOS.
So here's how it works.
Suppose the input is one, so there's a high voltage on the input wire.
We then have a high voltage on the gates of both of our transistors.
this turns the P-MOS off because P-MOS is always turned off by a high voltage.
That removes the inversion layer and gets rid of the channel, so the P-MOS turns off.
That means that the output is no longer connected to the high voltage, because remember,
the source of the P-MOS was connected up to the high voltage.
If the switch was on, the drain would be connected electrically to the source,
and the drain is connected electrically to the output.
So if the P-Moss was turned on, the output would be connected to the high voltage.
But it's not. When the input is 1, the P-MOS is off.
So the output is not connected to the high voltage.
However, when the input is 1, the N-MOS, the other transistor, does turn on,
because N-MOS always turns on with a high-gate voltage.
So in this case, because the transistor turns on,
there's an electrical connection formed between the source and the drain of the N-Moss transistor,
which pulls the output voltage down to 0,
because remember the source of the N-Moss is connected up to the ground.
and thus the output wire is electrically connected only to the ground and not to the high voltage,
and hence the output is zero. So when the input is one, the output is zero.
Simple. If the input is zero, it's just the opposite. The P-mos turns on, while the N-mos turns off.
Because the N-mos is off, the output is not connected to the ground, but because the P-Moss is on,
the output is connected to the high voltage. So if the input voltage is zero, the output voltage is high.
So if you put zero in, one comes out, and if you put a zero in, a one comes out.
That's an inverter.
Very simple setup just using two CMOS transistors, a P-Moss and an N-Moss.
The NAND-gate is a bit more complicated.
We need four transistors to get a NAND gate to work.
Remember, NAND is the logical operation not and.
So the output should be a 1 in all cases,
except the case in which both of the inputs are 1.
So the basic setup is kind of similar to the setup in our inverter, except in this case what we need to do is wire up both of the P-MOS transistors in parallel, whereas the N-MOS transistors are wide up in series.
Now, wiring up two circuit elements in series means that current has to flow through both of them in order to complete the circuit, whereas in parallel it means it can sort of take, it can go through one or the other.
They're sort of next to each other.
on separate wires that both lead to the same end rather than one next to each other along the same wire.
So we have, in this case, in this circuit, two P-Moss transistors, again with their sources both connected up to the high voltage,
and two N-Moss transistors, again with their sources both connected up to the low voltage to the ground.
The difference, though, is that the P-Mosses are in parallel, whereas the N-mosses are in series.
So what does this mean?
because the N mosses are in series,
the only way for the output wire
to be electrically connected to the ground,
in other words, the only way for output to be zero,
is if both of the N-MOS transistors
that are wired up in series,
if both of those are turned on.
In contrast, because our P-MOS transistors,
remember the P-Moss are the ones that connect up
with the source to the high voltage,
our P-MOS transistors are wide in parallel.
So in order for the output voltage to be electrically connected to the high voltage, all we need is at least one of those P-MOS transistors to be turned on, because the current can flow through one or the other, but it doesn't have to flow through both.
Now with that setup, it should be fairly clear how we can turn this into a nander gate.
All we need to do is connect up the gates of each of the transistors to each of them connects to one of the inputs.
So one P-MOS connects up to input A, and the other P-Moss connects up to input B.
one of the NMOSS connects up to input A
and the other of the NMOSS connects up to input B.
So you've got one input going to
one type of each gate.
With this setup, the only way
to get the output voltage connected up,
the output wire connected electrically
to the zero voltage of the ground
is if both of the inputs are
one, and hence
both of the NMOS transistors are turned on,
allowing current to flow through both of them,
because they're in series, it has to flow through both of them,
and thus electrically connect up
the output to the ground.
So the output is only a zero, it only connects to the ground, in the case where both inputs are one,
which is exactly what we want, not and.
It should be zero only when both inputs are one.
In all other cases, at least one, or possibly both of the inputs, are a zero.
But if either of the inputs is a zero, then at least one of those P-MOS transistors that connect up to the high voltage will be turned on.
remember P-MOS transistors turn on when you give them a low voltage on the gate region.
Therefore, if any of the inputs is a zero, at least one of those P-MOS transistors turns on,
thereby creating an electrical circuit between the high-voltage wire and the output wire,
and thus causing the output to be one.
So the way we've wired up this circuit, because of the difference in putting the P-Mosses in parallel
and the N-Mosses in series, the output will only ever be zero if both of the inputs are one.
In all of the cases, the output will be electrically connected to the high voltage, and thus will be a 1.
Hence, we have a NAND gate.
And the other types of gates we mentioned ore and XOR and so on can be implemented similarly,
but I'll only discuss the knot and the NAND gates here, because those are the main ones used in actual digital circuits.
One important point to mention before we move on to the logic components is that logic gates are subject to what's called propagation delay.
Now, this means that it takes some finite period of time for the logic components, is that logic gates are subject to what's called propagation delay.
Now this means that it takes some finite period of time for the electrical signals to pass through the wires and transistors and for the output to stabilize to match the appropriate input value.
That doesn't all happen instantaneously. You need to have an equilibration of charges and potentials and so on.
All of the electron motion and electric field changes take some time.
So there needs to be a time for that to settle down and the correct values to be observed on the output relative to the input.
And that period of time, this equilibrium time or propagation delay, places a limit on how long we need to wait before we can read the outputs of a given circuit.
So if you were able to read the outputs of a logic gate, just the tiniest fraction of a second, maybe a femtosecond or something, that's less than a 90 second.
After you apply the input voltages, you probably wouldn't see the correct output voltage.
It would probably be a bit of a mess because you haven't waited long enough for all of the charges and voltages to equilibrate.
you need to wait for that propagation delay in order to get the output to make sense.
Propagation delay places a limit on how fast you can run computers essentially
because the fast you try and run them, the more you push up against propagation delay.
Propagation delay can be reduced by making your devices smaller, obviously,
because then you don't have as long to wait for all the electrons to move around and things to equilibrate.
So that's a big reason why there's been a race to try and make transistors as small as possible
and to fit more of the monos circuit, because you can reduce propagation delay
and hence run your computer faster.
Technically it means running at a higher clock speed.
We'll get to what that means in a little bit.
But having now discussed the key logic gates
and how you can build them out of P-MOS and N-MOS transistors,
I'm now going to mostly stop talking about transistors
and focus on the logic gates
and how we can use these logic gates
and put them together in different arrangements
to form logical components,
which perform more useful functions
than just the very simple Boolean operations.
Now, remember that I'm going to be talking about
the logical connections of these components. So the input and the output wires, remember, as I said
previously, that there are also always, for each of these gates, there are always the high voltage wires
and the low voltage wires, which also are essential for their operation. But those are neglected
in logical diagrams, and I won't really discuss them henceforth, because although they're
essential to the physical implementation of the devices, they're not essential to their logical
behaviour and we're abstracting away from the implementation when we discussed a logical
behaviour of these devices. So I'll just talk about the inputs and the output wires and ignore
those high and low voltage wires. So to begin our survey of the main logical components
which will need to build our processor, we begin with a multiplexer. A multiplexer is just a fancy
name for an input selector. It takes as input a number of data inputs, so a bunch of wires,
maybe four different YSA, A, B, C, and D, and it outputs one of those.
It decides, or the circuit determines which of the inputs is outputted as the output,
in accordance with the pattern of control bits that are also fed as input.
So, for example, if we had four different input bits,
we would need two control bits to uniquely select which of them we wanted.
That's because two input bits allow us four different combinations to select between,
I could either put them both zero, one is zero and one as one as one, or the other is zero and the other is one, or both could be one.
So there are four possible combinations of zeros and ones in two bits, into selecting bits, that allow me to select uniquely which of the four input bits that I want.
And multiplexes are fairly simple to implement.
All you do is you take your control bits, knot them, so you split them, so you take the original signal and the knotted signal as well.
that just ensures that I have the original and the opposite of that signal, which is often useful.
That's a technique that we use in a number of these components.
I then feed these appropriately into a bunch of and gates.
In fact, I'll have four and gates, one for each of my possible inputs.
So this is a multiplexer with four inputs that I'm discussing here, four inputs and one output.
Each of my inputs connects up to one of my end gates.
That's simple.
An end gate only outputs of one, if all of its input bits are one.
So basically all I have to do is feed in one specific combination of control bits into each and gate alongside the input bit.
So each of my andgates effectively represents one of the input bits that I can select.
So for example, suppose I want to select input A, the first input.
A natural way of coding that would be to code it with the control bits zero-zero.
So to do that, I just feed in the knotted control bits into the first hand gate.
also into which I feed the A input. So that first end gate outputs a 1 when all of its inputs
are 1. When does that happen? It happens when A is 1 and also when both of the control bits are
0. Remember they're inverted before they go into this gate. So 0 is turned into 1s and then
are input it into the and gate. So only when A is 1 and both of the control bits are 0, is this
and gate going to output a 1. If my A input is a 0, then it will output.
is 0. So the two control bits effectively turn on the and gate, ensuring that only this
handgate will be able to produce a 1. And then whether it actually does produce a 1 or not, depends on
whether the input to the hand gate from A is a 1 or a 0. And then I just do that for each of my
possible inputs. So the first hand gate gets an input from my two inverted control bits,
but my second hand gate will get an inverted input from one and a non-inverted input from the other,
essentially because it's only going to be activated when I get when one of my control bits is a one and the other is zero.
So there's a particular combination of those control bits that will activate the second and gate.
The second and gate is also connected to my second input.
So again, it will mirror, the second egg gate will mirror the output of the second input bit,
but only when it's been selected by the appropriate combination of control signals.
Likewise for all of my other and gates as well.
Only one of them will ever be active at a given time, depending on the particular.
combination of control bits that I have, the active and gate will always mirror what the,
what its corresponding input gate is, and all of these and gates, or four of them in this case,
are then just fed into an all gate, which will just ensure that whatever the, only one of them
remember, will ever be active in a given time, so the or gate will just ensure that whatever
that one active and gate outputs is also outputted by the or gate. If the and gate outputs
are one, the all gate will two, if it outputs a zero, then none of the other hand gates will
will output a zero, so the or gate will output a zero as well.
So the or gate effectively just make sure that I pick whichever of the andgates is currently active.
So that's how you implement a multiplexer.
It's quite simple.
Just a one-to-one relationship between your inputs and your handgates,
you select an active handgate using your control bits,
and then feed them all into all gates, and the output comes out from the or gate.
And so the result of that is that using these control bits,
I can select which of the inputs that I want.
A decoder is the next device that we'll look at,
and it's the exact opposite of a multiplexer.
So it's also called a demultiplexer.
Instead of selecting one input from many,
it turns a small number of input bits
into a large number of output bits,
effectively taking a compact representation of some number
and outputting the full representation.
So that's why it's called a decoder.
It decodes some compact representation of a number
to the full representation.
So a multiplexer turns many to one,
whereas a decoder turns one or a few,
to many, so that's why they're opposites of each other.
It's mainly used for memory addressing.
So if I have thousands of memory registers,
we'll get to registers in a moment,
but they store memory in the computer,
I don't want to have to store and then send out thousands of bits
every time I want to specify exactly which of these registers that I want.
That would be very tedious.
Instead, I want to use a small number of control bits
that I use to address a specific register,
which then can be decoded.
that address is decoded by a decoder circuit,
and it sends out the appropriate signal to the exact register that I want.
Now, this is essential because in order to access the value of a particular register,
I have to what's called assert, that means turn on to logical one,
I have to assert a particular wire that runs to that circuit, to that register,
and only that register.
So each register in memory needs to have its own specific wire that's asserted
in order to read or write data off that register.
But if I have millions or even billions of these registers,
I need to have millions or billions of these wires.
It would be silly to have millions or billions of wires
connecting my computer directly to the RAM
just so the computer can decide exactly which register that it wants
and it asserts that wire and then gets this thing from it.
That's obviously absurd.
That would be like me having direct mail delivery
from my house straight to every other house,
or from every house in the world directly to every other house in the world.
it would be extremely inefficient.
You have all these millions of wires connecting each other,
and it would be chaos.
Instead, the way that it's done is that I write the address of the person
I want to send my message to, which is sent to a central location.
The address is decoded, and then that enables it to be sent on to its final destination.
So everyone sends their letters to the post office,
which decodes, effectively, the address,
and selects the appropriate route to send the letter on.
This is more or less what's happening with a decoder.
When the CPU decides that it wants to access a particular memory in a particular register,
it has to know the address of that register,
but the address needs to only contain N control bits
in order to be able to address two to the power of N different devices.
So, for example, if I have four gigabytes worth of RAM,
that's basically four billion different registers,
I only need 32 control bits to specify exactly which of those registers
that I want. So sending 32 control bits is much easier than sending out 4 billion control bits,
obviously. So sending out an exact combination of those 32 control bits allows me to specify
which of 2 to the power of 32 different memory registers that I want. Once the decoder takes in
that signal of those control bits, it's circuitry. Essentially, it's similar to the circuitry of the
multiplexer that I described, except in reverse, the outputs of the inputs and the inputs of the outputs.
So there's a bunch of hand gates and not gates from the control bits and so on.
But the base code is essentially the same.
The circuit allows decoding of the control bits
so that it will output exactly the wire necessary to activate the register that we want.
So in one of these memory decoders, there might be 32 input wires, say,
corresponding to a 32-bit address,
and 4 billion different output wires corresponding to exactly which of the memory registers we want to read from.
So our and gates in the decoder only have inputs from the control bits, so each and gate is activated when exactly the right combination of control bits is activated to select just that and gate, and then the and gate then turns on and activates the register appropriately.
So because of the many different combinations of 32 bits of numbers that I can have, I'm able to have all of those different possible combinations, all those very large number of registers that I can uniquely access.
So that's how a decoder works.
A comparator is a special circuit that checks the relative value of two numbers.
This is essential for implementing conditional branches,
which is one of those control structures that I mentioned before that we need
in order to have a true and complete computer.
Remember I said that we need those three different types of control structures.
One is a sequence and one is iteration.
The other one is essentially an if-then statement, a comparison,
so that we perform one operation in one case and a different operation in the other case.
So in order to perform that type of conditional branching instruction, we need to be able to compare the relative values of two different numbers.
And a simple way of doing that is just using a comparator.
You recall the X-Norgate that I mentioned, that was the last logic gate that we discussed, that outputs are one, only when the two inputs are both the same.
So effectively we can implement a comparator using a bunch of X-Norgates.
You just wire up the corresponding bits of each of the numbers that I want to check.
So remember the two numbers that I want to check.
check will be binary numbers, maybe there'll be 32-bit numbers, so there'll be 32 different wires
that encode the bits corresponding to those numbers. So we might say that the right-most,
the least significant of those bits, is called bit 0, and the one to the left of that,
the next to least-significant bit is called bit 1, and so on up to bit 31. There's no bit 32
because we started at 0, right? So all I have to do is put my 0-bit from my first number,
say A-0, as input into an X-Norgate, along with...
my 0 bit from my second number, so B0. So A0 and B0 both go in as the X NOR input to my XNOR gate. It checks to see if they're the same. And I do likewise for my A1 and my B1 bits and my A2 bits and so on, for all of the bits in the number that I want, the two numbers that I want to compare. And then I feed all of these X NOR outputs into an AND gate, because they all need to be the same if my numbers are to be equal, obviously. Each of the bits has to be equal.
And so then I take the output just straight from the and gate, if it's one only if all of the bits are equal to each other.
If even one of the bits is different, then the and gate won't go, will be a zero and my output will be a zero.
At this point, it would be useful to clarify that originally I discussed and gates and or gates as having only two inputs and one output.
But you can have and gates and or gates with any number of inputs that you want.
They always have to have one output.
but you can have endgates with 3, 4 or 20 inputs if you want or 2,
and they operate as you would think.
If only if all of the inputs are 1,
is the output going to be equal to 1.
If even one of them is not equal to 1,
then the output will be 0.
And for an or gate, it's the exact opposite.
Only exactly one of the inputs has to be 1
in order to the output of an or gate to be 1.
It doesn't matter if 19 of them are 0,
if only 1 of them is 1, then the output will be 1.
So that's how we can have these sort of handgates and all gates
with many different inputs.
The next logical component that we'll look at is called an adder.
An adder is a circuit that adds two numbers together.
So we just looked at a comparator which compares the values of numbers,
and adder adds them together.
Adders can also perform subtraction very easily,
because if you remember, the way two's complement numbers works
is that we just flip all of the individual bits and then add one to it.
So I can flip bits by just using individual knotgates,
and then if I've got an adder, I just add one.
So an adder with small modifications so that you flip the bits and add one can just be turned into a subtractive fairly easily.
So how does an adder work?
In order to implement an adder, I first need to consider a one-bit full adder.
A one-bit full adder takes three inputs and gives two outputs.
The two main inputs, if you like, are A and B, are just the two bits of my numbers that I want to add.
The other input, the third one, is called the carry-in input.
and this is if I have an additional bit to carry in from some previous part of the addition,
and we'll see what this means in a moment.
My two outputs are just my outputs, so the sum of A and B,
and also an additional carry-out bit that I will need if I can't represent the output with just a single bit.
So this is exactly the same as if I'm adding up regular decimal numbers.
If I have, say, 3 plus 9, I can't just write that as a single number because, in fact, it's 12,
so I have to write down a two and then carry the one over,
and then it included in my next calculation.
It's pretty much exactly the same with adding binary numbers together.
So you just have an output, which is the output of the sum,
and an additional carry-bit output.
That's a single-bit full adder.
It only adds single one-bit numbers, obviously by itself not that useful.
But to form a multi-bit adder, which can add arbitrarily large numbers,
you just add enough circuitry in,
all I have to do is connect up my carry-out bit from each segment of it to the carry-in bit of the next segment.
So the numbers are appropriately carried over, just as you carry over extra powers of 10 when you're doing an addition sum.
Now, let's think about this.
When should my output bit, not the carry-out, the regular output bit, when should that bit be equal to 1 and which should it be equal to 0?
Well, it should be equal to zero if all of my input bits, including the carry-in bit, are zero, obviously.
It should also be zero if exactly two of the input bits.
It doesn't matter if they're A and B or the carry bit.
If exactly two of those are zero, it should also be equal to zero.
Because if exactly two of them are zero, then that means that my output is two,
which I can represent by one in the carry-out bit, and then a zero in the regular out bit.
If I have exactly one of my inputs being a one, then my output should be one,
and if I have all three of them being one, then my output should be three,
in which case I represent that by a one in the output bit and also a one in the carryout bit.
So basically I just need to implement that circuitry,
the circuitry to ensure that the regular output bit is a one in the case where I have either
exactly one input being one or all three inputs being one.
And my carry-out bit is a 1 in the case where I have either two or three of the input bits, including the carry bit, being a 1.
And you can do that using X-all gates and-gates and-gates and all gates.
I won't describe the exact circuitry because it's a little bit confusing to try and explain it without being able to draw a diagram.
But it's fairly simple to do. You can do it just with a handful of gates.
And really all we're doing is picking out the right conditions in which the output is a 1 and which the carry-out is a 1.
And it's very easy to do because there are only a handful of possible conditions.
Really, my output could be 0, 1, 2 or 3,
and I just need to make sure my output bits are, as they should be in each of those cases.
So it's not hard to do that.
And then, that's my 1-bit adder.
I just have to connect the carry-out from each of my 1-bit adders
to the carry-in of the next 1-bit adder
and link them up in a big long series.
And that will ensure that I'm carrying over my extra powers of 2 as I should be,
and thus allowing me to add up arbitrarily long binary numbers put in on the inputs.
I'll also have an extra carry-out bit because it's possible that I could have a larger number,
obviously, than either of my input numbers by themselves.
So I'll need an extra carry-out bit to account for that situation.
So that's how you can implement an adder using just logic gates.
Multiplyers can also be implemented by using logic gates.
I won't really describe the circuitry there, but I'll just describe the basic idea.
One method taught in school for multiplying decimal numbers is based on calculating partial products.
Basically, that's the method where you write one number times and then the other number beneath it,
and then you just take each digit of the number that's below, the second number,
and multiply that by all the digits on the top number.
Then you take the next digit of the bottom number and multiply that by all the digits on the top number, and so on.
And then you just add up all of those partial products that you get along the way.
That might not make a whole lot of sense if you're a bit wrong.
on paper methods of multiplication, but don't worry too much about that.
Basically, the key point here is that you can reduce multiplication to, basically, lots of
additions as well as very simple multiplications of times by zero or times by one.
And multiplying by zero or by one is very easy in binary, because it just means either turn
it to zero or keep it the same. So, effectively, a multiplier can be implemented just by
combining a whole bunch of adders together in a very careful way, and also including a few
extra logic gates to account for those multiplying by zero, multiplying by one.
But you don't actually have to do that much new.
It's just a lot of adders put together, more or less.
You can use this algorithm of partial products to turn multiplication into addition.
In fact, that's what multiplication is, it's just iterated addition.
Now, let's shift gears slightly and talk about the clock generator.
This is not exactly a logic component, but it is crucial for the operation of the logic components inside the computer.
and so I wanted to talk about it here.
The clock generator is a piece of circuitry
that generates a regular clock signal,
usually a square wave consisting of equally spaced high and low signals.
The purpose of the clock signal is to act like a metronome.
It keeps the activities of the computer in order
and keeps them occurring in a regular rate.
So this clock signal is used all over the processor
in order to make sure that things keep happening.
If you didn't have a clock signal,
then you would just have whatever your original input to your processor is
and whatever your original output is, and they will just always stay like that forever.
Unless you manually change the inputs.
That's a bit of a pain.
What you want that to do is happen automatically.
So you generate this sequence of high and low signals from the clock,
which then sends those around the compute automatically,
and that allows things to happen automatically as you vary that cycle and change the input,
and I'll explain how that happens in a moment.
But this clock generated and the clock signal that it produces is essential,
having the computer operate automatically instead of essentially you having to do everything by hand.
And obviously, if you had to manually change the inputs every time you wanted to perform a computation
on a computer, it would be kind of pointless because it would just be way too slow.
The whole point of a computer is that you can do things much quicker than humans can.
Modern clock generators have frequencies, so that's just the time between when you go up
and when you come down and when you go up again, the time of a full cycle.
modern clocks have frequencies of several gigahertz, which is several billion oscillations per second.
The faster the clock operates, the more cycles the processes can go through in a given unit of time,
and thus the more processing it can get done.
The main limitation on the clock speed is the amount of heat that's generated,
and also propagation delay in the circuit elements, which decreases as you make transistors smaller.
So this is what I mentioned previously.
We want to make transistors smaller, so the propagation delay is smaller,
and therefore we can increase the speed of the clock and get the processor to run fast.
But how does the clock actually work? Well, clock signals are produced using a device called a crystal oscillator,
which is essentially a small strip of quartz that vibrates as a result of the reverse PZO electric effect.
That is, when an electric field is applied to this crystal, positive ions in the lattice are pushed in one direction,
while negative ions move in the other. This is what you'd expect. They essentially move apart to some small degree as a result of the applied electric field.
This opposite movement of the different types of charges causes the material to distort,
that is the physical shape of the material to distort, ever so slightly.
When the field is removed, the material returns to its original shape, thereby generating a field.
So if I apply a field, that leads to a change in the shape of the crystal,
which, when I remove the field, in turn, relaxes, changing the shape back, and then generating a field again.
So if I just put in a small amount of external current,
a self-generating process, which produces a very regular and predictable oscillation, which
can be converted to a square wave, a very high frequency. So this is how clock signals work.
Effectively, it's a crystal oscillating at a very high frequency as you put a current through it.
The next logical component that we're going to look at are called latches or flip-flops.
Now, there is a technical difference between latches and flip-flops. Flip-flops are clocked,
and so are edge triggered, while latches are not clocked and so are level triggered, but don't really worry about that.
If a logic component is clock, it means it takes input from the clock, which should be fairly evident,
so we'll change according to whether the clock is high or low on that part of the cycle.
But I'm not too worried about the technical difference between flip-flops and latches.
I'm just going to talk about them as if they're synonymous, focusing more on flip-flops,
because those are connected to the clock.
So a flip-slop is a circuit that has two stable states, and hence it can be used to store a single bit of information.
And flip-flops, therefore, form the basis for storing memories in a computer.
A flip-plop can be built by putting two Nandgates next to each other,
and wiring the output of each of them into one of the input bits of the other.
So they're sort of crossed over in this sort of X-shaped configuration.
The output of each goes into one of the inputs of the other,
and each of them takes one additional input aside from the output of the other.
So that might sound a bit strange, but it turns out that with this setup,
the output of the NANDGATE depends upon not only what the two input,
the two additional input signals are, but also on the previous state that it was in.
So the two additional input signals that I mentioned are called S and R for set and reset.
The output Q is taken from the NANDGate with the S input.
Now, this is actually an active low device.
Now, that means that when we want to achieve the effect of setting the input to 1,
we actually set it to 0 instead.
So active low is a bit confusing because it means that it's activated when it's set to 0 rather than 1.
But logically, it gets you the same result.
So the output Q is taken from the S-input nandgate,
and sometimes we take Q-0, which is just the opposite of output Q,
from the R-nand-gate.
That's the one that takes the R-in-put.
But don't worry about that. Let's just focus on the Q output coming from the NADGET with the S input.
Now, S stands for set and R stands for reset.
So it turns out that if both set and reset are set to zero, or in other words, if not set and not reset are set to 1,
there is no change in the output Q.
So we can't actually say what the output of Q is.
This is what makes these types of circuits different from the combinatorial circuits that we talked about previously.
like the multiplexes, decoders, and so on,
because we could always describe their outputs purely in terms of their inputs.
In this case, we can't actually do that,
because when the set and the reset are both set to one,
remembering that they're active low,
so the device is neither set nor reset,
there's no change in the outputs.
All we can say is that the output stays,
Q stays at whatever it was previously.
We don't actually know what Q is
without the additional information of what state
Q started off as being.
If we set the reset, by setting it to zero, and leave set zero, so you can only set one of the sets or resets at a time, it's not allowed to set them both at once.
Obviously, that wouldn't really make sense to simultaneously set and reset something.
But basically, if we set the flip-slop, the output always goes to one, whereas if we reset it, the output always goes to zero.
If then after setting or resetting, we turn both of the flip-flop, the output always goes to one.
If then after setting or resetting, we turn both of the flip-slap, the output always goes to one.
the set and resets inputs to zero, then the output of the flip-flop just stays at whatever it was,
either the set or the reset, it stays the same. And that is possible because of this sort of recursive
setup of the output of each of the nan gates feeding into one of the inputs of the other nan gate.
In order to maintain the correct output, you need to have a constant current flowing. So if you turn off
the power, then you don't know what's going to happen. The output's undefined. But as long as
the power still operating, the output of this flip-flop will always just be whatever the output was
last time you set or reset it. So that's a little bit confusing, but the basic point is that by
wiring two nangates into each other like this and having a set and a reset option, then we can
set up the circuit so that the output always stays what it was before it stays the same unless we
set it to one or reset it to zero. And this is very useful, obviously, for storing memory.
With a little bit of extra circuitry, we can change this SR flip-flop into what's called a JK flip-flop,
which is a little bit more complicated, but more versatile, because it now includes a toggle operation that changes the state to the opposite of whatever it was before.
And usually the way this works is that a clock signal is added into the circuit so that if I want to be able to set the value of the flip-flop to 1, I just put a 1 on the J input and a 0 on the K.
If I want to reset, I just put a 0 on the J and a 1 on the K,
so that's more or less the same as it was in the S&R case.
But now the difference is that I'm allowed to put a 1 on the J and the K at the same time.
I'm allowed to sort of set and reset at the same time,
although they're called J&K now to avoid the confusion.
And now what that does is it flips the bit.
So previously this operation wasn't allowed.
Now it flips whatever the bit is.
So if it was previously a 1, it goes to a 1,
and if it was previously a 1, it was previously a 0.
it goes to a 1. And also if I leave both of the inputs as 0, then there's no change.
So this jK flip-lop is very versatile. I can leave it the same. If I leave both J and K off,
I can set it if I set J to 1. I can reset it to 0 if I set K to 1, J to 0, or I can just flip it from whatever it is to the opposite if I set them both to 1.
And these changes always occur on the leading edge of the clock signal. So whenever the clock begins to go up from 0 to a higher voltage, the change takes place.
and then it will stay in the same state
until the clock next goes up again.
So this is what makes it a flip-plot
because it's clocked in this way.
The next logical device that I wanted to discuss is a counter.
A counter is a circuit that keeps track of a sequence,
either counting up or counting down.
It's very useful to keeping track
at what stage the processor is at
in a multi-stage operation.
We'll talk about that in the next episode.
So a synchronous counter can be made
by wiring up a series of JK flip-flops to a clock,
as they normally are, as I mentioned,
and then just taking the output of each of these JK flip-flops
and sending it to the input of the next one.
So essentially how this works is that the very first flip-flop
will toggle every clock cycle.
So the J and the K inputs are permanently wired to 1
so that they're always on.
So I've always set this first flip-flop to toggle
every time it's clocked, every time the clock changes from low to high.
The second flip-flop takes its J and K input
from the output of my first flip-flop,
which means that instead of toggling every cycle,
it toggles every other cycle,
because remember, it will only toggle
when the J&K inputs are equal to one,
and that only happens every second cycle,
because my first flip-flop is one in one cycle,
and then it's zero,
and then it's one again, and then it's zero again.
So my second flip-flop will toggle every second cycle.
My third flip-plop will toggle every fourth cycle,
because it will only flip-flop if the first two are both equal to one,
and the fourth flip-plot will only toggle every eight,
cycle and so on and so on. So by reading which of my flip-flops are toggled to on and which are
toggled to off, I can tell exactly what cycle I'm on up to however many I've got. So if I had
eight of these flip-flops all wide together, I would be able to count up to eight different cycles.
I could tell whether it was on cycle one, two, three, four, five, six, seven, all the way up to
eight before it would, the cycle would reset. I can't tell the difference between the ninth and
the first cycle. But by building a count of this way, I'm able to generate a signal,
is only on at the exact right stage in the cycle that I want.
So if my processor needs to step through four different micro-operations
in order to carry out a given operation,
I can send it just the right signal
so that control circuitry knows
whether I should be carrying out the first or the second
or the third component in that series of operations,
using this simple counter device here.
Now, I mentioned registers before,
but I just now want to talk about them in a little bit more detail.
A register is just a bunch of flip-flops connected together,
So instead of holding just one bit, one flip-flop holds one bit, it holds a bunch of bits.
So a 16-bit register will hold 16 bits, one for each flip-plop.
Often registers in a computer or in the processor will be the same size as the word size in an instruction set.
A word is the basic unit that you operate on.
So these days, a word is often either 32 or 64 bits long,
although in simpler models of computers the word bits will be shorter,
maybe they'll only be 8 bits or 16 bits long.
The longer the word, obviously the more information you can fit in there,
but also the more wastage there is if you don't need all of those bits.
Usually registers are made from D flip-flops,
which are especially useful for memory storage,
because instead of having the two or even three inputs that some of the other flip-lops have,
a D input only has one input, the D, and has one output, Q.
And a D flip-lop is very simple.
Every clock tick, on every clock tick, the flip-flop simply sets its value to whatever D is.
So if D is one, the flip-flop goes to, holds a value,
If D is 0, the flip-blop goes to a value of 0.
Obviously that wouldn't be useful for holding a memory if that was all there was,
because every time the clock ticked, the memory would keep flipping.
But all you have to do is you AND the clock tick with some enable bit that says
whether you want to write to that given register or not.
If the enable bit is set to 1, that's added with the clock bit,
then the clock input to all of these flip-flops is asserted,
and it will simply set the value of the D flip-flop to whatever the D input is.
input is. If on the other hand the enable be to set to zero, then it doesn't matter what the clock does
when you end it with a zero, the output is zero, and so the register won't be changed. So connecting a bunch
of D flip-flops together in parallel is a very simple way of instantiating a register.
A tri-state buffer is another very important device which is useful for dealing with registers.
A tri-state buffer is a device that is used to enable or disable writing to a particular
wire on a bus. Buses will get to in a moment, but a bus is basically like
shared output wires that lots of different devices can all connect to. If you
remember earlier in this episode though I said that you can't connect up the outputs
of multiple transistors to each other because what happens if one was turned on
and the other was turned off they'd both be competing to try and set the wire to
different values and you'd have undefined results. The way you get around this is
to use a tri-state buffer. A tri-state buffer is essentially just an enable device
when the signal to the tristate buffer is set to one, it will connect up two circuits to each other.
When it's set to zero, the circuits will be disconnected from each other.
And so if I have multiple devices that want to write to the same output wires, or the same bus, for example,
all I have to ensure is that all of them are connected to the wires, not directly, but via a tristate bus,
and then just enable one of those tristate buses corresponding to whichever of the, say, registers, for example,
that I want to write to this shared output.
And that way I can ensure that only one of them at any given time is connected to the shared bus,
and I don't have multiple devices all connected to the bus at the same time.
You can implement a tri-state buffer by adding a P-MOS and an N-MOS transistor either side of an inverter gate,
and then attaching a not-ed enable signal to the P-Moss and just a regular old enable symbol to the N-MOS.
This way, when the enable signal is off, both of the additional gates, the new gates,
that I've put on will be off.
So the reason I put a not input to the P-MOS, remember,
is that when the gate on a P-MOS transistor is given a high voltage,
that turns the transistor off.
Whereas in an N-MOS, in order to turn the transistor off,
I need a low voltage.
So if I want both of these transistors to be off at the same time,
the P-MOS and the N-Moss,
I have to send a regular old signal to the N-MOS
and an inverted signal to the P-Moss,
so that they'll always turn off and on.
in the same situation rather than in opposite situations as they normally would.
Now, with this setup, the advantage is that when the enable signal is off, both of the two new gates
that I've added will also be off, and thus the original inverter, with its outputs coming from
the drains of both of the gates, both of those will be disconnected from the entirety of the
rest of the circuit, and that's what we call a high Z state, Z standing for impedance.
So basically high Z means that there's no current flowing, it's disconnected from the rest of the
circuit. It's neither a logical 0 nor a logical 1. It's just undefined. And simply that just means
that if the enable bit is set to 0, I've disconnected my knot gate here with the rest of the circuit,
so it doesn't have a logical output. Only when I enable it, is it connected to the rest of the circuit,
and thus he's able to take on either a logical 1 or a logical 0, depending on what the
additional input bit is. So remember, there's an input bit, which goes directly to the not gate,
and then there's an enable bit, which allows the whole thing either to be connected or to be disconnected to the rest of the circuitry.
The enable bit doesn't determine what the output bit is.
It just allows it to take an output bit.
So having this set up at each of the connections between all of my, say, different registers and the bus line
is what allows me to connect up one and only one device to the bus at a time
and not have a situation where I'm trying to connect multiple devices up to the bus at once
and therefore getting confused results.
To finish out this episode, therefore, it's worthwhile to just mention the bus,
which we'll talk about more in the next episode.
But a bus is just a collection of wires connected up to a number of different components or devices,
often in the processor.
You can actually talk about different types of devices.
A bus that connects registers and the ALU together within the processor.
I'll talk about the ALU in the next episodes.
Don't worry about that.
So a bus can connect components inside a processor,
or it can also connect the processor as a whole with peripherals and other.
components on the motherboard. When two devices need to communicate, a typical way
doing this is to put a signal on the bus and the other device then reads it off
the bus. This saves from having to connect each device directly to each other
device. This is what I mentioned before with the post office thing. It's much easier
to have to put all signals in a central location and then read off that central
location rather than to send everything directly to every other device. It leads to
too many wires and too much confusion. Modern computers have lots of different buses
connecting to different devices.
Particularly, there's often a separate bus
for transferring data
and for transferring an address.
So if I want to access the memory,
what I can do is put an address on the address bus,
which is then decoded by the memory,
and that allows the appropriate enable wires to be set,
which then allows the memory to place
the relevant data onto the data bus,
which I can then read off into the processor.
Because of the fact that I want to try and connect
multiple devices up to a device,
single bus. I can't do that directly because then otherwise the output of the bus will be
undefined. The different devices have different values. Instead, I ensure that only one is actually
connected to the bus electrically at any given time using these tri-state buffers. So, that's all
of the logic gates and logic components that I wanted to talk about in this episode. What we need to do
in the next episode is show how we can put these different components together in accordance with
what's called the von Neumann architecture in order to make an actual process.
which is the device that, the physical device that carries out the logical operations
and that is at the heart of the functioning of a computer system.
And so that will discuss in the next episode.
So hopefully you enjoyed this episode.
If so, consider leaving a favourable review of the podcast
on a podcast aggregator of your choice,
such as iTunes or various other options as well.
You can also go onto the Facebook page of the podcast and like that,
which is a way of increasing awareness about the show,
and also finding new updates when I'm releasing new episodes.
If you have any questions, suggestions or other feedback,
feel free to email me.
My email address is FODS12 at gmail.com.
That's FODES12 at gmail.com.
Thank you very much for listening, and I'll talk to you next time.
