📄 lpm_counter.tdf
字号:
dffs[].clk = clock;
ce = cnt_en & cin;
-- Asynchronous signals
IF NEED_DFFEA_FOR_ASYNC() GENERATE
-- generating the constants for AVALUE, SVALUE
IF USED(LPM_AVALUE) GENERATE
a_val[] = ac.result[];
ELSE GENERATE
a_val[] = VCC;
END GENERATE;
dffs[].clrn = !aclr_actual;
IF USED(aset) # USED(aconst) GENERATE
IF USED(aclr) GENERATE -- latch circuitry
aclr_actual = aclr # aset # aconst # aload;
a_data[] = ((aset # aconst) & a_val[]) # ((aset !# aconst) & data[]);
effective_clrn[] = !(aclr # (!a_data[] & (aset # aconst # aload)));
effective_prn[] = !((aset # aconst # aload) & a_data[]);
pre_latch_signal[] = effective_prn[] & latch_signal[];
latch_signal[] = !effective_clrn[] # pre_latch_signal[];
ELSE GENERATE -- pushback circuitry for aset
aclr_actual = aclr # aset # aconst;
-- The usage of !aclr and !aset is to temporary workaround the priority problem in functional simulation
dffs[].aload = aload & !aclr & !aset;
dffs[].adata = data[] $ a_val[];
END GENERATE;
ELSE GENERATE -- Normal circuitry without latch or pushback
aclr_actual = aclr # aset # aconst;
-- The usage of !aclr and !aset is to temporary workaround the priority problem in functional simulation
dffs[].aload = aload & !aclr & !aset;
dffs[].adata = data[];
END GENERATE;
ELSE GENERATE
IF (USED(aconst)) GENERATE
dffs[].clrn = (!aconst # ac.result[]) & (aconst # !aload # data[]);
dffs[].prn = (!aconst # !ac.result[]) & (aconst # !aload # !data[]);
ELSE GENERATE
IF (USED(LPM_AVALUE)) GENERATE
dffs[].clrn = !aclr & (!aset # ac.result[]) & (aset # !aload # data[]);
dffs[].prn = aclr # (!aset # !ac.result[]) & (aset # !aload # !data[]);
ELSE GENERATE
IF (USED(aclr) # USED(aload)) GENERATE
dffs[].clrn = !aclr & (aset # !aload # data[]);
END GENERATE;
IF (USED(aset) # USED(aload)) GENERATE
dffs[].prn = aclr # !aset & (!aload # !data[]);
END GENERATE;
END GENERATE;
END GENERATE;
END GENERATE;
--------------------------------------------------------------------
-- Synchronous signals
IF COUNT_ONLY_UP() GENERATE
DirUpDown = VCC;
ELSE GENERATE
IF COUNT_ONLY_DOWN() GENERATE
DirUpDown = GND;
ELSE GENERATE
IF USED_UPDOWN() GENERATE
DirUpDown = updown;
ELSE GENERATE
DirUpDown = VCC;
END GENERATE;
END GENERATE;
END GENERATE;
IF NEED_dffeea() GENERATE
ASSERT (0) REPORT "NEED_dffeea" SEVERITY DEBUG;
END GENERATE;
--------------------------------------------------------------------
IF FLEXUseCarryChain() GENERATE
ASSERT (0) REPORT "SpecialCase()=%" SpecialCase() SEVERITY DEBUG;
ASSERT (0) REPORT "LoadMuxLCELL()=%" LoadMuxLCELL() SEVERITY DEBUG;
ASSERT (0) REPORT "UseClearableCounterMode()=%" UseClearableCounterMode() SEVERITY DEBUG;
ASSERT (0) REPORT "UseLabWideSclr()=%" UseLabWideSclr() SEVERITY DEBUG;
ASSERT (0) REPORT "CntEnThroughCarryChain()=%" CntEnThroughCarryChain() SEVERITY DEBUG;
ASSERT (0) REPORT "UseSyncClrModUp()=%" UseSyncClrModUp() SEVERITY DEBUG;
ASSERT (0) REPORT "COUNT_ONLY_UP()=%" COUNT_ONLY_UP() SEVERITY DEBUG;
--------------------------------------------------------------------
-- Generates the counter with the carry chain
IF NEED_DFFEA_FOR_ASYNC() GENERATE
Count[] = carrybit[LPM_WIDTH-1..0].cout xor safe_q[];
ELSE GENERATE
Count[] = carrybit[LPM_WIDTH-1..0].cout xor dffs[].q;
END GENERATE;
q[] = carrybit[LPM_WIDTH..1].sout;
IF CntEnThroughCarryChain() GENERATE
carrybit[0].cin = cnt_en and cin;
ELSE GENERATE
carrybit[0].cin = cin;
END GENERATE;
carrybit[0].sin = VCC;
IF SizeCarryChain()>1 GENERATE
IF CARRY_CHAIN_LENGTH>=LPM_WIDTH GENERATE
IF NEED_DFFEA_FOR_ASYNC() GENERATE
carrybit[SizeCarryChain()-1..1].cin =
(safe_q[SizeCarryChain()-2..0] !$ DirUpDown) & carrybit[SizeCarryChain()-2..0].cout;
ELSE GENERATE
carrybit[SizeCarryChain()-1..1].cin =
(dffs[SizeCarryChain()-2..0].q !$ DirUpDown) & carrybit[SizeCarryChain()-2..0].cout;
END GENERATE;
ELSE GENERATE
IF NEED_DFFEA_FOR_ASYNC() GENERATE
FOR ebit IN 1 TO SizeCarryChain()-1 GENERATE
IF (break_chain_here(ebit)) GENERATE
carrybit[ebit].cin = LCELL(CARRY(
(safe_q[ebit-1] !$ DirUpDown) & carrybit[ebit-1].cout ));
ASSERT REPORT "Breaking carry chain at bit %" ebit SEVERITY DEBUG;
ELSE GENERATE
carrybit[ebit].cin = (safe_q[ebit-1] !$ DirUpDown) & carrybit[ebit-1].cout;
END GENERATE;
END GENERATE;
ELSE GENERATE
FOR ebit IN 1 TO SizeCarryChain()-1 GENERATE
IF (break_chain_here(ebit)) GENERATE
carrybit[ebit].cin = LCELL(CARRY(
(dffs[ebit-1].q !$ DirUpDown) & carrybit[ebit-1].cout ));
ASSERT REPORT "Breaking carry chain at bit %" ebit SEVERITY DEBUG;
ELSE GENERATE
carrybit[ebit].cin = (dffs[ebit-1].q !$ DirUpDown) & carrybit[ebit-1].cout;
END GENERATE;
END GENERATE;
END GENERATE;
END GENERATE;
END GENERATE;
IF !ModulusCounter() GENERATE
cout = carrybit[LPM_WIDTH].cout;
ELSE GENERATE
cout = (upwrap or dnwrap) and cin;
cout = carrybit[LPM_WIDTH].cout and gnd; -- get rid of warning
END GENERATE;
--------------------------------------------------------------------
-- Special logic for MODULUS counters
IF !ModulusCounter() GENERATE
upwrap = GND;
dnwrap = GND;
ELSE GENERATE
IF COUNT_UP() GENERATE
IF NEED_DFFEA_FOR_ASYNC() GENERATE
upwrap = DirUpDown &
lpm_compare( .dataa[]=safe_q[], .datab[]=scdw.result[] )
WITH( LPM_WIDTH=LPM_WIDTH, ONE_INPUT_IS_CONSTANT="YES",
CASCADE_CHAIN = "IGNORE" )
RETURNS( .aeb );
ELSE GENERATE
upwrap = DirUpDown &
lpm_compare( .dataa[]=dffs[].q, .datab[]=scdw.result[] )
WITH( LPM_WIDTH=LPM_WIDTH, ONE_INPUT_IS_CONSTANT="YES",
CASCADE_CHAIN = "IGNORE" )
RETURNS( .aeb );
END GENERATE;
ELSE GENERATE
upwrap = GND;
END GENERATE;
IF COUNT_DOWN() GENERATE
IF UseExtraCarryBit4DownWrap() GENERATE
dnwrap = !DirUpDown & carrybit[LPM_WIDTH].cout;
ELSE GENERATE
IF NEED_DFFEA_FOR_ASYNC() GENERATE
dnwrap = !DirUpDown &
lpm_compare( .dataa[]=safe_q[], .datab[]=0 )
WITH( LPM_WIDTH=LPM_WIDTH, ONE_INPUT_IS_CONSTANT="YES",
CASCADE_CHAIN = "IGNORE" )
RETURNS( .aeb );
ELSE GENERATE
dnwrap = !DirUpDown &
lpm_compare( .dataa[]=dffs[].q, .datab[]=0 )
WITH( LPM_WIDTH=LPM_WIDTH, ONE_INPUT_IS_CONSTANT="YES",
CASCADE_CHAIN = "IGNORE" )
RETURNS( .aeb );
END GENERATE;
END GENERATE;
ELSE GENERATE
dnwrap = GND;
END GENERATE;
END GENERATE; -- ModulusCounter()
-------------------------------------------------------------------------------
-- Counter using the LUT load feature in Up/Down or Clearable counter mode
IF LoadMuxLCELL() GENERATE
IF USED(cnt_en) & !CntEnThroughCarryChain() &
(USED(clk_en) # (USED_UPDOWN() & !FAMILY_HAS_UPDOWN_COUNTER_MODE())) -- LUT0 only
GENERATE
LUTCntEn = cnt_en;
UseLUTCntEn = VCC;
ELSE GENERATE -- LUT1..7 assume cnt_en is already taken care of
LUTCntEn = VCC;
UseLUTCntEn = GND;
END GENERATE;
SyncClr = sclr;
IF UseSyncClrModUp() GENERATE
SyncClr = upwrap & !sset & !sload & ce;
LoadUpWrap = GND;
ELSE GENERATE
LoadUpWrap = upwrap;
END GENERATE;
-- Generates the Wrap signal according to the LUT used
IF USED(clk_en)
# (USED_UPDOWN() & !FAMILY_HAS_UPDOWN_COUNTER_MODE())
# (USED(cnt_en) & !CntEnThroughCarryChain())
# UseClearableCounterMode()
# (!UseLabWideSclr() & UseFuncSCLR())
# USED(sset)
GENERATE -- LUT 0-5: Wrap is a NODE
Wrap = ce & (LoadUpWrap # dnwrap);
ELSE GENERATE
IF COUNT_ONLY_UP() & !UseSyncClrModUp() GENERATE
-- LUT 6: Wrap is an LCELL for special wrap up
Wrap = ce & LoadUpWrap;
ELSE GENERATE
-- LUT 7: Wrap is an LCELL for special wrap down
Wrap = ce & dnwrap;
END GENERATE;
END GENERATE;
-- input usage nodes
IF UseFuncSCLR() GENERATE
UseSClr = VCC;
ELSE GENERATE
UseSClr = GND;
END GENERATE;
IF USED(sset) GENERATE
UseSSet = VCC;
ELSE GENERATE
UseSSet = GND;
END GENERATE;
IF USED(sload) GENERATE
UseSLoad = VCC;
ELSE GENERATE
UseSLoad = GND;
END GENERATE;
-- Generates Modulus related flags
IF !ModulusCounter() GENERATE
UseModulus = GND;
DnWrapOnly = GND;
ELSE GENERATE
IF UseSyncClrModUp() & COUNT_ONLY_UP() GENERATE
UseModulus = GND; -- sclr does modulus roll-over
ELSE GENERATE
UseModulus = VCC;
END GENERATE;
IF COUNT_ONLY_DOWN() GENERATE
DnWrapOnly = VCC;
ELSE GENERATE
DnWrapOnly = GND;
END GENERATE;
END GENERATE;
LoadModulus[] = (dnwrap # DnWrapOnly) & scdw.result[];
UseLoadCntEn = UseModulus # UseLUTCntEn;
IF NEED_DFFEA_FOR_ASYNC() GENERATE
LoadCntEn[] = ( LUTCntEn & LoadModulus[] ) #
( (!LUTCntEn # !UseModulus) & UseLUTCntEn & safe_q[] );
ELSE GENERATE
LoadCntEn[] = ( LUTCntEn & LoadModulus[] ) #
( (!LUTCntEn # !UseModulus) & UseLUTCntEn & dffs[].q );
END GENERATE;
UseLoadSLoad = UseSLoad # UseLoadCntEn;
LoadSLoad[] = ( (sload # !UseLoadCntEn) & data[] ) #
( !sload & LoadCntEn[] );
UseLoadSSet = UseSSet # UseLoadSLoad;
IF USED(LPM_SVALUE) GENERATE
LoadSSet[] = ( (sset # !UseLoadSLoad) & sc.result[] ) #
( !sset & LoadSLoad[] );
ELSE GENERATE
LoadSSet[] = ( (sset # !UseLoadSLoad) & UseSSet) # (!sset & LoadSLoad[]);
END GENERATE;
-- clk_en
IF FAMILY_HAS_ENABLE_LUT_INPUT() GENERATE
dffs[].ena = clk_en;
ENA_DATA = VCC;
ELSE GENERATE
ENA_DATA = clk_en;
END GENERATE;
-------------------------------------------------------------------------------
-- LUT logic
-- first we use the ENA input if available
IF USED(clk_en) & FAMILY_HAS_ENABLE_LUT_INPUT() GENERATE -- FLEX10K LUT input used ?
nState[] = Count[];
IF UseClearableCounterMode() # UseLabWideSclr() GENERATE -- space for nClr ?
ASSERT (0) REPORT "LUT0a" SEVERITY DEBUG;
nClr = !SyncClr;
LoadLCELL[] = LoadSSet[];
nLoad = !(sset # sload # !LUTCntEn # Wrap);
ELSE GENERATE -- no space for extra LUT input
ASSERT (0) REPORT "LUT0b" SEVERITY DEBUG;
nClr = VCC;
LoadLCELL[] = !SyncClr & LoadSSet[];
nLoad = !(SyncClr # sset # sload # !LUTCntEn # Wrap);
END GENERATE;
ELSE GENERATE
-- next we check if updown fills up the LUT
IF USED_UPDOWN() & !FAMILY_HAS_UPDOWN_COUNTER_MODE() GENERATE -- FLEX6000 LUT input used ?
nState[] = Count[];
IF UseClearableCounterMode() # UseLabWideSclr() GENERATE -- space for nClr ?
ASSERT (0) REPORT "LUT0c" SEVERITY DEBUG;
nClr = !(SyncClr & ENA_DATA);
LoadLCELL[] = (ENA_DATA & LoadSSet[]) # ((!ENA_DATA # !UseLoadSSet) & dffs[].q);
nLoad = !(!ENA_DATA # sset # sload # !LUTCntEn # Wrap);
ELSE GENERATE -- no space for extra LUT input
ASSERT (0) REPORT "LUT0d" SEVERITY DEBUG;
nClr = VCC;
LoadLCELL[] = (ENA_DATA & !SyncClr & UseLoadSSet & LoadSSet[]) #
((!ENA_DATA # !(UseLoadSSet # UseSClr)) & dffs[].q);
nLoad = !(!ENA_DATA # SyncClr # sset # sload # !LUTCntEn # Wrap);
END GENERATE;
ELSE GENERATE
-- next we try to feed the LUT with clk_en
IF USED(clk_en) GENERATE --> FLEX6000 or FLEX8000
nState[] = (ENA_DATA & Count[]) # (!ENA_DATA & dffs[].q);
IF UseClearableCounterMode() # UseLabWideSclr() GENERATE -- space for nClr ?
ASSERT (0) REPORT "LUT0e" SEVERITY DEBUG;
nClr = !(SyncClr & ENA_DATA);
LoadLCELL[] = LoadSSet[];
nLoad = !(ENA_DATA & (sset # sload # !LUTCntEn # Wrap));
ELSE GENERATE -- no space for extra LUT input
ASSERT (0) REPORT "LUT0f" SEVERITY DEBUG;
nClr = VCC;
LoadLCELL[] = !SyncClr & LoadSSet[];
nLoad = !(ENA_DATA & (SyncClr # sset # sload # !LUTCntEn # Wrap));
END GENERATE;
ELSE GENERATE
-- no clk_en, so we try to feed the unused LUT input
IF USED(cnt_en) & !CntEnThroughCarryChain() GENERATE
ASSERT (0) REPORT "LUT1" SEVERITY DEBUG;
IF UseClearableCounterMode() # UseLabWideSclr() GENERATE -- space for nClr ?
nClr = !SyncClr;
IF NEED_DFFEA_FOR_ASYNC() GENERATE
nState[] = (ce & Count[]) # (!ce & safe_q[]);
ELSE GENERATE
nState[] = (ce & Count[]) # (!ce & dffs[].q);
END GENERATE;
LoadLCELL[] = LoadSSet[];
nLoad = !(sset # sload # Wrap);
ELSE GENERATE
nClr = VCC;
IF NEED_DFFEA_FOR_ASYNC() GENERATE
nState[] = (ce & Count[]) # (!ce & safe_q[]);
ELSE GENERATE
nState[] = (ce & Count[]) # (!ce & dffs[].q);
END GENERATE;
LoadLCELL[] = !SyncClr & LoadSSet[];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -