Thursday, September 6, 2012

4-bit ALU - Progress, HDL code Fix

Today I realized just how long this ALU is going to take; a while. Cutting and placing wires is much more time consuming than I had hoped, though this is not exactly unexpected. I was warned about how long it would take if I used ICs instead of an FPGA. But I'm not backing down so easily. I bought all these ICs and I'll be damned if I don't use them. I think I'll use an FPGA for the 16 bit version, after I do some research to see if there's any loss in speed, and how much loss there would be. I'm suspecting it will actually be faster, as the gates are be a lot closer together in an FPGA than they'd be in an ALU made out of ICs, hence less resistance while the signals are moving. The max delays for most of the IC gates averages around 40 ns, so I'll do some math and compare specs with some FPGA's.

Above is a pic of my current progress. This was all done today, and took about 2 hours, including determining a good layout with short connections between ICs. As you can see, I've added some pull-down resistors to the switches. In my testing post, I mentioned that I was having trouble with the multiplexor; it was because I wasn't using either pull-up or pull-down resistors. Here's a relevant reddit post about the error. I've also added a 7447 chip and a 7-segment display to display the results of the computations. I was considering using the Arduino I have, but this looks cooler, imo. Plus I'd rather not use the arduino for anything other than power (sounds silly, I know), and let the ALU do all the work.

There are also some slight differences in this layout from my original hdl code, because I had made some errors and added 2 extra wires and a chip that didn't do anything. Below is the corrected code for the ALU. There is also another potential optimization, where I could use one of the available inputs on the 1st 4-bit NAND gate listed in the code and eliminate the need for the last NAND gate in the code, but the code doesn't allow it (even though it would work irl), and the layout would be a bit messier. I have NAND's to spare, so I went ahead and kept it.

4-Bit ALU HDL Code (v1.1)

// This file uses software accompanying the book
// "The Elements of Computing Systems" by Nisan and Schocken,
// Download the Hardware Simulator at

 * The ALU. Computes one of the following functions:
 * x+y, x-y, yñx, 0, 1, -1, x, y, -x, -y, !x, !y,
 * x+1, y+1, x-1, y-1, x&y, x|y on two 4-bit inputs,
 * according to 6 input bits denoted zx,nx,zy,ny,f,no.
 * The bit-combinations that yield each function are
 * documented in the book. In addition, the ALU
 * computes two 1-bit outputs: if the ALU output
 * is 0, zr is set to 1; otherwise zr is set to 0;
 * If out<0, ng is set to 1; otherwise ng is set to 0.

// Implementation: the ALU manipulates the x and y
// inputs and then operates on the resulting values,
// as follows:
// if (zx==1) set x = 0        // 4-bit constant
// if (nx==1) set x = ~x       // bitwise "not"
// if (zy==1) set y = 0        // 4-bit constant
// if (ny==1) set y = ~y       // bitwise "not"
// if (f==1)  set out = x + y  // integer 2's complement addition
// if (f==0)  set out = x & y  // bitwise "and"
// if (no==1) set out = ~out   // bitwise "not"
// if (out==0) set zr = 1
// if (out<0) set ng = 1

        x[4], y[4],  // 4-bit inputs      
        zx, // zero the x input?
        nx, // negate the x input?
        zy, // zero the y input?
        ny, // negate the y input?
        f,  // compute  out = x + y (if 1) or out = x & y (if 0)
        no; // negate the out output?

        out[4], // 4-bit output
        zr, // 1 if (out==0), 0 otherwise
        ng; // 1 if (out<0),  0 otherwise

    Nand4(a[0]=zx, a[1]=zy, b=true, out[0]=w1, out[1]=w5);
    And4(a=x, b[0]=w1, b[1]=w1, b[2]=w1, b[3]=w1, out=w2);
    Nand4(a=w2, b=true, out=w3);
    Mux4(a=w2, b=w3, sel=nx, out=w4);
    And4(a=y, b[0]=w5, b[1]=w5, b[2]=w5, b[3]=w5, out=w6);
    Nand4(a=w6, b=true, out=w7);
    Mux4(a=w6, b=w7, sel=ny, out=w8);
    And4(a=w4, b=w8, out=w9);
    Add4(a=w4, b=w8, out=w10);
    Mux4(a=w9, b=w10, sel=f, out=w11);
    Nand4(a=w11, b=true, out=w12);
    Mux4(a=w11, b=w12, sel=no, out=w13, out[3]=ng, out=out);
    Or4Way(in=w13, out=w14);
    Nand(a=w14, b=true, out=zr);


  1. Totally stick with it! There's something to be said building something from scratch. I think it will not only give you better appreciation for FPGAs it will help you understand how things are put together.

    1. Plus it this looks a lot cooler than an fpga, imo :P

      Despite the encouragement, I'm still a bit hesitant. I have to see what to do about breadboards, as I think I'll need at least 5 more if I want to make the full ALU, and I'll need more after that. That'll cost me like $80 and a lot more time than an FPGA, and I'm not sure I want to deal with wire wrapping. Know any other ways I could connect the IC's, or do you have any experience with wire wrapping?

    2. wire wrapping is not actually that bad once you get the hang of it. you need labels for the under side of the board, though, or you'll go insane. take a look at:

      make or find PDFs of those, print them out and use them.

      you might not save a lot, since the special wire wrap sockets are kind of expensive for being sockets, but the resulting product device will be much more solid/robust when handled, and you'll get less random capacitance on your signals.