has reached the end-of-life and is now read-only. Please see the EOL announcement for details
Show older

I'm about to finish the first program for my computer - a π calculating program, this naive algorithm based on arctan() series should be able to calculate π to 1000 digits and more. I'm not a 1337 assembly writer, the subroutine takes ~3500000 T-states (~1 second) to calculate a ONE decimal digit. I also need to implement a ring-buffer to handle repeated carry if the digit exceeds 10, so the actual program will be even slower, well, better to make it work first...

Fantastic. I got the ring-buffer working, now it handles results greater than 9. It's the first time that I've written ~30 lines of assembly which was not totally wrong, and worked like magic after correcting just 3 typos. Now it should calculate π to many digits. Time to try it on the real . It should take 20 minutes to compute 1000 digits, will be a good benchmark to uncover any hardware issues...

:oh_no: I loaded the π program to my breadboard , and the computer gives a different result on each run, none is correct... It must mean there's a hardware-level memory issue that corrupted some bytes, then got amplified by the algorithm. Let's hope the issue has a direct fix and not due to the signal integrity of the breadboard wiring, or I have to start making PCBs...

My π program accomplished its intended purpose at least, "uncover hardware issues", so it's a "successive failure"?

Okay, the breadboard is now completely impossible to debug. Even my design was divided to different functional blocks, with the board at the center being the "backplane", but now it's essentially unreachable for any probes as the bus wires are everywhere. Now I understand why was the S-100 bus invented, which meant to solve precisely this problem... Time to rewire everything to let the bus spreads vertically, not horizontally...

And no PCBs yet as the design is not complete.

Trying to rewire the breadboard based on a "bus-centric" approach - always dedicate a rightmost breadboard to the system bus for each functional block. At the expense of more board space and more wires, it should be easier to debug and build, let's see how it goes.

“Once, while hacking on a dedicated system, I was testing code by blowing EPROMs and plugging them in the system, then seeing what happened. One time, I plugged one in backwards. I only discovered that after I realized that Intel didn't put power-on lights under the quartz windows on the tops of their EPROMs — the die was glowing white-hot. Amazingly, the EPROM worked fine [...] Of course, this is because the magic smoke didn't get let out.” - Jay Maynard

I suddenly noticed the logic analyzer already includes a Z80 decoder in it 🤩 Great for debugging.

Thanks the Z80 decoder module in the logic analyzer, I was finally able to identify the true problem within a minute: the Write signal to the RAM was unconnected, and CPU always reads 0xFF.

Hollywood-style hacking is something that hardly occurs for real, but occasionally, it is real...

Oh yeah, finally found the smoking gun for the erroneous computation! It's random memory corruption indeed. I suspect it's a signal integrity issue (but may be timing as well). But once the problem is identified and confirmed, it's only a matter of time to track it down.

Finally, I probably found the culprit of memory corruption: a timing violation.

A write operation to SRAM can be initialized by pulling WRITE low, then ENABLE the chip, so I thought it's not necessary disable the output via OE before writing. But this mode works if and only if WRITE comes before ENABLE.

The CPU (and probably most others) always set an address and ENABLE the SRAM chip first, if OE is not pulled high at this point, it's an illegal operation, the result is undefined.

After fixing the "memory write" timing violation, my breadboard completed the π calculation program flawlessly, and was able to calculate π to 500+ digits.

In the troubleshooting process, boards were rewired based on a "bus-centric" approach - always use a row of rightmost boards as the system bus, so new modules can be daisy-chained, and the bus can be probed easily.

The Arduino board is only used as a PSU & USB serial, no cheating here.

TODO: in-system EEPROM programmer, video.

Once I connect the in-system programmer to the system bus, the computer would start acting up. But the strangest problem is, even if the 74xx595 bus driver on the programmer is disabled (essentially disconnected from the bus), the programmer circuit still interferes with the Z80. The interference only stops if I unplug the 595 chips... Weird. If it's crosstalk or reflection, the problem should still exhibit itself after unplugging the chip and leaving the wiring in-place, but no?

Finished drawing the schematics for the CPU board, need to route it. But it looks like a nightmare for routing. 😱

I finished building my first wirewrapped board. The EEPROM programmer breadboard is now a wirewrapped perfboard.

Untested, don't know whether it works or not yet, but at least the AVR microcontroller can talk to me via the serial port - a good sign.

Breadboard status update: it appears that I've fried my EEPROM due to bus contention while trying to troubleshoot the in-system programmer.... Now it always reads 0x00 regardless of control signals, as if all the outputs are in high-impedance (well, it is, and it's permanent!). Perhaps the output stage is fried, but more likely, I killed the ENABLE signal, which is backed by a transistor, must be a lot of current here... :doge: On the bright side, programmer should be operational now.

Breadboard status update: there are still some minor glitches, but the wirewrapped in-system programmer is now operational. It uses DMA to access and reprogram the EEPROM directly, on-the-fly. Now I'm able to reprogram the computer without turning the power off, physically swapping the EEPROM or changing wires. The ZIF socket also protects the EEPROM pins from damage.

