Using Altera-Provided Parameterized Functions (AHDL)

The Quartus® Prime software includes inherently parameterized megafunctions, including library of parameterized modules (LPM) functions. For example, parameters are used to specify the width of a port or whether a block of RAM should be implemented as synchronous or asynchronous memory. Parameterized functions can contain other subdesigns, which may be parameterized or unparameterized, however, primitives cannot be parameterized. All Quartus® Prime logic functions can be used to create hierarchical logic designs. Megafunctions are automatically installed in the \quartus\libraries\megafunctions directory created during installation; primitive logic is built into AHDL.

Parameterized functions are instantiated with an in-line logic function reference or an Instance Declaration in the same way as unparameterized functions, as described in Using Altera-Provided Unparameterized Functions, with a few additional steps:

The inputs, outputs, and parameters of the function are declared with a Function Prototype Statement. The Quartus® Prime software provides AHDL Include Files (.inc) that contain Function Prototypes for all Quartus® Prime megafunctions in the \quartus\libraries\megafunctions directory.

The lpm_add1.tdf file shown below implements an 8-bit adder with an in-line logic function reference to the parameterized lpm_add_sub megafunction:

INCLUDE "lpm_add_sub.inc";
SUBDESIGN lpm_add1
(
   a[8..1], b[8..1] : INPUT;
   c[8..1]          : OUTPUT;
   carry_out        : OUTPUT;
)
BEGIN
% Megafunction instance with positional port association %
   (c[], carry_out, ) = lpm_add_sub(GND, a[], b[], GND,,) 
                           WITH (LPM_WIDTH=8, 
                                 LPM_REPRESENTATION="unsigned");
% Equivalent instance with named port association %
-- (c[], carry_out, ) = lpm_add_sub(.dataa[]=a[], .datab[]=b[], 
--                            .cin=GND, .add_sub=GND) 
--                         WITH (LPM_WIDTH=8, 
--                               LPM_REPRESENTATION="unsigned");
END;

The Function Prototype for lpm_add_sub, which is stored in the AHDL Include File lpm_add_sub.inc, is shown below:

FUNCTION lpm_add_sub(cin, dataa[LPM_WIDTH-1..0], datab[LPM_WIDTH-1..0], 
      add_sub)
   WITH (LPM_WIDTH, LPM_REPRESENTATION, LPM_DIRECTION, ADDERTYPE, 
      ONE_INPUT_IS_CONSTANT)
   RETURNS (result[LPM_WIDTH-1..0], cout, overflow);

Only the LPM_WIDTH parameter is required, and the instance of the lpm_add_sub function in lpm_add1.tdf specifies parameter values only for the LPM_WIDTH and LPM_REPRESENTATION parameters.

The lpm_add2.tdf file shown below is identical to lpm_add1.tdf, but implements the 8-bit adder with an Instance Declaration:

INCLUDE "lpm_add_sub.inc";
SUBDESIGN lpm_add2
(
   a[8..1], b[8..1] : INPUT;
   c[8..1]          : OUTPUT;
   carry_out        : OUTPUT;
)
VARIABLE
   8bitadder : lpm_add_sub WITH (LPM_WIDTH=8, 
                  LPM_REPRESENTATION="unsigned");
BEGIN
   8bitadder.cin = GND
   8bitadder.dataa[] = a[]
   8bitadder.datab[] = b[]
   8bitadder.add_sub = GND
   c[] = 8bitadder.result[]
   carry_out = 8bitadder.cout
END;