📄 lpm_ad~1.tdf
字号:
--------------------------------------------------------------------
--
-- LPM_ADD_SUB Parameterized Megafunction
--
-- Copyright (C) 1988-2000 Altera Corporation
-- Any megafunction design, and related net list (encrypted or decrypted),
-- support information, device programming or simulation file, and any other
-- associated documentation or information provided by Altera or a partner
-- under Altera's Megafunction Partnership Program may be used only to
-- program PLD devices (but not masked PLD devices) from Altera. Any other
-- use of such megafunction design, net list, support information, device
-- programming or simulation file, or any other related documentation or
-- information is prohibited for any other purpose, including, but not
-- limited to modification, reverse engineering, de-compiling, or use with
-- any other silicon devices, unless such use is explicitly licensed under
-- a separate agreement with Altera or a megafunction partner. Title to
-- the intellectual property, including patents, copyrights, trademarks,
-- trade secrets, or maskworks, embodied in any such megafunction design,
-- net list, support information, device programming or simulation file, or
-- any other related documentation or information provided by Altera or a
-- megafunction partner, remains with Altera, the megafunction partner, or
-- their respective licensors. No other licenses, including any licenses
-- needed under any third party's intellectual property, are provided herein.
--
-- Version 4.0
--
--------------------------------------------------------------------
---------------------------------------------
-- top level design for lpm_add_sub design --
---------------------------------------------
INCLUDE "lpm_add_sub";
INCLUDE "addcore";
INCLUDE "look_add";
INCLUDE "bypassff";
INCLUDE "altshift";
PARAMETERS
(
LPM_WIDTH,
LPM_REPRESENTATION = "SIGNED",
LPM_DIRECTION = "DEFAULT", -- controlled by add_sub port
ONE_INPUT_IS_CONSTANT = "NO",
LPM_PIPELINE = 0,
MAXIMIZE_SPEED = 5,
OPTIMIZE_FOR_SPEED = 5,
CARRY_CHAIN = "IGNORE",
CARRY_CHAIN_LENGTH = 32,
DEVICE_FAMILY,
STYLE
);
INCLUDE "aglobal.inc"; % device family definitions %
DEFINE MIN(a, b) = a < b ? a : b;
CONSTANT LATENCY = LPM_PIPELINE;
DEFINE CONSTANT_CIN() = (((LPM_DIRECTION == "SUB" # LPM_DIRECTION == "ADD") & !USED(cin)) #
(LPM_DIRECTION == "DEFAULT" & !USED(cin) & !USED(add_sub))) ? 1 : 0;
-- Determine the effective speed (vs. size) optimization factor: If The local
-- param is used, take it as the effective value, otherwise use the global value
CONSTANT SPEED_MAX_FACTOR = USED(MAXIMIZE_SPEED) ? MAXIMIZE_SPEED : OPTIMIZE_FOR_SPEED;
CONSTANT INT_LATENCY = MIN(LPM_WIDTH, (LATENCY+1));
CONSTANT EXT_LATENCY = (LATENCY >= LPM_WIDTH) ? (LATENCY - LPM_WIDTH + 1) : 0;
CONSTANT RWIDTH = LPM_WIDTH MOD INT_LATENCY; -- width of the right side
CONSTANT LWIDTH = INT_LATENCY - RWIDTH; -- width of the left side
-- SUBWIDTH0 = width of the right side adders
-- SUBWIDTH1 = width of the left side adders
CONSTANT SUB_WIDTH1 = FLOOR(LPM_WIDTH DIV INT_LATENCY);
CONSTANT SUB_WIDTH0 = SUB_WIDTH1 + 1;
-- Number of 8-bit adder blocks in carry-look-ahead cases.
CONSTANT BLOCKS = CEIL(LPM_WIDTH DIV 8);
SUBDESIGN lpm_add_sub
(
dataa[LPM_WIDTH-1..0] : INPUT = GND;
datab[LPM_WIDTH-1..0] : INPUT = GND;
cin : INPUT = GND;
add_sub : INPUT = VCC;
clock : INPUT = GND;
aclr : INPUT = GND;
clken : INPUT = VCC;
result[LPM_WIDTH-1..0] : OUTPUT;
cout : OUTPUT;
overflow : OUTPUT;
)
VARIABLE
IF (FAMILY_FLEX() == 1) GENERATE
IF (CARRY_CHAIN != "IGNORE") GENERATE
IF USED(add_sub) & ONE_INPUT_IS_CONSTANT == "NO" GENERATE
datab_node[LPM_WIDTH-1..0] : LCELL;
ELSE GENERATE
datab_node[LPM_WIDTH-1..0] : NODE;
END GENERATE;
ELSE GENERATE
IF USED(add_sub) & ONE_INPUT_IS_CONSTANT == "NO" GENERATE
datab_node[LPM_WIDTH-1..0] : SOFT;
ELSE GENERATE
datab_node[LPM_WIDTH-1..0] : NODE;
END GENERATE;
END GENERATE;
ELSE GENERATE
IF USED(add_sub) & ONE_INPUT_IS_CONSTANT == "NO" GENERATE
datab_node[LPM_WIDTH-1..0] : SOFT;
ELSE GENERATE
datab_node[LPM_WIDTH-1..0] : SOFT;
END GENERATE;
END GENERATE;
cin_node : NODE;
IF INT_LATENCY > 1 GENERATE
IF LPM_REPRESENTATION == "UNSIGNED" & LPM_DIRECTION != "SUB" GENERATE
add_sub_ff[INT_LATENCY-2..0] : bypassff WITH (WIDTH = 1);
END GENERATE;
----------------------------------------------
-- cases where pipeline structure is needed --
----------------------------------------------
IF !(FAMILY_FLEX() == 1) GENERATE
----------------------------------
-- non-FLEX cases --
----------------------------------
-- if a nonhomogenous adder, generate the longer (right side) adders
IF RWIDTH > 0 GENERATE
adder0[RWIDTH-1..0] : lpm_add_sub
WITH (LPM_WIDTH = SUB_WIDTH0,
LPM_DIRECTION = "ADD",
LPM_PIPELINE = 0);
datab0_ff[INT_LATENCY-1..0][RWIDTH-1..0] : bypassff WITH (WIDTH = SUB_WIDTH0);
END GENERATE;
-- generate the shorter (left side) adders
adder1[LWIDTH-1..0] : lpm_add_sub
WITH (LPM_WIDTH = SUB_WIDTH1,
LPM_DIRECTION = "ADD",
LPM_PIPELINE = 0);
datab1_ff[INT_LATENCY-1..0][LWIDTH-1..0] : bypassff WITH (WIDTH = SUB_WIDTH1);
-- inter-stage carry holders
carry_ff[INT_LATENCY-1..0] : bypassff WITH (WIDTH = 1);
-- dataa pipeline registers
dataa_ff[INT_LATENCY-2..0] : bypassff WITH (WIDTH = LPM_WIDTH);
ELSE GENERATE
----------------------------------------------
-- FLEX cases --
----------------------------------------------
-- if a nonhomogenous adder, generate the longer (right side) adders
IF RWIDTH > 0 GENERATE
adder0[RWIDTH-1..0] : lpm_add_sub
WITH (LPM_WIDTH = SUB_WIDTH0 + 1,
LPM_DIRECTION = "ADD",
LPM_PIPELINE = 0);
IF RWIDTH > 1 GENERATE
adder0_0[RWIDTH-1..1] : lpm_add_sub
WITH (LPM_WIDTH = SUB_WIDTH0 + 1,
LPM_DIRECTION = "ADD",
LPM_PIPELINE = 0);
END GENERATE;
datab0_ff[INT_LATENCY-1..0][RWIDTH-1..0] : bypassff WITH (WIDTH = SUB_WIDTH0+1);
adder1_0[LWIDTH-1..0] : lpm_add_sub
WITH (LPM_WIDTH = SUB_WIDTH1 + 1,
LPM_DIRECTION = "ADD",
LPM_PIPELINE = 0);
adder1[LWIDTH-1..0] : lpm_add_sub
WITH (LPM_WIDTH = SUB_WIDTH1 + 1,
LPM_DIRECTION = "ADD",
LPM_PIPELINE = 0);
ELSE GENERATE
adder1[LWIDTH-1..0] : lpm_add_sub
WITH (LPM_WIDTH = SUB_WIDTH1 + 1,
LPM_DIRECTION = "ADD",
LPM_PIPELINE = 0);
IF LWIDTH > 1 GENERATE
adder1_0[LWIDTH-1..1] : lpm_add_sub
WITH (LPM_WIDTH = SUB_WIDTH1 + 1,
LPM_DIRECTION = "ADD",
LPM_PIPELINE = 0);
END GENERATE;
END GENERATE;
datab1_ff[INT_LATENCY-1..0][LWIDTH-1..0] : bypassff WITH (WIDTH = SUB_WIDTH1+1);
IF LPM_REPRESENTATION == "SIGNED" GENERATE
sign_ff[INT_LATENCY-2..0] : bypassff WITH (WIDTH = 2);
END GENERATE;
END GENERATE;
ELSE GENERATE
----------------------------------
-- non-pipelined adder cases --
----------------------------------
-- Will use a look-ahead type adder for FLEX/NORMAL with SPEED_MAX_FACTOR > 5 or
-- MAX/FAST cases. Will use a ripple type adder for all other cases.
IF ((FAMILY_FLEX() == 1) &
(CARRY_CHAIN != "IGNORE" # (CARRY_CHAIN == "IGNORE" & SPEED_MAX_FACTOR <= 5))) #
(!(FAMILY_FLEX() == 1) &
(STYLE == "NORMAL" & SPEED_MAX_FACTOR <= 5)) GENERATE
adder : addcore WITH (WIDTH = LPM_WIDTH, CONSTANT_CIN = CONSTANT_CIN());
ELSE GENERATE
adder[BLOCKS-1..0] : addcore WITH (WIDTH = 8, CONSTANT_CIN = CONSTANT_CIN());
look_aheader : look_add WITH (WIDTH = BLOCKS);
END GENERATE;
END GENERATE;
result_node [LPM_WIDTH-1..0] : NODE;
cout_node : NODE;
result_ext_latency_ffs : altshift WITH (WIDTH = LPM_WIDTH,
DEPTH = EXT_LATENCY);
carry_ext_latency_ffs : altshift WITH (WIDTH = 1,
DEPTH = EXT_LATENCY);
oflow_ext_latency_ffs : altshift WITH (WIDTH = 1,
DEPTH = EXT_LATENCY);
BEGIN
ASSERT REPORT "LPM_WIDTH = %" LPM_WIDTH SEVERITY DEBUG;
ASSERT REPORT "LATENCY = %" LATENCY SEVERITY DEBUG;
ASSERT REPORT "LWIDTH = %" LWIDTH SEVERITY DEBUG;
ASSERT REPORT "RWIDTH = %" RWIDTH SEVERITY DEBUG;
ASSERT REPORT "INT_LATENCY = %" INT_LATENCY SEVERITY DEBUG;
ASSERT REPORT "EXT_LATENCY = %" EXT_LATENCY SEVERITY DEBUG;
ASSERT REPORT "SUB_WIDTH1 = %" SUB_WIDTH1 SEVERITY DEBUG;
ASSERT (LPM_REPRESENTATION == "SIGNED" # LPM_REPRESENTATION == "UNSIGNED")
REPORT "Illegal value for LPM_REPRESENTATION parameter (""%"") -- value must be ""SIGNED"" or ""UNSIGNED"""
LPM_REPRESENTATION
SEVERITY ERROR
HELP_ID LPM_ADD_SUB_REPRESENTATION;
ASSERT (LPM_WIDTH > 0)
REPORT "LPM_WIDTH parameter value must be greater than 0"
SEVERITY ERROR
HELP_ID LPM_ADD_SUB_WIDTH;
ASSERT (USED(clock) ? LATENCY > 0 : LATENCY == 0)
REPORT "Value of LPM_PIPELINE parameter must be greater than 0 if clock input is used and vice versa"
SEVERITY ERROR
HELP_ID LPM_ADD_SUB_CLOCK_WITHOUT_LATENCY;
ASSERT (LATENCY <= LPM_WIDTH)
REPORT "Value of LPM_PIPELINE parameter (%) should be lower -- use % for best performance/utilization" LATENCY, INT_LATENCY
SEVERITY INFO
HELP_ID LPM_ADD_SUB_CLOCK_LATENCY_VALUE;
ASSERT (LPM_WIDTH > 0)
REPORT "Value of LPM_WIDTH parameter must be greater than 0"
SEVERITY ERROR
HELP_ID LPM_ADD_SUB_WIDTH2;
ASSERT (LPM_REPRESENTATION == "UNSIGNED" # LPM_REPRESENTATION == "SIGNED")
REPORT "Illegal value for LPM_REPRESENTATION parameter (%) -- value must be UNSIGNED (the default) or SIGNED"
LPM_REPRESENTATION
SEVERITY ERROR
HELP_ID LPM_ADD_SUB_REPRESENTATION2;
ASSERT (ONE_INPUT_IS_CONSTANT == "YES" # ONE_INPUT_IS_CONSTANT == "NO")
REPORT "Illegal value for ONE_INPUT_IS_CONSTANT parameter (%) -- value must be YES or NO (the default)"
ONE_INPUT_IS_CONSTANT
SEVERITY ERROR
HELP_ID LPM_ADD_SUB_ICONSTANT;
ASSERT (LPM_DIRECTION == "DEFAULT" # LPM_DIRECTION == "ADD" # LPM_DIRECTION == "SUB")
REPORT "Illegal value for LPM_DIRECTION parameter (%) -- value must be ADD, SUB, or DEFAULT"
LPM_DIRECTION
SEVERITY ERROR
HELP_ID LPM_ADD_SUB_DIRECTION;
ASSERT (LPM_DIRECTION == "DEFAULT" # USED(add_sub) == 0)
REPORT "Value of LPM_DIRECTION parameter (%) is not consistent with the use of the add_sub port"
LPM_DIRECTION
SEVERITY ERROR
HELP_ID LPM_ADD_SUB_DIRECTION_ADD_SUB;
-- The next assertion is not implemented because MAX+PLUS II implementation
-- differs from the LPM standard. Both overflow and cout are allowed
-- in MAX+PLUS II.
-- ASSERT (USED(overflow) == 0 # USED(cout) == 0)
-- REPORT "Can't use overflow port if cout port is used"
-- SEVERITY ERROR
-- HELP_ID LPM_ADD_SUB_OVERCOUT;
ASSERT (FAMILY_IS_KNOWN() == 1)
REPORT "Megafunction lpm_add_sub does not recognize the current device family (%) -- ensure that you are using the newest version of the megafunction"
DEVICE_FAMILY
SEVERITY WARNING
HELP_ID LPM_ADD_SUB_FAMILY_UNKNOWN;
----------------------------------------------------------------------
IF LPM_DIRECTION == "SUB" GENERATE
datab_node[] = !datab[];
ELSE GENERATE
IF USED(add_sub) GENERATE
datab_node[] = datab[] $ !add_sub;
ELSE GENERATE
datab_node[] = datab[];
END GENERATE;
END GENERATE;
IF USED(cin) GENERATE
cin_node = cin;
ELSE GENERATE
IF LPM_DIRECTION == "SUB" GENERATE
cin_node = VCC;
ELSE GENERATE
cin_node = !add_sub;
END GENERATE;
END GENERATE;
IF INT_LATENCY > 1 GENERATE
IF LPM_REPRESENTATION == "UNSIGNED" & LPM_DIRECTION != "SUB" GENERATE
add_sub_ff[0].d[0] = add_sub;
IF INT_LATENCY > 2 GENERATE
add_sub_ff[INT_LATENCY-2..1].d[0] = add_sub_ff[INT_LATENCY-3..0].q[0];
END GENERATE;
add_sub_ff[].(clk, clrn) = (clock, !aclr);
IF USED(clken) GENERATE
add_sub_ff[].ena = clken;
END GENERATE;
END GENERATE;
IF !(FAMILY_FLEX() == 1) GENERATE
----------------------------------------------
-- non-FLEX cases --
----------------------------------------------
-- clock connections
dataa_ff[].(clk, clrn) = (clock, !aclr);
IF USED(clken) GENERATE
dataa_ff[].ena = clken;
END GENERATE;
IF RWIDTH > 0 GENERATE
datab0_ff[INT_LATENCY-2..0][].(clk, clrn) = (clock, !aclr);
IF USED(clken) GENERATE
datab0_ff[INT_LATENCY-2..0][].ena = clken;
END GENERATE;
END GENERATE;
datab1_ff[INT_LATENCY-2..0][].(clk, clrn) = (clock, !aclr);
carry_ff[INT_LATENCY-2..0].(clk, clrn) = (clock, !aclr);
IF USED(clken) GENERATE
datab1_ff[INT_LATENCY-2..0][].ena = clken;
carry_ff[INT_LATENCY-2..0].ena = clken;
END GENERATE;
-- dataa connections as we have intermediate subadders.
dataa_ff[0].d[] = dataa[];
IF INT_LATENCY > 2 GENERATE
dataa_ff[INT_LATENCY-2..1].d[] = dataa_ff[INT_LATENCY-3..0].q[];
END GENERATE;
-- datab input connections
IF RWIDTH > 0 GENERATE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -