Simultaneously designing top-down and bottom-up until your designs meet in the middle to produce a functional result.
That sounds like a horrible idea.
For this project, this was the only design strategy that made sense, considering that I wanted to build a computer from light switches , my preferred use of transistors.
Starting from the bottom up.
Considering that I'm most familiar with logic design at the gate level, the most intuitive first step was to design logic at the transistor level, then design necessary chip logic at the gate level. This way, I could derive any chip logic at the transistor level by substitution.
Gates designed: AND, OR, INVERT, XOR, (and implicitly NAND and NOR)
Chip logic designed: JK FlipFlop, D FlipFlop, MUX/DEMUX( 1:8, 1:2 )
From the top down.
Given that I wanted a processor, I came up with a simple instruction set: ADD, NAND, STORE, and JUMP NO CARRY (JNC). Four instructions yields two bit op codes, leaving me a 6 bit address bus, hence the 64 byte memory.
The whole processor can be divided into blocks: Memory, bus controller, control logic (with instruction register), ALU, clock, and reset logic.
I did cheat on the clock a little bit. In the interest of time, I started with a 555 square generator whose width can be varied by a potentiometer. Past that, JK FlipFlops converted a quadrature wave, where all of the processor's combinational logic was generated on the leading rising edge, and latches trigger on the trailing rising edge, to account for propagation delay in the combinational logic.
Reset logic is straightforward. Pick your favorite momentary switch, tie one side to ground, and tie the other to a pull-up resistor. Or reverse it for active high, whatever floats your boat.
The control logic was the most complicated part and contained two registers, the Instruction Pointer and the Instruction Register. The whole processor operated on a load/execute cycle. First, the byte stored at the instruction pointer's position in memory was loaded into the instruction register. Second, the instruction register's instruction was executed. LatherRinseRepeat. The control logic was the last thing I designed, after determining what signals needed to be generated for the other segments. The only operation that bypassed the ALU was JNC, which sets the instruction pointer equal to a literal, the bottom 6 bits of the instruction. Reset sets the IP to 0.
Memory. 8*64 bits. 512 D FlipFlops. Have fun!
Bus controller. This is essentially a 1:64 mux for the input of each byte, output to each byte, and the clock signal. This mux was controlled by the address bus, which is managed by the control logic.
Lastly, the ALU. This was probably the most fun part to make. The ALU consisted of an ADD unit with carry, a bitwise NAND unit, and a set of 2:1 muxes to feed the output I cared about (based on the op code) to the accumulator register.
I apologize for the lack of detail. I don't have access to my original docs at the moment. I'll come back and add in more information when I get the chance.