⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 addcore.tdf

📁 用s3c44b0x和 CIS(ContactImage Sensor) 传感器接口
💻 TDF
字号:
----------------------------------------------------------------------
-- 	addcore: The adder core subdesign of LPM_ADD_SUB  				--
-- 		 	 addcore implements an adder optimized for FLEX/FAST,	--
--		 	 FLEX/NORMAL, and MAX cases by using					--
--																	--
--    FLEX/FAST: a carry-chain implementation with chain breaking	--
--				 when a maximum carry chain length smaller than 	--
--				 adder width has been specified.					--
--																	--
--	FLEX/NORMAL: a ripple carry structure.							--
--																	--
-- 		   MAX : a ripple carry structure between 8-bit sub-adders  --
--				 and 8-bit carry-look-ahead within each sub-adder.	-- 
----------------------------------------------------------------------
INCLUDE "addcore.inc";

PARAMETERS
(
	WIDTH,
 	CONSTANT_CIN,	-- Is cin connected to a fixed value? (0 No, 1 Yes)
	CARRY_CHAIN,
	CARRY_CHAIN_LENGTH,
	DEVICE_FAMILY
);

INCLUDE "aglobal.inc";	% device definitions %
 
------------------------------------------
-- parameters related to FLEX/FAST case
------------------------------------------
-- CARRY_LEN is the number of LCELLs in full carry chain, excluding
-- the beginning and terminating LCELLs when chain brek is needed
CONSTANT CARRY_LEN = (CARRY_CHAIN_LENGTH <= 2) ? 0 : (CARRY_CHAIN_LENGTH - 2);

-- FULL_WIDTH determines the full length of the adder carry chain taking
-- usage of cin and cout outputs into conideration. Note that overflow
-- generated from cout.
DEFINE FULL_WIDTH()	= WIDTH + (-(USED(cin) & (CONSTANT_CIN == 0))) + (-USED(cout));

-- FULL_CNT and PART_CNT are functions used to determine the number of full- and
-- partial carry chains, respectively  
DEFINE FULL_CNT(n, c, i) = (c <= 2 # n < c) ? 0 : ((n == c) ? ((i == 1) ? 0 :
															     (1 + FULL_CNT(n-(c-2), c, i+1))) : 
															  ((i == 1) ? (1 + FULL_CNT(n-((c-2)+1), c, i+1)) :
															 			 (1 + FULL_CNT(n-(c-2), c, i+1))));
