Tuesday, May 22, 2012

Cousin of HexOut

Inspired by Quinn Dunki's HexOut, I decided to build my own.  This wasn't completely on a whim -- I'll need to use it to debug my register board, which has been sitting there, all wired up, waiting for me to play with it.

I don't (yet) have the space/patience needed to make my own PCBs, and I think I'm a bit more space-constrained than Quinn is, so I decided to make a smaller version.  Not so small that I venture into the wild and wooly world of SMD, mind you, but small enough.

Here's the completed project:

The basic setup is the same as Quinn's -- '165 input latches feeding an ATTiny, which in turn controls '595s which feed four 7-segment displays.  A few changes, though, in no particular order:

  1. I opted to use an ATTiny85V instead of the ATTiny13 Quinn used.  Primarily this was because I happened to have '85Vs on hand.  At the same time, though, the '13 has 1K Flash and 64 bytes of SRAM, whereas the '85V has 8K Flash and 512 bytes of SRAM, so the extra headroom was nice.  I haven't a clue whether my program would fit on a '13.  It probably would've, but I just didn't want to have to even think about whether I was about to run the chip out of SRAM.
  2. My first time using resistor networks -- I have them acting as pull-downs for the inputs, just before the '165 latch.  I don't know whether that makes a difference in practice, but I've been burned by floating inputs before, and didn't want to repeat the experience.
  3. I really didn't want to have to remove the ATTiny to reprogram it, so I added a 6-pin ISP header. Adding in-system programming was an adventure in itself, which began on the breadboard.  I learned that I can't just slap a Bread Head (another Blondihacks invention) onto the microprocessor and expect it to start working.  In my case, the signals sent from the ISP to the ATTiny were causing the circuit to change the state the ATTiny pin I was using for serial input.  The circuit signals on that pin fought the ISP signals on that pin, and thus programmer no worky.  I solved (hacked?) that by adding a jumper for that input pin.  If you want to program the ATTiny, you remove the jumper.  If you want normal operation, you install the jumper.
  4. To reduce part count, I'm only using one resistor on each 7-segment display.  They're CA displays, wired so that the '595s talk directly to the cathodes, without any resistors.  The anodes are tied together, with each display connected to Vcc via a single 150 ohm resistor.  The downside of doing this is that the display is marginally brighter or dimmer depending on the number of segments illuminated, but I'm willing to put up with that to save 24 resistors.
Lessons learned:
  1. The 7-segment displays (Vishay TDSO 1150L's) have a staggered pin pattern.  In one direction they're on 0.1" centers, but in the other they're on 0.05" centers.  Turns out you can bend the middle pins out such that all pins end up on 0.1" centers around the perimeter of the device.  I did that to make a breakout board with a standard Radio Shack proto board, and for some reason chose to make the Eagle part that way as well.  Bending the pins out again for assembly of the real board was pointless, and the new pad layout complicated routing.  I should've just used the standard pad layout for the board.
  2. When I created the custom Eagle part for the 7-segment displays, I didn't check the drill hole diameters for the pins.  It's a really tight fit, which is even more annoying when your pins are hand-bent and could really do with some margin for error (see above).  Memo to self: check drill hole diameters.
  3. The mounting holes may be too close to the components.  This may or may not turn out to be a problem.
The boards arrived in very short order, thanks to Laen's excellent Dorkbot PCB service.  The boards are excellent quality, as always.  With the exception of the 7-segment displays (my fault), everything went together smoothly, and now I have my very own working HexOut.


Board layout:

Friday, April 6, 2012

How to breadboard an ALU in two easy steps

Here's a video which demonstrates a very simple method for breadboarding an 8-bit ALU.

The key is preparation.  You have to figure out how long all of your wires will be, cut them to size, and then put them in a pile.  Pile organization is also important, as you have to put the wires you'll use first on the top, and the ones you'll use last on the bottom.

Also important is the choice of tool you use for IC installation.

Tuesday, April 3, 2012

Edge connectors and abrasion

Prompted by a question about the durability of board when faced with multiple insertions and removals into the edge connector, I decided to run a little test.  I took one of the spare ALU boards (made by Dorkbot PDX) and one of the edge connectors I got from Jameco, and did 100 insertions.  I took measurements after each batch of 10 insertions and removals.  I didn't take pictures as I went, but I did take pictures at the end.

There was minor abrasion visible on the card edge after 10 cycles.  Nothing alarming by any means, but you could see it if you tilted the board to the light just right.  The abrasion got progressively more visible as the cycles continued; they're very visible at 100.  I characterized the abrasion by measuring resistance.  I figured if it got too bad, I'd see increased resistance.  I took measurements in two places:  First, from one end of the card edge pad to the other, and second from the card edge to the corresponding output pin on the edge connector.

There wasn't any noticeable change for the first 80 cycles.  I'd consistently see about 0.4-0.5 ohms on the pad, and about 0.6 ohms from pad to pin.  At the 90 cycle mark, I saw 1 ohm on the pad, and 2.2 ohms on from pad to pin.  The 100 cycle test saw the edge connector resistance increase to 2.3 ohms.  I took the measurements with my Extech EX330, using the stock pen-type probes.

Here are pictures of the board after 100 cycles.  I made a point of inserting the card into the connector the same way each time.  The side with the heavy abrasions went into the connector first, so I guess it had the insertion as well as some amount of rotation when I put the other end of the card in.

I went at one of the pins with a hobby knife, and what I found underneath the gold(?) coating matched the abrasions.  I'm assuming what that means is that the abrasions are the result of the coating being rubbed off, rather than some sort of transfer from the edge connectors.

The signals I'm sending across these edge connectors aren't terribly sensitive, so I'm guessing I needn't lose any sleep over the increase in resistance that comes from repeated insertion/removal cycles.  If I do start to care (or need to care), it looks like I can reduce the impact of those cycles by pushing the board straight in, rather than one corner at a time.  That'll increase the force on the board that's holding the edge connector, though.  So many tradeoffs...

Friday, March 16, 2012

ALU Boards!

My ALU boards have arrived! Laen has truly gone all out. Even the mailers are purple these days.

Thursday, February 16, 2012


Is there anything more exciting than running off the edge of a breadboard and realizing that your OCD won't let you put in long jumper wires -- that you're going to have to rip the whole thing up, shift it over a bit, and rewire it all again?

I say no.

Tuesday, February 7, 2012

Breadboarded ALU Complete

I think the ALU is finally done, and ready for PCB manufacture.

Of course, now that I've said that, something will go horribly wrong (but let's pretend it won't).

  • 8-bit ripple-carry
  • Supports addition, subtraction, AND, OR, and NOT
  • Exports Zero, Negative, Overflow, and Carry condition codes
  • 41 7400-series logic chips:
    • 21 Quad NAND (7400)
    • 2 Quad NOR (7402)
    • 2 Hex NOT (7404)
    • 4 Dual 4-1 Mux (74153)
    • 7 Quad 2-1 Mux (74157)
    • 2 Quad Buffer (74125)
    • 3 Octal Buffer (74541)
  • All the processing power (actually less) of a pair of 74183s, at several times the cost!
Here's a picture:

The blindingly-white breadboard on the left is the core of the ALU.  The buffer chips live on the middle breadboard.  The PCB on the right is the Front Panel I described earlier.  Briefly, the Front Panel allows me to control the ALU from my computer.  First, this allows me to implement the UI in software rather than switches and LEDs.  Second, I can perform automated regression tests by simply running a script.

With the exception of the rainbow-colored ribbon cables, I wired the entire circuit in red and black.  Why?  I was told that blue and yellow wires are slower than red and black ones.  Or Radio Shack only stocks red and black in the big rolls.  You choose.

The ribbon cables are Adafruit "Premium" Jumper Wires electrical-taped together.  I really wanted an 8-conductor cable, but Adafruit only carries 6-conductor cables (six???).  The only other choice seemed to be ordering housings, crimp terminals, and wire separately from Mouser and building them myself.  Compared to that, taping together cables seemed easier (not to mention cheaper).

Everyone loves video, so here's a video.  It's a flyover of the breadboarded circuit followed by a wonderfully-shaky look at the GUI I use to control the ALU interactively.

Now to the guts of the circuit.  First, the schematic:

Next, the board layout.  It's easily the most complicated board I've designed (n=2), and it just barely fits in the routing space allowed by Eagle Hobbyist.  Unless I'd been willing to cut the circuit in half (or maybe smaller), I quite simply wouldn't have been able to do it in free Eagle.  Had space not been so tight, I might've (ok, would've) ditched the buffer chips in favor of back-to-back NOTs.  Maybe if I get really really bored, I'll make daughterboards which plug into the buffer sockets and use NOTs to implement the buffers.

