I cross posted this question on the Xilinx Forum here:
http://forums.xilinx.com/t5/Implementation/How-to-determine-what-part-of-the-design-consumes-the-most/td-p/393247
This answer is largely based on the comments there. Thanks to Deepika, Sikta and Gabor.
First, enable 'Generate Detailed MAP Report' in the map process properties (-detail).
Then, open the Design Summary, and navigate to Module Level Utilization. Here is the complete hierarchy, showing exclusive and inclusive design utilization.
Each line will show a number pair like 0/5392. This means that that module contains zero of that specific element, but that module and all of its sub-modules contain a total of 5392 elements.
Here is my output (partially expanded)
When working on reducing the size, Gabor recommends switching to a larger FPGA in the synth tools so that it can completely map even when it's too large to fit in your current FPGA, and it will make the tools run faster.
In VHDL, the basic ASSERT
statement is used to ensure that when you are simulating, you catch all those conditions. Simulation is one step of the debugging process, which is most software-like, as you have access to everything within the design.
You can also (with access to sufficiently high-calibre tools) use PSL to write more complex assertions which can involve timings as well as simple conditionals.
Once you have simulated to your satisfaction, if you need to debug the real hardware, then you can use the following tools:
- embedded logic analyser (Xilinx: Chipscope, Altera: SignalTap) - you build this in at compile time and can then trigger and monitor signals. The signals are captured in real-time to internal memory, so there is a limit on how many and for how long, but it does give excellent visibility. It can be time-consuming though as each time you change your mind about the setup, you have to rebuild the FPGA (which is a process measured in tens of minutes or even hours, depending ont he complexity of the design)
- spare pins - with or without LEDs. Bring out critical internal signals and monitor them with an oscilloscope and logic analyser. Again, rebuild each time you change it. This can also be done more dynamically in Xilinx-land with the FPGA editor, so you can make relatively quick updates to the bitstream, if you can find the signal you want within the optimised netlist!
As Brian pointed out, you will also need an oscilloscope (and potentially logic analyser) to debug the external interfaces - checking the timing etc.
Regarding the issue of having "debug" and "release" builds, that is not handled in a "standard" way (unlike in the software world). The behaviour would not be wildly different in most cases: As the FPGA is very deterministic, you don't lose speed by having debug logic in there (or if you do, it still meets the required spec, as otherwise you couldn't debug the chip!). You do end up with more logic than you need, but again, it has to fit int he device you have (unless you are planning to downsize for release, but given the step ups in device size, you'd need a lot of debug logic for that to be worthwhile!).
Also note that (as far as I've heard) no-one build with different optimiser settings for debug vs. release, which can make finding the signals you want tricky, so you have to add attribute
s to them to stop them being as optimised as they otherwise would be, which is good as the rest of the design gets optimised. Not so good that you have to rebuild to change the attributes. (At least there's plenty of time for keeping your documentation up-to-date while you wait for the builds :)
If you do want to do this then I would suggest a couple of ways:
- Have a boolean
generic
on the top level instance - it can default to debugging off, and you can override it on the command-line/from the GUI of your synthesiser.
- Have a boolean
constant
in a package that you use in your main code - select between the two modes by editing this file
With the first option, only the top-level can see the state of the debug status (unless you pass it down the hierarchy, but that can get nasty quickly as you usually need to pass the debug signals back up then too!).
With the second, any entity can get at the debug constant, and make use of it - again you need to pass signals up the tree.
You can use the boolean in an if..generate..else generate
to instantiate the logic you want (or don;t want) depending on the "mode".
Best Answer
Xilinx Vivado:
Altera Quartus II: