📄 lpm_counter.tdf
字号:
-------------------------------------------------------------------------------
--
-- LPM_COUNTER Parameterized Megafunction
--
-- Copyright (C) 1988-1999 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 3.0
--
-------------------------------------------------------------------------------
INCLUDE "lpm_constant";
INCLUDE "lpm_decode";
INCLUDE "lpm_add_sub";
INCLUDE "cmpconst";
INCLUDE "lpm_compare";
INCLUDE "lpm_counter";
INCLUDE "dffeea";
INCLUDE "alt_synch_counter";
INCLUDE "alt_synch_counter_f";
INCLUDE "alt_counter_f10ke";
INCLUDE "alt_counter_stratix";
INCLUDE "aglobal60"; -- device family definitions
FUNCTION p8count(clk, clrn, setn, ldn, dnup, gn, h, g, f, e, d, c, b, a)
RETURNS (qh, qg, qf, qe, qd, qc, qb, qa, cout);
FUNCTION f8count(clk, clrn, setn, ldn, dnup, gn, h, g, f, e, d, c, b, a)
RETURNS (qh, qg, qf, qe, qd, qc, qb, qa, cout);
OPTIONS NAME_SUBSTITUTION = ON;
OPTIONS TREAT_DEFAULT_VALUE_AS_UNUSED = ON;
-------------------------------------------------------------------------------
PARAMETERS
(
LPM_WIDTH,
LPM_DIRECTION = "DEFAULT", -- optional, "UP", "DOWN" or "DEFAULT"
LPM_MODULUS = 0, -- optional, for modulus counters
LPM_AVALUE = "UNUSED", -- optional, asynchronous set value (loaded by aset)
LPM_SVALUE = "UNUSED", -- optional, synchronous set value (loaded by sset)
LPM_PORT_UPDOWN = "PORT_CONNECTIVITY", -- "PORT_USED", "PORT_UNUSED" or "PORT_CONNECTIVITY"
DEVICE_FAMILY, -- optional
CARRY_CHAIN = "IGNORE", -- optional
CARRY_CHAIN_LENGTH = 32, -- optional
NOT_GATE_PUSH_BACK = "OFF", -- optional, "ON" or "OFF"
CARRY_CNT_EN = "SMART", -- optional, "SMART", "ON" or "OFF"
LABWIDE_SCLR = "ON", -- optional, "ON" or "OFF"
USE_NEW_VERSION = "TRUE", -- optional, "TRUE" or "FALSE"
CBXI_PARAMETER = "NOTHING"
);
-- Constant defenition
-- this constant is to determine the minimum maximum chain length that will be
-- tolerated by the newer version of the counter
CONSTANT LOWER_CHAIN_LIMIT = 4;
-------------------------------------------------------------------------------
-- Determines whether or not to pass this function on to another module
DEFINE USE_OLD_VERSION() = USE_NEW_VERSION == "FALSE" # CARRY_CNT_EN == "OFF" #
LABWIDE_SCLR == "OFF" # !USE_CARRY_CHAINS() #
CARRY_CHAIN_LENGTH < LOWER_CHAIN_LIMIT # LPM_WIDTH <= 1
-- also check if there is a wysiwyg implementation
-- available
# (FAMILY_APEX20K() == 0 & FAMILY_APEX20KE() == 0 & FAMILY_APEXII() == 0
& FAMILY_FLEX6000() == 0 & FAMILY_MERCURY() == 0
& FAMILY_FLEX10KE() == 0 & FAMILY_STRATIX() == 0
& FAMILY_FLEX10K() == 0
);
-- currently only APEX20K & APEX20KE have the wysiwyg
-- implemntation available to force the chains
-------------------------------------------------------------------------------
-- Determines whether clearbox is used.
DEFINE CBX_FAMILY() = ((FAMILY_STRATIX() == 1 # FAMILY_STRATIXII() == 1 # FAMILY_CYCLONEII() == 1) ? 1 : 0);
-------------------------------------------------------------------------------
-- unified netlist connectivity check
DEFINE USED_UPDOWN() = LPM_PORT_UPDOWN == "PORT_USED" # (LPM_PORT_UPDOWN != "PORT_UNUSED" & USED(updown));
-------------------------------------------------------------------------------
-- Evaluated functions
DEFINE break_chain_here(p) = -- When to break carry chains
CEIL(LPM_WIDTH div 2) < CARRY_CHAIN_LENGTH & p == CEIL(LPM_WIDTH div 2)
# CEIL(LPM_WIDTH div 2) >= CARRY_CHAIN_LENGTH & (p mod (CARRY_CHAIN_LENGTH-2)) == 0;
DEFINE ModulusCounter() = -- do we need separate modulus checking logic?
((LPM_MODULUS != 0) & !((LPM_WIDTH<32) & (LPM_MODULUS==2^LPM_WIDTH)));
DEFINE Ceil_Log2_Modulus() = -- Number of bits needed for this LPM_MODULUS
(LPM_MODULUS != 0) ?
(LPM_MODULUS<0 ? (LPM_MODULUS==2^31 ? 31:32) : CEIL(LOG2(LPM_MODULUS)))
: 1;
DEFINE OK_to_use_pcustom() = -- If counter is simple enough, use custom logic for p-term
(LPM_WIDTH<=MAXPIA_SIZE())
& (FAMILY_FLEX() == 0)
& USED(aconst) == 0 & USED(sconst) == 0
& USED(aset) == 0 & USED(sset) == 0
& USED(aload) == 0 & USED(sload) == 0 & USED(data) == 0
& !ModulusCounter();
DEFINE OK_to_use_8count() = -- Can we just use 8count?
(LPM_WIDTH<=MAXPIA_SIZE())
& (FAMILY_FLEX()==0 # !USE_CARRY_CHAINS())
& (Is_multiple_of_8(LPM_WIDTH) # USED(cout)==0)
& (USED(cnt_en)==0 # USED(cout)==0)
& USED(aconst)==0 & USED(sconst)==0 & USED(clk_en)==0
& USED(aset)==0 & USED(sclr)==0
& (USED(sset)==0 # (USED(sload)==0 & USED(aload)==0))
& !ModulusCounter();
DEFINE Is_multiple_of_8(a) = (CEIL(a div 8) == FLOOR(a div 8));
-- if aconst or aset is used in a FLEX 8000 or FLEX 10K device, NOT_GATE_PUSH_BACK must be turned off
DEFINE need_not_gate_push_back_off() =
(NOT_GATE_PUSH_BACK == "ON")
& (FAMILY_FLEX() == 1)
& (FAMILY_HAS_NATIVE_ALOAD() == 1)
& (USED(aconst) # USED(aset));
-- If the device family doesn't have preset capability,
-- then we will need external async control logic
DEFINE NEED_dffeea() = (FAMILY_HAS_PRESET()==0) & (USED(aload) # (USED(aclr) & USED(aset)));
-------------------------------------------------------------------------------
-- For FLEX devices
-- UP or DOWN counter ?
DEFINE COUNT_ONLY_UP() = ((LPM_DIRECTION=="UP") # ((LPM_DIRECTION=="DEFAULT") & !USED_UPDOWN()));
DEFINE COUNT_ONLY_DOWN() = (LPM_DIRECTION=="DOWN");
DEFINE COUNT_UP() = (!COUNT_ONLY_DOWN()); -- up or up/down counter
DEFINE COUNT_DOWN() = (!COUNT_ONLY_UP()); -- down or up/down
-- check if we use clr for modulus overflow
DEFINE UseSyncClrModUp() = ( (COUNT_ONLY_UP() # USED_UPDOWN()) & (LPM_MODULUS != 0)
& (nBasicExtraSyncInput()>0) -- don't use clr if basic counter
-- FLEX10K and 8K specific: to be removed when SPR42458 is closed
-- & !(((FAMILY_FLEX10K()==1) # (FAMILY_FLEX8000()==1)) & USED_UPDOWN() %& !USED(SCLR)%)
);
-- count the number of extra sync inputs
DEFINE nBasicExtraSyncInput() = ExtraUpDown() + (USED(clk_en) & 1) + (USED(cnt_en) & 1) + (USED(cin) & 1) +
(USED(sclr) & 1) + (USED(sset) & 1) + (USED(sload) & 1) +
(ModulusCounter() & COUNT_UP() & 1) + (ModulusCounter() & COUNT_DOWN() & 1);
DEFINE UseFuncSCLR() = (UseSyncClrModUp() # USED(sclr));
DEFINE UseClearableCounterMode() = (FAMILY_HAS_CLEARABLE_COUNTER_MODE() & UseFuncSCLR() & !USED_UPDOWN());
DEFINE UseLabWideSclr()= ((FAMILY_HAS_LABWIDE_SCLR()==1) & UseFuncSCLR() & (LABWIDE_SCLR=="ON"));
-- & (nBasicExtraSyncInput()>2)); -- don't use lab-wide clr if basic counter
DEFINE FLEXUseCarryChain() =
-- !(need_not_gate_push_back_off()) & !(OK_to_use_8count()) &
!USED(sconst) & (FAMILY_FLEX()==1) & (USE_CARRY_CHAINS()) & (CARRY_CHAIN_LENGTH>3) & (LPM_WIDTH > 1);
-------------------------------------------------------------------------------
-- The dedicated inputs of a counter are UpDown, SClr and Data/nLoad (FLEX10K).
-- The FLEX LCELL have an extra input to accommodate any extra sync signal
-- like SSet or Wrap (modulus).
-- Check if sclr should be counted as an extra input.
DEFINE ExtraInputSClr() = (UseFuncSCLR() & !UseClearableCounterMode() & !UseLabWideSclr() & 1);
-- modulus
DEFINE UpWrapLoad() = (ModulusCounter() & COUNT_UP() & !UseSyncClrModUp() & 1);
DEFINE DnWrapLoad() = (ModulusCounter() & COUNT_DOWN() & 1);
-- updown
DEFINE ExtraUpDown() = (USED_UPDOWN() & !FAMILY_HAS_UPDOWN_COUNTER_MODE() & 1);
-- inputs with feedback
DEFINE ExtraClkEn() = (USED(clk_en) & %!FAMILY_HAS_ENABLE_LUT_INPUT() &% 1);
DEFINE ExtraCntEn() = (USED(cnt_en) & !CntEnThroughCarryChain() & 1);
DEFINE ExtraExternalFeedback() =
( USED_UPDOWN() & !FAMILY_HAS_UPDOWN_COUNTER_MODE() & (ExtraClkEn() # ExtraCntEn()) ) #
( ExtraClkEn() & ExtraCntEn() );
DEFINE nFeedbackInputs() = ( ExtraClkEn() + ExtraCntEn() + ExtraExternalFeedback() );
-- count the number of extra sync inputs
DEFINE nExtraSyncInput() = ExtraUpDown() + ExtraClkEn()*2 +
ExtraInputSClr() + (USED(sset) & 1) + UpWrapLoad() + DnWrapLoad() + (USED(sload) & 1);
-- Check if we use the carry chain to propagate cnt_en
DEFINE CntEnThroughCarryChain() = USED(cnt_en) & FLEXUseCarryChain() & !USED(cout) &
( (CARRY_CNT_EN=="ON") # ((CARRY_CNT_EN=="SMART") & (nExtraSyncInput()>1)) );
-- # of inputs that may use the nLoad input
DEFINE nLoadInput() = (
(USED(clk_en) & !FAMILY_HAS_ENABLE_LUT_INPUT() & 1) -- use ENA_DATA ?
+ (ExtraCntEn() & -- use LUTCntEn ?
(USED(clk_en) # (USED_UPDOWN() & !FAMILY_HAS_UPDOWN_COUNTER_MODE())) -- with LUT0
# UpWrapLoad() # DnWrapLoad()) -- or with wrap
+ ExtraInputSClr() + (USED(sset) & 1) + UpWrapLoad() + DnWrapLoad() + (USED(sload) & 1)
);
DEFINE nLoadDataInput() = ExtraUpDown() + nFeedbackInputs()
+ ExtraInputSClr() + (USED(sset) & 1) + UpWrapLoad() + DnWrapLoad() + (USED(sload) & 1);
-- Check if we use the LOAD LCELL scheme
DEFINE LoadMuxLCELL() = FLEXUseCarryChain() & !SpecialCase();
-- Special cases where the legacy expression leads to a better result
DEFINE SpecialCase() = USED(clk_en) & (USED(sclr) # USED(sset)) & (nBasicExtraSyncInput()==2);
-- Extra carry-out for modulus down counters
DEFINE SizeCarryChain() = (LPM_WIDTH+1);
DEFINE UseExtraCarryBit4DownWrap() = (DnWrapLoad() & !(
-- speed up simple counters by not using the extra carry-out but a comparator instead
!USED_UPDOWN() &
!(%USED(sclr) #% USED(sset) # USED(sload)) & !(USED(cnt_en) & USED(clk_en))
));
FUNCTION @CBXI_PARAMETER(data[LPM_WIDTH-1..0], clock, clk_en, cnt_en, updown, cin, aclr, aset, aconst, aload, sclr, sset, sconst, sload)
RETURNS( q[LPM_WIDTH-1..0], cout, eq[15..0]);
-------------------------------------------------------------------------------
SUBDESIGN LPM_COUNTER
(
clock : INPUT;
clk_en : INPUT = VCC; -- clock Enable
cnt_en : INPUT = VCC; -- count Enable
updown : INPUT = VCC; -- VCC counts up, GND counts down
aclr, aset, aconst, aload : INPUT = GND;
sclr, sset, sconst, sload : INPUT = GND;
data[LPM_WIDTH-1..0] : INPUT = GND; -- used by aload and/or sload
cin : INPUT = VCC;
q[LPM_WIDTH-1..0] : OUTPUT; -- counter output
cout : OUTPUT;
-- LPM specification calls for the following, but MAX+PLUS II only implements
-- 16 eq outputs:
-- eq[2^LPM_WIDTH-1..0] : OUTPUT;
eq[15..0] : OUTPUT; -- Counter decode output
)
-------------------------------------------------------------------------------
VARIABLE
IF (CBX_FAMILY() == 1 & CBXI_PARAMETER != "NOTHING") GENERATE
auto_generated : @CBXI_PARAMETER WITH (CBXI_PARAMETER = "NOTHING");
ELSE GENERATE
IF USE_OLD_VERSION() GENERATE
IF need_not_gate_push_back_off() GENERATE
c2: lpm_counter WITH( NOT_GATE_PUSH_BACK="OFF", CBXI_PARAMETER = "NOTHING" ); -- New LPM_COUNTER instance
ELSE GENERATE
IF OK_to_use_pcustom() GENERATE
IF LPM_DIRECTION!="DOWN" GENERATE
and_a[LPM_WIDTH-1..0]:NODE;
END GENERATE;
and_b[LPM_WIDTH-1..0]: NODE;
dffs[LPM_WIDTH-1..0]: DFFE; -- state storage
ELSE GENERATE
IF OK_to_use_8count() GENERATE -- feature set is limited to 8count, so use 8count
IF FAMILY_FLEX()==1 GENERATE
p8c[CEIL(LPM_WIDTH div 8)-1..0]: f8count;
ELSE GENERATE
p8c[CEIL(LPM_WIDTH div 8)-1..0]: p8count;
END GENERATE;
ELSE GENERATE
-- state storage
IF NEED_dffeea() GENERATE
dffs[LPM_WIDTH-1..0]: dffeea;
ELSE GENERATE
IF NEED_DFFEA_FOR_ASYNC() GENERATE
dffs[LPM_WIDTH-1..0]: DFFEA;
ELSE GENERATE
dffs[LPM_WIDTH-1..0]: DFFE;
END GENERATE;
END GENERATE;
-- Device aware customization. For device having aload port
IF NEED_DFFEA_FOR_ASYNC() GENERATE
aclr_actual : NODE;
a_val[LPM_WIDTH-1..0] : NODE;
safe_q[LPM_WIDTH-1..0] : NODE;
IF (USED(aset) # USED(aconst)) & USED(aclr) GENERATE
a_data[LPM_WIDTH-1..0] : NODE;
effective_prn[LPM_WIDTH-1..0] : NODE;
effective_clrn[LPM_WIDTH-1..0] : NODE;
pre_latch_signal[LPM_WIDTH-1..0] : NODE;
latch_signal[LPM_WIDTH-1..0] : NODE;
pre_hazard[LPM_WIDTH-1..0] : NODE;
END GENERATE;
END GENERATE;
IF USED(LPM_AVALUE) GENERATE
ac: lpm_constant WITH( LPM_WIDTH=LPM_WIDTH, LPM_CVALUE=LPM_AVALUE, CBXI_PARAMETER = "NOTHING" );
END GENERATE;
IF USED(LPM_SVALUE) GENERATE
sc: lpm_constant WITH( LPM_WIDTH=LPM_WIDTH, LPM_CVALUE=LPM_SVALUE, CBXI_PARAMETER = "NOTHING" );
END GENERATE;
IF FLEXUseCarryChain() GENERATE
carrybit[SizeCarryChain()-1..0] : carry_sum;
Count[LPM_WIDTH-1..0] : NODE;
IF LoadMuxLCELL() GENERATE
IF nLoadInput()<=1 GENERATE nLoad:NODE; ELSE GENERATE nLoad:LCELL; END GENERATE;
IF nLoadDataInput()<=3 GENERATE
LoadLCELL[LPM_WIDTH-1..0]: NODE;
ELSE GENERATE
LoadLCELL[LPM_WIDTH-1..0]: LCELL;
END GENERATE;
IF UseClearableCounterMode() # (UseLabWideSclr() & (USED(clk_en) # UseSyncClrModUp())) GENERATE
nClr : LCELL;
ELSE GENERATE
nClr : NODE;
END GENERATE;
IF USED(clk_en)
# (USED_UPDOWN() & !FAMILY_HAS_UPDOWN_COUNTER_MODE())
# (USED(cnt_en) & !CntEnThroughCarryChain())
# UseClearableCounterMode()
# (!UseLabWideSclr() & UseFuncSCLR())
# USED(sset)
# !USED(cnt_en)
GENERATE -- LUT 0-5 or no cnt_en
Wrap : NODE;
ELSE GENERATE -- LUT 6-7 with cnt_en: special wrap
Wrap : LCELL;
END GENERATE;
LoadModulus[LPM_WIDTH-1..0] : NODE;
LoadCntEn[LPM_WIDTH-1..0] : NODE;
LoadSLoad[LPM_WIDTH-1..0] : NODE;
LoadSSet[LPM_WIDTH-1..0] : NODE;
nState[LPM_WIDTH-1..0] : NODE;
UseSClr, UseSSet, UseSLoad : NODE;
UseLoadCntEn, UseLoadSLoad, UseLoadSSet : NODE;
DnWrapOnly, UseModulus, ENA_DATA, SyncClr, LoadUpWrap : NODE;
LUTCntEn, UseLUTCntEn : NODE;
ELSE GENERATE -- no LoadMuxLCELL
DontWrap: NODE;
END GENERATE;
ELSE GENERATE -- FLEX doesn't UsesCarryChain
nState[LPM_WIDTH-1..0]: NODE;
-- Adder/encoder for next-state logic when count is enabled
IF COUNT_ONLY_UP() GENERATE
add_sub : lpm_add_sub WITH( LPM_WIDTH=LPM_WIDTH, CBXI_PARAMETER = "NOTHING",
ONE_INPUT_IS_CONSTANT="YES",
LPM_DIRECTION="ADD" );
ELSE GENERATE
IF COUNT_ONLY_DOWN() GENERATE
add_sub : lpm_add_sub WITH( LPM_WIDTH=LPM_WIDTH, CBXI_PARAMETER = "NOTHING",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -