1 |
4 |
divadnauj |
library ieee;
|
2 |
|
|
use ieee.std_logic_1164.all;
|
3 |
|
|
use ieee.std_logic_arith.all;
|
4 |
|
|
use ieee.std_logic_unsigned.all;
|
5 |
|
|
|
6 |
|
|
entity prueba is
|
7 |
|
|
--generic(K: natural:= 64; P: natural:= 53; E: natural:= 11);
|
8 |
|
|
generic(K: natural:= 32; P: natural:= 24; E: natural:= 8);
|
9 |
|
|
Port ( FP_A : in std_logic_vector (K-1 downto 0);
|
10 |
|
|
FP_B : in std_logic_vector (K-1 downto 0);
|
11 |
|
|
add_sub: in std_logic; --resta con '0', suma con '1'.
|
12 |
|
|
FP_Z : out std_logic_vector (K-1 downto 0));
|
13 |
|
|
end prueba;
|
14 |
|
|
|
15 |
|
|
architecture Behavioral of prueba is
|
16 |
|
|
function log2 (n : natural) return natural is
|
17 |
|
|
variable a, m : natural;
|
18 |
|
|
begin
|
19 |
|
|
a := 0; m := 1;
|
20 |
|
|
while m < n loop
|
21 |
|
|
a := a + 1; m := m * 2;
|
22 |
|
|
end loop;
|
23 |
|
|
return a;
|
24 |
|
|
end log2;
|
25 |
|
|
constant PLOG : natural := log2(P+3) - 1;
|
26 |
|
|
constant ZEROS : std_logic_vector(K-1 downto 0) := (others => '0');
|
27 |
|
|
constant ONES : std_logic_vector(K-1 downto 0) := (others => '1');
|
28 |
|
|
|
29 |
|
|
signal A_int : std_logic_vector(K-1 downto 0);
|
30 |
|
|
signal B_int : std_logic_vector(K-1 downto 0);
|
31 |
|
|
signal expA_FF, expB_FF, expA_Z, expB_Z : std_logic;
|
32 |
|
|
signal fracA_Z, fracB_Z : std_logic;
|
33 |
|
|
|
34 |
|
|
signal isNaN_A, isNaN_B, isInf_A, isInf_B, isZero_A, isZero_B, isNaN, isInf : std_logic;
|
35 |
|
|
signal underflow_sub : std_logic;
|
36 |
|
|
|
37 |
|
|
signal sign_A, sign_B : std_logic;
|
38 |
|
|
signal exp_A, exp_B : std_logic_vector(E-1 downto 0);
|
39 |
|
|
|
40 |
|
|
signal efectExp: std_logic_vector(E downto 0);
|
41 |
|
|
|
42 |
|
|
signal efectFracA, efectFracB, efectFracB_align : std_logic_vector(P+3 downto 0);--P-1+1+3
|
43 |
|
|
signal diffExpAB, diffExpBA, diffExp : std_logic_vector(E downto 0);
|
44 |
|
|
signal addAB, addSubAB, subAB : std_logic_vector(P+3 downto 0);
|
45 |
|
|
signal frac_add_Norm1 : std_logic_vector(P+3 downto 0);
|
46 |
|
|
signal isSUB : std_logic;
|
47 |
|
|
|
48 |
|
|
signal subBAExpEq : std_logic_vector(P+3 downto 0);
|
49 |
|
|
signal frac_sub_Norm1 : std_logic_vector(P+3 downto 0);
|
50 |
|
|
signal sign : std_logic;
|
51 |
|
|
|
52 |
|
|
-- Component Declarations
|
53 |
|
|
component right_shifter is
|
54 |
|
|
generic (P: natural; E: natural; PLOG: natural);
|
55 |
|
|
Port ( frac : in std_logic_vector (P downto 0);
|
56 |
|
|
diff_exp : in std_logic_vector (E downto 0);
|
57 |
|
|
frac_align : out std_logic_vector (P downto 0));
|
58 |
|
|
end component;
|
59 |
|
|
|
60 |
|
|
component fp_leading_zeros_and_shift is
|
61 |
|
|
generic (P: natural:= 27; E: natural := 8; PLOG: natural := 4);
|
62 |
|
|
Port ( frac : in std_logic_vector (P downto 0);
|
63 |
|
|
exp : in std_logic_vector (E-1 downto 0);
|
64 |
|
|
frac_Norm : out std_logic_vector (P downto 0);
|
65 |
|
|
exp_Norm : out std_logic_vector (E-1 downto 0);
|
66 |
|
|
underFlow : out std_logic);
|
67 |
|
|
end component;
|
68 |
|
|
|
69 |
|
|
signal isZero_AorB : std_logic;
|
70 |
|
|
|
71 |
|
|
--signals for stage 2
|
72 |
|
|
signal frac, frac_Norm1 : std_logic_vector (P+3 downto 0);
|
73 |
|
|
signal frac_Norm2 : std_logic_vector (P-2 downto 0);
|
74 |
|
|
signal frac_stg2 : std_logic_vector (P+3 downto 0);
|
75 |
|
|
signal exp_Norm1, efectExp_stg2: std_logic_vector(E-1 downto 0);
|
76 |
|
|
signal sign_stg2, isSUB_stg2, isNaN_stg2, isInf_stg2, overflow, underflow: std_logic;
|
77 |
|
|
signal isZero_AorB_stg2: std_logic;
|
78 |
|
|
signal isTwo : std_logic;
|
79 |
|
|
signal exp_add_Norm1, exp_sub_Norm1 : std_logic_vector(E-1 downto 0);
|
80 |
|
|
signal isRoundUp, didNorm1 : std_logic;
|
81 |
|
|
signal FP_Z_int : std_logic_vector(K-1 downto 0);
|
82 |
|
|
|
83 |
|
|
begin
|
84 |
|
|
|
85 |
|
|
A_int <= FP_A;
|
86 |
|
|
B_int <= FP_B;
|
87 |
|
|
|
88 |
|
|
--unpacking and detections
|
89 |
|
|
expA_FF <= '1' when A_int(K-2 downto K-E-1)= ONES(K-2 downto K-E-1) else '0'; --In single (30..23)
|
90 |
|
|
expB_FF <= '1' when B_int(K-2 downto K-E-1)= ONES(K-2 downto K-E-1) else '0';
|
91 |
|
|
expA_Z <= '1' when A_int(K-2 downto K-E-1)= ZEROS(K-2 downto K-E-1) else '0';
|
92 |
|
|
expB_Z <= '1' when B_int(K-2 downto K-E-1)= ZEROS(K-2 downto K-E-1) else '0';
|
93 |
|
|
fracA_Z <= '1' when A_int(P-2 downto 0) = ZEROS(P-2 downto 0) else '0'; --In single (22..00)
|
94 |
|
|
fracB_Z <= '1' when B_int(P-2 downto 0) = ZEROS(P-2 downto 0) else '0';
|
95 |
|
|
|
96 |
|
|
isNaN_A <= expA_FF and (not fracA_Z);
|
97 |
|
|
isNaN_B <= expB_FF and (not fracB_Z);
|
98 |
|
|
isInf_A <= expA_FF; -- not compared the fractional part since NaN has priority.
|
99 |
|
|
isInf_B <= expB_FF; --
|
100 |
|
|
isZero_A <= expA_Z and fracA_Z;
|
101 |
|
|
isZero_B <= expB_Z and fracB_Z;
|
102 |
|
|
isZero_AorB <= isZero_A or isZero_B;
|
103 |
|
|
|
104 |
|
|
--NaN Generacion del valor infinito.
|
105 |
|
|
isNaN <= (isNaN_A or isNaN_B) or (isInf_A and isInf_B and isSUB); --NaN generation
|
106 |
|
|
isInf <= (isInf_A xor isInf_B) or (isInf_A and isInf_B and (not isSUB)); --Infinite generation
|
107 |
|
|
|
108 |
|
|
sign_A <= A_int(K-1); -- asignacion del valor de 32 bits.
|
109 |
|
|
exp_A <= A_int(K-2 downto K-E-1); --in simple(30 .. 23);
|
110 |
|
|
|
111 |
|
|
sign_B <= B_int(K-1) when add_sub='1' else not B_int(K-1); --establecimiento de bit de signo de operando B.
|
112 |
|
|
exp_B <= B_int(K-2 downto K-E-1); --in simple(30 .. 23);
|
113 |
|
|
|
114 |
|
|
isSUB <= sign_A XOR sign_B;
|
115 |
|
|
|
116 |
|
|
diffExpAB <= ('0' & exp_A) - ('0' & exp_B); --one extra bit for sign
|
117 |
|
|
diffExpBA <= ('0' & exp_B) - ('0' & exp_A);
|
118 |
|
|
|
119 |
|
|
diffExp <= diffExpAB when diffExpAB(E)='0' else diffExpBA; --in binary32 E = 8;
|
120 |
|
|
|
121 |
|
|
--swap
|
122 |
|
|
efectFracA <= "01" & A_int(P-2 downto 0) & "000" when diffExpAB(E)='0' else "01" & B_int(P-2 downto 0) & "000";
|
123 |
|
|
efectFracB <= "01" & B_int(P-2 downto 0) & "000" when diffExpAB(E)='0' else "01" & A_int(P-2 downto 0) & "000";
|
124 |
|
|
efectExp <= '0' & exp_A when diffExpAB(E)='0' else '0' & exp_B;
|
125 |
|
|
--in efectFracA, the number with bigger exponent, In efectFracB, nro with lower exp --> alignment needed
|
126 |
|
|
--end swap
|
127 |
|
|
|
128 |
|
|
--Effective alignment
|
129 |
|
|
unioa: right_shifter generic map (P => P+3, E => E, PLOG => PLOG)
|
130 |
|
|
port map( frac => efectFracB, diff_exp => diffExp, frac_align => efectFracB_align);
|
131 |
|
|
|
132 |
|
|
|
133 |
|
|
--Addition / subtraction
|
134 |
|
|
addAB <= efectFracA + efectFracB_align;
|
135 |
|
|
subAB <= efectFracA - efectFracB_align;
|
136 |
|
|
addSubAB <= addAB when isSUB = '0' else subAB ;
|
137 |
|
|
|
138 |
|
|
--subtraction without alignment (equal exponents); no swap was done
|
139 |
|
|
subBAExpEq <= (("01" & B_int(P-2 downto 0)) - ("01" & A_int(P-2 downto 0))) & "000";
|
140 |
|
|
|
141 |
|
|
--selection of correct fractional (significand) result
|
142 |
|
|
frac <= "01" & B_int(P-2 downto 0) & "000" when isZero_A='1' else
|
143 |
|
|
"01" & A_int(P-2 downto 0) & "000" when isZero_B='1' else
|
144 |
|
|
subBAExpEq when subBAExpEq(P+3) = '0' and exp_A = exp_B and isSUB = '1' else
|
145 |
|
|
addSubAB;
|
146 |
|
|
|
147 |
|
|
--sign computation
|
148 |
|
|
sign <= sign_A when sign_A = sign_B else
|
149 |
|
|
sign_B when diffExpAB(E)='1' else
|
150 |
|
|
sign_A when addSubAB(P+3)='0' else sign_B;
|
151 |
|
|
|
152 |
|
|
-- isSpecialCase <= isZero_A or isZero_B or isNan or isInf;
|
153 |
|
|
|
154 |
|
|
-- second stage: Norm1, Round And Norm2
|
155 |
|
|
frac_stg2 <= frac;
|
156 |
|
|
efectExp_stg2 <= efectExp(E-1 downto 0);
|
157 |
|
|
isZero_AorB_stg2 <= isZero_AorB;
|
158 |
|
|
isNaN_stg2 <= isNaN;
|
159 |
|
|
isInf_stg2 <= isInf;
|
160 |
|
|
sign_stg2 <= sign;
|
161 |
|
|
isSUB_stg2 <= isSUB;
|
162 |
|
|
|
163 |
|
|
|
164 |
|
|
-- Establecimiento de criterios de normalizacion.
|
165 |
|
|
|
166 |
|
|
--para sumas:
|
167 |
|
|
addition_norm: process(frac_stg2)
|
168 |
|
|
begin
|
169 |
|
|
if (frac_stg2(P+3)='1') then
|
170 |
|
|
frac_add_Norm1 <= '0' & frac_stg2(P+3 downto 2)&(frac_stg2(1) or frac_stg2(0));
|
171 |
|
|
didNorm1 <= '1';
|
172 |
|
|
else
|
173 |
|
|
frac_add_Norm1 <= frac_stg2;
|
174 |
|
|
didNorm1 <= '0';
|
175 |
|
|
end if;
|
176 |
|
|
end process;
|
177 |
|
|
|
178 |
|
|
isTwo <= '1' when (frac_stg2(P+2 downto 2)= ONES(P+2 downto 2)) else '0'; --only could happen in addition
|
179 |
|
|
exp_add_Norm1 <= efectExp_stg2 + (didNorm1 or isTwo);
|
180 |
|
|
|
181 |
|
|
--para resta:
|
182 |
|
|
subtraction_norm: fp_leading_zeros_and_shift
|
183 |
|
|
generic map(P => P+3, E => E, PLOG => PLOG)
|
184 |
|
|
port map(
|
185 |
|
|
frac => frac_stg2,
|
186 |
|
|
exp => efectExp_stg2,
|
187 |
|
|
frac_Norm => frac_sub_Norm1,
|
188 |
|
|
exp_Norm => exp_sub_Norm1,
|
189 |
|
|
underFlow => underflow_sub
|
190 |
|
|
);
|
191 |
|
|
|
192 |
|
|
--seleccion entre suma resta:
|
193 |
|
|
frac_Norm1 <= frac_add_Norm1 when isSUB_stg2 = '0' else frac_sub_Norm1;
|
194 |
|
|
exp_Norm1 <= exp_add_Norm1(E-1 downto 0) when isSUB_stg2 = '0' else exp_sub_Norm1(E-1 downto 0);
|
195 |
|
|
|
196 |
|
|
|
197 |
|
|
--aplicacion de criterios de redondeo, criterio de aprox al par.
|
198 |
|
|
isRoundUp <= '1' when ( (frac_Norm1(2) = '1' and (frac_Norm1(1) = '1' or frac_Norm1(0) = '1')) or frac_Norm1(3 downto 0)="1100") else '0';
|
199 |
|
|
frac_Norm2 <= frac_Norm1(P+1 downto 3) + isRoundUp;
|
200 |
|
|
|
201 |
|
|
--seguda normalizacion.
|
202 |
|
|
--Itīs only necessary for the case 01.111...1111 (almost 2). This is catched with isTwo and round up.
|
203 |
|
|
|
204 |
|
|
--overflow, underflow detection
|
205 |
|
|
overflow <= '1' when (exp_Norm1 = ONES(E-1 downto 0) and (isSUB_stg2 = '0')) else '0';
|
206 |
|
|
underflow <= underflow_sub when isSUB_stg2 = '1' else '0';
|
207 |
|
|
|
208 |
|
|
--pack
|
209 |
|
|
FP_Z_int <= sign_stg2 & ONES(E-1 downto 0) & ZEROS(P-2 downto 1) & '1' when isNaN_stg2='1' else
|
210 |
|
|
sign_stg2 & ONES(E-1 downto 0) & ZEROS(P-2 downto 0) when (isInf_stg2='1' or overflow = '1') else
|
211 |
|
|
sign_stg2 & efectExp_stg2(E-1 downto 0) & frac_stg2(P+1 downto 3) when isZero_AorB_stg2 = '1' else
|
212 |
|
|
sign_stg2 & ZEROS(K-2 downto 0) when underflow='1' else --if underflow => to zero.
|
213 |
|
|
sign_stg2 & exp_Norm1 & frac_Norm2;
|
214 |
|
|
|
215 |
|
|
-- asignacion de salida.
|
216 |
|
|
FP_Z <= FP_Z_int;
|
217 |
|
|
|
218 |
|
|
end Behavioral;
|