Late in the 1990s, I was assigned the task of developing a new version of a proprietary serial-interface board used in my employer’s medical products. The product was based on an x86 PC motherboard with a few—then still popular in embedded systems—ISA bus slots. The current version of the interface then in use had already been ported from a fully discrete circuit to one based on a few PALs. The new product was going to be based on an x86 all-in-one PC board with a PC/104 bus. Because of the smaller form factor of a PC/104 board and a desire to simplify the design, including from a production standpoint, we decided that the new serial-interface board would use a CPLD. Read Also: Defending FPGAs Against Radiation: Detection, Recovery, and Mitigation Strategies for Mission-Critical Systems Navigating the Tradeoffs of Boosting Low AC and DC Voltages in Modern Circuit Design I designed the electrical schematic and sent it to a PCB design house, and a few weeks later we had a few prototypes in hand. After testing and verifying that the boards were functional, I started designing the logic inside the CPLD that would emulate the logic in the current version. The CPLD development environment supported both a graphical interface, in which the logic was laid out much like an electrical schematic, and an HDL-based approach. The two approaches could be mixed if desired. At the time, C compilers were not particularly efficient, even those intended for embedded systems and microcontrollers. I assumed the same was true of the HDL compiler and, given that the CPLD had few resources, I decided to use the old-school method: draw the timing charts on paper, draw the logic that was supposed to implement them, and then enter it into the design tool. Designing the logic on paper took several days, and the result did not work as intended. After a few unsuccessful iterations, I had a meeting with the FAE supporting the CPLD product line. He strongly recommended that I should use the HDL rather than the graphical tool and simply describe what the logic was supposed to do. When I expressed my concern that the HDL implementation might use too many resources, he said something along the lines of “Trust the tool developers; they are very good at this. At least give it a try.” I agreed, and the following day he sent me a template containing the scaffolding code based on the CPLD’s external connections, which saved me hours of work figuring out that part from the documentation. At the time, reference designs and application examples were far less common than they are today. The template spared me that initial steep learning curve, leaving me to focus on the HDL syntax and the logic itself. Having programmed in C and assembly language, that part was relatively straightforward. I then added the code implementing the logic and, voilá, it worked after only a few iterations and in less than one working day. Moreover, the compilation report indicated that the HDL-generated—and correct—logic used fewer resources than my handcrafted—and incorrect—implementation. Fast-forward a few years, and I was working on a different, more complex FPGA-based design using VHDL. I mostly applied what I had learned from the CPLD design experience. Still, I designed part of the logic in a similar fashion, this time out of ignorance rather than stubbornness. For example, I used relatively low-level abstractions, such as counters, registers, and Boolean logic, to implement sequential logic, all using valid VHDL code, instead of using state machines that would have resulted in cleaner, more maintainable code. Another example was instantiating DSP blocks, following the FPGA manufacturer’s documentation, to implement multiply-accumulate (MAC) blocks instead of describing the functionality using arithmetic operations that would result in clearer and shorter code, while letting the synthesis tool infer the correct underlying FPGA resources. Yet another example involved memory blocks: I instantiated the memory components explicitly, following the documentation, instead of simply describing the behavior of a memory, which would also result in shorter, clearer, and more abstract code. I worried that it might use distributed memory instead of the FPGA’s dedicated memory blocks, but it consistently inferred the latter. In later designs, I incorporated these hard-earned lessons, trusting the tools more and more — not blindly, though — and with admiration for those who created them. There are a few lessons in this story. The first is that, when stuck, one should ask for help; a fresh perspective can be surprisingly valuable. The second lesson, which also applies to firmware development, is that one should not try to optimize right at the beginning. Often, the optimization is completely unnecessary and, if it turns out to be necessary, it is easier and more effective to act on a very small part of the design instead of the whole of it. Another lesson is that, when it comes to tools, the people who develop them know their craft; respect that. It can save time, resources, and frustration. Finally, designers should learn what their tools can do. The time invested will pay off, although often the hard part is convincing management (but that is another story for another day 😜). Elder Costa has spent decades having fun developing hardware and firmware, while also taking care of the less enjoyable — but equally essential — tasks of documentation and regulatory affairs support, primarily for medical devices. Post navigation Nintendo Switch 2 Owners Prepare for The Legend of Zelda: Ocarina of Time Remaster With Controller Upgrades