I'd like to thank all of you generous patrons; your support means that I can commit to doing a proper run of beta boards once the design is ready. With the financial pressure off, I still feel that getting this right is critical: because my available time and energy are now the most limited resource, and each spin of the board would add weeks to the project.
The prototype PCB was designed rather speculatively as I sat on a train crossing Europe. I wasn't exactly sure how it was going to work on the real hardware - being such a complicated system - so I took a best guess at a few things and pushed the button. That turned out to be good enough for the next several years and getting up to a full-featured device.
Along the way this one PCB has collected a lot of bodge wires where I've had to change something. Most of them have been due to unanticipated needs, but a couple of them are due to mistakes in the original board.
Updating the board to include these changes is a not insignificant refactoring. In fact, it's been so long since I touched the original that I can't be entirely sure I have the exact design files that went out to fabrication (this is another type of lesson learned on my part).
I had to think about how I can be confident that I've captured all of the changes I want, and not made any other mistakes. One method would be to take the final design and manually compare every connection on the PCB with what's in my head; but that's a huge task, which makes it error-prone - particularly if I'm regularly interrupted by a tiny human needing attention. And then if I decide to change something I have to do it all over again...
If you've read my posts here then you can probably guess what comes next. Have you worked out what we're looking for? Yes, that's right. The answer is: software.
What are PCBs?
In solving this problem, the place to start is with the ultimate goal. The PCB exists to connect different components together; in this case mostly chips (ICs). Each bit of copper on the PCB connects together two or more pins; such a connection is called a net.
Pretty much every modern PCB design tool works in two phases. First, you define the connections that you want to have: you say what components you want to use, and which pins connect to which other pins. The output of this phase is a list of nets - unsurprisingly called a netlist.
In the second phase, you do the actual physical layout of the board. First you define or choose a footprint for each component, which defines the copper pads that you'll need to solder its pins to. Then you can lay out the parts and run copper traces between them to complete each of the nets.
Modern tools make sure that the layout phase is very hard to get wrong. They use the netlist from the first phase to make sure that what should be connected is connected, and what should not be connected is not. The challenge is in the first phase, where the netlist is created.
The usual method for creating netlists is to essentially draw a schematic in the tool. Each component is represented by some sort of symbol, and lines drawn between their pins indicate connections.
Schematics can get pretty complicated; if you had to draw wires for every connection, you'd end up with an unreadable mess - particularly if split across several pages. You can also specify connections by using netlabels - these are text tags which say "this wire is part of net X". By placing netlabels on different wires, you can indicate that they are connected without having a wire drawn all the way between them every time.
This is one place I made a mistake. I connected various signals from the MCU to the MicroSD slot using netlabels; one of these was a clock signal. I carefully wrote MCK at the MCU end - and then MCLK at the SD card. This formed two separate nets, each with one pin - rather than the connection I needed.
This is an example of a problem that can be caught by PCB programs: any net which only has one pin is probably a mistake. When a pin should not be connected to anything, the user can be forced to put in an explicit no-connect marker. Unfortunately I either didn't have these configured or didn't run whatever manual process was required, so this error snuck through.
Most mistakes are much harder for programs to catch. A particular challenge is that, with many complex modern chips, the exact function of each pin can be reconfigured. In this project, almost every pin on the CPLD can be used interchangeably; it's up to me to specify the pin locations as an input to the logic compilation process, and then verify that they are unchanged at the end of compilation.
Even more complicated is the MCU. Most of its pins can be used as general purpose input/outputs (GPIOs), which means they can be set as input or output and controlled by software, when that's appropriate. But that's not suitable for every task; sometimes you need to use dedicated hardware peripherals, which can include serial ports, audio interfaces, and so forth. Each peripheral can only be used on very particular pins. All of this functionality is configured by the firmware, so the PCB tool has zero idea about any of it.
MCU pin configuration is complex and tedious, and in many designs it tends to be scattered throughout the firmware. In this case, I avoided this problem by writing a tool in the early days of the project that autogenerates the configuration and access code based on a very simple centralised pin specification. This has saved me a lot of time whenever I've needed to add, change, or look up pins.
Unfortunately, I did that only after building the hardware, so it didn't catch my second mistake: mixing up two of the I2S signals that carry CD audio out of the card. Because the audio output uses one of the on-chip peripherals, there was no way to remap the pins after the fact, so I had to cut the traces and bodge it up.
These mistakes are simple, but they took time to track down and time to fix. Now that time's more precious than ever, I'd rather spend a little time avoiding them; particularly where I'm going to be assembling a number of beta boards to send out, that time really adds up. So I spent an evening writing a tool to check for these and several other classes of problem. This tool needs to check the PCB netlist contains the connections that I actually want.
I already have machine-readable files which list the pin configuration of the MCU and the CPLD, which I can guarantee are in sync with the firmware and the configurable logic. To these I add pinouts for things which don't change: the SD card and Saturn connector, for example.
I still need to describe what I actually want to have connected. For this all I need is a simple spreadsheet: each row describes a net, and where I want a connection, I fill in the pin name. This is so simple that I can very easily check it manually - so that I don't end up back where I started with another hellishly complex thing to check.
Now, I have a little script that ingests all the pinouts and the connection spreadsheet; it then slurps up the PCB netlist and tells me all my mistakes. Here it is running against what I have for the prototype PCB:
This not only shows my original mistakes, but also where the firmware has changed since I designed the board. In fact, it correctly captures every bodge wire that I've put on there for any reason (not all are shown); this result validates the tool.
There's certainly room for further improvement - for example, it doesn't currently handle peripheral pin functions in full detail, which it could do in future, but that's not a class of problem I can cause from this point.
Bringing up the new PCB is the most significant design risk going into beta phase. A mistake here could cost days of debugging and then weeks waiting for a new board.
My new tool guarantees that the PCB netlist will be functionally identical to the current, working prototype with all its bodge wires (as well as verifying some new additions and changes). Since I can already rely on the layout stage after netlisting, this means that I can be 100% confident that the PCB will be electrically correct, first try.
The tool took about an evening to write - comparable to the time it took to write up this post. Definitely a case where a gram of prevention is worth a tonne of cure, and an approach I'll reuse in future projects.
I've also completed various more time-consuming things for the PCB respin, like choosing new components and entering footprints. I still need to make some mechanical decisions around housing the card, but at this point I'm ready to begin the actual layout. Thanks to the enforced correctness of netlisted PCB layout, I can do that in dribs and drabs as I get time.