How to Get Logisim Clock to Run Continuously
So great, we understand adders, registers, decoders, and multiplexers: the three larger-scale circuits that we need to understand before making more prominent CPU components. But now we need to combine all these logic components into larger circuits. We're going up a layer in abstraction: from the logic gate to the integrated circuit.
Recall that our model CPU has four instructions, but can do each one differently:
- 00 can load a number into a register encoded in the instruction (an immediate) or memory. Its abbreviation is LI or LR1R2.
- 01 can do four math operations on registers. Its abbreviation is MATH.
- 10 is the store instruction. It stores data into memory, using either a register's value or an immediate value as an address, and its abbreviation is STIM or SR1R2.
- 11 allows you to jump to a different section of code. Its abbreviation is JMP.
We also have four registers. I'll refer to the actual physical registers by using $ and then its number. Note that the register values r1 and r2 are variables for instructions:
- $0 always stores 0.
- $1 is a general-purpose register and gets compared to 0 by the jump unit when we need a conditional jump.
- $2 and $3 are general-purpose registers
We'll start with the clock. In our case, the clock is a simple on-off switch that tells the processor when to change register values. A real CPU would connect this to a crystal oscillator circuit of some sort, probably with a chain of frequency multipliers, but we don't need to know how that works.
The critical component is the instruction decoder. It's the boss of the CPU. This component takes the instruction, figures out what it's supposed to do (one of six things: load, load-immediate, do math, store, store-immediate, or jump) and relays operations, conditions, register numbers, and immediate values to other CPU components. It's a fancy binary decoder with some added logic to determine instruction parameters.
We need an ALU to process data. It takes two register values and sends them into an adder, subtractor (adder with 2's complement applied to second input), multiplier, and divider. The inputs and outputs are controlled by muxes connected to the instruction decoder.
We also need a space to store the program we're running and another to save user data because we can't keep everything in 4 tiny registers. For that purpose, we use two banks of RAM. RAM works just like registers (an array of D-latches), but it operates more slowly, and each sub-array of registers has an address (a number). When we send the address to RAM, we can save or receive the data at the address. A real computer stores everything together in RAM, and the operating system controls where everything is stored. It does this with a complicated memory management unit, which is on the CPU die.
We handle user memory with a memory management unit, but it's way simpler. It allows programs to read and write data at an address. It's active with LR1R2 instruction, SR1R2 instruction, and SI instruction. It finds the correct address and data to RAM and returns data. It uses muxes to route data to RAM, which are controlled by the instruction decoder.
A similar Register Control Unit enables registers and changes whether the ALU, memory or immediate line is connected to the register input line. It's also controlled by the instruction decoder. The registers connect to the clock and update their value when the clock changes, and the register is enabled. They're in a separate register file.
We also need a program counter, which keeps track of which instruction we're executing. It's a register that contains the address of the current instruction. It also has an adder which allows it to increment by one address every time the clock line turns on, and it's got some circuitry so that the CPU can change the value of the counter when it needs to jump.
The jump decoder is a separate component. It figures out which address the CPU should jump to and on what condition. It uses the value in R1 to compare, and the address is the immediate value in the instruction.
We can now assemble (put together) the CPU. Here's a circuit diagram:
Here's some test code I wrote for the machine. It uses all operations that we can do. We need to write it out in binary, and then into hexadecimal to get things working in Logisim.
TEST PROGRAM 00000000 #Do nothing, also called NOP (no-operation) 00010110 #Load 6 into $1 00110001 #Load 1 into $3 LOOP: 10101111 #Store $2 at f 00100001 #Load 1 into $2 01010110 #$1 = $1 - $2 00101111 #Load 0xf into $2 00001010 #Load user data at address f into $2 01001011 # $2 = $3 + $2 11010011 #Jump to line 4 if r1 > 0 (one line before due to circuit limitations) #This program should loop five times through the jump, starting from line 4, and then continue, leaving the value five at 0xf in memory #We need this hex code for Logisim, to put into program memory HEX 00 16 31 AF 21 56 2f 0A 4B D4
And if we manually generate a clock signal by repeatedly pulsing the clock line, we see it loops through 5 times, and we get five at address f. So we see that it does work, thanks to multiplexers, decoders, and a bunch of logic gates, organized into many components that make up the CPU.
Explaining how a basic CPU works isn't exactly the easiest task. You get more out of hands-on experience than an explanation. It can take a few minutes, hours, days until it clicks when reading, but it instantly clicks when you play around with the circuits. Of course, I encourage you to download Logisim and experiment with this circuit with links below.
The next article will explain cores, hyperthreading, virtual memory, and other things in real processors, but we're moving up a layer in abstraction. Peace out until the next article.
Download my CPU circuit
Download Logisim
Source: https://www.andyexplainstech.com/articles/cpu-basics-building-cpu-logisim
0 Response to "How to Get Logisim Clock to Run Continuously"
Post a Comment