The global chip shortage has placed significant strain on all chip vendors, including FPGA manufacturers, where the risk of the FPGA part not being available when the time comes to mass manufacture your product is now significantly higher than ever before.
It could be that a specific part within a family your team was hoping for is no longer available and another similar part still exists if you are lucky or it could be that FPGA devices from an entire family are no longer available, how can we write flexible HDL code to handle situations like these?
There are times where having a software background can really help with FPGA development and this is one of those times!
In the software world we have the concept of wrappers which in a nutshell is a way of making multiple implementations of a module available which can be selected either at runtime or compile time depending on the needs of the application. We can illustrate this concept pictorially as below:
If we are using Embedded C++ for example, the above diagram describes an ethernet_driver_wrapper class which operates as either an analog_eth or maxim_eth implementation as required. We now have a flexible ethernet driver supporting both an analog ethernet module and maxim ethernet module.
We can then extend this concept over to the FPGA world which we will take a look at both for VHDL and Verilog to keep both camps happy :)
For VHDL we can create a wrapper by having an entity containing multiple architectures or a single architecture with generics and generate statements in the architecture which we can then select as required in the top level.
Let's use an example of implementing a Dual Port Memory Wrapper supporting Xilinx and Efinix devices:
As you can see above, the idea is to simply instantiate the required memory IP module within each architecture. In the top level we can then instantiate the required architecture.
Generic with Generate Statements:
The added C_DEVICE generic shall be used to select the desired implementation.
For Verilog we can create a wrapper by using generate statements where we select the implementation required in the top level.
As above, let's use an example of implementing a Dual Port Memory Wrapper supporting Xilinx and Efinix devices:
NOTE: The entity/module has omitted most of the required signals for brevity in the examples.