Overall I'm fairly pleased with how the project turned out. It more or less works, in the sense that its an accurate free running digital clock, and the hardware isn't too hacked together. That being said I think there are a number of things I could have done better:
- improved board design
- improved electrical/mechanical integration
- better parts selection
- better software/firmware
Improved board design:
The biggest issue with the main PCB is that it doesn't have a proper high frequency transmission path to the FPGA for the main time source signal. I initially did this since I was worried about needing to swap FPGA pins during development, and I figured my main time source signal wasn't fast enough to warrant designing proper microstriplines and adding RF connectors. In practice these turned out to be not great assumptions, I didn't really need to shuffle FPGA pins, and a 20MHz square wave is really pushing what you can just send down a normal wire. Hence the hack of adding in an SMA cable to get from the main oscillator to the FPGA.
Furthermore, if I was doing this again I think that I would redesign the PCB to plug right into the display module and thereby get rid of the need for a separate display wiring board, which brings me to the next section:
Improved electrical mechanical integration:
Right now the clock's electronics are spread across 3 circuit boards:
- the main board - a custom PCB
- the OCXO board - a chunk of copper clad board
- the wiring board - a chunk of perf-board
and the display module is separate from the main board/wiring board stack. I think that having the oscillator separate from the main board is reasonable since it allows me to change out the oscillator in the future, however, I think that the wiring board and main board probably should have been combined in to one PCB that just mounted onto the back of the display module. This would have reduced the board count, made the insides a lot neater, and would have made the final design a little smaller. I originally decided to separate the wiring board and the main board since I thought that having a general purpose AVR+FPGA board might be handy, but after all of the nonsense of changing the FPGA part way through due to supply issues I'm not sure that the final board is all that useful as a general purpose thing after all.
I also would've done a PCB for the OCXO if I was doing this again, since that way I could get the SMA connector and microstriplines exactly right.
The final major annoyance is that the AVR programming port is buried under the display wiring board, which just adds more friction to the firmware development process. If I was doing this again I'd certainly try to find a better spot for the programmer.
Better parts selection:
I'm not too unhappy with the parts that I ended up using, since they were informed by the current parts shortage, but if that hadn't been an issue I think that I could've done a better job of picking parts.
The FPGA I used is complete overkill for this project, and was really only selected due to availability. Really I should've used a much smaller FPGA, or also put a softcore mcu on the FPGA in addition to my time counting logic.
Conversely the AVR micro is a little anemic. I mostly picked it since I'm familiar with the tools, but handling 64 bit time stamps in 8 bit C gets old fast. The other obvious fast solution would've been to thrown an ESP32 in there and just do everything in micropython, but that feels like overkill. Probably I should've spent some time looking at 32 bit arm stuff, and learning a new tool chain...
I'm very happy with how well the verilog works, and I think I did a good job designing and simulating everything (I was even able to catch a bug in the simulator!), but the firmware and software are another story.
The firmware on the AVR is functional, but pretty rudimentary. Its basically just one giant thread, and I think it could be made a bit more functional if I added interrupt routines to handle the SPI and UART communications since that would allow me to adjust the clock's displayed time without needing to reset everything. The firmware also doesn't handle daylight savings time right now, which is a pretty big issue since it means that the clock will be resynchronized every 6 months, so I won't really get to watch it accumulate error over time. I think this could be fixed by writing firmware that lets me update the display without a reset, or by figuring out a good way to encode all of the nonsense that is timezones in the clock's firmware.
The software that sets the clock from a host computer is also nothing special. Right now its just a hundred lines of python and could certainly be a lot more sophisticated. But for now I think its good enough.
So in conclusion, the clock isn't perfect, but I'm still happy with it. That being said there are some obvious next steps:
there are a few things I still want to do:
- get timezones worked out so that the clock can be truly perpetual
- add an uninterruptible power supply/battery back up so that the clock can be transported/survive power outages without losing the epoch
- change the oscillator for an atomic source
- build an atomic oscilllator?
Getting timezones working is basically just a software/firmware effort and so it shouldn't be that hard, but we'll see how motivated I am to do pure software...
Adding an uninterruptible power supply would be pretty cool and I have some ideas for this right now, but the question of how much power the clock needs will in large part be determined by its oscillator, so this might have to wait until I figure out a better oscillator.
Changing the OCXO for an ebay surplus rubidium oscillator is what I really want to do next since then I'd finally have an atomic clock, but rubidium oscillators are a little expensive (even as surplus), and could likely be a project on its own just to get powered up and working, which is why I didn't do it as part of the first phase of this project. Additionally, I'd like to spend some more time trying to figure out how to characterize the accuracy of my clock as is, since I don't want to spend the money on a rubidium oscillator, unless I can demonstrate that it actually made the clock better, and really measuring the clock's current accuracy could be a project in and of itself...
One day when I'm smarter and I have a lots of time and money (lol) I want to see if I can build a diy atomic oscillator, since I haven't been able to find anyone else who's done one online. This is starting to be the realm of wishful thinking, so I guess I'll end this project here.