8-bit CPU: Planning PCBs - architectural upgrades and addressing common issues

I built a prototype ALU block and it appears to work fine, where to go now?

I should remind that I do not want to build multiple copies of the same circuit. I already wired up the Program Counter board temporarily as B register. I'll need that for the intended purpose later.

The logical step is to design a PCBs for parts I've built. I decided to start with ALU, Register and Flags boards. I had some extra ideas for features and improvements, that are not tested on breadboards. The changes are not that complicated so I decided to implement them directly to PCBs. Some of them will allow greater flexibility later on, some should help to prevent come common issues other builders are facing.

As for PC, I decided to keep it on breadboard, as only one copy is needed and I'm not really decided if I want to do something different there.

Flags

I decided to deviate from Ben's design and build Flags register as a separate entity. The main reason is that at some point I plan to build several ALU modules. The initial one will provide Add/Subtract functionality, but I'm planning to add more modules for And/Or, Xor/Not and Shift functionality. All of these should affect Z and N flags. I do not want to replicate the circuitry for Z on each of them. So I'll move that to Flags register itself and use value on the bus as an input.

When adding or subtracting, the ALU outputs result on the bus anyway. Now there will be an opportunity to calculate flags from any value that appears on the bus, for example, when reading it from RAM.

V flag can be produced only by Add/Subtact unit, but C can also be produced and consumed by Shift unit. I'll need a flags "minibus" for those.

Registers

The computer needs a lot of these. Obviously I need 2 of these for A and B registers, but MAR and IR are basically the same, just some features can be left out, for example MAR does not ever need to output it's value back to the Bus. And since my design will use full 8-bit opcodes (in contrast to Ben's 4-bit), neither will IR. I can use same board for these, just skip some chips when soldering.

Double-latch

There's a behavior in Ben's design that is a bit annoying: when computer adds two numbers, the result is latched into a register. But then value on the bus immediately changes to "next" result. It does not cause any issues, because register chip is not going to latch that again until next clock pulse. 

In contrast, my design will calculate and latch Flags from value that are currently on the bus. But which one? Before the bus changes of after? I must be the "before" value, but the margin for the error is only few nanoseconds. What if there is an extra-slow chip somewhere? I don't want to take any chances, I want it guaranteed.

I came up with an idea, that keeps the original result on the bus for all half-cycle. That can be achieved by inserting additional D flip-flops between register's primary ones and its output to the ALU and making them latch on the inverted clock.

Register should keep sending the old value to the ALU until the inverted clock rises. Plenty of time for Flags or anything else (Arduino debugger???) to get the result out.

With general purpose registers I might have gotten away without this improvement, but for IR it is a must. It should prevent issues caused by the infamous "EEPROM noise". It has been observed by many builders that for few moments EEPROM outputs switches unpredictably when address lines are changed. In original design they change immediately when IR is loaded with new opcode. If this occurs on rising edge of the clock, there's a big chance of computer doing something unexpected.

With double-latch the IR-dependent address lines stays constant until the inverted clock hits. Then it changes together with step-counter and "noise" at this stage should not cause harm.

And while at it, the Flags register will also get the same upgrade for its output to Control Logic.

Dual output

In Ben's design ALU is hardwired to take its inputs from A and B registers. It's simple and works, but imposes some limitations. One can not subtract from B register, or double the register adding it to itself. Additionally I'm planning for more than 2 registers (most likely - 4), it would be great if those also could be used with ALU.

To achieve this I plan to add 2 additional 74HC245 output buffers, connecting register to either input side of the ALU. Essentially the register-ALU connections transforms to two 8-bit buses, each register can output values to either of them.

ALU

ALU  follows same design as I built on breadboard, with exception that Z flag calculation is removed. The oVerflow and Carry flag calculations stays as they are unique to this module.

The V and C flag outputs has to be 3-state, as there will be another modules (at least one - Shift) that also might want to output these. Could use 74HC245 there, but it will be half-wasted then. Choosing smaller 3-state buffer - 74HC125 has only 4 units.

 That was a lot of text, perhaps a diagram may make it clearer.

I've left out some parts, some of them are planned for later, but this is the overall picture.


Board form factor

One of my initial design goals was to be able to use breadboards and PCBs interchangeably. To achieve this I decided to design PCBs in a way that can be plugged into breadboards. I'm hoping I will be able to make them be less than a half-breadboard wide, and allow one or two rows on top and bottom for wiring.

Not much space to work with actually. I'll definitely will have to use SMD components and place them on both sides. I think ALU will have the most chips. If I manage to place and route that, others should be easier.

Soldering SMD might sound a little scary, I've actually built and soldered just 1 board in the past. Did not feel too hard to solder then, I think I'll manage.

Comments

Popular posts from this blog

8-bit CPU: ALU and Flags

8-bit CPU: Clock module

8-bit CPU: Memory