Initial Commit (steal code from https://github.com/jop-devel/jop)
[ipdf/vfpu.git] / src / pre_norm_addsub.vhd
1 -------------------------------------------------------------------------------
2 --
3 -- Project:     <Floating Point Unit Core>
4 --      
5 -- Description: pre-normalization entity for the addition/subtraction unit
6 -------------------------------------------------------------------------------
7 --
8 --                              100101011010011100100
9 --                              110000111011100100000
10 --                              100000111011000101101
11 --                              100010111100101111001
12 --                              110000111011101101001
13 --                              010000001011101001010
14 --                              110100111001001100001
15 --                              110111010000001100111
16 --                              110110111110001011101
17 --                              101110110010111101000
18 --                              100000010111000000000
19 --
20 --      Author:          Jidan Al-eryani 
21 --      E-mail:          [email protected]
22 --
23 --  Copyright (C) 2006
24 --
25 --      This source file may be used and distributed without        
26 --      restriction provided that this copyright statement is not   
27 --      removed from the file and that any derivative work contains 
28 --      the original copyright notice and the associated disclaimer.
29 --                                                           
30 --              THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     
31 --      EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   
32 --      TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   
33 --      FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      
34 --      OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         
35 --      INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    
36 --      (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   
37 --      GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        
38 --      BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  
39 --      LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  
40 --      (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  
41 --      OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         
42 --      POSSIBILITY OF SUCH DAMAGE. 
43 --
44
45 library ieee ;
46 use ieee.std_logic_1164.all;
47 use ieee.std_logic_unsigned.all;
48 use ieee.std_logic_misc.all;
49
50 library work;
51 use work.fpupack.all;
52
53 entity pre_norm_addsub is
54         port(
55                         clk_i                   : in std_logic;
56                         opa_i                   : in std_logic_vector(FP_WIDTH-1 downto 0);
57                         opb_i                   : in std_logic_vector(FP_WIDTH-1 downto 0);
58                         fracta_28_o             : out std_logic_vector(FRAC_WIDTH+4 downto 0);  -- carry(1) & hidden(1) & fraction(23) & guard(1) & round(1) & sticky(1)
59                         fractb_28_o             : out std_logic_vector(FRAC_WIDTH+4 downto 0);
60                         exp_o                   : out std_logic_vector(EXP_WIDTH-1 downto 0)
61                 );
62 end pre_norm_addsub;
63
64
65 architecture rtl of pre_norm_addsub is
66
67
68         signal s_exp_o : std_logic_vector(EXP_WIDTH-1 downto 0);
69         signal s_fracta_28_o, s_fractb_28_o : std_logic_vector(FRAC_WIDTH+4 downto 0);
70         signal s_expa, s_expb : std_logic_vector(EXP_WIDTH-1 downto 0);
71         signal s_fracta, s_fractb : std_logic_vector(FRAC_WIDTH-1 downto 0);
72         
73         signal s_fracta_28, s_fractb_28, s_fract_sm_28, s_fract_shr_28 : std_logic_vector(FRAC_WIDTH+4 downto 0);
74         
75         signal s_exp_diff : std_logic_vector(EXP_WIDTH-1 downto 0);
76         signal s_rzeros : std_logic_vector(5 downto 0);
77
78         signal s_expa_eq_expb : std_logic;
79         signal s_expa_lt_expb : std_logic;
80         signal s_fracta_1 : std_logic;
81         signal s_fractb_1 : std_logic;
82         signal s_op_dn,s_opa_dn, s_opb_dn : std_logic;
83         signal s_mux_diff : std_logic_vector(1 downto 0);
84         signal s_mux_exp : std_logic;
85         signal s_sticky : std_logic;
86 begin
87
88         -- Input Register
89         --process(clk_i)
90         --begin
91         --      if rising_edge(clk_i) then      
92                         s_expa <= opa_i(30 downto 23);
93                         s_expb <= opb_i(30 downto 23);
94                         s_fracta <= opa_i(22 downto 0);
95                         s_fractb <= opb_i(22 downto 0);
96         --      end if;
97         --end process;          
98         
99         -- Output Register
100         process(clk_i)
101         begin
102                 if rising_edge(clk_i) then      
103                 exp_o <= s_exp_o;
104                 fracta_28_o <= s_fracta_28_o;
105                 fractb_28_o <= s_fractb_28_o;   
106                 end if;
107         end process;    
108         
109         s_expa_eq_expb <= '1' when s_expa = s_expb else '0';
110         s_expa_lt_expb <= '1' when s_expa > s_expb else '0';
111         
112         -- '1' if fraction is not zero
113         s_fracta_1 <= or_reduce(s_fracta);
114         s_fractb_1 <= or_reduce(s_fractb); 
115         
116         -- opa or Opb is denormalized
117         s_op_dn <= s_opa_dn or s_opb_dn; 
118         s_opa_dn <= not or_reduce(s_expa);
119         s_opb_dn <= not or_reduce(s_expb);
120         
121         -- output the larger exponent 
122         s_mux_exp <= s_expa_lt_expb;
123         process(clk_i)
124         begin
125                 if rising_edge(clk_i) then       
126                         case s_mux_exp is
127                                 when '0' => s_exp_o <= s_expb;
128                                 when '1' => s_exp_o <= s_expa;
129                                 when others => s_exp_o <= "11111111";
130                         end case; 
131                 end if;
132         end process;
133         
134         -- convert to an easy to handle floating-point format
135         s_fracta_28 <= "01" & s_fracta & "000" when s_opa_dn='0' else "00" & s_fracta & "000";
136         s_fractb_28 <= "01" & s_fractb & "000" when s_opb_dn='0' else "00" & s_fractb & "000";
137         
138         
139         s_mux_diff <= s_expa_lt_expb & (s_opa_dn xor s_opb_dn);
140         process(clk_i)
141         begin
142                 if rising_edge(clk_i) then      
143                         -- calculate howmany postions the fraction will be shifted
144                         case s_mux_diff is
145                                 when "00"=> s_exp_diff <= s_expb - s_expa;
146                                 when "01"=>     s_exp_diff <= s_expb - (s_expa+"00000001");
147                                 when "10"=> s_exp_diff <= s_expa - s_expb;
148                                 when "11"=> s_exp_diff <= s_expa - (s_expb+"00000001");
149                                 when others => s_exp_diff <= "11110000";
150                         end case;
151                 end if;
152         end process;
153         
154         
155         s_fract_sm_28 <= s_fracta_28 when s_expa_lt_expb='0' else s_fractb_28;
156         
157         -- shift-right the fraction if necessary
158         s_fract_shr_28 <= shr(s_fract_sm_28, s_exp_diff);
159         
160         -- count the zeros from right to check if result is inexact
161         s_rzeros <= count_r_zeros(s_fract_sm_28);
162         s_sticky <= '1' when s_exp_diff > s_rzeros and or_reduce(s_fract_sm_28)='1' else '0';
163         
164         s_fracta_28_o <= s_fracta_28 when s_expa_lt_expb='1' else s_fract_shr_28(27 downto 1) & (s_sticky or s_fract_shr_28(0));
165         s_fractb_28_o <= s_fractb_28 when s_expa_lt_expb='0' else s_fract_shr_28(27 downto 1) & (s_sticky or s_fract_shr_28(0));
166         
167
168 end rtl;

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