OpenCores
URL https://opencores.org/ocsvn/fpu100/fpu100/trunk

Subversion Repositories fpu100

[/] [fpu100/] [branches/] [avendor/] [sqrt.vhd] - Blame information for rev 27

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 jidan
-------------------------------------------------------------------------------
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:          jidan@gmx.net
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_count=0 then
182
                                                if r1_2 > s_rad_i then
183
                                                        s_sqr_o <= r1 - '1';
184
                                                else
185
                                                        s_sqr_o <= r1;
186
                                                end if;
187
                        end if;
188
                end if;
189
        end process;
190
 
191
 
192
        -- check if result is inexact. In this way we saved 1 clk cycle!
193
        process(clk_i)
194
                variable v_r1_2 : std_logic_vector(RD_WIDTH-1 downto 0);
195
        begin
196
                if rising_edge(clk_i) then
197
                        v_r1_2 := r1_2 - (r1(RD_WIDTH-2 downto 0)&"0") + '1';
198
                        if s_count=0 then
199
                                if r1_2 = s_rad_i or v_r1_2=s_rad_i then
200
                                        s_ine_o <= '0';
201
                                else
202
                                        s_ine_o <= '1';
203
                                end if;
204
                        end if;
205
 
206
                end if;
207
        end process;
208
 
209
end rtl;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.