1 -------------------------------------------------------------------------------
3 -- Project: <Floating Point Unit Core>
5 -- Description: square-root entity for the square-root unit
6 -------------------------------------------------------------------------------
8 -- 100101011010011100100
9 -- 110000111011100100000
10 -- 100000111011000101101
11 -- 100010111100101111001
12 -- 110000111011101101001
13 -- 010000001011101001010
14 -- 110100111001001100001
15 -- 110111010000001100111
16 -- 110110111110001011101
17 -- 101110110010111101000
18 -- 100000010111000000000
20 -- Author: Jidan Al-eryani
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.
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.
46 use ieee.std_logic_1164.all;
47 use ieee.std_logic_unsigned.all;
50 generic (RD_WIDTH: integer:=52; SQ_WIDTH: integer:=26); -- SQ_WIDTH = RD_WIDTH/2 (+ 1 if odd)
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);
61 architecture rtl of sqrt is
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;
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
76 signal s_count : integer range 0 to ITERATIONS;
78 type t_state is (waiting,busy);
79 signal s_state : t_state;
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);
84 signal s_op1, s_op2, s_sum1a, s_sum1b, s_sum2a, s_sum2b : std_logic_vector(RD_WIDTH-1 downto 0);
92 if rising_edge(clk_i) then
101 if rising_edge(clk_i) then
102 sqr_o <= s_sqr_o(SQ_WIDTH-1 downto 0);
104 ready_o <= s_ready_o;
112 if rising_edge(clk_i) then
113 if s_start_i ='1' then
115 s_count <= ITERATIONS;
116 elsif s_count=0 and s_state=busy then
119 s_count <=ITERATIONS;
120 elsif s_state=busy then
121 s_count <= s_count - 1;
131 if rising_edge(clk_i) then
132 if s_start_i='1' then
137 b <= '0'&b(RD_WIDTH-1 downto 1); -- shr 1
138 b_2 <= "00"&b_2(RD_WIDTH-1 downto 2);-- shr 2
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;
156 variable v_r1, v_r1_2 : std_logic_vector(RD_WIDTH-1 downto 0);
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
180 if rising_edge(clk_i) then
181 if s_start_i = '1' then
182 s_sqr_o <= (others =>'0');
184 if r1_2 > s_rad_i then
194 -- check if result is inexact. In this way we saved 1 clk cycle!
196 variable v_r1_2 : std_logic_vector(RD_WIDTH-1 downto 0);
198 if rising_edge(clk_i) then
199 v_r1_2 := r1_2 - (r1(RD_WIDTH-2 downto 0)&"0") + '1';
201 if r1_2 = s_rad_i or v_r1_2=s_rad_i then