Initial Commit (steal code from https://github.com/jop-devel/jop)
[ipdf/vfpu.git] / src / sqrt.vhd
1 -------------------------------------------------------------------------------
2 --
3 -- Project:     <Floating Point Unit Core>
4 --      
5 -- Description: square-root entity for the square-root 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
49 entity sqrt is
50         generic (RD_WIDTH: integer:=52; SQ_WIDTH: integer:=26); -- SQ_WIDTH = RD_WIDTH/2 (+ 1 if odd)
51         port(
52                          clk_i                   : in std_logic;
53                          rad_i                  : in std_logic_vector(RD_WIDTH-1 downto 0); -- hidden(1) & fraction(23)
54                          start_i                        : in std_logic;
55                          ready_o                        : out std_logic;
56                          sqr_o                  : out std_logic_vector(SQ_WIDTH-1 downto 0);
57                          ine_o                  : out std_logic
58                 );
59 end sqrt;
60
61 architecture rtl of sqrt is
62
63 signal s_rad_i: std_logic_vector(RD_WIDTH-1 downto 0);
64 signal s_start_i, s_ready_o : std_logic;
65 signal s_sqr_o: std_logic_vector(RD_WIDTH-1 downto 0);
66 signal s_ine_o : std_logic;
67
68 constant ITERATIONS : integer:= RD_WIDTH/2; -- iterations = N/2
69 constant WIDTH_C : integer:= 5; -- log2(ITERATIONS)
70                                                                                   --0000000000000000000000000000000000000000000000000000
71 constant CONST_B : std_logic_vector(RD_WIDTH-1 downto 0) :="0000000000000000000000000010000000000000000000000000"; -- b = 2^(N/2 - 1)
72 constant CONST_B_2: std_logic_vector(RD_WIDTH-1 downto 0):="0100000000000000000000000000000000000000000000000000"; -- b^2
73 constant CONST_C : std_logic_vector(WIDTH_C-1 downto 0):= "11010"; -- c = N/2
74
75
76 signal s_count : integer range 0 to ITERATIONS;
77
78 type t_state is (waiting,busy);
79 signal s_state : t_state;
80
81 signal b, b_2, r0, r0_2, r1, r1_2 : std_logic_vector(RD_WIDTH-1 downto 0);
82 signal c : std_logic_vector(WIDTH_C-1 downto 0);
83
84         signal s_op1, s_op2, s_sum1a, s_sum1b, s_sum2a, s_sum2b : std_logic_vector(RD_WIDTH-1 downto 0);
85         
86 begin
87
88
89         -- Input Register
90         process(clk_i)
91         begin
92                 if rising_edge(clk_i) then      
93                         s_rad_i <= rad_i;
94                         s_start_i <= start_i;
95                 end if;
96         end process;    
97         
98         -- Output Register
99         process(clk_i)
100         begin
101                 if rising_edge(clk_i) then      
102                         sqr_o <= s_sqr_o(SQ_WIDTH-1 downto 0);
103                         ine_o <= s_ine_o;
104                         ready_o <= s_ready_o;
105                 end if;
106         end process;
107
108
109         -- FSM
110         process(clk_i)
111         begin
112                 if rising_edge(clk_i) then
113                         if s_start_i ='1' then
114                                 s_state <= busy;
115                                 s_count <= ITERATIONS; 
116                         elsif s_count=0 and s_state=busy then
117                                 s_state <= waiting;
118                                 s_ready_o <= '1';
119                                 s_count <=ITERATIONS; 
120                         elsif s_state=busy then
121                                 s_count <= s_count - 1;
122                         else
123                                 s_state <= waiting;
124                                 s_ready_o <= '0';
125                         end if;
126                 end if; 
127         end process;
128
129         process(clk_i)
130         begin
131                 if rising_edge(clk_i) then
132                                 if s_start_i='1' then
133                                         b    <= CONST_B;
134                                         b_2  <= CONST_B_2;
135                                         c    <= CONST_C;
136                                 else
137                                         b   <= '0'&b(RD_WIDTH-1 downto 1); -- shr 1
138                                         b_2 <= "00"&b_2(RD_WIDTH-1 downto 2);-- shr 2   
139                                         c <= c - '1';
140                                 end if;
141                 end if;
142         end process;
143         
144
145         
146         s_op1 <= r0_2 + b_2;
147         s_op2 <= shl(r0, c);
148         s_sum1a <= "00000000000000000000000000"& (r0(25 downto 0) - b(25 downto 0));
149         s_sum2a <= "00000000000000000000000000"& (r0(25 downto 0) + b(25 downto 0));
150         s_sum1b <= s_op1 - s_op2;
151         s_sum2b <= s_op1 + s_op2;       
152
153
154
155         process(clk_i)
156                 variable v_r1, v_r1_2 : std_logic_vector(RD_WIDTH-1 downto 0);
157         begin
158                 if rising_edge(clk_i) then
159                                 if s_start_i='1' then
160                                         r0   <= (others =>'0');
161                                         r0_2 <= (others =>'0');
162                                 elsif s_state=busy then
163                                         if r0_2 > s_rad_i then
164                                                 v_r1 := s_sum1a;
165                                                 v_r1_2 := s_sum1b;
166                                         else
167                                                 v_r1 := s_sum2a;
168                                                 v_r1_2 := s_sum2b;                              
169                                         end if;
170                                         r0 <= v_r1;
171                                         r0_2 <= v_r1_2;
172                                         r1 <= v_r1;
173                                         r1_2 <= v_r1_2;
174                                 end if;
175                 end if;
176         end process;
177         
178         process(clk_i)
179         begin
180                 if rising_edge(clk_i) then
181                         if s_start_i = '1' then
182                                 s_sqr_o <= (others =>'0');
183                         elsif s_count=0 then
184                                                 if r1_2 > s_rad_i then
185                                                         s_sqr_o <= r1 - '1';
186                                                 else
187                                                         s_sqr_o <= r1;
188                                                 end if;         
189                         end if;
190                 end if;
191         end process;
192         
193         
194         -- check if result is inexact. In this way we saved 1 clk cycle!
195         process(clk_i)
196                 variable v_r1_2 : std_logic_vector(RD_WIDTH-1 downto 0);
197         begin
198                 if rising_edge(clk_i) then
199                         v_r1_2 := r1_2 - (r1(RD_WIDTH-2 downto 0)&"0") + '1';
200                         if s_count=0 then                               
201                                 if r1_2 = s_rad_i or v_r1_2=s_rad_i then
202                                         s_ine_o <= '0';
203                                 else
204                                         s_ine_o <= '1';
205                                 end if;
206                         end if;
207                         
208                 end if;
209         end process;                            
210         
211 end rtl;

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