I have learnt in school about opcodes and how it works with the ALU to add numbers and such, now is my question how the computer is able to understand this, because it is codes and the computer needs something to translate that to actually doing that, in't it? (correct me if I'm wrong plz) I also want to, when I understand that, make my own processor so I can learn the computer bottom-up and become a good computer engineer.
-
5\$\begingroup\$ Instructions are often easier to think of as addresses, rather than a commands. These addresses are not a location in memory, but rather a location in hardware to which the parameters of the instruction are sent. This location is a complex set of logic gates designed to fulfill some purpose, e.g. addition, subtraction, etc. \$\endgroup\$– PolynomialMay 15, 2012 at 9:28
-
\$\begingroup\$ Back in the old days, you can physically see machines controlled by several levers, switches, buttons, etc. Think of opcodes as settings specifying which lever to pull/push. A certain combination of lever positions will yield to a certain functioning for the machine. \$\endgroup\$– shimofuriMay 15, 2012 at 9:40
-
1\$\begingroup\$ In this case, the cogs and levers are replaced by bus multiplexers. \$\endgroup\$– PolynomialMay 15, 2012 at 10:15
-
\$\begingroup\$ A great example of "cogs and levers" would be arithmometer. It's a type of mechanical calculator. Operator would enter numbers, use levers and switches to select operation and turn winch to provide mechanical energy. Some later models even had electrical motors which made longer calculations easier. \$\endgroup\$– AndrejaKoFeb 8, 2013 at 10:54
4 Answers
At the very lowest level, consider something like microcode. That's what Wouter was talking about when he mentioned Very Long Instruction Word architectures.
A CPU is a collection of busses, registers, memory, and arithmetic logic unit (ALU). Each of these do simple and finite things. Any one higher level instruction is a coordinated set of actions between all the blocks. For example, the low level operations to add a memory location value into the accumulator could be:
- Enable the operand address onto the memory address bus. Assume memory is always in read mode when not explicitly writing.
- Enable the accumulator onto the ALU input 1.
- Enable the memory data bus onto the ALU input 2.
- Set the ALU operation to addition.
- Wait the minimum number of clock ticks so that you know the output of the ALU has settled. In this case it includes the memory read time, the ALU propagation time, and any intermediate data path propagation times.
- Latch the ALU output into the accumulator.
When you break it down into the basic hardare operations, you note that orchestrating a instruction is mostly routing data to the right places in the right sequence. If this were implemented with descrete logic, #1 would be asserting a single output enable line of a tri-state buffer that drives the memory address bus. #2 and #3 likewise require asserting a single line. #4 is a little different in that the ALU is usually a canned logic block itself and often has a set of lines that code the operation. For example, 000 might be pass input 1 to output, 001 add both inputs to the output, 010 logical AND both inputs to the output, etc.
The point is that at the level described above, each instruction is just asserting a certain set of control lines in sequence, possibly with minimum wait times between some actions. A stripped down CPU could simply tie each bit in the instruction word to one of these control lines. That would be simple and highly flexible, but one drawback is that the instruction word would need to be quite wide to contain all the necessary control lines and a operand address field. The instruction memory is used very inefficiently.
A bunch of years ago, there were machines with microcoded architecture. They worked as I described at the low level, but these microinstructions weren't what you wrote when you programmed the machine. Each user level instruction essentially kicked off a small microcode routine. The user instructions would now be more compact with less redundant information in them. This was good because there could be many many of them and memory was limited. But the actual low level control of the hardware was done from microcode. This was stored in a special wide and fast and therefore expensive memory, but it didn't need to be very big because there were only a few microcode instruction for each user level opcode.
Nowadays, relatively simple machines like microcontrollers don't really have microcode. The instruction set has been made a little simpler and more regular so that it can be decoded directly by hardware, although that hardware may have a sort of sequencer or state machine that isn't exactly a microcode engine but sortof does that job with combinatorial logic with pipeline stages where things get held up waiting on clock edges. This is one reason, for example, that smaller PICs have a CPU clock that is 4x the instruction clock. That allows 4 clock edges per instruction, which is useful for managing propagation delays thru the logic. Some of the PIC documentation even tells you at what Q edges what operations are performed.
So if you want to get something very basic up and running, try implementing just a microcode machine. You may need a 24 bit or wider instruction word, but for demonstration and learning that is fine. Each bit controls a single flip flop clock, enable line, or whatever. You will also need some way of sequencing thru the instructions and doing conditional branching. A brute force way is to put a new address for possible use depending on the result of some conditional operation right into the microcode word.
-
\$\begingroup\$ In a VLIW architecture there is no microcode, the bits is the (ISA = Instruction Set Architecture = assembly level) instructions directly control the internal logic. \$\endgroup\$ May 15, 2012 at 15:18
-
\$\begingroup\$ @Wouter: Or you can look at it like there is only microcode that the programmer programs directly. It depends on whether you consider microcode as instruction bits directly controlling hardware or a layer of execution below the user-visible instruction level. \$\endgroup\$ May 15, 2012 at 17:36
-
\$\begingroup\$ One may simplify branching logic considerably by having some bits of the "program counter" loaded unconditionally from bits in the microcode word, while others are loaded based upon various conditions. If there are four conditions, one might use two bits in the microcode word to select one of the bits to feed a bit of the PC address, or one might simply feed all four conditions into PC address bits. The former approach would reduce the ROM size, while the latter would reduce the amount of other circuitry. \$\endgroup\$– supercatAug 22, 2012 at 21:36
-
\$\begingroup\$ The Apple ][ floppy drive controller "Woz Machine" ran at 2MHz, and used a 256x8 PROM to convert four inputs (read-head data, bit 7 of a shifter, and two 6502-controlled latches), plus four bits of state, into four outputs (two shifter-mode outputs, shifter-clear, and a shifter-data output). In many states, the state machine wouldn't care about all of the inputs, but the PROM contents would simply be duplicated as needed in the addresses where the "don't care" state was high and where it was low. \$\endgroup\$– supercatAug 22, 2012 at 21:49
Any translation from one set of codes to another set of codes can be done by a (conceptually) simple piece of logic. A ROM for instance will do. A simple (not pipelined or microprogrammed) processor translates (parts of) the instruction to bits that control the various hardware parts inside the CPU, like the ALU function, register selection, and control lines for buffers, multiplexers, read/write selects, etc.
An interesting case is te Very Long Instruction Word type of architectures, where there is no such translation: the bits in the instruction directly control the functions inside the CPU.
Just adding to Wouter's answers.
To keep things simple, imagine that an opcode represents the actual control signals inside a chip. For an imaginary processor, an opcode for ADD, R1, R2, R3 may be:
1111 0001 0010 0011
The first '1111' may represents the ADD operation and might be used as a direct control signal to the ALU to select the addition operation. For this imaginary processor, it's 1111 but real-world processors will need to refer to the Instruction Set Architecture (ISA) document for the actual bits.
The other three represent the operands: R1, R2 and R3. All these signals can be connected directly to the internal function units of the processor. If a translation is needed between opcode and control signals, something as simple as a ROM will do.
Though I am not going to repeat the same thing discussed at various places, I am sharing a link to a post I came across in "Programmers" stack exchange. Here an answer by Lie Ryan for the above question is discussed in detail with electrical and programming aspects.
-
\$\begingroup\$ Presumably whoever downvoted you thinks this would be better as a comment than as an answer, and they may well have a point. \$\endgroup\$ Feb 8, 2013 at 18:31
-
\$\begingroup\$ Sorry I am new to this. Thanks for highlighting my mistake. \$\endgroup\$– ElaFeb 21, 2013 at 10:00