Creating Hard Macros
It is possible to create special reusable circuit blocks with the Xilinx tools, called hard macros. Hard macros preserve every aspect of a design, from individual LUT configuration down to to the physical routing between components. One can then instantiate this macro in a separate design, and expect that the entity is perfectly replicated on the hardware for each instantiation.
This guide is based on ISE Webpack 12.2, Windows version.
- First have open in ISE the project which you want to transform into a hard macro. Open the routed design in FPGA editor by running "View/Edit Routed Design (FPGA Editor)"
- Save this file as a .nmc macro file. Click File > Save As, Selecting Hard Macro as the type. Save the file into the directory of the project for which you intend to instantiate the hard macro.
- Enable logic changes by opening the dialog under File > Main Properties and changing edit mode to Read Write
- Next, unplace each of the pads. Within FPGA Editor take a look at the list "All Components" in the List window (default). Double-click each item in turn to cause the main window to focus on that component. Right click the component and select "unplace" to remove the component and its associated routing. You will want to unplace all the pads, as well as any buffers that are not to be included in the macro.
- The components that you unplaced are now in the list "Unplaced Components" in the List window. Switch to this list and delete each item by highlighting it and pressing the "Delete" key.
- Add external hard macro pins to the design. These pins represent the public interface to your macro. All other pins will not be visible to your HDL. Select a pin in the main design window, then select Edit > Add Hard Macro External Pin. A dialog appears. Give the hard macro external pin a name--remember this, as it is what you will refer to when you instantiate it in the HDL code. Save the file again after all pins have been added. These pins appear green when the Hard Macros layer button is active on the toolbar.
- Set the Reference Component by selecting a component (eg slice), then clicking Edit > Set Macro Reference Comp. In some sense the Reference Component represents the origin of the macro. That component is marked with a "bull's eye".
- Open the project which will instantiate the hard macro. Instantiate the hard macro as you would any other component, using the filename (minus the file extension) as the component name. Explicitly map each component port name to your local signals. VHDL example is shown. First is the component declaration. The filename was test.nmc, therefore the component name is test:
en: in std_logic;
rst: in std_logic;
q1: out std_logic;
q2: out std_logic
Then the instantiation:
puf1: test port map(
- Each instance of the hard macro must be explicitly placed in the project .ucf file--the tools cannot place them automatically. Note that the macro can only be placed on a component of the same type as the Reference Component. As an example, this macro is only a single slice of type SLICEX, so it is being placed at a location known to be a SLICEX. Example is shown:
INST "puf1" LOC=SLICE_X1Y2;
- Rebuild the project
Caution: Constant signals (VCC/GND) should not be included in a hard macro. This will produce errors when building the instantiating project. Constant signals can be generated using LUTs instead.