Designing Complicated Circuits

CS 441 Lecture, Dr. Lawlor

The little calculator circuit we designed last class really gained power when we connected the arithmetic output back into the register input--this lets the circuit keep working away on the same variables, without anybody having to feed it.

This feedback idea can be boiled down to this simple counter circuit:
circuit diagram

The idea is that each clock cycle, we increment count by adding it to zero plus a carry.  Note rather than manually flipping the clock, I'm using TkGate's "Clock" object to avoid timing glitches (the annoying yellow undefined results).  With a clock, you can advance the simulator by one clock cycle by pressing the tab key.

Note that this counter is equivalent to the code:
    int count=0;
    while (1) count++;

This counter will keep counting forever, but you can turn off its clock line (e.g., by ANDing it with a false value) to stop the count.

Here's a more complicated circuit we developed in class.  It's a (inefficient) multiplier circuit, equivalent to this code:
int multiply(int A,int B) {
    int RESULT=0;
    for (int COUNT=0;COUNT!=B;COUNT++)
       RESULT = RESULT + A;
    return RESULT;

multiplier circuit using a count-and-increment strategy

Note how every temporary expression (such as RESULT+A) in the program has a corresponding wire in the circuit.  We implement equality testing by XORing the two numbers, and ORing the bits of the result; because anything XOR itself is zero, this hits zero when COUNT==B, which shuts off the clock.  This control flow dependence is the only interaction between the COUNT circuit and the RESULT circuit.

The same feedback idea can be used to add a stored-program ROM to our little CPU.  The idea is we increment a "program counter" every clock cycle, and use that location as an address into a little ROM:

Tiny CPU with instruction fetch
You'll also need this ".mem" file, which contains "0/" (meaning start at simulated ROM address zero) followed by separate bytes of machine code.