In my previous column, I mentioned differences in implementation. Today we'll take a quick look at how the compiler (OK, synthesizer, but I'm probably still gonna call it a compiler) appears to translate some things.
In my brief time here on All Programmable Planet, I've noticed that a lot of people out there are hammering out code to develop not just FPGAs, but also ASICs, PLDs, and whatever other stuff they use HDLs for. I respect those guys a lot -- they're doing lots of work and getting some nifty things done. Hopefully, some of them (and you) respect me for my background of hardware nuts and bolts, even though I've not done all that much.
Or maybe not. Thinking about it, you probably respect me as much as my kids do. To them, I'm just a wallet with wheels.
Speaking of kids, they seem to think you can regularly get something for nothing. That's the whole point of this installment. Let's take a look at the technology schematic of the ring counter we built last time. In the Design Hierarchy window, under the Synthesize line, there is a View Technology Schematic option, as illustrated below.
Double-click that option to access the following dialogue window.
Click OK on the wizard, and you'll be presented with the following schematic/symbol.
No big deal, right? Now double-click on the big symbol, and the integrated software environment will show you what's in the guts, as illustrated below (click here for a larger version).
This looks pretty much like what we built in the schematic, right? Well, now open up Duane Benson's project from a few months back, and do the same thing. Make sure it's all compiled and working, and then take a look at the technology schematic. What do you see? This is what I got (click here for a larger version).
Quite a bit different, huh? Never mind the clock buffer thingy (that's a nifty piece of kit), but the implementation of his design looks to have used a lot more hardware. I see lookup tables, registers, XORs -- maybe twice as much hardware. It looks to me like his single line "led_count <= led_count+1" has created a full adder -- 26 bits wide. Here's that portion of the code (click here for a larger version).
OK, that's neat, and maybe with the way logic cells work, it doesn't make a big difference. But from my point of view, there's a big warning flag waving here. Blindly hammering out code could lead to some unforeseen issues. These issues could be related to timing loop closure, the availablility of resources on your device, or who knows what.
I also have to wonder about optimization. Is this already optimized, or is there another step that cleans some stuff up? Is there a way to see the after-optimization schematic? Is the way Benson incremented his register one reason so much hardware was used? Would it have been different had he added only a single bit?
What do the experts say? Is this something we should worry about? In general, do we use tons more real estate coding in Verilog (or VHDL) than we do just wiring things up by hand? Could these things create timing problems? What are the pitfalls? Was this a stupid exercise and a waste of my time? Are my intuitions like bird dogs barking up the wrong tree?