Posted by Doug Amos on March 9, 2012
Following on from our intro to wrappers, and the excellent discussion both here and on LinkedIn groups, I’d like to go into more detail on how we can use wrappers for memories.
As a recap, when mapping SoC RAMs into FPGA it is necessary to adapt the RTL so that the FPGA tool flow can map them into the appropriate resource. We can do this without changing the existing RTL, but instead, we add extra RTL files to act as adaptors; we call these wrappers.
During prototyping, the wrapper contains an item to be implemented in the FPGA, but which has a top-level boundary that maps to the component/module instantiation in the SoC RTL. Experienced prototypers will be very familiar with wrappers and may indeed have built up their own libraries of wrappers for use in various situations. We always like to hear about your experience and methods, so feel free to comment below.
The diagram form the FPMM (above) shows the basic arrangement, in this case of two wrappers used in the same level of hierarchy. Notice that the SoC physical memory is not instantiated directly into the RTL, thus keeping that RTL clean (i.e. not target-specific). The physical memory for the target, usually a generated memory cell for the SoC, is written into the lowest level of hierarchy only. The logical memory instantiation should be chosen to be as generic and reusable as possible.
A naming convention for the logical memory and its ports could be adopted within a project or even across an entire company. Once such an in-house standard is in place, it is easier for prototypers to have a ready-made FPGA or board-level equivalents to fill the wrappers in place of the physical memory.
If a wrapper is not used, and the target-specific physical memory is placed directly into the SoC’s RTL, then it will appear as a black box in the FPGA flow. The prototypers will still need to fill that black box; only now the top-level boundary of the black-box has the names and ports of whichever target-specific physical memory was instantiated, including BIST ports and all. In those cases it is more difficult to understand exactly what memory function is required and less likely that the prototype team will already have an FPGA-ready version, e4specially is your company uses memory cells from different library vendors.
As pointed out in your comments to previous blog postings, a sophisticated approach to swapping the contents of wrappers is to use an IP-XACT description for the wrapper, so we can automate the use of different fillers. A simpler approach is also available in VHDL by the use of Configuration statements, which control the choice between different Architectures for the same Entity. Whichever method is used to control the use of an FPGA or SoC filler for the wrapper, the FPGA version still needs to be created.
I find that the good way to start creating a wrapper is to copy the component/module declaration from the SoC RTL and paste into a new RTL file. This ensures that the boundary of the lower level matches the higher-level instantiation.
Naming can be adopted as standard. for example, in the FPMM workshop labs, we used parameterized memory wrappers with names such as M64X14H1M8S00_wrapper. The M means memory, 64 is the depth in words and 14 is the width of the word, and so forth. Here, we are following the naming scheme used for Synopsys’s own memories (previously Virage logic) but you can adopt any suitable naming style of your own.
We then have to find the equivalent memory for use in the FPGA. The best way to do that (for internal memories) is to let the FPGA synthesis tool infer the memory from an RTL description. An excellent script is available, created by my friend Peter Calabrese, of Synopsys Boston, which parses the wrapper names and creates RTL from which the FPGA tool can infer the necessary rams. If you want to adopt an in-house wrapper scheme, then this might be an easy place to start. Please comment below to email me at firstname.lastname@example.org to let me know what you think.