Electronic – the proper methodology to create portable FPGA designs

fpgahdlliberoportablequartus

FPGA designs may contain RTL along with IP blocks. These IP blocks most likely shall be from the vendor of the FPGA. Examples of such IP blocks are instantiating dual clock FIFOs, floating point and fixed point maths blocks so we can precisely set the latency e.t.c, low level primitives e.g device I/O buffers e.t.c. Such things cannot be inferred from the RTL code.

It may happen that development is usually carried out on a certain platform e.g Altera Quartus targetting Cyclone V. However, it may be that the final design for whatever reason has to be implemented in a completely different device e.g Microsemi Igloo 2.

What is the proper method to create portable designs in this case?

In theory the proper method will require:

  1. A design where files exist for the two versions of IP blocks from the two vendors. A wrapper can be used to instantiate one of the two IP blocks during simulation and synthesis.

  2. The synthesis tool to determine which files to use and which to exclude as it synthesizes the design. Thus, Quartus shall only use files that are relevant to it and Libero only use those relevant to it.

  3. The simulation tool can be set to compile and simulate design using one of the two vendors' IP.

An assumption made here is IP blocks with similar functions exist from both vendors.

Best Answer

HDL portability, like portability of software, is an unattainable ideal. Every synthesizer has different strategies and different bugs, and vendor specific libraries will come into play. However, it's worth striving for, as actual portability is like actual immortality...you'll never get there, but closer is always better.

Synthesizers can infer latches, and they usually do it in the same way--triggered by a block with a sensitivity list. The primary rule of portable RTL is to write processes that trigger from common clocks. If it's clear from your RTL where the latches are, it should be clear to the synthesizer.

Combinatorial logic can be included in your latching processes to allow the synthesizer freedom to use it at input or output. Keep it outside the latching process if you want to make sure that a specific internal value is latched.

In general, don't partition combinatorial blocks if you don't have to...the compiler may find optimizations you won't. However, if there's a clear and obvious architectural choice (such as a highly optimized algorithm), you might wish to impose that structure implicitly. Further, unusually large blocks of combinatorial logic may send some synthesizers down a rabbit hole; repartitioning could give it guidance.