The first page shows the board layout without the back-side ground fill.  The second page shows the fill (the individual wires are a mite difficult to see through the rivers of purple).

Just routing this board was an adventure.  When I first laid it out, I naively let the autorouter do the whole thing.  It routed every trace, which was great, but it picked some mindbendingly roundabout paths for some of the signals.  I knew I'd go insane if I tried to route the whole thing, so instead I hand-routed the traces I cared about (primarily the A0-7, B0-7, R0-7, and control lines) and let the auto-router take care of the rest.  Eagle doesn't seem to go quite so crazy when you only give it short wires to route.  Unfortunately, it wasn't able to route the entire board -- there's one signal left, so I'll have to solder a jumper wire to complete the circuit.

When I made the Front Panel, I was a little conservative with the silkscreening.  This time, I went in the other direction.  Waaaay too far in the other direction.  I added silkscreen labels to everything that wasn't moving, and also labeled some things that were just moving slowly.  The chips that calculate the individual bits are labeled.  The control bits are labeled.  The pads on the edge connector are labeled.  Every IC has a label which will be (gasp) still visible when the socket is installed (I learned this the hard way with the Front Panel).  I'm sure there's something I forgot to label, but I should be in much better shape with this board.

At the suggestion of a coworker, I made some space in the bottom right of the board for a single 16-pin DIP just in case.  Just in case what, I don't know yet, but I'm sure it'll be nice to have a place to put a chip if I need it.

Why is there an edge connector on the board?  This board will be but one component of my microprocessor.  The control logic will live on a backplane board, and individual subsystem boards will plug into it via ISA sockets.  I'm not using the ISA bus -- just the physical sockets.  There won't be any bus at all, as a matter of fact.  I'm simply breaking the microprocessor up into several boards so that a) I can develop them separately and b) I can work with them in Eagle without having to shell out $1600 for the professional version.

Lessons Learned

The Front Panel as originally designed has 27 output pins (numbered 0-26) and 8 input pins (numbered 100-107).  Output pins 0-23 use 74595 serial-to-parallel latches (which are in turn connected to the Front Panel's microcontroller), while pins 24-26 are connected directly to the microcontroller.  Input pins 100-107 connect to the microcontroller via a 74165 parallel-to-serial latch.  This configuration worked when I was testing ALU bits 0-7, but came up short when I added the four condition codes (zero, negative, overflow, and carry).  Negative is the same as R7, so I needed to find three extra input pins.

I solved that problem by changing the Front Panel software to allow pins 24-26 to function as input pins (numbered 124-126) on demand.  Very happy with myself for coming up with this solution, I wired the whole thing up and watched as my current consumption skyrocketed from a normal 20mA to 120mA.  Some very exciting(?) debugging ensued.  It turns out that the newly-minted input pins 124-126 sink about 30mA each.  Maybe I don't have them configured correctly in the microcontroller -- who knows.  Bottom line, they were sinking power in a way pins 100-107 weren't.  They differ from 100-107 in that 124-126 carry condition codes, which means the weird power behavior only exhibited itself when those codes were active, and of course the power consumption changed depending on how many were active.  Only condition code zero?  +30mA.  Zero, Overflow, and Carry?  +90mA.  Very exciting.  Eventually I figured out what was happening, added some series resistors, and all is well.  I need to double-check that I'm initializing the pins correctly in the Front Panel microcontroller, as it's possible the microcontroller could take care of this for me, ridding me of the need to use the series resistors.

I also learned, the hard way, that thou shalt always ground thy unused inputs.  I don't have many unused gates in this design (3 NAND, 3 NOR, and 4 NOT), but I had initially left their inputs floating. I was seeing some truly bizarre behavior from the chips containing those unused gates.  I haven't tried to reproduce since then, but I swear the unused gates were influencing the output of the active ones.  That is, use gate A on a 7400, leave B-D floating, and watch A behave very strangely.  I'm far too burned out on this circuit at the moment to go investigate further, but I think that's what I saw.  Anyway, I haven't seen anymore weirdness since I grounded the inputs for every unused gate.

Labels and diagrams are very important.  Every ribbon cable now has a label on it which says which wires are which signals.  Almost every IC has a sticker on it with its U number.  I even created a map of the breadboard in Inkscape which shows the position of every IC and the signals for every header pin.  These diagrams saved much time.

Next Steps

Now that I have the circuit working in breadboarded form, I'm going to have PCBs made by DorkbotPDX.  They did an awesome job with the Front Panel, so I'm very happy to have them make this board too.  I had to use 6mil traces for everything (except power), so hopefully that'll turn out OK.  Once the PCBs come in, I'll populate one, test it out, and then gleefully reclaim my breadboards.  The ALU has consumed almost all of my breadboard space, leaving me with one dinky Radio Shack 63-row breadboard to play with.  It'll be nice to have the big breadboard back.

Once I'm satisfied with the ALU, I think it'll be time to tackle the register file.  Perhaps I should start designing it.  I also have to think about the control circuitry for the whole processor, what the instruction set will look like, and all that.  While I had initially planned to implement the microprocessor in CODE, I may have decided to just do my own thing instead.  We'll see.

A friend asked how many boards I'd get from Dorkbot (3), and promptly suggested that I could populate all of them, chain them together, and get a 24-bit adder.  Then I could build a 24-bit machine!  Um, no.  Eight bits is enough for me until I work on microprocessor v2, which will be done with a CPLD.  Well, eight bits is enough for me for the datapath.  The address path will be at least 24 bits, if not 32.  But that's a story for another day.

Last but not least

Here's the output from the verifier running its regression tests over the breadboarded ALU.  It's music to my ... eyes.

Testing ADD
ADD case 1/7
ADD case 2/7
ADD case 3/7
ADD case 4/7
ADD case 5/7
ADD case 6/7
ADD case 7/7
Testing SUB
SUB case 1/7
SUB case 2/7
SUB case 3/7
SUB case 4/7
SUB case 5/7
SUB case 6/7
SUB case 7/7
Testing NOT
NOT case 1/3
NOT case 2/3
NOT case 3/3
Testing OR
OR case 1/9
OR case 2/9
OR case 3/9
OR case 4/9
OR case 5/9
OR case 6/9
OR case 7/9
OR case 8/9
OR case 9/9
Testing AND
AND case 1/9
AND case 2/9
AND case 3/9
AND case 4/9
AND case 5/9
AND case 6/9
AND case 7/9
AND case 8/9
AND case 9/9

Wednesday, January 18, 2012

Eagle Edge Connector

Eagle has a symbol for an old-style 8-bit ISA edge connector.  It's called IBM8BIT, and it's in the con-pc library.  Unfortunately, it has some extra gunk on it (dimension lines, a PC board outline, and the outline of that metal thing where external ports go) that I just didn't need when adding an edge connector to the ALU board.

As my second adventure into Eagle library editing, I copied the symbol from the con-pc library and removed the gunk.  The newly-slimmed-down library can be found here.

Back to Eagle

I switched from Eagle to Kicad awhile back.  Now I'm back to Eagle, by way of DipTrace.

Why did I leave Kicad?  In short, lack of support for non-hierarchical sheets, a mysterious bug in pin connection, possibly related to hierarchical sheets, and continued annoyance at the the little things I pointed out earlier -- spotty documentation, the need to create most of my symbols, and an opaque release process.

My ALU circuit, in contrast to the one for the Front Panel, is complicated enough that it needs to be on multiple sheets.  Kicad wants you to use hierarchical sheets about as much as I don't want to use hierarchical sheets.  As far as I can tell, there's no way to use non-hierarchical sheets, unless you create a fake two-level hierarchy, with one page at the top level, and everything else at the second level.

I wanted to do things The Kicad Way, so I started in on transforming the schematic for my ALU circuit into a hierarchy.  The design is such that this transformation is pretty straightforward, but you end up passing lots of signals in and out of each component.  I was just about done, when I ran into a crashing bug in eeschema (the schematic capture program), and lost all the hierarchy work I'd done.  That was exciting.

Later on, I tried again (saving all the while), and got everything back in shape.  Now to the electrical rules check, and from there to PCB layout.  Except the electrical rules check kept flagging lots of pins as unconnected, even though they clearly were.  Some poking around with a test schematic seemed to suggest that this was related to the use of hierarchical sheets, but (shame on me) I didn't collect enough data to file a bug report.  Maybe the rules check is wrong.  Maybe I can still lay out the board.  So off to board layout, and the connections the rules check was warning about were actually missing.  It seems the rules check was correct -- it was just flagging a problem caused by eeschema.  Googling and poking around didn't reveal any obvious solutions.

This was enough to tip me over the edge.  I was tired of having to run my EDA package under VMWare, remote-displaying to my X11 on my Mac.  I was tired of not having any visibility into the Kicad release process -- what's in a given release, and when new releases are made available.  I yearned for documentation.  For complete symbol libraries.  For actual non-hierarchical sheet support.

It may well be that everything I wanted (non-hierarchical sheets, documentation, release notes) could be found somewhere or worked around somehow, but I came to realize that I just didn't want to deal with it.  Free and Open Source are fun, but sometimes it's just easier to buy a commercial package so you don't have to deal with the rough edges.


Which one to choose?  Altium Designer?  Just $4,995!  Hahaha...no.  I didn't want to go running straight back to Eagle.  If I was going to switch again, I wanted to try out at least one other package first.  I'd heard people talking about DipTrace, so I gave that a shot.  DipTrace has nice pricing for non-profit use.  They do all of their licensing based on pin count, with the unlimited-pin, unlimited-layer non-profit license coming in at $348.  The trial version, at $0, supports 500 pins on two layers (their website says 300, but I swear I got 500).  So that's quite attractive.

To evaluate DipTrace, I used it to capture the schematic for the ALU.  I then asked it to lay out the ALU PCB.

I was only partially successful.  One of the attractive things about DipTrace was the licensing model.  Trading a sheet restriction for a pin restriction seemed like a no-brainer.  It gave me a chance to play with DipTrace's non-hierarchical sheets, and surely my teeny circuit wouldn't run into those seemingly-massive pin limits.

Even better, they have a version for the Mac!  Well, almost.  The version for the Mac is the same as the Windows version (and presumably the Linux version too).  Literally the same -- it's the Windows version running under Wine.  They have lots of libraries, with lots of symbols, support for non-hierarchical sheets, a very detailed tutorial ... but it's the Windows interface.  On my Mac.  I have nothing against the Windows interface on a Windows machine, but it's a jarring change when you try to use it on a Mac.  As one example, hitting Command-Tab to switch to another app (in my case Preview, showing the DipTrace tutorial) sends an Alt keypress to DipTrace.  When you press and release Alt on Windows, the menubar is selected, letting you use the arrow keys to select menu items.  Combine the two together, and Command-Tab, Command-Tab (i.e. switch to Preview, then back to DipTrace) leaves you in DipTrace with the menus selected.  All sorts of hilarity ensues.  Typing something can magically select an unexpected menu item.  Selection of symbols on the schematic doesn't quite work until you leave menu mode.  Very exciting.  Someone's also capturing Command-`, so you can't use it to flip between DipTrace windows.

Back to the pin limit.  The limit is probably no big deal for someone adding, say, some glue logic to an existing microprocessor.  40-50 pins for the microprocessor, another few dozen for some caps, regulator, and a support chip or two, and you're done.  I'd forgotten that my ALU is not like those projects.  When all is said and done, it'll have about 40 ICs.  That's 600 pins for the ICs alone (assuming an average of 15 pins/chip) before we even get to the edge connector.

Something weird also happened with printing.  I used the standard NAND and NOT gates, but the inverting bubble didn't print on either of them, leaving me with an ALU which looked for all the world like it was made with AND gates and buffers.

On to PCB layout.  The tool looked to be very flexible.  It had a single-layer-with-jumper-wires mode for the autorouter, which seemed like fun.  It had more knobs and adjustments than I quite frankly even knew existed.  More Wine-related UI issues here -- the inability to use Command-`, for example, made it painful to switch between PCB layout and schematic capture.

Unfortunately, my circuit's voracious appetite for pins meant that I would've had to plunk down actual money in order to fully capture the ALU, and to lay out the complete board.  I knew the UI issues would plague me until the end of time.  The printing issue was mysterious as well.  I decided to give Eagle another look.


When last we left Eagle, it was in version 5.something, and was writing files in its own binary format.  One thing Kicad taught me was the value of having plain-text data files, as you never know when it'll be far easier to fix something with Emacs than with the app itself.  Version 6 writes its data files using XML, which means they can be edited.  Case in point: Eagle doesn't seem to support the reordering of sheets; nor does it support the addition of new sheets in arbitrary locations (or I don't think it does).  Now that the sch file is XML, adding a new sheet is as simple as adding the string "" in the appropriate place.

I looked long and hard at the pricing page, since I knew that was going to make or break the deal.  I already know there are zillions of symbols and packages available for Eagle, and I already know it runs natively on my Mac.  But I didn't want to pay a fortune for a license.  I no longer mind paying some sort of licensing fee, but I'd rather it not be over $250 or so just yet.

Eagle Hobbyist, which I think is new since I last looked at Eagle, is $169.  It supports 99 sheets, 6 layers, and a 160x100mm routing area (6.3"x3.9").  Assuming I break the microprocessor up into individual daughterboards (something which I think is a good idea in its own right), I think it'll be awhile before I run out of room.  Unfortunately, the next step up from Hobbyist is Professional.  Unlimited everything, but it costs $1640.  Sigh.  Maybe they'll have come up with an intermediate price point in the meantime.  I could see myself paying $500 for a Hobbyist+ version with a larger routing area.

I downloaded the free Eagle version (1 sheet, 2 layers, 3.9"x3.1"), and added the Freemium license code.  This gives me 4 sheets and 4 layers (of which I only need the sheets), but keeps the routing area the same.  Enough to re-evaluate schematic capture, but not enough to lay out the board.

As I remembered, the symbol selection is excellent, especially after I added the Sparkfun library.  The Eagle windows play well with others, which makes sense since Eagle at least pretends to be a native app.  The way you perform actions on groups is beyond annoying, but (grumblingly) manageable.  I don't even find package-selection-in-schematic-capture to be as annoying as I found it in the past.  Perhaps that's because I'm now making actual PCBs, and thus it's a useful step.  It's less useful when I'm simply creating a schematic for a breadboarded circuit.

Once I got some hotkeys set up (DipTrace and Kicad ship with a much more useful set, IMO), the schematic went together quickly.  I started poking around the PCB layout tool, but haven't done a whole lot with it -- primarily because my IC footprint alone exceeds the routing area for this version.

All in all, the XML file formats, the extensiveness of the part library (and the size of the part-making community), and the way the UI plays well with the rest of the system have convinced me to give Eagle another try.  Next step, paying for Eagle Hobbyist, and getting the ALU laid out.

Saturday, January 14, 2012

A nice chilly ride

Today was a chilly day for riding.  It started at about 29 degrees in the city (lower outside the city), and gradually warmed up from there.  And by "warmed up", I mean to a balmy 31 degrees.  This was officially my first cold weather ride of the season.  I got some minor ice formation in my uninsulated bottle, but not enough to call it a frozen bottle ride.  I like my bottles to be nice and solid before I put that label on.  It usually takes several hours in the low 20s to pull that off.

I like this new route.  It doesn't have a name yet, but that's not nearly as important as the fact that it doesn't repeat.  I dislike repeating with a fiery passion.  I had previously resigned myself to needing to repeat the last three miles to the bridge, along Hudson Terrace.  Basically you take 9W to Piermont (or beyond), and 340/Piermont Rd back to Churchill, over Churchill, up Palisades, and back to 9W/Hudson Terrace.  Now I've found a new way to continue past Churchill (i.e. not over it), into Fort Lee, through downtown, returning to the GWB from the south.

It's not flat as a pancake, but I think it does pretty well given that this part of NY and NJ is littered with ridges.  Certainly there's nothing to compare to Nyack's Old Mountain Rd or Toga Hill.  While we omit Churchill and Palisades, the altitude gained during those climbs must be made up somewhere.  This route splits those big hills into several shorter ones.

Total mileage is about 55-57, and it takes me about four and a half hours.

View Sickletown addition in a larger map
That said, if I'm going to do 55-57, I might as well do 60, so I'm exploring some options for extending it a little bit.  Rather than turning down Sickletown from West Nyack Rd, I'd like to try continuing on West Nyack until it turns south after Rockland Shopping Center.  West Nyack ends at Church St, so then we jog east to Blauvelt Rd, take Blauvelt to Townline (CR 42), and Townline back to Sickletown.  I've done Townline from South Middletown (CR 33) to Sickeltown, and that was pretty reasonable.  We'll have to see how the rest looks.

My success with finding a nice way through Fort Lee (I had previously thought that escaping east via Palisades back to 9W was the only way to go) inspired me to take another look at the beginning of my Philly route.  I'd been going south from Fort Lee, through Palisades Park, Ridgefield, Ridgefield Park, and then Little Ferry.  This involves a truly unfortunate river crossing on US-46, which is so busy that even I ride on the sidewalk.  That bridge is then followed by a very busy roundabout.  All in all, not a good time.  I had accepted that crossing as a necessary evil, but now I'm not so sure.

View Northern start of Philly route in a larger map
What if I could cross that same river at Bogota/Hackensack?  Basically come around from the north side of I-80, rather than staying to the south of it.  Streetview suggests that there are some nice crossings into Hackensack on Cedar Lane and Main Street.  Cedar Lane looks a bit busier, but the bridge is paved.  Main Street is quiet, and goes through a park, but its bridge is metal grate.  I'll need to investigate both to be sure.  Getting to those bridges might be a bit tricky, though.  Fort Lee Road / Degraw Ave is the obvious choice, but it gets very busy in stretches.  Today's route put me further west on Palisade Ave than I had been before -- far enough down that I could see quite a bit more to the west than I had been able to see from my typical crossing at Woodland Street.  Palisades definitely crosses a ridge to the west, but I'm going to give it a shot to see what it's like.  If this works, it should add about 6 miles to the ride, but it'll get rid of some unpleasantness.  Probably worth the tradeoff.

So much riding to do!  So little time.

Thursday, January 5, 2012

No, really -- 2 bits this time

It took me far longer than I had anticipated, but I've finally got the two-bit ALU working correctly.  As I said in my previous post, the problems were all in the control bits.  All sorts of unholy things happen when you try to reduce their number.  Had I chosen to use five bits, the control bit space would've been very sparse, but getting the circuit working would've been merely a matter of nailing down which combination of control bits to use for each operation.  But no, I had to try to be clever.  I had to see if I could use three bits.  Turns out yes, I can.  The trickiness arises when you try to find the one magical bit pattern which will allow all five operations to work without stepping on each other.

Hardware Layout

Here's a diagram of a typical bit in the ALU:

The circuit for a typical bit is best described as a modified full adder.  These modifications, which are necessary to support five operations (ADD, SUB, AND, OR, and 1-bit NOT), are as follows:
  1. There's now a subtraction mux which determines whether the full adder sees B or not-B.  Not-B is presented only when we're subtracting.
  2. I added two result taps (RA and RB), in addition to the traditional output (labeled RC).  RA gives me access to AND and NOT; RB to OR; and RC to ADD and SUB.  A final 4-1 mux, controlled by OP0 (low bit) and OP1 (high bit), selects between the three.
  3. Two muxes -- one controlled by OP2 for AND, and one controlled by OP0 for OR and NOT -- intercept input values and replace them with hard-coded values.  The OP0 mux, for example, allows us to turn the two following NAND gates into NOT gates.
I started out thinking I'd need five control bits -- OP0-3 and SUB.  Somehow I realized that only OP0-2 and SUB were required, and started working on eliminating one of those four.  SUB is pretty much off the table, as it can't be derived from any other line, and doesn't influence any other lines.  I tried guessing at values, with marginal success, until I came up with an approach which simplified things significantly.

First, realize that OP0 and OP2 are the important players.  We'll need OP1 to help select among the result bits, but we can reorder the input values to the R mux just about any way we like, so there's less pressure there.  So first we'll figure out the OP0, OP2, and SUB values for each operation, and then we'll come up with values for OP1 which make the R mux work (i.e. which don't result in overlap).  Once we've come up with OP1 values, we'll see if we can derive one of the OP bits from the other two.

If we just happen to pick OP0 and OP2 alignments (i.e. which bit gives the hard-coded 1 and which passes the existing value through) shown in the diagram above, we get the following truth table:


Looking at this table, we can see that OP2 is easily derived as OP0+OP1.  Three extra NAND gates, and we're down to three input control lines (OP0, OP1, and SUB).

An aside: We had some flexibility with the OP0 and OP2 mux pin assignments, because it's trivial to swap the pins, reversing the entire column in the truth table.  Say we started with the OP2 mux having the hard-coded 1 when OP2 is high.  OP2 in the truth table would thus be 0, 0, 0, 1, 0.  This can still be synthesized from OP0 and OP1 as OP0 NOR OP1, but that requires four NAND gates.  Flip the pin assignments on the OP2 mux, and we need only build an OR gate, which requires three NANDs.


Testing the ALU is a bit of a pain with 2 bits, and would be even more annoying when fully built out. Five operations times 2 bits (eventually 8 bits) -- it just screams for automation. While the Front Panel may seem a bit silly for interactive use (wiring up LEDs and switches isn't that hard, though it is tedious), it really comes into its own for testing. I wrote a program which uses the Front Panel to set the control and input bits to a particular configuration, and to then verify that the output bits have the expected value. That program takes an input file which describes how to perform each verification.

Armed with an input file which contains 36 test cases, I can now validate the entire ALU in about 15 seconds by running a single command. Suddenly all that time spent building the Front Panel seems quite worthwhile.