-- test 2, ISE 14.7 ---A.Kurka, 13.05.21, --afkt mit neue Formel, mit 10 clk und 5 componenten -- P(X) = P0 + X*(P1 + X*P2), ausgewertet von innen nach außen -- Q(X) = Q0 + X*(Q1 + X*Q2), ausgewertet von innen nach außen -- a(X) = P(X) / Q(X) --========================================================== library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; --X"3f7ffffd",--P0 +0.99999984852024669 index 0 --X"be8c8cb6",--P1 -0.27451104135987186 --X"00000000",--P2 +0.0 index 2 --X"00000000" ---------------------------------- --X"3f800000",--Q0 +1.0 index 0 --X"beb73881",--Q1 -0.35785296234245088 --X"3c36a182",--Q2 +0.011146905255803363 indesx 2 --X"00000000" entity afkt is generic( P0:std_logic_vector(31 downto 0):=X"00000000"; P1:std_logic_vector(31 downto 0):=X"00000000"; P2:std_logic_vector(31 downto 0):=X"00000000"; Q0:std_logic_vector(31 downto 0):=X"00000000"; Q1:std_logic_vector(31 downto 0):=X"00000000"; Q2:std_logic_vector(31 downto 0):=X"00000000" ); port( nrst : in std_logic; clk : in std_logic; ceafkt : in std_logic; -- startimpuls afkt Xinp : in std_logic_vector(31 downto 0); -- Input in [0, 0.5] in FP-Format aout : OUT std_logic_vector(31 downto 0) -- Output in [1, 1.047197+] in FP-Format, 1.047197=2*asin(0.5) ); end afkt; architecture Behavioral of afkt is ---------------------------------------------------- COMPONENT mulFP IS port ( a: IN std_logic_VECTOR(31 downto 0); b: IN std_logic_VECTOR(31 downto 0); clk: IN std_logic; ce: IN std_logic; result: OUT std_logic_VECTOR(31 downto 0)); END COMPONENT; --------------------------------------------- COMPONENT addFP IS port ( a: IN std_logic_VECTOR(31 downto 0); b: IN std_logic_VECTOR(31 downto 0); clk: IN std_logic; ce: IN std_logic; result: OUT std_logic_VECTOR(31 downto 0)); END COMPONENT; ------------------------------------------------------------ COMPONENT divFP IS port ( a: IN std_logic_VECTOR(31 downto 0); b: IN std_logic_VECTOR(31 downto 0); clk: IN std_logic; ce: IN std_logic; result: OUT std_logic_VECTOR(31 downto 0) ); END COMPONENT; ----------------------------------------------------- TYPE T_PQTab IS ARRAY(0 TO 3) OF std_logic_vector(31 DOWNTO 0); -- Koeff Tabelle für Polynom mit Grad <= 3. --========================================================================== CONSTANT Cnan : std_logic_vector(31 DOWNTO 0) := X"FFC00000"; -- silent NaN (Not-a-Number) in FP IEEE single (32bit) CONSTANT C0 :std_logic_vector(31 DOWNTO 0) := X"FFC00000";--Null im FP Format ------------------------------------------------------------------------ -- Koeffizienten-Tabellen für P / Q, MiniMax Approximation, X in [0, 1/2]. -- a(x) = p(x) / q(x) = asin(sqrt(x/2)) / sqrt(x/2) -- p(x) = 2.2395545700203E+01 + x * (-9.2247557732604 + x * 4.9573581589364E-01) -- q(x) = 2.2395545641439E+01 + x * (-1.1091046068928E+01 + x) -- |rel. Fehler| < 1.63e-9 (5e-7 mit IEEE single). -- --CONSTANT PTab : T_PQTab := --( -- X"41b32a14", -- P0 +2.2395545700203E+01 -- X"c113989a", -- P1 -9.2247557732604 -- X"3efdd116", -- P2 +4.9573581589364E-01 -- X"00000000" -- unused --); --CONSTANT QTab : T_PQTab := --( -- X"41b32a14", -- Q0 +2.2395545641439E+01 -- X"c13174ed", -- Q1 -1.1091046068928E+01 -- X"3f800000", -- Q2 +1.0 -- X"00000000" -- unused --); -- koeffizienten Tabellen für P , MinMax Approximation CONSTANT PTab :T_PQTab:= -- alle werte in FP ( P0,------------------X"3f7ffffd",--P0 +0.99999984852024669 index 0 P1,-------------------X"be8c8cb6",--P1 -0.27451104135987186 P2,--------------------X"00000000",--P2 +0.0 index 2 X"00000000" ); -------------------------------- CONSTANT QTab :T_PQTab:= -- alle werte in FP ( Q0,--------------X"3f800000",--Q0 +1.0 index 0 Q1,----------X"beb73881",--Q1 -0.35785296234245088 Q2,-----------X"3c36a182",--Q2 +0.011146905255803363 indesx 2 X"00000000" ); --==================== Signale für afkt ================================== SIGNAL stateafkt :integer range 0 to 7:= 0; --SIGNAL ceafkt :std_logic:='0';-- Startimpuls afkt, extern SIGNAL ce1 :std_logic:='0';-- Start Pmul = Xinp*Pinp; Qmul = Xinp*Qinp SIGNAL ce2 :std_logic:='0';-- Start Padd = Pmul+PKoeff; Qadd = Qmul+QKoeff SIGNAL ce3 :std_logic:='0';-- Start aout = Pplus/Qplus SIGNAL ce4 :std_logic:='0';-- Start aout = Padd/Qadd SIGNAL RDYdiv :std_logic:='0';-- Div Result Ready SIGNAL Pinp :std_logic_vector(31 DOWNTO 0):=X"00000000";-- 2. Input cPmul SIGNAL Qinp :std_logic_vector(31 DOWNTO 0):=X"00000000";-- 2. input cQmul SIGNAL Pmul :std_logic_vector(31 DOWNTO 0):=X"00000000";-- Resultat cPmul SIGNAL Qmul :std_logic_vector(31 DOWNTO 0):=X"00000000";-- Resultat cQmul SIGNAL Pplus :std_logic_vector(31 DOWNTO 0):=X"00000000";-- Resultat cPmul SIGNAL Qplus :std_logic_vector(31 DOWNTO 0):=X"00000000";-- Resultat cQmul SIGNAL Pa :std_logic_vector(31 DOWNTO 0):=X"00000000";-- Resultat cPadd SIGNAL Qa :std_logic_vector(31 DOWNTO 0):=X"00000000";-- Resultat cPadd SIGNAL Padd :std_logic_vector(31 DOWNTO 0):=X"00000000";-- Resultat cPadd, Ergebnis Auswertung P() SIGNAL Qadd :std_logic_vector(31 DOWNTO 0):=X"00000000";-- Resultat cQadd, Ergebnis Auswertung Q() SIGNAL PKoeff :std_logic_vector(31 DOWNTO 0):=X"00000000";-- Koeff von P() SIGNAL QKoeff :std_logic_vector(31 DOWNTO 0):=X"00000000";-- Koeff von Q() --================================================================ begin --=========== a(x) ============================================== -- a(X) = (P0 + P1*X + P2*X^2) / (Q0 + Q1*X + Q2*X^2) -- Berechnungsformel: -- P(X) = P0 + X*(P1 + X*P2), ausgewertet von innen nach außen -- Q(X) = Q0 + X*(Q1 + X*Q2), ausgewertet von innen nach außen -- a(X) = P(X) / Q(X) --************************************************************************ pafkt:PROCESS(clk) -- Process für a(Xinp), vorläufig 8(?) clk. -- als Index in PTab und QTab. VARIABLE TabIdx : INTEGER RANGE 0 TO 3 := 0; VARIABLE count :INTEGER RANGE 0 TO 7:= 0; BEGIN IF rising_edge(clk) THEN IF nrst = '0' THEN TabIdx := 0; -- Init Inx Pointer PKoeff <= C0; QKoeff <= C0; Pinp <= C0; Qinp <= C0; ce1 <= '0'; ce2 <= '0'; ce4 <= '0'; stateafkt <= 0; ELSE CASE stateafkt IS WHEN 0 => -- Start afkt IF ceafkt = '1' THEN TabIdx := 2; -- Init Index in Tabellen (1 = max. Polynomgrad - 1)--****************. Pinp <= PTab(2); -- Init Pinp = PTab(2), (2 = max. Polynomgrad) Qinp <= QTab(2); -- Init Qinp = QTab(2), (2 = max. Polynomgrad) ce1 <= '1';--starten mul ce2 <= '0'; ce3 <= '0'; ce4 <= '0'; stateafkt <= 1;-- Dann Auswertung gestartet ELSE Padd <= X"00000000"; Qadd <= X"00000000"; stateafkt <= 0; END IF; --------------------------------- WHEN 1 => -- ausführen mul : Xinp * Ptab(2),Xinp * Qtab(2), ce1 <= '0'; -- reset -- Pmul,Qmul sind bereit -- Decrement Tab-Index TabIdx := TabIdx - 1; PKoeff <= PTab(TabIdx); QKoeff <= QTab(TabIdx); stateafkt <= 2; WHEN 2 => Pplus <= Pmul; Qplus <= Qmul; ce2 <= '1'; stateafkt <= 3; When 3 => ce2 <= '0'; stateafkt <= 4; When 4 => Padd <= Pa; Qadd <= Qa; IF TabIdx = 0 THEN Pplus <= X"00000000"; Qplus <= X"00000000"; ce3 <= '1';-- start div count := 1; stateafkt <= 5; -- und div ELSE Pinp <= Pa; Qinp <= Qa; ce1 <= '1'; -- start für Pmul,Qmul stateafkt <= 1; -- und wiederholen END IF; WHEN 5 => -- div fertig IF count > 0 THEN count := count - 1; ce3 <= '0'; stateafkt <= 5; ELSE stateafkt <= 0;--un warten auf neustart END IF; WHEN OTHERS => stateafkt <= 0; END CASE; -- stateafkt END IF; -- nrst END IF; --clk END PROCESS; --end pafkt --=========Components Implementation==================================== -- ce1 cPmul: mulFP port map(a=>Xinp, b=>Pinp, clk=>clk, ce=>ce1, result=>Pmul); cQmul: mulFP port map(a=>Xinp, b=>Qinp, clk=>clk, ce=>ce1, result=>Qmul); -- ce2 cPadd: addFP port map(a=>Pplus, b=>PKoeff, clk=>clk, ce=>ce2, result=>Pa);-- cQadd: addFP port map(a=>Qplus, b=>QKoeff, clk=>clk, ce=>ce2, result=>Qa);-- -- ce3 cPQdiv: divFP port map(a=>Padd, b=>Qadd,clk=>clk, ce=>ce3,result=>aout); --===============================================================================00 end Behavioral;