2
$\begingroup$

I'm asking this question as an early computer science student who is beginning to get way more interested in really low level stuff/computer/electrical engineering. I am very unfamiliar with hardware, and even after watching numerous videos and reading numerous articles there is still something I can't seem to grasp.

You write a program, compile it, it is loaded into memory, and then...???

I know a transistor can be made to store one bit of data. Okay, fair enough....

But when you load a program into memory, what is...happening? I'm familiar with logic gates and all of that, but what does it mean to be...In memory?

If you have a program loaded into memory, it's in its machine code computer readable format and being processed, how do those values translate from "being in memory" into transistors being on and off? From my understanding, the program counter is reading these pieces of data into your memory, so when you're in memory, does that automatically mean there's this on-off process going on? Is that the last step? How do physical hardware chips "read" this data that is in memory?

I think what's throwing me off is that every video I've seen representing how a transistor stores a bit of data shows a guy switching wires into different holes on a board demonstrating it. But there isn't a little man inside the computer switching wires around. How does that process take place?

Please help me out here, I am ignorant and want to learn.

$\endgroup$
2
  • $\begingroup$ This blog has an interactive ALU simulation and a pretty good overall explanation from when this stuff was still at a scale humans could comprehend. Ken Shirriff's blog. It explains the Motorola 74181 ALU. The only ALU I was trained on was from 1957 and was the size of a fridge. It's still in use, and I was trained on it around 1990. With only 2k of memory, you had to be real efficient. Coders were expected to generate 4 or 5 instructions per day on average. But they were also designing bits of the CPU circuitry. $\endgroup$
    – Phil Sweet
    Dec 24 '18 at 2:58
  • $\begingroup$ You need to understand that: 1) Algorithms can be implemented in hardware. 2) Running a program in memory is an algorithm. 3) The CPU is a hardware implementation of this algorithm. $\endgroup$
    – user253751
    Nov 11 '20 at 18:24
1
$\begingroup$

When somebody in a demo is "switching wires", what he is really doing is applying different voltages (representing logical "0" and "1" levels) to some point in the circuit. In a typical memory circuit, there is a "write enable" control voltage as well as the "data input" voltage.

When the "write enable" signal is "on", the memory circuit will change its internal state depending on whether "0" or "1" is applied to its input. When the "write enable" is "off", the memory ignores any changes to the input, and remains in the same state - i.e. it "remembers" what the last input was.

You might find it easier to understand this by not going directly to the level of what each transistor is doing, but to learn how digital circuits can be designed and constructed from building blocks (often called "logic gates") that implement simple logical functions like "and", "or", and "not".

In computer science terms, that is the interface to a set of "digital functions" that can be used to design circuits, while the details of what the transistors are doing is the implementation of each function.

Most good books and web courses on digital electronics will separate teaching about the design and implementation aspects of the problem. Many circuit designers will never be concerned with the details of the implementation - in exactly the same way that many computer programmers use the API of a library of functions, without knowing (or needing to know!) exactly how they were written.

Of course memory circuits are used in very large quantities, and need to be as efficient (fast, low power dissipation, physically small, etc) as possible, so the design using transistors or other semiconductor devices is often highly "optimised." Just as in computer programming, this can make their internal operation hard to understand, but it doesn't change the way it is used - i.e. its interface.

As with other topics in computer science, an important concept here is working at different "levels of abstraction". A complete, functional CPU is "only" a (large!) collection of transistors, which are used to create logic gates, which are used to create more complex sub-components (e.g. registers, adders, multipliers, etc) … right up the the level of "the CPU". In fact there may be a course in your CS degree which takes you through the whole process in detail, for a simple CPU design. But to understand even a simple CPU (built from "only" thousands of transistors, not millions), trying to understand what each individual transistor is doing is not the best approach - just as you wouldn't attempt to understand a computer program containing thousands of lines of code by looking at each line of code separately, and ignoring the fact that the individual lines are organized into several nested "layers of abstraction" like statement groups, functions, classes, design patterns, etc.

$\endgroup$
1
  • $\begingroup$ You can probably get away with a thousand transistors if really simple is all you need. $\endgroup$
    – joojaa
    Oct 24 '18 at 14:34
1
$\begingroup$

You have to understand that even a stupidly simple computer is at minimum hundreds of transistors grouped into tens of separate functions. Even then the computer in question is nearly useless, since it has no pheripherals like a keyboard or a usb port.

Since many of these would require some software to use. So the critical question is how do you manage the computer while every piece is not in place, and how do you program before you have any pheripherals.

Now if you are following something like Ben Eater's 8-bit computer, you have to watch each and every video untill it is a computer. And even then because it has no keyboard he has to initialize the memory by loading each memory bank by hand, after that the computer works fine. Now this may seem counter productive since in fact manual input is slower than doing the thing he programs by hand, but he has no other input devices.

