-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
--
|
--
|
-- 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;
|
|
|
|
|