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

Subversion Repositories fpu100

[/] [fpu100/] [branches/] [avendor/] [sqrt.vhd] - Diff between revs 2 and 21

Only display areas with differences | Details | Blame | View Log

Rev 2 Rev 21
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--
--
-- Project:     <Floating Point Unit Core>
-- Project:     <Floating Point Unit Core>
--      
--      
-- Description: square-root entity for the square-root unit
-- Description: square-root entity for the square-root unit
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--
--
--                              100101011010011100100
--                              100101011010011100100
--                              110000111011100100000
--                              110000111011100100000
--                              100000111011000101101
--                              100000111011000101101
--                              100010111100101111001
--                              100010111100101111001
--                              110000111011101101001
--                              110000111011101101001
--                              010000001011101001010
--                              010000001011101001010
--                              110100111001001100001
--                              110100111001001100001
--                              110111010000001100111
--                              110111010000001100111
--                              110110111110001011101
--                              110110111110001011101
--                              101110110010111101000
--                              101110110010111101000
--                              100000010111000000000
--                              100000010111000000000
--
--
--      Author:          Jidan Al-eryani 
--      Author:          Jidan Al-eryani 
--      E-mail:          jidan@gmx.net
--      E-mail:          jidan@gmx.net
--
--
--  Copyright (C) 2006
--  Copyright (C) 2006
--
--
--      This source file may be used and distributed without        
--      This source file may be used and distributed without        
--      restriction provided that this copyright statement is not   
--      restriction provided that this copyright statement is not   
--      removed from the file and that any derivative work contains 
--      removed from the file and that any derivative work contains 
--      the original copyright notice and the associated disclaimer.
--      the original copyright notice and the associated disclaimer.
--                                                           
--                                                           
--              THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     
--              THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     
--      EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   
--      EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   
--      TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   
--      TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   
--      FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      
--      FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      
--      OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         
--      OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         
--      INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    
--      INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    
--      (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   
--      (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   
--      GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        
--      GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        
--      BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  
--      BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  
--      LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  
--      LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  
--      (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  
--      (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  
--      OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         
--      OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         
--      POSSIBILITY OF SUCH DAMAGE. 
--      POSSIBILITY OF SUCH DAMAGE. 
--
--
 
 
library ieee ;
library ieee ;
use ieee.std_logic_1164.all;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_unsigned.all;
 
 
entity sqrt is
entity sqrt is
        generic (RD_WIDTH: integer:=52; SQ_WIDTH: integer:=26); -- SQ_WIDTH = RD_WIDTH/2 (+ 1 if odd)
        generic (RD_WIDTH: integer:=52; SQ_WIDTH: integer:=26); -- SQ_WIDTH = RD_WIDTH/2 (+ 1 if odd)
        port(
        port(
                         clk_i                   : in std_logic;
                         clk_i                   : in std_logic;
                         rad_i                  : in std_logic_vector(RD_WIDTH-1 downto 0); -- hidden(1) & fraction(23)
                         rad_i                  : in std_logic_vector(RD_WIDTH-1 downto 0); -- hidden(1) & fraction(23)
                         start_i                        : in std_logic;
                         start_i                        : in std_logic;
                         ready_o                        : out std_logic;
                         ready_o                        : out std_logic;
                         sqr_o                  : out std_logic_vector(SQ_WIDTH-1 downto 0);
                         sqr_o                  : out std_logic_vector(SQ_WIDTH-1 downto 0);
                         ine_o                  : out std_logic
                         ine_o                  : out std_logic
                );
                );
end sqrt;
end sqrt;
 
 
architecture rtl of sqrt is
architecture rtl of sqrt is
 
 
signal s_rad_i: std_logic_vector(RD_WIDTH-1 downto 0);
signal s_rad_i: std_logic_vector(RD_WIDTH-1 downto 0);
signal s_start_i, s_ready_o : std_logic;
signal s_start_i, s_ready_o : std_logic;
signal s_sqr_o: std_logic_vector(RD_WIDTH-1 downto 0);
signal s_sqr_o: std_logic_vector(RD_WIDTH-1 downto 0);
signal s_ine_o : std_logic;
signal s_ine_o : std_logic;
 
 
constant ITERATIONS : integer:= RD_WIDTH/2; -- iterations = N/2
constant ITERATIONS : integer:= RD_WIDTH/2; -- iterations = N/2
constant WIDTH_C : integer:= 5; -- log2(ITERATIONS)
constant WIDTH_C : integer:= 5; -- log2(ITERATIONS)
                                                                                  --0000000000000000000000000000000000000000000000000000
                                                                                  --0000000000000000000000000000000000000000000000000000
constant CONST_B : std_logic_vector(RD_WIDTH-1 downto 0) :="0000000000000000000000000010000000000000000000000000"; -- b = 2^(N/2 - 1)
constant CONST_B : std_logic_vector(RD_WIDTH-1 downto 0) :="0000000000000000000000000010000000000000000000000000"; -- b = 2^(N/2 - 1)
constant CONST_B_2: std_logic_vector(RD_WIDTH-1 downto 0):="0100000000000000000000000000000000000000000000000000"; -- b^2
constant CONST_B_2: std_logic_vector(RD_WIDTH-1 downto 0):="0100000000000000000000000000000000000000000000000000"; -- b^2
constant CONST_C : std_logic_vector(WIDTH_C-1 downto 0):= "11010"; -- c = N/2
constant CONST_C : std_logic_vector(WIDTH_C-1 downto 0):= "11010"; -- c = N/2
 
 
 
 
signal s_count : integer range 0 to ITERATIONS;
signal s_count : integer range 0 to ITERATIONS;
 
 
type t_state is (waiting,busy);
type t_state is (waiting,busy);
signal s_state : t_state;
signal s_state : t_state;
 
 
signal b, b_2, r0, r0_2, r1, r1_2 : std_logic_vector(RD_WIDTH-1 downto 0);
signal b, b_2, r0, r0_2, r1, r1_2 : std_logic_vector(RD_WIDTH-1 downto 0);
signal c : std_logic_vector(WIDTH_C-1 downto 0);
signal c : std_logic_vector(WIDTH_C-1 downto 0);
 
 
        signal s_op1, s_op2, s_sum1a, s_sum1b, s_sum2a, s_sum2b : std_logic_vector(RD_WIDTH-1 downto 0);
        signal s_op1, s_op2, s_sum1a, s_sum1b, s_sum2a, s_sum2b : std_logic_vector(RD_WIDTH-1 downto 0);
 
 
begin
begin
 
 
 
 
        -- Input Register
        -- Input Register
        process(clk_i)
        process(clk_i)
        begin
        begin
                if rising_edge(clk_i) then
                if rising_edge(clk_i) then
                        s_rad_i <= rad_i;
                        s_rad_i <= rad_i;
                        s_start_i <= start_i;
                        s_start_i <= start_i;
                end if;
                end if;
        end process;
        end process;
 
 
        -- Output Register
        -- Output Register
        process(clk_i)
        process(clk_i)
        begin
        begin
                if rising_edge(clk_i) then
                if rising_edge(clk_i) then
                        sqr_o <= s_sqr_o(SQ_WIDTH-1 downto 0);
                        sqr_o <= s_sqr_o(SQ_WIDTH-1 downto 0);
                        ine_o <= s_ine_o;
                        ine_o <= s_ine_o;
                        ready_o <= s_ready_o;
                        ready_o <= s_ready_o;
                end if;
                end if;
        end process;
        end process;
 
 
 
 
        -- FSM
        -- FSM
        process(clk_i)
        process(clk_i)
        begin
        begin
                if rising_edge(clk_i) then
                if rising_edge(clk_i) then
                        if s_start_i ='1' then
                        if s_start_i ='1' then
                                s_state <= busy;
                                s_state <= busy;
                                s_count <= ITERATIONS;
                                s_count <= ITERATIONS;
                        elsif s_count=0 and s_state=busy then
                        elsif s_count=0 and s_state=busy then
                                s_state <= waiting;
                                s_state <= waiting;
                                s_ready_o <= '1';
                                s_ready_o <= '1';
                                s_count <=ITERATIONS;
                                s_count <=ITERATIONS;
                        elsif s_state=busy then
                        elsif s_state=busy then
                                s_count <= s_count - 1;
                                s_count <= s_count - 1;
                        else
                        else
                                s_state <= waiting;
                                s_state <= waiting;
                                s_ready_o <= '0';
                                s_ready_o <= '0';
                        end if;
                        end if;
                end if;
                end if;
        end process;
        end process;
 
 
        process(clk_i)
        process(clk_i)
        begin
        begin
                if rising_edge(clk_i) then
                if rising_edge(clk_i) then
                                if s_start_i='1' then
                                if s_start_i='1' then
                                        b    <= CONST_B;
                                        b    <= CONST_B;
                                        b_2  <= CONST_B_2;
                                        b_2  <= CONST_B_2;
                                        c    <= CONST_C;
                                        c    <= CONST_C;
                                else
                                else
                                        b   <= '0'&b(RD_WIDTH-1 downto 1); -- shr 1
                                        b   <= '0'&b(RD_WIDTH-1 downto 1); -- shr 1
                                        b_2 <= "00"&b_2(RD_WIDTH-1 downto 2);-- shr 2   
                                        b_2 <= "00"&b_2(RD_WIDTH-1 downto 2);-- shr 2   
                                        c <= c - '1';
                                        c <= c - '1';
                                end if;
                                end if;
                end if;
                end if;
        end process;
        end process;
 
 
 
 
 
 
        s_op1 <= r0_2 + b_2;
        s_op1 <= r0_2 + b_2;
        s_op2 <= shl(r0, c);
        s_op2 <= shl(r0, c);
        s_sum1a <= "00000000000000000000000000"& (r0(25 downto 0) - b(25 downto 0));
        s_sum1a <= "00000000000000000000000000"& (r0(25 downto 0) - b(25 downto 0));
        s_sum2a <= "00000000000000000000000000"& (r0(25 downto 0) + b(25 downto 0));
        s_sum2a <= "00000000000000000000000000"& (r0(25 downto 0) + b(25 downto 0));
        s_sum1b <= s_op1 - s_op2;
        s_sum1b <= s_op1 - s_op2;
        s_sum2b <= s_op1 + s_op2;
        s_sum2b <= s_op1 + s_op2;
 
 
 
 
 
 
        process(clk_i)
        process(clk_i)
                variable v_r1, v_r1_2 : std_logic_vector(RD_WIDTH-1 downto 0);
                variable v_r1, v_r1_2 : std_logic_vector(RD_WIDTH-1 downto 0);
        begin
        begin
                if rising_edge(clk_i) then
                if rising_edge(clk_i) then
                                if s_start_i='1' then
                                if s_start_i='1' then
                                        r0   <= (others =>'0');
                                        r0   <= (others =>'0');
                                        r0_2 <= (others =>'0');
                                        r0_2 <= (others =>'0');
                                elsif s_state=busy then
                                elsif s_state=busy then
                                        if r0_2 > s_rad_i then
                                        if r0_2 > s_rad_i then
                                                v_r1 := s_sum1a;
                                                v_r1 := s_sum1a;
                                                v_r1_2 := s_sum1b;
                                                v_r1_2 := s_sum1b;
                                        else
                                        else
                                                v_r1 := s_sum2a;
                                                v_r1 := s_sum2a;
                                                v_r1_2 := s_sum2b;
                                                v_r1_2 := s_sum2b;
                                        end if;
                                        end if;
                                        r0 <= v_r1;
                                        r0 <= v_r1;
                                        r0_2 <= v_r1_2;
                                        r0_2 <= v_r1_2;
                                        r1 <= v_r1;
                                        r1 <= v_r1;
                                        r1_2 <= v_r1_2;
                                        r1_2 <= v_r1_2;
                                end if;
                                end if;
                end if;
                end if;
        end process;
        end process;
 
 
        process(clk_i)
        process(clk_i)
        begin
        begin
                if rising_edge(clk_i) then
                if rising_edge(clk_i) then
                        if s_count=0 then
                        if s_count=0 then
                                                if r1_2 > s_rad_i then
                                                if r1_2 > s_rad_i then
                                                        s_sqr_o <= r1 - '1';
                                                        s_sqr_o <= r1 - '1';
                                                else
                                                else
                                                        s_sqr_o <= r1;
                                                        s_sqr_o <= r1;
                                                end if;
                                                end if;
                        end if;
                        end if;
                end if;
                end if;
        end process;
        end process;
 
 
 
 
        -- check if result is inexact. In this way we saved 1 clk cycle!
        -- check if result is inexact. In this way we saved 1 clk cycle!
        process(clk_i)
        process(clk_i)
                variable v_r1_2 : std_logic_vector(RD_WIDTH-1 downto 0);
                variable v_r1_2 : std_logic_vector(RD_WIDTH-1 downto 0);
        begin
        begin
                if rising_edge(clk_i) then
                if rising_edge(clk_i) then
                        v_r1_2 := r1_2 - (r1(RD_WIDTH-2 downto 0)&"0") + '1';
                        v_r1_2 := r1_2 - (r1(RD_WIDTH-2 downto 0)&"0") + '1';
                        if s_count=0 then
                        if s_count=0 then
                                if r1_2 = s_rad_i or v_r1_2=s_rad_i then
                                if r1_2 = s_rad_i or v_r1_2=s_rad_i then
                                        s_ine_o <= '0';
                                        s_ine_o <= '0';
                                else
                                else
                                        s_ine_o <= '1';
                                        s_ine_o <= '1';
                                end if;
                                end if;
                        end if;
                        end if;
 
 
                end if;
                end if;
        end process;
        end process;
 
 
 
 

powered by: WebSVN 2.1.0

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