The noise level on the lines is slighter stronger after this modification, but so far still within tolerance.

TI TMS9918/28 video chip uses a 10.738 MHz clock from the analog days, which is just awkward today, PLL/DDS is cheating, easier to use a 21.477 MHz crystal with a CD4017 to divide it by two.

And here's my epic fail: I've assumed all 40xx/74xx were the same, and forgotten the speed here is 21 MHz! :doge: So I ordered random CD4017s, and only to discover today that they would cease to work above 5 MHz :doge:

Only the HCT family can handle that well.

The proper 74HCT4017 divider I wanted for generating the video clock is still on its way. But sometimes, one can just be a bit creative to arrange some ad-hoc solutions before the proper parts arrive. 🤔

One can make a divide-by-2 counter from a D flip-flop, and a flip-flop can be made from NAND gates, problem solved!

Now I can continue building the video output for my breadboard .

Started routing the PCB of my computer in my spare time, still has a long way to go. It's only the CPU board, the memory board probably needs as much work as this one. The bright side is, the routing is not that difficult as I initially thought, all it needs was some pinout adjustments.

Four signals left...

The naughty /INT, /NMI and /HALT did a impressive job interrupting my traces on the PCB, I guess this is why we call them the "interrupt" signals...

Edge connector is routed! A few traces around the CPU still need some routing, but the board is now near-complete.

It's not a complete computer yet, I need to start working on the backplane board and the RAM/ROM board.

First mask. Isn't too bad.

The major limiting factor is the ink-jet printer, the ink just spreads out. Surprisingly, the bus lines still get crystal-clear traces. But the traces at the bottom of the CPU is a bit too dense, I need to increase a little bit of clearance around those areas.

Rev 2, near-perfection. Time to eat some brunch and start bringing my UV light and chemicals out of the dust later...

I etched the CPU board, it looks okay, but don't be fooled...

It's probably the doggy expired chemical sitting in the dust for 6 months I used... There is ZERO continuity anywhere, none of the traces are connected, not even the 20-mil power traces... :oh_no: I've never seen something even close to it...

I'm going to give it another try tomorrow...

I'm now designing the backplane for the computer.

I think I'm gonna need some ESD protections on it, I'm already seeing a future nightmare of someone curiously touching a board during a demo and killing every single TTL, NMOS and CMOS vintage chips on the bus!

Added ESD protection to my computer backplane. I got 100 NXP brand ESD diode for 2 USD, gonna use them generously on other boards.

Running 16-mil traces between DIP pins turned to be a terrible idea, many shorted wires. Before I fixed the design rule for the next board, I have to use this "cutting-edge PCB prototyping tool", it's pretty effective, the only disadvantage is: if you are not careful, it would become the "bleeding-edge" instead...

I thought I have 0805 capacitors for the oscillator, but turned out I only have 0402 in my inventory. Soldered them on the 0805 pad by dragging a lot of solder - not pretty but it does save two days of shipping time...

Finally got some spare time to finish soldering my CPU board. Although there's no ROM, RAM, I/O, or backplane yet, it's now ready for a Power-On Smoke Test!

Without releasing its magic smoke, the CPU board comes alive! starts to fetch, decode and execute instructions as expected, although there's nothing to fetch so far.

My breadboard prototype reached the same first step in April 7th. It's a full cycle redoing it on a PCB four months later, learned a lot about 8-bit machines in this process, will continue updating the thread.

Thinking about making a front panel for my , but I didn't understand how could one "move" the CPU to execute code at an user-specified address. I decided to check Altair 8800.

Basically on the Altair, when you press "Examine", it injects a hardwired 8-bit "JMP" opcode directly to the data bus, single-step, inject low addr, single-step, inject high addr, single-step, done! The CPU just executed a full "JMP xxxxh", while RAM is always disabled so it's unaffected. As easy as that!

I decided to be pragmatic and use a USB port as the power source for my backplane, as those are readily available - a hot and inefficient LM317 doesn't directly contribute to , so I'd skip it for now.

The problem is that there are a hundred types of micro-USB connectors on sale and almost no reusable footprints, have to create my own based on the original mechanical drawings. I hope I correctly interpreted them, I have no idea on anything mechanical, don't even know how to read them...

Backplane for my computer is fully routed.

Drilling those 300 holes one-by-one by hand without a CNC is not the fun thing do to though. :doge:


Fully assembled my backplane!

Nothing fancy for now, it's just a passive board with a USB power port, and a power-on reset button using the 555 timer as a Schmitt trigger inverter.

Time to design the RAM/ROM board.

· · Web · 1 · 4 · 14

@piggo the 100 nF is actually installed, look harder (It's not the best schematics, I know 🤣 ). Also, since I got 100+ TVS, I thought I'd better make use of them liberally.

Sign in to participate in the conversation

the mastodon instance at is retired

see the end-of-life plan for details: