------------------------------------------------------------
-- Inverse Iteration Method  (Lower FLEX10k)
-- < invit.vhd >
-- 1999/03/15 (Fri) 
-- yamaoka@tube.ee.uec.ac.jp
------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;

library metamor;
use metamor.attributes.all;

entity invit is
  port (CLK  : in std_logic;
		A    : inout std_logic_vector(15 downto 0); 
		BL   : in std_logic_vector(7 downto 0);   
		BH   : out std_logic_vector(5 downto 0);    
		B_CONF  : in std_logic_vector(1 downto 0);
		CL   : in std_logic_vector(5 downto 0);
		
		DATA_BUS  : inout std_logic_vector(31 downto 0);
		ADRS_BUS  : out std_logic_vector(16 downto 0);  
		CTRL_BUS  : out std_logic_vector(4 downto 0);   
		CALC_DONE : in  std_logic;                      
		OE_ALU    : out std_logic;                      

		OBF  : in std_logic_vector(1 downto 0); 
		ACK  : out std_logic_vector(1 downto 0);
		STB  : out std_logic_vector(1 downto 0);
		IBF  : in std_logic_vector(1 downto 0)
);

attribute pinnum of CLK : signal is  "D22";
attribute pinnum of A   : signal is  "BC23,BB24,BC25,BB26,BC27,BB28,BC29,BB30,BC31,BB32,BC33,BB34,BC35,BB36,BC37,BB38"; 
attribute pinnum of BL  : signal is  "BC13,BB14,BC15,BB16,BC17,BB18,BC19,BB20"; 
attribute pinnum of BH  : signal is  "BC7,BB8,BC9,BB10,BC11,BB12";
attribute pinnum of B_CONF  : signal is  "BC5,BB6";
attribute pinnum of CL   : signal is  "AU23,AV24,AU25,AU33,AV34,AU35";

attribute pinnum of DATA_BUS  : signal is  "A5,B6,A7,B8,A9,B10,A11,B12,A13,B14,A15,B16,A17,B18,A19,B20,A23,B24,A25,B26,A27,B28,A29,B30,A31,B32,A33,B34,A35,B36,A37,B38"; 
attribute pinnum of ADRS_BUS  : signal is  "F16,G19,F20,G21,F22,G23,F24,G25,F26,G29,F30,G31,F32,G33,F34,G35,F36"; 
attribute pinnum of CTRL_BUS  : signal is  "G11,F12,G13,F14,G15"; 
attribute pinnum of CALC_DONE : signal is  "F10";
attribute pinnum of OE_ALU    : signal is  "G9";

attribute pinnum of OBF : signal is  "AV18,AV28";
attribute pinnum of ACK : signal is  "AU19,AU29";
attribute pinnum of STB : signal is  "AU21,AU31";
attribute pinnum of IBF : signal is  "AV20,AV30";

end invit;
architecture RTL of invit is

-------------<< Floating point Number Divider >>-------
component fpdiv is
 port (CLK : in std_logic;                    
		FA  : in std_logic_vector(31 downto 0); 
		FB  : in std_logic_vector(31 downto 0);  
		Q   : out std_logic_vector(31 downto 0)    
    );
end component; 

signal DIV_A : std_logic_vector(31 downto 0);
signal DIV_B : std_logic_vector(31 downto 0);
signal DIV_Q : std_logic_vector(31 downto 0); 
signal DIV_ACK   : std_logic; 
signal DIV_DONE  : std_logic; 
signal DCNT : std_logic;
signal DCNT3 : std_logic_vector(3 downto 0); 

signal A_REG : std_logic_vector(15 downto 0);	
signal ACK_BUF : std_logic_vector(1 downto 0);	
signal STB_BUF : std_logic_vector(1 downto 0);	 
signal OUT_CNT : std_logic;
signal OUT_ACK : std_logic;
signal OUT_ACK2 : std_logic;

signal N : std_logic_vector(7 downto 0);

-------------------------------

type CALC_STATE_TYPE is (
		FIRST_DATA, SECOND_DATA
		);

signal CALC_STATE : CALC_STATE_TYPE;

type ALU_STATE_TYPE is (
		R_MEM_WR, R_MEM_RD, 
		L_MEM_WR, L_MEM_RD,
		LR_MEM_WR,
		MEM_STOP,
		RR_INPRO, LL_INPRO, LR_INPRO, 
		INPRO_F, INPRO_R, INPRO_L, INPRO_LR,
		FF_MUL, FR_MUL, FL_MUL, RR_MUL, LL_MUL, LR_MUL, 
		FF_ADD, FR_ADD, FL_ADD, RR_ADD, LL_ADD, LR_ADD, 
		CALC_F, CALC_R, CALC_L, CALC_LR,
		aSTOP 
		);

signal ALU_STATE : ALU_STATE_TYPE;
signal DATA_BUS_BUF : std_logic_vector(31 downto 0);	 
signal DATA_BUF1 : std_logic_vector(31 downto 0);	 
signal DATA_BUF2 : std_logic_vector(31 downto 0);	 
signal OE_BUF : std_logic;
signal ADRS_BUF1 : std_logic_vector(16 downto 0);	 
signal ADRS_BUF2 : std_logic_vector(16 downto 0);	 
signal ALU_ACK : std_logic;

-------------------------------

type INV_STATE_TYPE is (
		InvDimRead,
		InvLambdaRead, InvAlphamLambdaCalc,
		InvViceRead, InvViceWrite, 
		InvAlpha1Read, InvAlpha2Read, InvBeta1Read, InvBeta2Read, InvBeta3Read,
		InvAbsComp, InvMCalc, InvMWrite, 
		InvAlpha1Write, InvBeta2Write, InvBeta3Write, 
		InvMxBeta3Calc, InvMxBeta2Calc, InvAlpha2mMxBeta2Calc, 
		InvRRange, InvRxXCalc, InvXRead, InvXmRxXCalc, InvAlphaRead, InvXCalc, InvXWrite,
		InvX1Read, InvX2Read, InvX1X2Comp, InvX1Write, InvMxX1Calc, InvEvCalc,		
		InvResRead, 
		InvStop 
		);
      
signal INV_STATE : INV_STATE_TYPE;
signal Lambda, Vice, Alpha1, Alpha2, Beta1, Beta2, Beta3, M, MxBeta2, X, RxX, XmRxX, Alpha, X1, X2, MxX1 : std_logic_vector(31 downto 0);

signal Ex     : std_logic_vector(254 downto 1);
signal Rrange : std_logic_vector(7 downto 0);
signal RES    : std_logic_vector(31 downto 0);

constant FP_ONE : std_logic_vector(31 downto 0) := "00111111100000000000000000000000";
constant FP_TWO : std_logic_vector(31 downto 0) := "01000000000000000000000000000000";

constant cR_MEM_WR  : std_logic_vector(4 downto 0) := "00001";
constant cR_MEM_RD  : std_logic_vector(4 downto 0) := "00010";
constant cL_MEM_WR  : std_logic_vector(4 downto 0) := "00011";
constant cL_MEM_RD  : std_logic_vector(4 downto 0) := "00100";
constant cLR_MEM_WR : std_logic_vector(4 downto 0) := "00101";
constant cMEM_STOP  : std_logic_vector(4 downto 0) := "00110";
constant cRR_INPRO  : std_logic_vector(4 downto 0) := "00111";
constant cLL_INPRO  : std_logic_vector(4 downto 0) := "01000";
constant cLR_INPRO  : std_logic_vector(4 downto 0) := "01001";
constant cINPRO_F   : std_logic_vector(4 downto 0) := "01010";
constant cINPRO_R   : std_logic_vector(4 downto 0) := "01011";
constant cINPRO_L   : std_logic_vector(4 downto 0) := "01100";
constant cINPRO_LR  : std_logic_vector(4 downto 0) := "01101";
constant cFF_MUL    : std_logic_vector(4 downto 0) := "01110";
constant cFR_MUL    : std_logic_vector(4 downto 0) := "01111";
constant cFL_MUL    : std_logic_vector(4 downto 0) := "10000";
constant cRR_MUL    : std_logic_vector(4 downto 0) := "10001";
constant cLL_MUL    : std_logic_vector(4 downto 0) := "10010";
constant cLR_MUL    : std_logic_vector(4 downto 0) := "10011";
constant cFF_ADD    : std_logic_vector(4 downto 0) := "10100";
constant cFR_ADD    : std_logic_vector(4 downto 0) := "10101";
constant cFL_ADD    : std_logic_vector(4 downto 0) := "10110";
constant cRR_ADD    : std_logic_vector(4 downto 0) := "10111";
constant cLL_ADD    : std_logic_vector(4 downto 0) := "11000";
constant cLR_ADD    : std_logic_vector(4 downto 0) := "11001";
constant cCALC_F    : std_logic_vector(4 downto 0) := "11010";
constant cCALC_R    : std_logic_vector(4 downto 0) := "11011";
constant cCALC_L    : std_logic_vector(4 downto 0) := "11100";
constant cCALC_LR   : std_logic_vector(4 downto 0) := "11101";

