Don't print random debug information
[ipdf/vfpu.git] / src / fpu.vhd
1 -------------------------------------------------------------------------------         
2 -- Description: top entity
3 -- See COPYRIGHT.jop
4
5
6 library ieee;
7 use ieee.std_logic_1164.all;
8 use ieee.numeric_std.all;
9 use ieee.std_logic_misc.all;
10
11 library work;
12 use work.comppack.all;
13 use work.fpupack.all;
14
15
16 entity fpu is
17     port (
18         clk_i                   : in std_logic;
19
20         -- Input Operands A & B
21         opa_i           : in std_logic_vector(FP_WIDTH-1 downto 0);  -- Default: FP_WIDTH=32 
22         opb_i           : in std_logic_vector(FP_WIDTH-1 downto 0);
23         
24         -- fpu operations (fpu_op_i):
25                 -- ========================
26                 -- 000 = add, 
27                 -- 001 = substract, 
28                 -- 010 = multiply, 
29                 -- 011 = divide,
30                 -- 100 = square root
31                 -- 101 = unused
32                 -- 110 = unused
33                 -- 111 = unused
34         fpu_op_i                : in std_logic_vector(2 downto 0);
35         
36         -- Rounding Mode: 
37         -- ==============
38         -- 00 = round to nearest even(default), 
39         -- 01 = round to zero, 
40         -- 10 = round up, 
41         -- 11 = round down
42         rmode_i                 : in std_logic_vector(1 downto 0);
43         
44         -- Output port   
45         output_o        : out std_logic_vector(FP_WIDTH-1 downto 0);
46         
47         -- Control signals
48         start_i                 : in std_logic; -- is also restart signal
49         ready_o                 : out std_logic;
50         
51         -- Exceptions
52         ine_o                   : out std_logic; -- inexact
53         overflow_o      : out std_logic; -- overflow
54         underflow_o     : out std_logic; -- underflow
55         div_zero_o      : out std_logic; -- divide by zero
56         inf_o                   : out std_logic; -- infinity
57         zero_o                  : out std_logic; -- zero
58         qnan_o                  : out std_logic; -- queit Not-a-Number
59         snan_o                  : out std_logic -- signaling Not-a-Number
60         );   
61 end fpu;
62
63 architecture rtl of fpu is
64     
65
66         constant MUL_SERIAL: integer range 0 to 1 := 1; -- 0 for parallel multiplier, 1 for serial
67         constant MUL_COUNT: integer:= 34; --11 for parallel multiplier, 34 for serial
68                 
69         -- Input/output registers
70         signal s_opa_i, s_opb_i : std_logic_vector(FP_WIDTH-1 downto 0);
71         signal s_fpu_op_i               : std_logic_vector(2 downto 0);
72         signal s_rmode_i : std_logic_vector(1 downto 0);
73         signal s_output_o : std_logic_vector(FP_WIDTH-1 downto 0);
74     signal s_ine_o, s_overflow_o, s_underflow_o, s_div_zero_o, s_inf_o, s_zero_o, s_qnan_o, s_snan_o : std_logic;
75         
76         type   t_state is (waiting,busy);
77         signal s_state : t_state;
78         signal s_start_i : std_logic;
79         signal s_count : integer;
80         signal s_output1 : std_logic_vector(FP_WIDTH-1 downto 0);       
81         signal s_infa, s_infb : std_logic;
82         
83         --      ***Add/Substract units signals***
84
85         signal prenorm_addsub_fracta_28_o, prenorm_addsub_fractb_28_o : std_logic_vector(FRAC_COMP_WIDTH-1 downto 0);
86         signal prenorm_addsub_exp_o : std_logic_vector(EXP_WIDTH-1 downto 0); 
87         
88         signal addsub_fract_o : std_logic_vector(FRAC_COMP_WIDTH-1 downto 0); 
89         signal addsub_sign_o : std_logic;
90         
91         signal postnorm_addsub_output_o : std_logic_vector(FP_WIDTH-1 downto 0); 
92         signal postnorm_addsub_ine_o : std_logic;
93         
94         --      ***Multiply units signals***
95         
96         signal pre_norm_mul_exp_10 : std_logic_vector(9 downto 0);
97         signal pre_norm_mul_fracta_24   : std_logic_vector(FRAC_WIDTH downto 0);
98         signal pre_norm_mul_fractb_24   : std_logic_vector(FRAC_WIDTH downto 0);
99                 
100         signal mul_24_fract_48 : std_logic_vector(2*FRAC_WIDTH+1 downto 0);
101         signal mul_24_sign      : std_logic;
102         signal serial_mul_fract_48 : std_logic_vector(2*FRAC_WIDTH+1 downto 0);
103         signal serial_mul_sign  : std_logic;
104         
105         signal mul_fract_48: std_logic_vector(2*FRAC_WIDTH+1 downto 0);
106         signal mul_sign: std_logic;
107         
108         signal post_norm_mul_output     : std_logic_vector(FP_WIDTH-1 downto 0);
109         signal post_norm_mul_ine        : std_logic;
110         
111         --      ***Division units signals***
112         
113         signal pre_norm_div_dvdnd : std_logic_vector(49 downto 0);
114         signal pre_norm_div_dvsor : std_logic_vector(FRAC_WIDTH+3 downto 0);
115         signal pre_norm_div_exp : std_logic_vector(EXP_WIDTH+1 downto 0);
116         
117         signal serial_div_qutnt : std_logic_vector(FRAC_WIDTH+3 downto 0);
118         signal serial_div_rmndr : std_logic_vector(FRAC_WIDTH+3 downto 0);
119         signal serial_div_sign : std_logic;
120         signal serial_div_div_zero : std_logic;
121         
122         signal post_norm_div_output : std_logic_vector(FP_WIDTH-1 downto 0);
123         signal post_norm_div_ine : std_logic;
124         
125         --      ***Square units***
126         
127         signal pre_norm_sqrt_fracta_o           : std_logic_vector(2*(FRAC_COMP_WIDTH-2)-1 downto 0);
128         signal pre_norm_sqrt_exp_o                              : std_logic_vector(7 downto 0);
129                          
130         signal sqrt_sqr_o                       : std_logic_vector(FRAC_WIDTH+2 downto 0);
131         signal sqrt_ine_o                       : std_logic;
132
133         signal post_norm_sqrt_output    : std_logic_vector(FP_WIDTH-1 downto 0);
134         signal post_norm_sqrt_ine_o             : std_logic;
135         
136         
137 begin
138         --***Add/Substract units***
139         
140         i_prenorm_addsub: pre_norm_addsub
141         port map (
142           clk_i => clk_i,
143                                 opa_i => s_opa_i,
144                                 opb_i => s_opb_i,
145                                 fracta_28_o => prenorm_addsub_fracta_28_o,
146                                 fractb_28_o => prenorm_addsub_fractb_28_o,
147                                 exp_o=> prenorm_addsub_exp_o);
148                                 
149         i_addsub: addsub_28
150                 port map(
151                          clk_i => clk_i,                        
152                          fpu_op_i => s_fpu_op_i(0),              
153                          fracta_i       => prenorm_addsub_fracta_28_o,  
154                          fractb_i       => prenorm_addsub_fractb_28_o,          
155                          signa_i =>  s_opa_i(FP_WIDTH-1),                       
156                          signb_i =>  s_opb_i(FP_WIDTH-1),                               
157                          fract_o => addsub_fract_o,                     
158                          sign_o => addsub_sign_o);      
159                          
160         i_postnorm_addsub: post_norm_addsub
161         port map(
162                 clk_i => clk_i,         
163                 opa_i => s_opa_i,
164                 opb_i => s_opb_i,       
165                 fract_28_i => addsub_fract_o,
166                 exp_i => prenorm_addsub_exp_o,
167                 sign_i => addsub_sign_o,
168                 fpu_op_i => s_fpu_op_i(0), 
169                 rmode_i => s_rmode_i,
170                 output_o => postnorm_addsub_output_o,
171                 ine_o => postnorm_addsub_ine_o
172                 );
173         
174         --***Multiply units***
175         
176         i_pre_norm_mul: pre_norm_mul
177         port map(
178                 clk_i => clk_i,         
179                 opa_i => s_opa_i,
180                 opb_i => s_opb_i,
181                 exp_10_o => pre_norm_mul_exp_10,
182                 fracta_24_o     => pre_norm_mul_fracta_24,
183                 fractb_24_o     => pre_norm_mul_fractb_24);
184                                 
185         i_mul_24 : mul_24
186         port map(
187                          clk_i => clk_i,
188                          fracta_i => pre_norm_mul_fracta_24,
189                          fractb_i => pre_norm_mul_fractb_24,
190                          signa_i => s_opa_i(FP_WIDTH-1),
191                          signb_i => s_opb_i(FP_WIDTH-1),
192                          start_i => start_i,
193                          fract_o => mul_24_fract_48, 
194                          sign_o =>      mul_24_sign,
195                          ready_o => open);      
196                          
197         i_serial_mul : serial_mul
198         port map(
199                          clk_i => clk_i,
200                          fracta_i => pre_norm_mul_fracta_24,
201                          fractb_i => pre_norm_mul_fractb_24,
202                          signa_i => s_opa_i(FP_WIDTH-1),
203                          signb_i => s_opb_i(FP_WIDTH-1),
204                          start_i => s_start_i,
205                          fract_o => serial_mul_fract_48, 
206                          sign_o =>      serial_mul_sign,
207                          ready_o => open);      
208         
209         -- serial or parallel multiplier will be choosed depending on constant MUL_SERIAL
210         mul_fract_48 <= mul_24_fract_48 when MUL_SERIAL=0 else serial_mul_fract_48;
211         mul_sign <= mul_24_sign when MUL_SERIAL=0 else serial_mul_sign;
212         
213         i_post_norm_mul : post_norm_mul
214         port map(
215                          clk_i => clk_i,
216                          opa_i => s_opa_i,
217                          opb_i => s_opb_i,
218                          exp_10_i => pre_norm_mul_exp_10,
219                          fract_48_i     => mul_fract_48,
220                          sign_i => mul_sign,
221                          rmode_i => s_rmode_i,
222                          output_o => post_norm_mul_output,
223                          ine_o => post_norm_mul_ine
224                         );
225                 
226         --***Division units***
227         
228         i_pre_norm_div : pre_norm_div
229         port map(
230                          clk_i => clk_i,
231                          opa_i => s_opa_i,
232                          opb_i => s_opb_i,
233                          exp_10_o => pre_norm_div_exp,
234                          dvdnd_50_o     => pre_norm_div_dvdnd,
235                          dvsor_27_o     => pre_norm_div_dvsor);
236                          
237         i_serial_div : serial_div
238         port map(
239                          clk_i=> clk_i,
240                          dvdnd_i => pre_norm_div_dvdnd,
241                          dvsor_i => pre_norm_div_dvsor,
242                          sign_dvd_i => s_opa_i(FP_WIDTH-1),
243                          sign_div_i => s_opb_i(FP_WIDTH-1),
244                          start_i => s_start_i,
245                          ready_o => open,
246                          qutnt_o => serial_div_qutnt,
247                          rmndr_o => serial_div_rmndr,
248                          sign_o => serial_div_sign,
249                          div_zero_o     => serial_div_div_zero);
250         
251         i_post_norm_div : post_norm_div
252         port map(
253                          clk_i => clk_i,
254                          opa_i => s_opa_i,
255                          opb_i => s_opb_i,
256                          qutnt_i =>     serial_div_qutnt,
257                          rmndr_i => serial_div_rmndr,
258                          exp_10_i => pre_norm_div_exp,
259                          sign_i => serial_div_sign,
260                          rmode_i =>     s_rmode_i,
261                          output_o => post_norm_div_output,
262                          ine_o => post_norm_div_ine);
263                          
264         
265         --***Square units***
266
267         i_pre_norm_sqrt : pre_norm_sqrt
268         port map(
269                          clk_i => clk_i,
270                          opa_i => s_opa_i,
271                          fracta_52_o => pre_norm_sqrt_fracta_o,
272                          exp_o => pre_norm_sqrt_exp_o);
273                 
274         i_sqrt: sqrt 
275         generic map(RD_WIDTH=>52, SQ_WIDTH=>26) 
276         port map(
277                          clk_i => clk_i,
278                          rad_i => pre_norm_sqrt_fracta_o, 
279                          start_i => s_start_i, 
280                          ready_o => open, 
281                          sqr_o => sqrt_sqr_o,
282                          ine_o => sqrt_ine_o);
283
284         i_post_norm_sqrt : post_norm_sqrt
285         port map(
286                         clk_i => clk_i,
287                         opa_i => s_opa_i,
288                         fract_26_i => sqrt_sqr_o,
289                         exp_i => pre_norm_sqrt_exp_o,
290                         ine_i => sqrt_ine_o,
291                         rmode_i => s_rmode_i,
292                         output_o => post_norm_sqrt_output,
293                         ine_o => post_norm_sqrt_ine_o);
294                         
295                         
296                         
297 -----------------------------------------------------------------                       
298
299         -- Input Register
300         process(clk_i)
301         begin
302                 if rising_edge(clk_i) then      
303                         s_opa_i <= opa_i;
304                         s_opb_i <= opb_i;
305                         s_fpu_op_i <= fpu_op_i;
306                         s_rmode_i <= rmode_i;
307                         s_start_i <= start_i;
308                 end if;
309         end process;
310           
311         -- Output Register
312         process(clk_i)
313         begin
314                 if rising_edge(clk_i) then      
315                         output_o <= s_output_o;
316                         ine_o <= s_ine_o;
317                         overflow_o <= s_overflow_o;
318                         underflow_o <= s_underflow_o;
319                         div_zero_o <= s_div_zero_o;
320                         inf_o <= s_inf_o;
321                         zero_o <= s_zero_o;
322                         qnan_o <= s_qnan_o;
323                         snan_o <= s_snan_o;
324                 end if;
325         end process;    
326
327     
328         -- FSM
329         process(clk_i)
330         begin
331                 if rising_edge(clk_i) then
332                         if s_start_i ='1' then
333                                 s_state <= busy;
334                                 s_count <= 0;
335                         elsif s_count=6 and ((fpu_op_i="000") or (fpu_op_i="001")) then
336                                 s_state <= waiting;
337                                 ready_o <= '1';
338                                 s_count <=0;
339                         elsif s_count=MUL_COUNT and fpu_op_i="010" then
340                                 s_state <= waiting;
341                                 ready_o <= '1';
342                                 s_count <=0;
343                         elsif s_count=33 and fpu_op_i="011" then
344                                 s_state <= waiting;
345                                 ready_o <= '1';
346                                 s_count <=0;
347                         elsif s_count=33 and fpu_op_i="100" then
348                                 s_state <= waiting;
349                                 ready_o <= '1';
350                                 s_count <=0;                    
351                         elsif s_state=busy then
352                                 s_count <= s_count + 1;
353                         else
354                                 s_state <= waiting;
355                                 ready_o <= '0';
356                         end if;
357         end if; 
358         end process;
359                 
360         -- Output Multiplexer
361         process(clk_i)
362         begin
363                 if rising_edge(clk_i) then
364                         if fpu_op_i="000" or fpu_op_i="001" then        
365                                 s_output1               <= postnorm_addsub_output_o;
366                                 s_ine_o                 <= postnorm_addsub_ine_o;
367                         elsif fpu_op_i="010" then
368                                 s_output1       <= post_norm_mul_output;
369                                 s_ine_o                 <= post_norm_mul_ine;
370                         elsif fpu_op_i="011" then
371                                 s_output1       <= post_norm_div_output;
372                                 s_ine_o                 <= post_norm_div_ine;           
373 --                      elsif fpu_op_i="100" then
374 --                              s_output1       <= post_norm_sqrt_output;
375 --                              s_ine_o         <= post_norm_sqrt_ine_o;                        
376                         else
377                                 s_output1       <= (others => '0');
378                                 s_ine_o                 <= '0';
379                         end if;
380                 end if;
381         end process;    
382
383         
384         s_infa <= '1' when s_opa_i(FP_WIDTH-2 downto FRAC_WIDTH)= (FP_WIDTH-2 downto FRAC_WIDTH => '1')  else '0';
385         s_infb <= '1' when s_opb_i(FP_WIDTH-2 downto FRAC_WIDTH)= (FP_WIDTH-2 downto FRAC_WIDTH => '1')  else '0';
386         
387
388         --In round down: the subtraction of two equal numbers other than zero are always -0!!!
389         process(s_output1, s_rmode_i, s_div_zero_o, s_infa, s_infb, s_qnan_o, s_snan_o, s_zero_o, s_fpu_op_i, s_opa_i, s_opb_i )
390         begin
391                         if s_rmode_i="00" or (s_div_zero_o or (s_infa or s_infb) or s_qnan_o or s_snan_o)='1' then --round-to-nearest-even
392                                 s_output_o <= s_output1;
393                         elsif s_rmode_i="01" and s_output1(FP_WIDTH-2 downto FRAC_WIDTH)="11111111" then
394                                 --In round-to-zero: the sum of two non-infinity operands is never infinity,even if an overflow occures
395                                 s_output_o <= s_output1(FP_WIDTH-1) & "1111111011111111111111111111111";
396                         elsif s_rmode_i="10" and s_output1(FP_WIDTH-1 downto FRAC_WIDTH)="111111111" then
397                                 --In round-up: the sum of two non-infinity operands is never negative infinity,even if an overflow occures
398                                 s_output_o <= "11111111011111111111111111111111";
399                         elsif s_rmode_i="11" then
400                                 --In round-down: a-a= -0
401                                 if (s_fpu_op_i="000" or s_fpu_op_i="001") and s_zero_o='1' and (s_opa_i(FP_WIDTH-1) or (s_fpu_op_i(0) xor s_opb_i(FP_WIDTH-1)))='1' then
402                                         s_output_o <= "1" & s_output1(FP_WIDTH-2 downto 0);     
403                                 --In round-down: the sum of two non-infinity operands is never postive infinity,even if an overflow occures
404                                 elsif s_output1(FP_WIDTH-1 downto FRAC_WIDTH)="011111111" then
405                                         s_output_o <= "01111111011111111111111111111111";
406                                 else
407                                         s_output_o <= s_output1;
408                                 end if;                 
409                         else
410                                 s_output_o <= s_output1;
411                         end if;
412         end process;
413                 
414
415         -- Generate Exceptions 
416         s_underflow_o <= '1' when s_output1(FP_WIDTH-2 downto FRAC_WIDTH)="00000000" and s_ine_o='1' else '0'; 
417         s_overflow_o <= '1' when s_output1(FP_WIDTH-2 downto FRAC_WIDTH)="11111111" and s_ine_o='1' else '0';
418         s_div_zero_o <= serial_div_div_zero when fpu_op_i="011" else '0';
419         s_inf_o <= '1' when s_output1(FP_WIDTH-2 downto FRAC_WIDTH)="11111111" and (s_qnan_o or s_snan_o)='0' else '0';
420         s_zero_o <= '1' when or_reduce(s_output1(FP_WIDTH-2 downto 0))='0' else '0';
421         s_qnan_o <= '1' when s_output1(FP_WIDTH-2 downto 0)=QNAN else '0';
422     s_snan_o <= '1' when s_opa_i(FP_WIDTH-2 downto 0)=SNAN or s_opb_i(FP_WIDTH-2 downto 0)=SNAN else '0';
423
424
425 end rtl;

UCC git Repository :: git.ucc.asn.au