------------------------------------------------------------ -- Bisection Method (Lower FLEX10k) -- < bisec.vhd > -- 1999/03/15 (Mon) -- 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 bisec 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 bisec; architecture RTL of bisec 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 BIS_STATE_TYPE is ( BisDimRead, BisAlphaRead, BisBetaRead, BisAlphapBetaCalc, BisMaxCalc, BisMaxComp, BisMaxSet, BisApBCalc, BisCCalc, BisAlphamCCalc, BisBeta2Calc, BisBeta2dQCalc, BisQCalc, BisQComp, BisNewRange, BisEvWrite, BisResRead, BisStop ); signal BIS_STATE : BIS_STATE_TYPE; signal Alpha, Beta, OldBeta, AlphapBeta, tMax, Max, BisA, BisB, ApB, BisC, AlphamC, Beta2, Beta2dQ, Q : std_logic_vector(31 downto 0); signal RES : std_logic_vector(31 downto 0); constant BISEC_R : std_logic_vector(4 downto 0) := "11000"; -- 24 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; ------------<< Bisection Method ?>------------- process( BL(0), CLK ) variable i, k, nPos : std_logic_vector(7 downto 0); variable r : std_logic_vector(4 downto 0); begin if BL(0) = '1' then BIS_STATE <= BisStop; 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'); -- Alpha <= (others => '0'); -- Beta <= (others => '0'); -- OldBeta <= (others => '0'); -- AlphapBeta <= (others => '0'); -- tMax <= (others => '0'); Max <= (others => '0'); -- BisA <= (others => '0'); -- BisB <= (others => '0'); -- ApB <= (others => '0'); -- BisC <= (others => '0'); -- AlphamC <= (others => '0'); -- Beta2 <= (others => '0'); -- Beta2dQ <= (others => '0'); -- Q <= (others => '0'); i := ( 0 => '1', others => '0' ); k := ( 0 => '1', others => '0' ); r := ( others => '0' ); nPos := ( others => '0' ); BH <= ( others => '0' ); elsif rising_edge( CLK ) then case BIS_STATE is when BisStop => if BL(5) = '1' then BIS_STATE <= BisDimRead; else ALU_STATE <= aSTOP; BIS_STATE <= BisStop; end if; when BisDimRead => 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'; BIS_STATE <= BisAlphaRead; end if; when BisAlphaRead => if ALU_ACK = '0' then ALU_STATE <= R_MEM_RD; ADRS_BUF1 <= '0' & i & i; ALU_ACK <= '1'; else ALU_STATE <= MEM_STOP; end if; if CALC_DONE = '1' then Alpha <= DATA_BUS; ALU_ACK <= '0'; if i < N then BIS_STATE <= BisBetaRead; else BIS_STATE <= BisAlphapBetaCalc; end if; end if; when BisBetaRead => 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 Beta <= DATA_BUS; ALU_ACK <= '0'; BIS_STATE <= BisAlphapBetaCalc; end if; when BisAlphapBetaCalc => ALU_STATE <= FF_ADD; DATA_BUF1 <= '0' & Alpha(30 downto 0); DATA_BUF2 <= '0' & Beta(30 downto 0); if CALC_STATE = SECOND_DATA then ALU_STATE <= CALC_F; end if; if CALC_DONE = '1' then if i = "00000001" or i = N then tMax <= DATA_BUS; BIS_STATE <= BisMaxComp; else AlphapBeta <= DATA_BUS; BIS_STATE <= BisMaxCalc; end if; end if; when BisMaxCalc => ALU_STATE <= FF_ADD; DATA_BUF1 <= AlphapBeta; DATA_BUF2 <= '0' & OldBeta(30 downto 0); if CALC_STATE = SECOND_DATA then ALU_STATE <= CALC_F; end if; if CALC_DONE = '1' then tMax <= DATA_BUS; BIS_STATE <= BisMaxComp; end if; when BisMaxComp => if tMax(30 downto 0) > Max(30 downto 0) then Max <= tMax; end if; if i < N then i := i + '1'; OldBeta <= Beta; BIS_STATE <= BisAlphaRead; else i := ( 0 => '1', others => '0' ); BIS_STATE <= BisMaxSet; end if; when BisMaxSet => BisA <= '1' & Max(30 downto 0); BisB <= '0' & Max(30 downto 0); BIS_STATE <= BisApBCalc; when BisApBCalc => ALU_STATE <= FF_ADD; DATA_BUF1 <= BisA; DATA_BUF2 <= BisB; nPos := (others => '0'); if CALC_STATE = SECOND_DATA then ALU_STATE <= CALC_F; end if; if CALC_DONE = '1' then ApB <= DATA_BUS; BIS_STATE <= BisCCalc; end if; when BisCCalc => if DIV_ACK = '0' then DIV_A <= ApB; DIV_B <= FP_TWO; DIV_ACK <= '1'; --else -- DIV_A <= ( others => '0' ); -- DIV_B <= ( others => '0' ); end if; if DIV_DONE = '1' then BisC <= DIV_Q; DIV_ACK <= '0'; BIS_STATE <= BisAlphamCCalc; end if; when BisAlphamCCalc => if ALU_ACK = '0' then ALU_STATE <= FR_ADD; DATA_BUF1 <= ( not BisC(31) ) & BisC(30 downto 0); ADRS_BUF1 <= '0' & i & i; ALU_ACK <= '1'; else ALU_STATE <= CALC_F; end if; if CALC_DONE = '1' then ALU_ACK <= '0'; if i = "00000001" then Q <= DATA_BUS; BIS_STATE <= BisQComp; else AlphamC <= DATA_BUS; BIS_STATE <= BisBeta2Calc; end if; end if; when BisBeta2Calc => if ALU_ACK = '0' then ALU_STATE <= RR_MUL; ADRS_BUF1 <= '0' & ( i - '1' ) & i; ALU_ACK <= '1'; else ALU_STATE <= CALC_F; end if; if CALC_DONE = '1' then Beta2 <= DATA_BUS; ALU_ACK <= '0'; BIS_STATE <= BisBeta2dQCalc; end if; when BisBeta2dQCalc => if DIV_ACK = '0' then DIV_A <= Beta2; DIV_B <= Q; DIV_ACK <= '1'; --else -- DIV_A <= ( others => '0' ); -- DIV_B <= ( others => '0' ); end if; if DIV_DONE = '1' then Beta2dQ <= DIV_Q; DIV_ACK <= '0'; BIS_STATE <= BisQCalc; end if; when BisQCalc => ALU_STATE <= FF_ADD; DATA_BUF1 <= AlphamC; DATA_BUF2 <= ( not Beta2dQ(31) ) & Beta2dQ(30 downto 0); if CALC_STATE = SECOND_DATA then ALU_STATE <= CALC_F; end if; if CALC_DONE = '1' then Q <= DATA_BUS; BIS_STATE <= BisQComp; end if; when BisQComp => if Q(31) = '0' then nPos := nPos + '1'; end if; if Q(30 downto 0) = "0000000000000000000000000000" then i := i + '1'; end if; if i < N then i := i + '1'; BIS_STATE <= BisAlphamCCalc; else i := ( 0 => '1', others => '0'); BIS_STATE <= BisNewRange; end if; when BisNewRange => if nPos >= k then BisA <= BisC; else BisB <= BisC; end if; if r < BISEC_R then r := r + '1'; BIS_STATE <= BisApBCalc; else r := (others => '0'); BIS_STATE <= BisEvWrite; end if; when BisEvWrite => if ALU_ACK = '0' then ALU_STATE <= L_MEM_WR; DATA_BUF1 <= BisC; ADRS_BUF1 <= "100000001" & k; ALU_ACK <= '1'; else ALU_STATE <= MEM_STOP; end if; if CALC_DONE = '1' then ALU_ACK <= '0'; if k < N then k := k + '1'; BisA <= '1' & Max(30 downto 0); BisB <= BisC; BIS_STATE <= BisApBCalc; else BIS_STATE <= BisResRead; end if; end if; when BisResRead => if ALU_ACK = '0' then ALU_STATE <= L_MEM_RD; ADRS_BUF1 <= "100000001" & 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'; else i := ( 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;