begin

A <= "ZZZZZZZZZZZZZZZZ" when ACK_BUF = "00" else A_REG;

ACK_BUF <= OBF;
ACK <= ACK_BUF;

-----------<< Output Result Data to PC >>------------
process ( BL(0), BL(3), IBF ) begin
if BL(0) = '1' then
	STB <= "11";
	OUT_CNT <= '0';
	A_REG <= ( others => '0' ); 
elsif rising_edge( BL(3) ) then
	STB <= "00";
	if OUT_CNT = '0' then
		A_REG <= RES(15 downto 0);
		OUT_CNT <= '1';
	else
		A_REG <= RES(31 downto 16);
		OUT_CNT <= '0';
	end if;
end if;
if IBF = "11" then
	STB <= "11";
end if;
end process;

-----------<< Generate Memory Read Signal of Result Data >>------------
process ( BL(0), BL(4), OUT_ACK2 ) begin
if BL(0) = '1' or OUT_ACK2 = '1' then
	OUT_ACK <= '0';
elsif rising_edge( BL(4) ) then
	OUT_ACK <= '1';
end if;
end process;

process ( BL(0), CLK ) begin
if BL(0) = '1' then
	OUT_ACK2 <= '0';
elsif rising_edge( CLK ) then
	if OUT_ACK = '1' then
		OUT_ACK2 <= '1';
	else
		OUT_ACK2 <= '0';
	end if;
end if;
end process;

-----<< Selecter of ALU Operation >>-----
DATA_BUS <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" when OE_BUF = '1' else DATA_BUS_BUF;
OE_ALU <= OE_BUF;

process ( BL(0), CLK ) begin
if BL(0) = '1' then
	CTRL_BUS <= ( others => '0' );
elsif falling_edge( CLK ) then
	case ALU_STATE is
		when R_MEM_WR =>
		   	CTRL_BUS <= cR_MEM_WR;
		when R_MEM_RD =>
			CTRL_BUS <= cR_MEM_RD;
		when L_MEM_WR =>
		   	CTRL_BUS <= cL_MEM_WR;
		when L_MEM_RD =>
			CTRL_BUS <= cL_MEM_RD;
		when LR_MEM_WR =>
			CTRL_BUS <= cLR_MEM_WR;
		when MEM_STOP =>
			CTRL_BUS <= cMEM_STOP;
		when RR_INPRO =>
			CTRL_BUS <= cRR_INPRO;
		when LL_INPRO =>
			CTRL_BUS <= cLL_INPRO;
		when LR_INPRO =>
			CTRL_BUS <= cLR_INPRO;
		when INPRO_F =>
			CTRL_BUS <= cINPRO_F;
		when INPRO_R =>
			CTRL_BUS <= cINPRO_R;
		when INPRO_L =>
			CTRL_BUS <= cINPRO_L;
		when INPRO_LR =>
			CTRL_BUS <= cINPRO_LR;
		when FF_MUL => 
			CTRL_BUS <= cFF_MUL;
		when FR_MUL => 
			CTRL_BUS <= cFR_MUL;
		when FL_MUL => 
			CTRL_BUS <= cFL_MUL;
		when RR_MUL => 
			CTRL_BUS <= cRR_MUL;
		when LL_MUL => 
			CTRL_BUS <= cLL_MUL;
		when LR_MUL => 
			CTRL_BUS <= cLR_MUL;
		when FF_ADD => 
			CTRL_BUS <= cFF_ADD;
		when FR_ADD => 
			CTRL_BUS <= cFR_ADD;
		when FL_ADD => 
			CTRL_BUS <= cFL_ADD;
		when RR_ADD => 
			CTRL_BUS <= cRR_ADD;
		when LL_ADD => 
			CTRL_BUS <= cLL_ADD;
		when LR_ADD => 
			CTRL_BUS <= cLR_ADD;
		when CALC_F => 
			CTRL_BUS <= cCALC_F;
		when CALC_R => 
			CTRL_BUS <= cCALC_R;
		when CALC_L => 
			CTRL_BUS <= cCALC_L;
		when CALC_LR => 
			CTRL_BUS <= cCALC_LR;
		when others => null;
	end case;
end if;
end process;

process ( BL(0), CLK ) begin
if BL(0) = '1' then
	DATA_BUS_BUF <= ( others => '0' );
	OE_BUF <= '0';
elsif falling_edge( CLK ) then
	case ALU_STATE is
		when R_MEM_WR | L_MEM_WR | LR_MEM_WR | FR_MUL | FL_MUL | FR_ADD | FL_ADD =>
		   	DATA_BUS_BUF <= DATA_BUF1; 
			OE_BUF <= '0';
		when MEM_STOP | INPRO_F | CALC_F =>
			DATA_BUS_BUF <= ( others => '0' );
			OE_BUF <= '1';
		when LR_INPRO | INPRO_LR | LR_MUL | LR_ADD | CALC_LR =>
			DATA_BUS_BUF(16 downto 0) <= ADRS_BUF2;
			OE_BUF <= '0';
		when FF_MUL | FF_ADD => 
			OE_BUF <= '0';
			if CALC_STATE = FIRST_DATA then
				DATA_BUS_BUF <= DATA_BUF1;
			else	
				DATA_BUS_BUF <= DATA_BUF2;
			end if; 			
		when others => null;
	end case;
end if;
end process;

process ( BL(0), CLK ) begin
if BL(0) = '1' then
	CALC_STATE <= FIRST_DATA;
elsif rising_edge( CLK ) then
	case ALU_STATE is
		when FF_MUL | FF_ADD => 
			 CALC_STATE <= SECOND_DATA;			
		when others =>	
			if CALC_DONE = '1' then
				CALC_STATE <= FIRST_DATA;
			end if;
	end case;
end if;
end process;

process ( BL(0), CLK ) begin
if BL(0) = '1' then
	ADRS_BUS <= ( others => '0' );
elsif falling_edge( CLK ) then
	case ALU_STATE is
		when MEM_STOP | INPRO_F | FF_MUL | FF_ADD | CALC_F => 
			ADRS_BUS <= ( others => '0' );
		when others => 
			ADRS_BUS <= ADRS_BUF1;
	end case;
end if;
end process;

------------<< Inverse Iteration Method >>-------------
process( BL(0), CLK )
	variable i, j, k : std_logic_vector(7 downto 0);
	variable r : std_logic;
begin
if BL(0) = '1' then
	INV_STATE <= InvStop;
	ALU_STATE <= aStop;
	ALU_ACK <= '0';	
	DIV_ACK <= '0';
	DATA_BUF1 <= (others => '0');
	DATA_BUF2 <= (others => '0');
	ADRS_BUF1 <= (others => '0');
	ADRS_BUF2 <= (others => '0');
--	DIV_A <= (others => '0');
--	DIV_B <= (others => '0');
--	Lambda  <= (others => '0');
--	Vice <= (others => '0');
--	Alpha1 <= (others => '0');
--	Alpha2 <= (others => '0');
--	Beta1 <= (others => '0');
--	Beta2 <= (others => '0');
--	Beta3 <= (others => '0');
--	M <= (others => '0');
--	MxBeta2 <= (others => '0');
--	X <= (others => '0');
--	RxX <= (others => '0');
--	XmRxX <= (others => '0');
--	Alpha <= (others => '0');
--	X1 <= (others => '0');
--	X2 <= (others => '0');
--	MxX1 <= (others => '0');
--	Res <= (others => '0');
--	Ex <= (others => '0');
--	N <= (others => '0');
	i := ( 0 => '1', others => '0' );
	j := ( 0 => '1', others => '0' );
	k := ( 0 => '1', others => '0' );
	r := '0';
	BH <= ( others => '0' );
elsif rising_edge( CLK ) then
	case INV_STATE is
		when InvStop =>
			if BL(5) = '1' then
				INV_STATE <= InvDimRead;
			else
				ALU_STATE <= aSTOP;
				INV_STATE <= InvStop;
			end if;	

		when InvDimRead =>
			if ALU_ACK = '0' then
				ALU_STATE <= L_MEM_RD;	
				ADRS_BUF1 <= "10000000000000000";
				ALU_ACK <= '1';	
			else
				ALU_STATE <= MEM_STOP;
			end if;				

			if CALC_DONE = '1' then
				N <= DATA_BUS(7 downto 0);
				ALU_ACK <= '0';
				INV_STATE <= InvLambdaRead;
			end if;

		when InvLambdaRead =>
			if ALU_ACK = '0' then
				ALU_STATE <= L_MEM_RD;
				ADRS_BUF1 <= "100000001" & k;
				ALU_ACK <= '1';	
			else
				ALU_STATE <= MEM_STOP;
			end if;

			if CALC_DONE = '1' then
				Lambda <= DATA_BUS;
				ALU_ACK <= '0';
				INV_STATE <= InvAlphamLambdaCalc;
			end if;
		
		when InvAlphamLambdaCalc =>
			if ALU_ACK = '0' then
				ALU_STATE <= FR_ADD;
				DATA_BUF1 <= ( not Lambda(31) ) & Lambda(30 downto 0);
				ADRS_BUF1 <= '0' & i & i;
				ALU_ACK <= '1';
			else
				ALU_STATE <= CALC_L;
				ADRS_BUF1 <= '0' & i & i;
			end if;

			if CALC_DONE = '1' then
				ALU_ACK <= '0';
				if i < N then
					i := i + '1';
				else
					i := ( 0 => '1', others => '0' );
					INV_STATE <= InvViceRead;
				end if;
			end if;

		when InvViceRead =>
			if ALU_ACK = '0' then
				ALU_STATE <= R_MEM_RD;
				ADRS_BUF1 <= '0' & i & (i + '1');
				ALU_ACK <= '1';	
			else
				ALU_STATE <= MEM_STOP;
			end if;

			if CALC_DONE = '1' then
				Vice <= DATA_BUS;
				ALU_ACK <= '0';
				INV_STATE <= InvViceWrite;
			end if;

		when InvViceWrite =>
			if ALU_ACK = '0' then
				ALU_STATE <= L_MEM_WR;
				DATA_BUF1 <= Vice;
				ADRS_BUF1 <= '0' & i & (i + '1');
				ALU_ACK <= '1';	
			else
				ALU_STATE <= MEM_STOP;
			end if;

			if CALC_DONE = '1' then
				ALU_ACK <= '0';
				if i < ( N - '1' ) then
					i := i + '1';
					INV_STATE <= InvViceRead;
				else
					i := ( 0 => '1', others => '0' );
					INV_STATE <= InvAlpha1Read;
				end if;
			end if;

		when InvAlpha1Read =>
			if ALU_ACK = '0' then
				ALU_STATE <= L_MEM_RD;	
				ADRS_BUF1 <= '0' & i & i;
				ALU_ACK <= '1';	
			else
				ALU_STATE <= MEM_STOP;
			end if;				

			if CALC_DONE = '1' then
				Alpha1 <= DATA_BUS;
				ALU_ACK <= '0';
				INV_STATE <= InvAlpha2Read;
			end if;

		when InvAlpha2Read =>
			if ALU_ACK = '0' then
				ALU_STATE <= L_MEM_RD;	
				ADRS_BUF1 <= '0' & (i + '1') & (i + '1');
				ALU_ACK <= '1';
			else
				ALU_STATE <= MEM_STOP;
			end if;				

			if CALC_DONE = '1' then
				Alpha2 <= DATA_BUS;
				ALU_ACK <= '0';
				INV_STATE <= InvBeta1Read;
			end if;

		when InvBeta1Read =>
			if ALU_ACK = '0' then
				ALU_STATE <= R_MEM_RD;	
				ADRS_BUF1 <= '0' & i & (i + '1');
				ALU_ACK <= '1';
			else
				ALU_STATE <= MEM_STOP;
			end if;				

			if CALC_DONE = '1' then
				Beta1 <= DATA_BUS;
				ALU_ACK <= '0';
				INV_STATE <= InvBeta2Read;
			end if;

		when InvBeta2Read =>
			if ALU_ACK = '0' then
				ALU_STATE <= L_MEM_RD;	
				ADRS_BUF1 <= '0' & i & (i + '1');
				ALU_ACK <= '1';
			else
				ALU_STATE <= MEM_STOP;
			end if;				

			if CALC_DONE = '1' then
				Beta2 <= DATA_BUS;
				ALU_ACK <= '0';
				if i < (N - '1') then
					INV_STATE <= InvBeta3Read;
				else
					INV_STATE <= InvAbsComp;
				end if;
			end if;

		when InvBeta3Read =>
			if ALU_ACK = '0' then
				ALU_STATE <= L_MEM_RD;	
				ADRS_BUF1 <= '0' & (i + '1') & (i + "00000010");
				ALU_ACK <= '1';
			else
				ALU_STATE <= MEM_STOP;
			end if;	

			if CALC_DONE = '1' then
				Beta3 <= DATA_BUS;
				ALU_ACK <= '0';
				INV_STATE <= InvAbsComp;
			end if;

		when InvAbsComp =>
			if Alpha1(30 downto 0) < Beta1(30 downto 0) then 
				Ex(conv_integer(i)) <= '1';
				Alpha1 <= Beta1;
				Beta1 <= Alpha1;
				Alpha2 <= Beta2;
				Beta2 <= Alpha2;
			else
				Ex(conv_integer(i)) <= '0';	
			end if;
			INV_STATE <= InvMCalc;

		when InvMCalc =>
			if DIV_ACK = '0' then
				DIV_A <= Beta1;
				DIV_B <= Alpha1;
				DIV_ACK <= '1';
			--else
			--	DIV_A <= ( others => '0' );
			--	DIV_B <= ( others => '0' );
			end if;

			if DIV_DONE = '1' then
				M <= DIV_Q;
				DIV_ACK <= '0';
				INV_STATE <= InvMWrite;
			end if;

		when InvMWrite =>
			if ALU_ACK = '0' then
				ALU_STATE <= L_MEM_WR;	
				DATA_BUF1 <= M;
				ADRS_BUF1 <= "100000010" & i;
				ALU_ACK <= '1';	
			else
				ALU_STATE <= MEM_STOP;
			end if;

			if CALC_DONE = '1' then
				ALU_ACK <= '0';
				if Ex(conv_integer(i)) = '1' then
					INV_STATE <= InvAlpha1Write;
				else
					INV_STATE <= InvMxBeta2Calc;
				end if;
			end if;

		when InvAlpha1Write => 
			if ALU_ACK = '0' then
				ALU_STATE <= L_MEM_WR;	
				DATA_BUF1 <= Alpha1;
				ADRS_BUF1 <= '0' & i & i;
				ALU_ACK <= '1';	
			else
				ALU_STATE <= MEM_STOP;
			end if;

			if CALC_DONE = '1' then
				ALU_ACK <= '0';
				INV_STATE <= InvBeta2Write;
			end if;

		when InvBeta2Write => 
			if ALU_ACK = '0' then
				ALU_STATE <= L_MEM_WR;	
				DATA_BUF1 <= Beta2;
				ADRS_BUF1 <= '0' & i & (i + '1');
				ALU_ACK <= '1';	
			else
				ALU_STATE <= MEM_STOP;
			end if;

			if CALC_DONE = '1' then
				ALU_ACK <= '0';
				if i < (N - '1') then
					INV_STATE <= InvBeta3Write;
				else
					INV_STATE <= InvMxBeta2Calc;
				end if;
			end if;

		when InvBeta3Write => 
			if ALU_ACK = '0' then
				ALU_STATE <= L_MEM_WR;	
				DATA_BUF1 <= Beta3;
				ADRS_BUF1 <= '0' & i & (i + "00000010");
				ALU_ACK <= '1';
			else
				ALU_STATE <= MEM_STOP;
			end if;

			if CALC_DONE = '1' then
				ALU_ACK <= '0';
				INV_STATE <= InvMxBeta3Calc;
			end if;

		when InvMxBeta3Calc =>
			ALU_STATE <= FF_MUL;
			DATA_BUF1 <= M;
			DATA_BUF2 <= ( not Beta3(31) ) & Beta3(30 downto 0);
			
			if CALC_STATE = SECOND_DATA then
				ALU_STATE <= CALC_L;
				ADRS_BUF1 <= '0' & (i + '1') & (i + "00000010");
			end if;

			if CALC_DONE = '1' then
				INV_STATE <= InvMxBeta2Calc;
			end if;

		when InvMxBeta2Calc =>
			ALU_STATE <= FF_MUL;
			DATA_BUF1 <= M;
			DATA_BUF2 <= Beta2;
			
			if CALC_STATE = SECOND_DATA then
				ALU_STATE <= CALC_F;
			end if;

			if CALC_DONE = '1' then
				MxBeta2 <= DATA_BUS;
				INV_STATE <= InvAlpha2mMxBeta2Calc;
			end if;

		when InvAlpha2mMxBeta2Calc =>
			ALU_STATE <= FF_ADD;
			DATA_BUF1 <= Alpha2;
			DATA_BUF2 <= ( not MxBeta2(31) ) & MxBeta2(30 downto 0);
			
			if CALC_STATE = SECOND_DATA then
				ALU_STATE <= CALC_L;
				ADRS_BUF1 <= '0' & (i + '1') & (i + '1');
			end if;

			if CALC_DONE = '1' then
				if i < (N - '1') then
					i := i + '1';
					INV_STATE <= InvAlpha1Read;
				else
					i := N;
					j := N;
					X <= FP_ONE;
					RxX <= (others => '0');
					INV_STATE <= InvXmRxXCalc;
				end if;
			end if;

		when InvRRange =>
			if Ex(conv_integer(i)) = '1' then
				Rrange <= i + "00000010";
			else
				Rrange <= i + "00000001";
			end if;

			if i = (N - '1') then
				Rrange <= N;
			end if;
			INV_STATE <= InvRxXCalc;

		when InvRxXCalc =>
			if i < Rrange then
				ALU_STATE <= LR_INPRO;
				i := i + '1';
				ADRS_BUF1 <= '1' & i & k;
				ADRS_BUF2 <= '0' & j & i;
			else
				ALU_STATE <= INPRO_F;
			end if;
			
			if CALC_DONE = '1' then
				RxX <= DATA_BUS;
				if r = '1' then
					INV_STATE <= InvXRead;
				else
					X <= FP_ONE;
					INV_STATE <= InvXmRxXCalc;
				end if;
			end if;

		when InvXRead => 
			if ALU_ACK = '0' then
				ALU_STATE <= R_MEM_RD;	
				ADRS_BUF1 <= '1' & j & k; 
				ALU_ACK <= '1';
			else
				ALU_STATE <= MEM_STOP;
			end if;				

			if CALC_DONE = '1' then
				X <= DATA_BUS;
				ALU_ACK <= '0';
				INV_STATE <= InvXmRxXCalc;
			end if;

		when InvXmRxXCalc =>
			ALU_STATE <= FF_ADD;
			DATA_BUF1 <= X;
			DATA_BUF2 <= ( not RxX(31) ) & RxX(30 downto 0);
			
			if CALC_STATE = SECOND_DATA then
				ALU_STATE <= CALC_F;
			end if;

			if CALC_DONE = '1' then
				XmRxX <= DATA_BUS;
				INV_STATE <= InvAlphaRead;
			end if;

		when InvAlphaRead =>
			if ALU_ACK = '0' then
				ALU_STATE <= L_MEM_RD;	
				ADRS_BUF1 <= '0' & j & j;
				ALU_ACK <= '1';
			else
				ALU_STATE <= MEM_STOP;
			end if;				

			if CALC_DONE = '1' then
				Alpha <= DATA_BUS;
				ALU_ACK <= '0';
				INV_STATE <= InvXCalc;
			end if;

		when InvXCalc =>
			if DIV_ACK = '0' then
				DIV_A <= XmRxX;
				DIV_B <= Alpha;
				DIV_ACK <= '1';
			--else
			--	DIV_A <= ( others => '0' );
			--	DIV_B <= ( others => '0' );
			end if;

			if DIV_DONE = '1' then
				X <= DIV_Q;
				DIV_ACK <= '0';
				INV_STATE <= InvXWrite;
			end if;

		when InvXWrite => 
			if ALU_ACK = '0' then
				ALU_STATE <= R_MEM_WR;
				DATA_BUF1 <= X;
				ADRS_BUF1 <= '1' & j & k;
				ALU_ACK <= '1';	
			else
				ALU_STATE <= MEM_STOP;
			end if;

			if CALC_DONE = '1' then
				ALU_ACK <= '0';
				if j > "00000001" then
					j := j - '1';
					i := j;
					INV_STATE <= InvRRange;
				elsif r = '1' then
					j := ( 0 => '1', others => '0' );
					i := ( 0 => '1', others => '0' );
					if k < N then
						k := k + '1';
						r := '0';
						INV_STATE <= InvLambdaRead;
					else
						INV_STATE <= InvResRead;
					end if;
				else
					j := ( 0 => '1', others => '0' );
					i := ( 0 => '1', others => '0' );
					INV_STATE <= InvX1Read;
				end if;
			end if;

		when InvX1Read =>
			if ALU_ACK = '0' then
				ALU_STATE <= R_MEM_RD;	
				ADRS_BUF1 <= '1' & i & k;
				ALU_ACK <= '1';	
			else
				ALU_STATE <= MEM_STOP;
			end if;				

			if CALC_DONE = '1' then
				X1 <= DATA_BUS;
				ALU_ACK <= '0';
				INV_STATE <= InvX2Read;
			end if;

		when InvX2Read =>
			if ALU_ACK = '0' then
				ALU_STATE <= R_MEM_RD;	
				ADRS_BUF1 <= '1' & (i + '1') & k;
				ALU_ACK <= '1';	
			else
				ALU_STATE <= MEM_STOP;
			end if;				

			if CALC_DONE = '1' then
				X2 <= DATA_BUS;
				ALU_ACK <= '0';
				INV_STATE <= InvX1X2Comp;
			end if;

		when InvX1X2Comp =>
			if Ex(conv_integer(i)) = '1' then
				X1 <= X2;
				X2 <= X1;
				INV_STATE <= InvX1Write;
			else
				INV_STATE <= InvMxX1Calc;
			end if;

		when InvX1Write =>
			if ALU_ACK = '0' then
				ALU_STATE <= R_MEM_WR;	
				DATA_BUF1 <= X1;
				ADRS_BUF1 <= '1' & i & k;
				ALU_ACK <= '1';	
			else
				ALU_STATE <= MEM_STOP;
			end if;

			if CALC_DONE = '1' then
				ALU_ACK <= '0';
				INV_STATE <= InvMxX1Calc;
			end if;

		when InvMxX1Calc =>
			if ALU_ACK = '0' then	
				ALU_STATE <= FL_MUL;
				DATA_BUF1 <= X1;
				ADRS_BUF1 <= "100000010" & i;
				ALU_ACK <= '1';
			else
				ALU_STATE <= CALC_F;
			end if;

			if CALC_DONE = '1' then
				MxX1 <= DATA_BUS;
				ALU_ACK <= '0';
				INV_STATE <= InvEvCalc;
			end if;

		when InvEvCalc =>
			ALU_STATE <= FF_ADD;
			DATA_BUF1 <= X2;
			DATA_BUF2 <= ( not MxX1(31) ) & MxX1(30 downto 0);
			
			if CALC_STATE = SECOND_DATA then
				ALU_STATE <= CALC_R;
				ADRS_BUF1 <= '1' & (i + '1') & k;
			end if;

			if CALC_DONE = '1' then
				if i < (N - '1') then
					i := i + '1';
					INV_STATE <= InvX1Read;
				else
					r := '1';
					i := N;
					j := N;
					RxX <= (others => '0');
					INV_STATE <= InvXRead;
				end if;
			end if;

		when InvResRead =>
			if ALU_ACK = '0' then
				ALU_STATE <= R_MEM_RD;	
				ADRS_BUF1 <= '1' & j & i;
				ALU_ACK <= '1';	
			else
				ALU_STATE <= MEM_STOP;
			end if;

			if CALC_DONE = '1' then
				BH <= ( 0 => '1', others => '0' );  
				RES <= DATA_BUS;
			end if;

			if OUT_ACK2 = '1' then
				BH <= ( others => '0' );  
				ALU_ACK <= '0';
				if i < N then
					i := i + '1';
				elsif j < N then
					i := ( 0 => '1', others => '0' );
					j := j + '1';
				else
					i := ( 0 => '1', others => '0' );
					j := ( 0 => '1', others => '0' );
				end if;
			end if;

		when others =>
			null;
	end case;
end if;
end process;

process ( BL(0), CLK ) begin
if BL(0) = '1' then
	DCNT <= '0';
--	DCNT3 <= "0000";
	DIV_DONE <= '0';
elsif rising_edge( CLK ) then
--if DIV_ACK = '1' and DIV_DONE = '0' then
--	DCNT3 <= DCNT3 + '1';
--else
--	DCNT3 <= "0000";
--end if;
--
--if DCNT3 = "1111" then
--	DIV_DONE <= '1';
--else
--	DIV_DONE <= '0';
--end if;

	if DIV_ACK = '1' and DCNT = '0' and DIV_DONE = '0' then
		DCNT <= '1';
	else	
		DCNT <= '0';
	end if;
	if DCNT = '1' then
		DIV_DONE <= '1';
	else
		DIV_DONE <= '0';
	end if;
end if;
end process;

------------<< Floating Point Number Divider >>--------------
divider : fpdiv  port map ( CLK => CLK, FA => DIV_A, FB => DIV_B, Q => DIV_Q );

end RTL;