------------------------------------------------------------ -- Householder Inverse Transform (Lower FLEX10k) -- < hsinv.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; use WORK.MATH.all; library metamor; use metamor.attributes.all; entity hsinv 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 hsinv; architecture RTL of hsinv 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 HSINV_STATE_TYPE is ( HsInvDimRead, HsInvVarIni, HsInvUtxXCalc, HsInvUtxXxCCalc, HsInvUtxXxCxUCalc, HsInvXmUtxXxCxUCalc, HsInvX2Calc, HsInvNormCalc, HsInvInvNormCalc, HsInvXNorm, HsInvResRead, HsInvStop ); signal HSINV_STATE : HSINV_STATE_TYPE; signal UtxX, UtxXxC, UtxXxCxU, X2, Norm, InvNorm : std_logic_vector(31 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; ------------<< Householder Inverse Transform >>------------- process( BL(0), CLK ) variable i, j, k : std_logic_vector(7 downto 0); begin if BL(0) = '1' then HSINV_STATE <= HsInvStop; 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 := ( others => '0' ); j := ( others => '0' ); k := ( 0 => '1', others => '0' ); BH <= ( others => '0' ); elsif rising_edge( CLK ) then case HSINV_STATE is when HsInvStop => if BL(5) = '1' then HSINV_STATE <= HsInvDimRead; else ALU_STATE <= aSTOP; HSINV_STATE <= HsInvStop; end if; when HsInvDimRead => 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'; HSINV_STATE <= HsInvVarIni; end if; when HsInvVarIni => j := N - "00000010"; i := j; HSINV_STATE <= HsInvUtxXCalc; when HsInvUtxXCalc => if i < N then ALU_STATE <= LR_INPRO; i := i + '1'; ADRS_BUF1 <= '1' & i & k; ADRS_BUF2 <= '0' & i & j; else ALU_STATE <= INPRO_F; end if; if CALC_DONE = '1' then UtxX <= DATA_BUS; i := j + '1'; HSINV_STATE <= HsInvUtxXxCCalc; end if; when HsInvUtxXxCCalc => if ALU_ACK = '0' then ALU_STATE <= FL_MUL; DATA_BUF1 <= UtxX; ADRS_BUF1 <= "100000000" & j; ALU_ACK <= '1'; else ALU_STATE <= CALC_F; end if; if CALC_DONE = '1' then UtxXxC <= DATA_BUS; ALU_ACK <= '0'; HSINV_STATE <= HsInvUtxXxCxUCalc; end if; when HsInvUtxXxCxUCalc => if ALU_ACK = '0' then ALU_STATE <= FL_MUL; DATA_BUF1 <= UtxXxC; ADRS_BUF1 <= '0' & i & j; ALU_ACK <= '1'; else ALU_STATE <= CALC_F; end if; if CALC_DONE = '1' then UtxXxCxU <= DATA_BUS; ALU_ACK <= '0'; HSINV_STATE <= HsInvXmUtxXxCxUCalc; end if; when HsInvXmUtxXxCxUCalc => if ALU_ACK = '0' then ALU_STATE <= FR_ADD; DATA_BUF1 <= ( not UtxXxCxU(31) ) & UtxXxCxU(30 downto 0); ADRS_BUF1 <= '1' & i & k; ALU_ACK <= '1'; else ALU_STATE <= CALC_R; ADRS_BUF1 <= '1' & i & k; end if; if CALC_DONE = '1' then ALU_ACK <= '0'; if i < N then i := i + '1'; HSINV_STATE <= HsInvUtxXxCxUCalc; elsif j > "00000001" then j := j - '1'; i := j; HSINV_STATE <= HsInvUtxXCalc; elsif k < N then k := k + '1'; HSINV_STATE <= HsInvVarIni; else i := ( others => '0' ); j := ( 0 => '1', others => '0' ); HSINV_STATE <= HsInvX2Calc; end if; end if; when HsInvX2Calc => if i < N then ALU_STATE <= RR_INPRO; i := i + '1'; ADRS_BUF1 <= '1' & i & j; else ALU_STATE <= INPRO_F; end if; if CALC_DONE = '1' then X2 <= DATA_BUS; i := (0 => '1', others => '0'); HSINV_STATE <= HsInvNormCalc; end if; when HsInvNormCalc => Norm <= sqrt(X2); HSINV_STATE <= HsInvInvNormCalc; when HsInvInvNormCalc => if DIV_ACK = '0' then DIV_A <= FP_ONE; DIV_B <= Norm; DIV_ACK <= '1'; --else -- DIV_A <= ( others => '0' ); -- DIV_B <= ( others => '0' ); end if; if DIV_DONE = '1' then InvNorm <= DIV_Q; DIV_ACK <= '0'; HSINV_STATE <= HsInvXNorm; end if; when HsInvXNorm => if ALU_ACK = '0' then ALU_STATE <= FR_MUL; DATA_BUF1 <= InvNorm; ADRS_BUF1 <= '1' & i & j; ALU_ACK <= '1'; else ALU_STATE <= CALC_R; ADRS_BUF1 <= '1' & i & j; end if; if CALC_DONE = '1' then ALU_ACK <= '0'; if i < N then i := i + '1'; elsif j < N then j := j + '1'; i := (others => '0'); HSINV_STATE <= HsInvX2Calc; else i := ( 0 => '1', others => '0' ); j := ( 0 => '1', others => '0' ); HSINV_STATE <= HsInvResRead; end if; end if; when HsInvResRead => if ALU_ACK = '0' then ALU_STATE <= R_MEM_RD; ADRS_BUF1 <= '1' & i & j; 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;