So if we assume that the arcitecture is some sort of microstepping latency oriented processor, for ease of understanding. Then it works conceptually like this:

Control logic that activate each part of the system triggers:

  1. Clock causes copy of program counter to instruction register.
  2. Microstep time moves one unit
  3. This causes control logic to fetch/switch the first micro step of the instruction In the control system. This turns contol signals on to modules.
  4. Increment microstep counter
  5. fetch second microstep controll pattern
  6. increment microstep counter
  7. ...
  8. Zero microstep counter, increment program, counter loop to beginning.

So yes the control logic is sort of the man connecting wires. But its a long way there, things need verifying a long long time before you reach this stage. Even then system needs to be programmed somehow before it can do anything.

And no this does not nesseserily involve a compiler, because it probably does not exist yet untill you have designed all opcodes.

$\endgroup$
1
$\begingroup$

First: A transistor acts as a switch - amplifier. Base gets token amount of electricity - Emitter starts emitting as much as is put into the collector.

Connect two transistors in a row - Collector of (1) to power, emitter of (1) to collector of (2). Emitter of (2) is "output". Apply voltage to bases of both, and it passes current, producing a "1". But remove any, and it's "0". That's an AND gate.

Now connect them in parallel instead. Two collectors to power, two emitters together to output. Any of them will output current into output line. You must disable both to produce a "0". That's OR.

Now connect a resistor and a transistor between power and ground. Tap into the point between the transistor and the resistor as "output". If you apply voltage to the base, the transistor passes all the current and voltage on 'output' drops to zero, connected through the open transistor to ground. Whatever comes through the resistor escapes through the path of least resistance. You have zero output on positive input. Now remove the base voltage and the transistor's resistance skyrockets. Now the resistor drives enough current from the power line to produce a clear '1' on output. That's NOT.

You can now combine these, connecting outputs to inputs, into a whole bunch of others. NAND = NOT A AND NOT B. XOR: A AND NOT B, OR B AND NOT A. XNOR: (A AND B) OR (NOT A AND NOT B). And so on.

Connect two XNOR gates in an X: one input pin of each as input, the other connected to output of the other.

enter image description here

There, this is one bit of memory. With a rather cumbersome writing (S=1: set to 1, R=1: set to 0, S=0,R=0 - hold value, S=1,R=1 - burst in flames, or at least produce nonsensical noise) but it can be made into a much more sensible thing with a couple other gates on input and output. Attach NAND and AND on input, one input on each from 'in', the other from 'write'. Attach a 3-state buffer on output, with 3rd state (high impedance) input marked 'read'. Now you can write or read this on demand, without 'read' it won't touch the bus you connect it to, without 'write' it won't change state no matter what appears on 'in'. You may connect 'in' and 'out' to the same line. If 'write' is active, it will read and remember what's on that line. If 'read' is active, it will drive that line.

That's a fully usable bit of memory.

Put 8 in a row, each output to one line. The 8 lines are a data bus. You have a byte of data.

Get other 8 lines (from now on known as Address Bus) and connect them to a demultiplexer. That's a construct of a mass of AND and NAND gates, that converts every possible combination of the states of the 8 lines into 256 different output lines.

Now put repeat the row of 8 bits 256 times, every row getting an AND between the one dedicated incoming line from the demultiplexer dedicated to it, and a single global 'Write', and one AND between the same demux line and the 'Read'. And you have a working 8KB bank of memory. Set the right combination of 8 bits on the address bus, state your intent: 'read=1' or 'write=1' and you'll either store the state of the data bus in given byte, or output it onto the data bus from that byte.

Add three-state buffer on all inputs and outputs (you have 18 of them so far, 8 data, 8 address, 1 read, 1 write), and activate them through 19th input: Chip Enable. Pack that into an integrated circuit and you have the 8KB RAM chip.

Want more RAM? A demultiplexer controlling 'Chip Enables' of multiple chips will let you switch between multiple dies.

Then, in the CPU, as the internal sequence moves to 'READ COMMAND', a register (just a byte, 8 RS flip-flops, set aside for a special purpose) named Program Counter is connected to the address line. Read is activated. Through the Data line the set of bits that corresponds to the new command returns to the CPU. It goes to 'command decoder' - which is just another demultiplexer. And that demultiplexer activates one line that activates a specific subsystem of a whole zoo of subsystems of the CPU - responsible for that specific instruction.

Say, the instruction is JMP. Jump to a different place in the program, marked by the value in memory immediately after the command. The set of gates activated through the Command decoder will activate the following operations in sequence: first, advance the program counter. Then output it onto the address bus. Activate 'Read', and then stuff the output from the data bus - right into Program Counter. Command done. The control returns to reading the next command - except 'next' is now pointed by the Program Counter which just got modified. That's what the JMP command worked.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.