DEFINE PART_CNT(n, c, i) = (n < c) ? ((n < (c-1)) # ((n == (c-1)) & (I == 1)) ? (n) : 0) : 
									((n == c) ? ((i == 1) ? 0 : PART_CNT(n-(c-2), c, i+1)) :
										        ((i == 1) ? PART_CNT(n-((c-2)+1), c, i+1) : 
												    			  PART_CNT(n-(c-2), c, i+1)));

-- The number of full-length carry chain segements
DEFINE FULL_SEGS() 	   	= FULL_CNT (FULL_WIDTH(), CARRY_CHAIN_LENGTH, 1);
-- The length of a (possible) partial chain
DEFINE PART_WIDTH()    	= FULL_WIDTH() - (FULL_SEGS() * CARRY_LEN + CBASE());
-- index base, depending on the usage of cin
DEFINE CBASE() 		   	= -(!(USED(cin) & CONSTANT_CIN == 0));
DEFINE ADJ_WIDTH()		= WIDTH + (-USED(cout));
DEFINE ADJ_PART_WIDTH()	= (PART_WIDTH() == 0) ? 0 :
							(ADJ_WIDTH() - (CARRY_LEN*FULL_SEGS()+CBASE())); 
DEFINE NEED_PART_SEG() 	= (PART_WIDTH() == 0) ? 0 : 1;
DEFINE TOT_SEGS() 	   	= FULL_SEGS()+NEED_PART_SEG();

------------------------------------
-- parameters related to MAX cases
------------------------------------
CONSTANT TOT_BLOCKS   = CEIL(WIDTH DIV 8);
CONSTANT FULL_BLOCKS  = FLOOR(WIDTH DIV 8);
CONSTANT REM_WIDTH    = WIDTH MOD 8;
CONSTANT REM_BLOCKS   = (REM_WIDTH > 0) ? 1 : 0; 

-- use FLEX/FAST or switch to NORMAL style?
DEFINE NEED_CHAIN()	  = (WIDTH > 2) & --# (WIDTH == 2 & USED(cin))) &
						(CARRY_CHAIN != "IGNORE") & (CARRY_LEN > 1) ? 1 : 0;

SUBDESIGN addcore
(
	dataa[WIDTH-1..0]	: INPUT = GND;
	datab[WIDTH-1..0]	: INPUT = GND;
	cin					: INPUT = GND;
	result[WIDTH-1..0]	: OUTPUT;
	cout				: OUTPUT;
	bg_out, bp_out		: OUTPUT;		-- block generate/propagate outputs
)

VARIABLE
	IF WIDTH == 1 GENERATE	
		cin_node : NODE;

	ELSE GENERATE
		IF (FAMILY_FLEX() == 1) GENERATE
			IF NEED_CHAIN() == 1 GENERATE
				----------------------
				-- FLEX/FAST cases	--
				----------------------
				result_node[ADJ_WIDTH()-1..0] 	: NODE;

				IF TOT_SEGS() == 1 GENERATE
					cin_node : CARRY;
					IF ADJ_WIDTH() > 1 GENERATE
						pcarry[0][ADJ_WIDTH()-2..0] : CARRY;
					END GENERATE;

				ELSE GENERATE
					cin_node : NODE;
					first_seg_adder 	: addcore WITH (WIDTH = CARRY_LEN+CBASE(),
														CONSTANT_CIN = CONSTANT_CIN);

					IF (FULL_SEGS() > 1) GENERATE
						full_seg_adder[FULL_SEGS()-2..0] 	: addcore WITH (WIDTH = CARRY_LEN,
  																			CONSTANT_CIN = 0);
					END GENERATE;

					IF NEED_PART_SEG() > 0 GENERATE
 						part_seg_adder	: addcore WITH (WIDTH = ADJ_PART_WIDTH(),
 														CONSTANT_CIN = 0);
 					END GENERATE;
 				END GENERATE;

				-- block gen/prop signals are non-GND only when
				-- width of the adder is 8.
				IF WIDTH == 8 GENERATE
	 				prop_node[3..0] : NODE;
					genr_node[3..0] : NODE;
					gp0 : NODE;
				END GENERATE;

			ELSE GENERATE
				--------------------------
				-- FLEX/NORMAL cases	--
				--------------------------
				cin_node : NODE;
 				pcarry[WIDTH-1..0] : NODE;

				IF WIDTH == 8 GENERATE
		 			prop_node[3..0] : NODE;
					genr_node[3..0] : NODE;
					gp0 : NODE;
				END GENERATE;
			END GENERATE;

		ELSE GENERATE
			------------------------------
			-- MAX cases with WIDTH = 8	--
			------------------------------
			-- this special case implements the 8-bit gdf version in tdf.
			IF WIDTH == 8 GENERATE
	 			gn[7..0] 	: NODE; 	
				gs[7..1] 	: SOFT; 
				pp[7..0] 	: NODE;
				ps[7..0] 	: SOFT;
				psi[7..0] 	: NODE;
				pc[6..0] 	: NODE;
				gc[2..0] 	: NODE;
				g2c[2..0] 	: NODE;
				p2c[2..0] 	: NODE;

				g3 			: NODE;
				g4 			: SOFT;
				g2cp[2..1] 	: SOFT;
				gcp[2] 		: SOFT;
	
				cin_node 			: NODE;
				tot_cin_node[6..0]	: NODE;
				result_node[7..0] 	: SOFT;
				cout_node			: SOFT;

 				prop_node[3..0] 	: SOFT;
				genr_node[3..0] 	: SOFT; 
				gp0 				: NODE;

 			ELSE GENERATE
				--------------------------------------
				-- all MAX cases with WIDTH != 8	--
				--------------------------------------
				-- this case will use recursive call to itself to 
				-- implement a group of 8-bit MAX adders.
				cin_node			: NODE;
				adder[TOT_BLOCKS-1..0] 	: addcore WITH (WIDTH = 8);
 			END GENERATE;
		END GENERATE;
	END GENERATE;
		

BEGIN
	assert report "WIDTH = %, USED(cin) = %, NEED_CHAIN = %, CBASE = %" WIDTH, USED(cin), NEED_CHAIN(), CBASE() SEVERITY DEBUG;	
	assert report "WIDTH = %, TOT_SEGS = %, FULL_SEGS = %, FULL_WIDTH = %, PART_WIDTH = % , ADJ_PART_WIDTH = %, CBASE = %" 
				WIDTH, TOT_SEGS(), FULL_SEGS(), FULL_WIDTH(), PART_WIDTH(), ADJ_PART_WIDTH(), CBASE() SEVERITY DEBUG;	
	assert report "CIN_CONST = %, USED(cin) = %, RESULT = %,USED_COUT = %" 
				CONSTANT_CIN, USED(cin), USED(cin) & (CONSTANT_CIN == 0), (-USED(cout)) SEVERITY DEBUG;	

	-- cin is common between single-segment and multi-segment chains.
 	cin_node = cin;

	IF WIDTH == 8 GENERATE
		FOR I IN 0 TO 3 GENERATE
			prop_node[I] = (dataa[2*I+1] # datab[2*I+1]) & (dataa[2*I] # datab[2*I]);  
			genr_node[I] = (dataa[2*I+1] & datab[2*I+1]) # (dataa[2*I+1] # datab[2*I+1]) & 
						   (dataa[2*I] & datab[2*I]);
		END GENERATE;
	
		gp0 = prop_node[2] & (genr_node[1] # prop_node[1] & genr_node[0]);
		bg_out = genr_node[3] # prop_node[3] & (genr_node[2] # gp0);
		bp_out = prop_node[0] & prop_node[1] & prop_node[2] & prop_node[3];
	
	ELSE GENERATE
		bg_out = GND;
		bp_out = GND;
	END GENERATE;

	-- the special case WIDTH = 1 is straightforward and no carry chains are needed.
	IF WIDTH == 1 GENERATE
		result[0]  = dataa[0] $ datab[0] $ cin_node;
		cout = dataa[0] & datab[0] # dataa[0] & cin_node # datab[0] & cin_node;

	ELSE GENERATE
		IF (FAMILY_FLEX() == 1)  GENERATE 
			IF NEED_CHAIN() == 1 GENERATE
				----------------------
				-- FLEX/FAST cases	--
				----------------------
				IF TOT_SEGS() == 1 GENERATE
					-- Single-segment chain case
					result_node[0] = dataa[0] $ datab[0] $ cin_node;

					IF ADJ_WIDTH() > 1 GENERATE
						pcarry[0][0] = (dataa[0] & datab[0]) # 
									   (dataa[0] # datab[0]) & cin_node;
						
						IF ADJ_WIDTH() > 2 GENERATE
							FOR I IN 1 TO ADJ_WIDTH()-2 GENERATE
								result_node[I] = dataa[I] $ datab[I] $ pcarry[0][I-1];
								pcarry[0][I] = (dataa[I] & datab[I]) # 
											   (dataa[I] # datab[I]) & pcarry[0][I-1];
							END GENERATE;
						END GENERATE;

						IF USED(cout) GENERATE
							result_node[ADJ_WIDTH()-1] = pcarry[0][ADJ_WIDTH()-2];
						ELSE GENERATE
							result_node[ADJ_WIDTH()-1] = dataa[ADJ_WIDTH()-1] $ 
														 datab[ADJ_WIDTH()-1] $ 
														 pcarry[0][ADJ_WIDTH()-2];
						END GENERATE;
					END GENERATE;

					result[] = result_node[WIDTH-1..0];

					IF USED(cout) GENERATE
						cout = result_node[ADJ_WIDTH()-1];
					END GENERATE;

				ELSE GENERATE
					-- Multi-segment chain case
					-- First full segment
 					first_seg_adder.cin = cin_node;
	
					first_seg_adder.dataa[] = dataa[CARRY_LEN+CBASE()-1..0];
					first_seg_adder.datab[] = datab[CARRY_LEN+CBASE()-1..0];
					result_node[CARRY_LEN+CBASE()-1..0] = first_seg_adder.result[];
 					
					-- Intermediate full segments
					IF FULL_SEGS() > 1 GENERATE
 						full_seg_adder[0].cin = LCELL(first_seg_adder.cout);
						full_seg_adder[0].dataa[] = dataa[2*CARRY_LEN+CBASE()-1..CARRY_LEN+CBASE()];
						full_seg_adder[0].datab[] = datab[2*CARRY_LEN+CBASE()-1..CARRY_LEN+CBASE()];					
						result_node[2*CARRY_LEN+CBASE()-1..CARRY_LEN+CBASE()] = full_seg_adder[0].result[];
						IF FULL_SEGS() > 2 GENERATE
							FOR I IN 1 TO FULL_SEGS()-2 GENERATE
								full_seg_adder[I].cin = LCELL(full_seg_adder[I-1].cout);
								full_seg_adder[I].dataa[] = dataa[(I+2)*CARRY_LEN+CBASE()-1..(I+1)*CARRY_LEN+CBASE()];
								full_seg_adder[I].datab[] = datab[(I+2)*CARRY_LEN+CBASE()-1..(I+1)*CARRY_LEN+CBASE()];					
								result_node[(I+2)*CARRY_LEN+CBASE()-1..(I+1)*CARRY_LEN+CBASE()] = full_seg_adder[I].result[];
							END GENERATE;
						END GENERATE;
					END GENERATE;

					-- Possible partially full segment
					IF NEED_PART_SEG() > 0 GENERATE
						IF FULL_SEGS() == 1 GENERATE
 							part_seg_adder.cin = LCELL(first_seg_adder.cout);
						ELSE GENERATE
 							part_seg_adder.cin = LCELL(full_seg_adder[FULL_SEGS()-2].cout);
						END GENERATE;

						IF USED(cout) GENERATE
							part_seg_adder.dataa[] = (GND, dataa[WIDTH-1..FULL_SEGS()*CARRY_LEN+CBASE()]);
							part_seg_adder.datab[] = (GND, datab[WIDTH-1..FULL_SEGS()*CARRY_LEN+CBASE()]);
						ELSE GENERATE
							part_seg_adder.dataa[] = dataa[WIDTH-1..FULL_SEGS()*CARRY_LEN+CBASE()];
							part_seg_adder.datab[] = datab[WIDTH-1..FULL_SEGS()*CARRY_LEN+CBASE()];
						END GENERATE;

						result_node[ADJ_WIDTH()-1..FULL_SEGS()*CARRY_LEN+CBASE()] = part_seg_adder.result[];
					END GENERATE;

					result[] = result_node[WIDTH-1..0];

					IF USED(cout) GENERATE
						cout = result_node[ADJ_WIDTH()-1];
					END GENERATE;
				END GENERATE;

 			ELSE GENERATE
				assert report "FLEX/NORMAL" severity DEBUG;
				--------------------------
				-- FLEX/NORMAL cases	--
				--------------------------
	 			pcarry[0] = (dataa[0] & datab[0]) # (dataa[0] & cin_node) # 
							(datab[0] & cin_node);

				FOR I IN 1 TO WIDTH-1 GENERATE
					pcarry[I] = (dataa[I] & datab[I]) # (dataa[I] # datab[I]) & pcarry[I-1];
				END GENERATE;
	
				result[0] = dataa[0] $ datab[0] $ cin_node;
				result[WIDTH-1..1] = (dataa[WIDTH-1..1] $ pcarry[WIDTH-2..0]) $ datab[WIDTH-1..1];
				cout = pcarry[WIDTH-1];

 			END GENERATE;

		ELSE GENERATE
			IF WIDTH == 8 GENERATE  
			assert report "MAX device with size 8" severity DEBUG;
				------------------------------
				-- MAX cases with WIDTH = 8	--
				------------------------------
				-- GENERATE (gn, gs) and PROPAGATE (!pp, !ps) functions
				pp[0] = dataa[0] !# datab[0];
				ps[0] = pp[0];
				psi[0] = !ps[0];
				gn[0] = dataa[0] & datab[0];
				gc[0] = gn[0];

				FOR I in 1 TO 7 GENERATE
					pp[I] = dataa[I] !# datab[I];
					ps[I] = pp[I];
					psi[I] = !ps[I];
					gn[I] = dataa[I] & datab[I];
					gs[I] = gn[I];
				END GENERATE;

				-- Propagate cin all through 7 stages
				pc[0] = psi[0] & cin_node;
				FOR I in 1 TO 6 GENERATE
					pc[I] = psi[I] & pc[I-1];
				END GENERATE;
	
				g3 = psi[3] & !gs[3];
				-- g4 is the GENERATE function of first 4 bit positions
				g4 = gn[3] $ (gc[2] & g3);

				-- Propagate g4 through the positions 4-7
				-- p2c is the propagated carry with g4 as carry input. 
				p2c[0] = g4 & psi[4];
				p2c[1] = p2c[0] & psi[5];
				p2c[2] = p2c[1] & psi[6];

				-- gc is the generated carry at poistions 0 - 3.
				gc[0] = gn[0];
				gc[1] = gn[1] # psi[1] & gc[0];
				gc[2] = gn[2] # psi[2] & gc[1];
	
				-- gcp is the generated carry at poistion 4 - 6.				
				gcp[2] = gc[2];
				g2c[0] = gn[4];
				g2c[1] = gn[5] # psi[5] & g2c[0];
				g2c[2] = gn[6] # psi[6] & g2c[1];
	
				g2cp[1] = g2c[1];
				g2cp[2] = g2c[2];

				-- tot_cin_node is the total (propagated + generated) carry 
				-- input to each bit post 
				tot_cin_node[0] = gc[0] # pc[0];
				tot_cin_node[1] = gc[1] # pc[1];
				tot_cin_node[2] = gcp[2] # pc[2];
				tot_cin_node[3] = g4 # pc[3];
				tot_cin_node[4] = g2c[0] # pc[4] # p2c[0];
				tot_cin_node[5] = g2cp[1] # pc[5] # p2c[1];
				tot_cin_node[6] = g2cp[2] # pc[6] # p2c[2];

				-- compute result (sum) bits. Note that (!ps[I] & !gs[I])
				-- is the same as (data[I] $ datab[I]). However, using ps[I]
				-- and gs[I] (or equivalently, pp[I] and gn[I]) results
				-- in more common factors that can be crammed in shared
				-- expanders and thus reduce cell count.
				result_node[0] = (pp[0] # gn[0]) !$ cin_node;
				FOR I in 1 TO 7 GENERATE
					IF I == 3 GENERATE
						result_node[I] = g3 $ tot_cin_node[I-1];
					ELSE GENERATE
						result_node[I] = (psi[I] & !gs[I]) $ tot_cin_node[I-1];
					END GENERATE;
				END GENERATE;
			
				-- cout
 				cout_node = gn[7] $ (psi[7] & !gs[7] & tot_cin_node[6]);

				-- all outputs are SOFT-buffered.
			 	result[] = result_node[];
				cout = cout_node;

 			ELSE GENERATE
				----------------------------------
				-- MAX cases with WIDTH != 8 	--
				----------------------------------
				IF FULL_BLOCKS > 0 GENERATE
					FOR I IN 0 TO FULL_BLOCKS-1 GENERATE
						adder[I].dataa[] = dataa[(I+1)*8-1..I*8];
						adder[I].datab[] = datab[(I+1)*8-1..I*8];
						result[(I+1)*8-1..I*8] = adder[I].result[];
					END GENERATE;
				END GENERATE;

				IF REM_BLOCKS == 1 GENERATE
					adder[TOT_BLOCKS-1].dataa[REM_WIDTH-1..0] = dataa[WIDTH-1..(TOT_BLOCKS-1)*8];
					adder[TOT_BLOCKS-1].datab[REM_WIDTH-1..0] = datab[WIDTH-1..(TOT_BLOCKS-1)*8];
					result[WIDTH-1..(TOT_BLOCKS-1)*8] = adder[TOT_BLOCKS-1].result[REM_WIDTH-1..0];
				END GENERATE;

				adder[0].cin = cin_node;
				IF TOT_BLOCKS > 1 GENERATE
					FOR I IN 1 TO TOT_BLOCKS-1 GENERATE
						adder[I].cin = adder[I-1].cout;
					END GENERATE;
				END GENERATE;

				IF REM_BLOCKS == 1 GENERATE						
					cout = adder[TOT_BLOCKS-1].result[REM_WIDTH];
				ELSE GENERATE
					cout = adder[TOT_BLOCKS-1].cout;
				END GENERATE;
				
			END GENERATE;
		END GENERATE;
	END GENERATE;
END;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -