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

Subversion Repositories fpu_double

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/trunk/fpu_round.vhd
0,0 → 1,128
---------------------------------------------------------------------
---- ----
---- FPU ----
---- Floating Point Unit (Double precision) ----
---- ----
---- Author: David Lundgren ----
---- davidklun@gmail.com ----
---- ----
---------------------------------------------------------------------
---- ----
---- Copyright (C) 2009 David Lundgren ----
---- davidklun@gmail.com ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer.----
---- ----
---- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ----
---- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ----
---- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ----
---- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ----
---- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ----
---- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ----
---- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ----
---- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ----
---- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ----
---- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ----
---- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ----
---- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ----
---- POSSIBILITY OF SUCH DAMAGE. ----
---- ----
---------------------------------------------------------------------
 
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_misc.all;
 
ENTITY fpu_round IS
 
PORT(
clk, rst, enable : IN std_logic;
round_mode : IN std_logic_vector (1 DOWNTO 0);
sign_term : IN std_logic;
mantissa_term : IN std_logic_vector (55 DOWNTO 0);
exponent_term : IN std_logic_vector (11 DOWNTO 0);
round_out : OUT std_logic_vector (63 DOWNTO 0);
exponent_final : OUT std_logic_vector (11 DOWNTO 0)
);
 
END fpu_round;
architecture rtl of fpu_round is
 
signal rounding_amount : std_logic_vector(55 downto 0);
signal round_nearest : std_logic;
signal round_to_zero : std_logic;
signal round_to_pos_inf : std_logic;
signal round_to_neg_inf : std_logic;
signal round_nearest_trigger : std_logic;
signal round_to_pos_inf_trigger : std_logic;
signal round_to_neg_inf_trigger : std_logic;
signal round_trigger : std_logic;
signal sum_round : std_logic_vector(55 downto 0);
signal sum_round_overflow : std_logic;
-- will be 0 if no carry, 1 if overflow from the rounding unit
-- overflow from rounding is extremely rare, but possible
signal sum_round_2 : std_logic_vector(55 downto 0);
signal exponent_round : std_logic_vector(11 downto 0);
signal exponent_final_2 : std_logic_vector(11 downto 0);
signal sum_final : std_logic_vector(55 downto 0);
begin
rounding_amount <= "00000000000000000000000000000000000000000000000000000100";
round_nearest <= '1' when (round_mode = "00") else '0';
round_to_zero <= '1' when (round_mode = "01") else '0';
round_to_pos_inf <= '1' when (round_mode = "10") else '0';
round_to_neg_inf <= '1' when (round_mode = "11") else '0';
round_nearest_trigger <= '1' when round_nearest = '1' and mantissa_term(1) = '1'
else '0';
round_to_pos_inf_trigger <= '1' when sign_term = '0' and
or_reduce(mantissa_term(1 downto 0)) = '1' else '0';
round_to_neg_inf_trigger <= '1' when sign_term = '1' and
or_reduce(mantissa_term(1 downto 0)) = '1' else '0';
round_trigger <= '1' when ( round_nearest = '1' and round_nearest_trigger = '1')
or (round_to_pos_inf = '1' and round_to_pos_inf_trigger = '1')
or (round_to_neg_inf = '1' and round_to_neg_inf_trigger = '1')
else '0';
sum_round_overflow <= sum_round(55);
process
begin
wait until clk'event and clk = '1';
if (rst = '1') then
sum_round <= (others =>'0');
sum_round_2 <= (others =>'0');
exponent_round <= (others =>'0');
sum_final <= (others =>'0');
exponent_final <= (others =>'0');
exponent_final_2 <= (others =>'0');
round_out <= (others =>'0');
else
sum_round <= rounding_amount + mantissa_term;
if sum_round_overflow = '1' then
sum_round_2 <= shr(sum_round, conv_std_logic_vector('1', 56));
exponent_round <= exponent_term + "000000000001";
else
sum_round_2 <= sum_round;
exponent_round <= exponent_term;
end if;
if round_trigger = '1' then
sum_final <= sum_round_2;
exponent_final_2 <= exponent_round;
else
sum_final <= mantissa_term;
exponent_final_2 <= exponent_term;
end if;
exponent_final <= exponent_final_2;
round_out <= sign_term & exponent_final_2(10 downto 0) & sum_final(53 downto 2);
end if;
end process;
end rtl;
/trunk/fpu_add.vhd
0,0 → 1,191
---------------------------------------------------------------------
---- ----
---- FPU ----
---- Floating Point Unit (Double precision) ----
---- ----
---- Author: David Lundgren ----
---- davidklun@gmail.com ----
---- ----
---------------------------------------------------------------------
---- ----
---- Copyright (C) 2009 David Lundgren ----
---- davidklun@gmail.com ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer.----
---- ----
---- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ----
---- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ----
---- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ----
---- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ----
---- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ----
---- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ----
---- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ----
---- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ----
---- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ----
---- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ----
---- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ----
---- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ----
---- POSSIBILITY OF SUCH DAMAGE. ----
---- ----
---------------------------------------------------------------------
 
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_misc.all;
 
 
ENTITY fpu_add IS
 
PORT(
clk : IN std_logic;
rst : IN std_logic;
enable : IN std_logic;
opa : IN std_logic_vector (63 DOWNTO 0);
opb : IN std_logic_vector (63 DOWNTO 0);
sign : OUT std_logic;
sum_3 : OUT std_logic_vector (55 DOWNTO 0);
exponent_2 : OUT std_logic_vector (10 DOWNTO 0)
);
 
-- Declarations
 
END fpu_add;
 
architecture rtl of fpu_add is
 
 
signal exponent_a : std_logic_vector(10 downto 0);
signal exponent_b : std_logic_vector(10 downto 0);
signal mantissa_a : std_logic_vector(51 downto 0);
signal mantissa_b : std_logic_vector(51 downto 0);
signal exponent_small : std_logic_vector(10 downto 0);
signal exponent_large : std_logic_vector(10 downto 0);
signal mantissa_small : std_logic_vector(51 downto 0);
signal mantissa_large : std_logic_vector(51 downto 0);
signal small_is_denorm : std_logic;
signal large_is_denorm : std_logic;
signal large_norm_small_denorm : std_logic_vector(10 downto 0);
signal exponent_diff : std_logic_vector(10 downto 0);
signal large_add : std_logic_vector(55 downto 0);
signal small_add : std_logic_vector(55 downto 0);
signal small_shift : std_logic_vector(55 downto 0);
signal small_shift_nonzero : std_logic;
signal small_is_nonzero : std_logic;
signal small_fraction_enable : std_logic;
signal small_shift_2 : std_logic_vector(55 downto 0);
signal small_shift_3 : std_logic_vector(55 downto 0);
signal sum : std_logic_vector(55 downto 0);
signal sum_2 : std_logic_vector(55 downto 0);
signal sum_overflow : std_logic;
signal exponent : std_logic_vector(10 downto 0);
signal sum_leading_one : std_logic;
signal denorm_to_norm : std_logic;
 
signal exp_diff_int : integer;
 
begin
 
small_shift_nonzero <= or_reduce(small_shift);
small_is_nonzero <= or_reduce(exponent_small) or or_reduce(mantissa_small(51 downto 0));
small_fraction_enable <= small_is_nonzero and not small_shift_nonzero;
small_shift_2 <= "00000000000000000000000000000000000000000000000000000001";
sum_overflow <= sum(55); -- sum[55] will be 0 if there was no carry from adding the 2 numbers
sum_leading_one <= sum_2(54); -- this is where the leading one resides, unless denorm
--exp_diff_int <= to_integer(exponent_diff);
 
process
begin
wait until clk'event and clk = '1';
if (rst = '1') then
sign <= '0';
exponent_a <= (others =>'0');
exponent_b <= (others =>'0');
mantissa_a <= (others =>'0');
mantissa_b <= (others =>'0');
exponent_small <= (others =>'0');
exponent_large <= (others =>'0');
mantissa_small <= (others =>'0');
mantissa_large <= (others =>'0');
small_is_denorm <= '0';
large_is_denorm <= '0';
large_norm_small_denorm <= (others =>'0');
exponent_diff <= (others =>'0');
large_add <= (others =>'0');
small_add <= (others =>'0');
small_shift <= (others =>'0');
small_shift_3 <= (others =>'0');
sum <= (others =>'0');
sum_2 <= (others =>'0');
sum_3 <= (others =>'0');
exponent <= (others =>'0');
denorm_to_norm <= '0';
exponent_2 <= (others =>'0');
elsif (enable = '1') then
sign <= opa(63);
exponent_a <= opa(62 downto 52);
exponent_b <= opb(62 downto 52);
mantissa_a <= opa(51 downto 0);
mantissa_b <= opb(51 downto 0);
if (exponent_a > exponent_b) then
exponent_small <= exponent_b;
exponent_large <= exponent_a;
mantissa_small <= mantissa_b;
mantissa_large <= mantissa_a;
else
exponent_small <= exponent_a;
exponent_large <= exponent_b;
mantissa_small <= mantissa_a;
mantissa_large <= mantissa_b;
end if;
if (exponent_small > 0) then
small_is_denorm <= '0';
else
small_is_denorm <= '1';
end if;
if (exponent_large > 0) then
large_is_denorm <= '0';
else
large_is_denorm <= '1';
end if;
if (small_is_denorm = '1' and large_is_denorm = '0') then
large_norm_small_denorm <= "00000000001";
else
large_norm_small_denorm <= "00000000000";
end if;
exponent_diff <= exponent_large - exponent_small - large_norm_small_denorm;
large_add <= '0' & not large_is_denorm & mantissa_large & "00";
small_add <= '0' & not small_is_denorm & mantissa_small & "00";
small_shift <= shr(small_add, exponent_diff);
if (small_fraction_enable = '1') then
small_shift_3 <= small_shift_2;
else
small_shift_3 <= small_shift;
end if;
sum <= large_add + small_shift_3;
if (sum_overflow = '1') then
sum_2 <= shr(sum, conv_std_logic_vector('1', 56));
else
sum_2 <= sum;
end if;
sum_3 <= sum_2;
if (sum_overflow = '1') then
exponent <= exponent_large + 1;
else
exponent <= exponent_large;
end if;
denorm_to_norm <= sum_leading_one and large_is_denorm;
if (denorm_to_norm = '1') then
exponent_2 <= exponent + 1;
else
exponent_2 <= exponent;
end if;
end if;
end process;
 
 
end rtl;
/trunk/fpu_sub.vhd
0,0 → 1,234
---------------------------------------------------------------------
---- ----
---- FPU ----
---- Floating Point Unit (Double precision) ----
---- ----
---- Author: David Lundgren ----
---- davidklun@gmail.com ----
---- ----
---------------------------------------------------------------------
---- ----
---- Copyright (C) 2009 David Lundgren ----
---- davidklun@gmail.com ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer.----
---- ----
---- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ----
---- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ----
---- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ----
---- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ----
---- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ----
---- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ----
---- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ----
---- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ----
---- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ----
---- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ----
---- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ----
---- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ----
---- POSSIBILITY OF SUCH DAMAGE. ----
---- ----
---------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_misc.all;
library work;
use work.fpupack.all;
ENTITY fpu_sub IS
 
PORT(
clk : IN std_logic;
rst : IN std_logic;
enable : IN std_logic;
opa : IN std_logic_vector (63 DOWNTO 0);
opb : IN std_logic_vector (63 DOWNTO 0);
fpu_op : IN std_logic_vector (2 DOWNTO 0);
sign : OUT std_logic;
diff_2 : OUT std_logic_vector (55 DOWNTO 0);
exponent_2 : OUT std_logic_vector (10 DOWNTO 0)
);
 
-- Declarations
 
END fpu_sub;
architecture rtl of fpu_sub is
signal fpu_op_add : std_logic;
signal diff_shift : std_logic_vector(5 downto 0);
signal diff_shift_2 : std_logic_vector(5 downto 0);
signal exponent_a : std_logic_vector(10 downto 0);
signal exponent_b : std_logic_vector(10 downto 0);
signal mantissa_a : std_logic_vector(51 downto 0);
signal mantissa_b : std_logic_vector(51 downto 0);
signal expa_gt_expb : std_logic;
signal expa_et_expb : std_logic;
signal mana_gtet_manb : std_logic;
signal a_gtet_b : std_logic;
signal exponent_small : std_logic_vector(10 downto 0);
signal exponent_large : std_logic_vector(10 downto 0);
signal mantissa_small : std_logic_vector(51 downto 0);
signal mantissa_large : std_logic_vector(51 downto 0);
signal small_is_denorm : std_logic;
signal large_is_denorm : std_logic;
signal large_norm_small_denorm : std_logic;
signal small_is_nonzero : std_logic;
signal exponent_diff : std_logic_vector(10 downto 0);
signal minuend : std_logic_vector(54 downto 0);
signal subtrahend : std_logic_vector(54 downto 0);
signal subtra_shift : std_logic_vector(54 downto 0);
signal subtra_shift_nonzero : std_logic;
signal subtra_fraction_enable : std_logic;
signal subtra_shift_2 : std_logic_vector(54 downto 0);
signal subtra_shift_3 : std_logic_vector(54 downto 0);
signal diff : std_logic_vector(54 downto 0);
signal diffshift_gt_exponent : std_logic;
signal diffshift_et_55 : std_logic; -- when the difference = 0
signal diff_1 : std_logic_vector(54 downto 0);
signal exponent : std_logic_vector(10 downto 0);
signal in_norm_out_denorm : std_logic;
begin
subtra_shift_nonzero <= or_reduce(subtra_shift);
subtra_fraction_enable <= small_is_nonzero and not subtra_shift_nonzero;
subtra_shift_2 <= "0000000000000000000000000000000000000000000000000000001";
in_norm_out_denorm <= or_reduce(exponent_large) and not or_reduce(exponent);
fpu_op_add <= '1' when fpu_op = "000" else '0';
process
begin
wait until clk'event and clk = '1';
if (rst = '1') then
exponent_a <= (others =>'0');
exponent_b <= (others =>'0');
mantissa_a <= (others =>'0');
mantissa_b <= (others =>'0');
expa_gt_expb <= '0';
expa_et_expb <= '0';
mana_gtet_manb <= '0';
a_gtet_b <= '0';
exponent_small <= (others =>'0');
exponent_large <= (others =>'0');
mantissa_small <= (others =>'0');
mantissa_large <= (others =>'0');
sign <= '0';
small_is_denorm <= '0';
large_is_denorm <= '0';
large_norm_small_denorm <= '0';
small_is_nonzero <= '0';
exponent_diff <= (others =>'0');
minuend <= (others =>'0');
subtrahend <= (others =>'0');
subtra_shift <= (others =>'0');
subtra_shift_3 <= (others =>'0');
diff_shift_2 <= (others =>'0');
diff <= (others =>'0');
diffshift_gt_exponent <= '0';
diffshift_et_55 <= '0';
diff_1 <= (others =>'0');
exponent <= (others =>'0');
exponent_2 <= (others =>'0');
diff_2 <= (others =>'0');
elsif (enable = '1') then
exponent_a <= opa(62 downto 52);
exponent_b <= opb(62 downto 52);
mantissa_a <= opa(51 downto 0);
mantissa_b <= opb(51 downto 0);
if (exponent_a > exponent_b) then
expa_gt_expb <= '1';
else
expa_gt_expb <= '0';
end if;
if (exponent_a = exponent_b) then
expa_et_expb <= '1';
else
expa_et_expb <= '0';
end if;
if (mantissa_a >= mantissa_b) then
mana_gtet_manb <= '1';
else
mana_gtet_manb <= '0';
end if;
a_gtet_b <= expa_gt_expb or (expa_et_expb and mana_gtet_manb);
if (a_gtet_b = '1') then
exponent_small <= exponent_b;
exponent_large <= exponent_a;
mantissa_small <= mantissa_b;
mantissa_large <= mantissa_a;
sign <= opa(63);
else
exponent_small <= exponent_a;
exponent_large <= exponent_b;
mantissa_small <= mantissa_a;
mantissa_large <= mantissa_b;
sign <= (not opb(63)) xor fpu_op_add;
end if;
if (exponent_small > 0) then
small_is_denorm <= '0';
else
small_is_denorm <= '1';
end if;
if (exponent_large > 0) then
large_is_denorm <= '0';
else
large_is_denorm <= '1';
end if;
if (small_is_denorm = '1' and large_is_denorm = '0') then
large_norm_small_denorm <= '1';
else
large_norm_small_denorm <= '0';
end if;
small_is_nonzero <= (not small_is_denorm) or or_reduce(mantissa_small);
exponent_diff <= exponent_large - exponent_small - large_norm_small_denorm;
minuend <= not large_is_denorm & mantissa_large & "00";
subtrahend <= not small_is_denorm & mantissa_small & "00";
subtra_shift <= shr(subtrahend, exponent_diff);
if (subtra_fraction_enable = '1') then
subtra_shift_3 <= subtra_shift_2;
else
subtra_shift_3 <= subtra_shift;
end if;
diff <= minuend - subtra_shift_3;
diff_shift <= count_l_zeros(diff(54 downto 0));
diff_shift_2 <= diff_shift;
if (diff_shift_2 > exponent_large) then
diffshift_gt_exponent <= '1';
else
diffshift_gt_exponent <= '0';
end if;
if (diff_shift_2 = "0110111") then -- 55
diffshift_et_55 <= '1';
else
diffshift_et_55 <= '0';
end if;
if (diffshift_gt_exponent = '1') then
diff_1 <= shl(diff, exponent_large);
exponent <= "00000000000";
else
diff_1 <= shl(diff, diff_shift_2);
exponent <= exponent_large - diff_shift_2;
end if;
if (diffshift_et_55 = '1') then
exponent_2 <= "00000000000";
else
exponent_2 <= exponent;
end if;
if (in_norm_out_denorm = '1') then
diff_2 <= '0' & shr(diff_1,conv_std_logic_vector('1', 55));
else
diff_2 <= '0' & diff_1;
end if;
end if;
end process;
 
end rtl;
 
/trunk/fpu_double.vhd
0,0 → 1,349
---------------------------------------------------------------------
---- ----
---- FPU ----
---- Floating Point Unit (Double precision) ----
---- ----
---- Author: David Lundgren ----
---- davidklun@gmail.com ----
---- ----
---------------------------------------------------------------------
---- ----
---- Copyright (C) 2009 David Lundgren ----
---- davidklun@gmail.com ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer.----
---- ----
---- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ----
---- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ----
---- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ----
---- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ----
---- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ----
---- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ----
---- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ----
---- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ----
---- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ----
---- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ----
---- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ----
---- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ----
---- POSSIBILITY OF SUCH DAMAGE. ----
---- ----
---------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_misc.all;
library work;
use work.comppack.all;
use work.fpupack.all;
ENTITY fpu_double IS
 
PORT(
clk, rst, enable : IN std_logic;
rmode : IN std_logic_vector (1 DOWNTO 0);
fpu_op : IN std_logic_vector (2 DOWNTO 0);
opa, opb : IN std_logic_vector (63 DOWNTO 0);
out_fp: OUT std_logic_vector (63 DOWNTO 0);
ready, underflow, overflow, inexact : OUT std_logic;
exception, invalid : OUT std_logic
);
 
END fpu_double;
-- FPU Operations (fpu_op):
--========================
-- 0 = add
-- 1 = sub
-- 2 = mul
-- 3 = div
 
--Rounding Modes (rmode):
--=======================
-- 0 = round_nearest_even
-- 1 = round_to_zero
-- 2 = round_up
-- 3 = round_down
 
architecture rtl of fpu_double is
signal opa_reg : std_logic_vector(63 downto 0);
signal opb_reg : std_logic_vector(63 downto 0);
signal fpu_op_reg : std_logic_vector(2 downto 0);
signal rmode_reg : std_logic_vector(1 downto 0);
signal enable_reg : std_logic;
signal enable_reg_1 : std_logic; -- high for one clock cycle
signal enable_reg_2 : std_logic; -- high for one clock cycle
signal enable_reg_3 : std_logic; -- high for two clock cycles
signal op_enable : std_logic;
signal count_cycles : std_logic_vector(6 downto 0);
signal count_ready : std_logic_vector(6 downto 0);
signal count_busy : std_logic;
signal ready_0 : std_logic;
signal ready_1 : std_logic;
signal underflow_0 : std_logic;
signal overflow_0 : std_logic;
signal inexact_0 : std_logic;
signal exception_0 : std_logic;
signal invalid_0 : std_logic;
signal add_enable_0 : std_logic;
signal add_enable_1 : std_logic;
signal add_enable : std_logic;
signal sub_enable_0 : std_logic;
signal sub_enable_1 : std_logic;
signal sub_enable : std_logic;
signal mul_enable : std_logic;
signal div_enable : std_logic;
signal except_enable : std_logic;
signal sum_out : std_logic_vector(55 downto 0);
signal diff_out : std_logic_vector(55 downto 0);
signal addsub_out : std_logic_vector(55 downto 0);
signal mul_out : std_logic_vector(55 downto 0);
signal div_out : std_logic_vector(55 downto 0);
signal mantissa_round : std_logic_vector(55 downto 0);
signal exp_add_out : std_logic_vector(10 downto 0);
signal exp_sub_out : std_logic_vector(10 downto 0);
signal exp_mul_out : std_logic_vector(11 downto 0);
signal exp_div_out : std_logic_vector(11 downto 0);
signal exponent_round : std_logic_vector(11 downto 0);
signal exp_addsub : std_logic_vector(11 downto 0);
signal exponent_post_round : std_logic_vector(11 downto 0);
signal add_sign : std_logic;
signal sub_sign : std_logic;
signal mul_sign : std_logic;
signal div_sign : std_logic;
signal addsub_sign : std_logic;
signal sign_round : std_logic;
signal out_round : std_logic_vector(63 downto 0);
signal out_except : std_logic_vector(63 downto 0);
begin
i_fpu_add: fpu_add
port map (
clk => clk , rst => rst , enable => add_enable , opa => opa_reg , opb => opb_reg ,
sign => add_sign , sum_3 => sum_out , exponent_2 => exp_add_out);
i_fpu_sub: fpu_sub
port map (
clk => clk , rst => rst , enable => sub_enable , opa => opa_reg , opb => opb_reg ,
fpu_op => fpu_op_reg , sign => sub_sign , diff_2 => diff_out ,
exponent_2 => exp_sub_out);
i_fpu_mul: fpu_mul
port map (
clk => clk , rst => rst , enable => mul_enable , opa => opa_reg , opb => opb_reg ,
sign => mul_sign , product_7 => mul_out , exponent_5 => exp_mul_out);
i_fpu_div: fpu_div
port map (
clk => clk , rst => rst , enable => div_enable , opa => opa_reg , opb => opb_reg ,
sign => div_sign , mantissa_7 => div_out , exponent_out => exp_div_out);
i_fpu_round: fpu_round
port map (
clk => clk , rst => rst , enable => op_enable , round_mode => rmode_reg ,
sign_term => sign_round , mantissa_term => mantissa_round , exponent_term => exponent_round ,
round_out => out_round , exponent_final => exponent_post_round);
i_fpu_exceptions: fpu_exceptions
port map (
clk => clk , rst => rst , enable => op_enable , rmode => rmode_reg ,
opa => opa_reg , opb => opb_reg ,
in_except => out_round , exponent_in => exponent_post_round ,
mantissa_in => mantissa_round(1 downto 0) , fpu_op => fpu_op_reg , out_fp => out_except ,
ex_enable => except_enable , underflow => underflow_0 , overflow => overflow_0 ,
inexact => inexact_0 , exception => exception_0 , invalid => invalid_0);
count_busy <= '1' when (count_ready <= count_cycles) else '0';
 
add_enable_0 <= '1' when fpu_op_reg = "000" and (opa_reg(63) xor opb_reg(63)) = '0' else '0';
add_enable_1 <= '1' when (fpu_op_reg = "001") and (opa_reg(63) xor opb_reg(63)) = '1' else '0';
sub_enable_0 <= '1' when (fpu_op_reg = "000") and (opa_reg(63) xor opb_reg(63)) = '1' else '0';
sub_enable_1 <= '1' when (fpu_op_reg = "001") and (opa_reg(63) xor opb_reg(63)) = '0' else '0';
process
begin
wait until clk'event and clk = '1';
if (rst = '1') then
mantissa_round <= (others =>'0');
exponent_round <= (others =>'0');
sign_round <= '0';
count_cycles <= (others =>'0');
else
if (fpu_op_reg = "000") then -- add
mantissa_round <= addsub_out;
exponent_round <= exp_addsub;
sign_round <= addsub_sign;
count_cycles <= "0010100"; -- 20
elsif (fpu_op_reg = "001") then -- subtract
mantissa_round <= addsub_out;
exponent_round <= exp_addsub;
sign_round <= addsub_sign;
count_cycles <= "0010101"; -- 21
elsif (fpu_op_reg = "010") then
mantissa_round <= mul_out;
exponent_round <= exp_mul_out;
sign_round <= mul_sign;
count_cycles <= "0011000"; -- 24
elsif (fpu_op_reg = "011") then
mantissa_round <= div_out;
exponent_round <= exp_div_out;
sign_round <= div_sign;
count_cycles <= "1000111"; -- 71
else
mantissa_round <= (others =>'0');
exponent_round <= (others =>'0');
sign_round <= '0';
count_cycles <= (others =>'0');
end if;
end if;
end process;
 
process
begin
wait until clk'event and clk = '1';
if (rst = '1') then
add_enable <= '0';
sub_enable <= '0';
mul_enable <= '0';
div_enable <= '0';
addsub_out <= (others =>'0');
addsub_sign <= '0';
exp_addsub <= (others =>'0');
else
if ((add_enable_0 = '1' or add_enable_1 = '1') and op_enable= '1') then
add_enable <= '1';
else
add_enable <= '0';
end if;
if ((sub_enable_0 = '1' or sub_enable_1 = '1') and op_enable = '1') then
sub_enable <= '1';
else
sub_enable <= '0';
end if;
if fpu_op_reg = "010" and op_enable = '1' then
mul_enable <= '1';
else
mul_enable <= '0';
end if;
if fpu_op_reg = "011" and op_enable = '1' and enable_reg_3 = '1' then
div_enable <= '1';
else
div_enable <= '0';
end if; -- div_enable needs to be high for two clock cycles
if add_enable = '1' then
addsub_out <= sum_out;
addsub_sign <= add_sign;
exp_addsub <= '0' & exp_add_out;
else
addsub_out <= diff_out;
addsub_sign <= sub_sign;
exp_addsub <= '0' & exp_sub_out;
end if;
end if;
end process;
process
begin
wait until clk'event and clk = '1';
if (rst = '1') then
count_ready <= (others =>'0');
elsif (enable_reg_1 = '1') then
count_ready <= (others =>'0');
elsif (count_busy = '1') then
count_ready <= count_ready + "0000001";
end if;
end process;
process
begin
wait until clk'event and clk = '1';
if (rst = '1') then
enable_reg <= '0';
enable_reg_1 <= '0';
enable_reg_2 <= '0';
enable_reg_3 <= '0';
else
enable_reg <= enable;
if enable = '1' and enable_reg = '0' then
enable_reg_1 <= '1';
else
enable_reg_1 <= '0';
end if;
enable_reg_2 <= enable_reg_1;
if enable_reg_1 = '1' or enable_reg_2 = '1' then
enable_reg_3 <= '1';
else
enable_reg_3 <= '0';
end if;
end if;
end process;
process
begin
wait until clk'event and clk = '1';
if (rst = '1') then
opa_reg <= (others =>'0');
opb_reg <= (others =>'0');
fpu_op_reg <= (others =>'0');
rmode_reg <= (others =>'0');
op_enable <= '0';
elsif (enable_reg_1 = '1') then
opa_reg <= opa;
opb_reg <= opb;
fpu_op_reg <= fpu_op;
rmode_reg <= rmode;
op_enable <= '1';
end if;
end process;
process
begin
wait until clk'event and clk = '1';
if (rst = '1') then
ready_0 <= '0';
ready_1 <= '0';
ready <= '0';
elsif (enable_reg_1 = '1') then
ready_0 <= '0';
ready_1 <= '0';
ready <= '0';
else
ready_0 <= not count_busy;
ready_1 <= ready_0;
ready <= ready_1;
end if;
end process;
process
begin
wait until clk'event and clk = '1';
if (rst = '1') then
underflow <= '0';
overflow <= '0';
inexact <= '0';
exception <= '0';
invalid <= '0';
out_fp <= (others =>'0');
elsif (ready_1 = '1') then
underflow <= underflow_0;
overflow <= overflow_0;
inexact <= inexact_0;
exception <= exception_0;
invalid <= invalid_0;
if except_enable = '1' then
out_fp <= out_except;
else
out_fp <= out_round;
end if;
end if;
end process;
end rtl;
/trunk/fpu_mul.vhd
0,0 → 1,267
---------------------------------------------------------------------
---- ----
---- FPU ----
---- Floating Point Unit (Double precision) ----
---- ----
---- Author: David Lundgren ----
---- davidklun@gmail.com ----
---- ----
---------------------------------------------------------------------
---- ----
---- Copyright (C) 2009 David Lundgren ----
---- davidklun@gmail.com ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer.----
---- ----
---- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ----
---- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ----
---- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ----
---- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ----
---- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ----
---- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ----
---- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ----
---- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ----
---- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ----
---- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ----
---- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ----
---- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ----
---- POSSIBILITY OF SUCH DAMAGE. ----
---- ----
---------------------------------------------------------------------
 
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_misc.all;
library work;
use work.fpupack.all;
ENTITY fpu_mul IS
 
PORT(
clk : IN std_logic;
rst : IN std_logic;
enable : IN std_logic;
opa : IN std_logic_vector (63 DOWNTO 0);
opb : IN std_logic_vector (63 DOWNTO 0);
sign : OUT std_logic;
product_7 : OUT std_logic_vector (55 DOWNTO 0);
exponent_5 : OUT std_logic_vector (11 DOWNTO 0)
);
 
END fpu_mul;
architecture rtl of fpu_mul is
signal product_shift : std_logic_vector(5 downto 0);
signal product_shift_2 : std_logic_vector(5 downto 0);
signal mantissa_a : std_logic_vector(51 downto 0);
signal mantissa_b : std_logic_vector(51 downto 0);
signal exponent_a : std_logic_vector(11 downto 0);
signal exponent_b : std_logic_vector(11 downto 0);
signal a_is_norm : std_logic;
signal b_is_norm : std_logic;
signal a_is_zero : std_logic;
signal b_is_zero : std_logic;
signal in_zero : std_logic;
signal exponent_terms : std_logic_vector(11 downto 0);
signal exponent_gt_expoffset : std_logic;
signal exponent_under : std_logic_vector(11 downto 0);
signal exponent_1 : std_logic_vector(11 downto 0);
signal exponent : std_logic_vector(11 downto 0);
signal exponent_2 : std_logic_vector(11 downto 0);
signal exponent_gt_prodshift : std_logic;
signal exponent_3 : std_logic_vector(11 downto 0);
signal exponent_4 : std_logic_vector(11 downto 0);
signal exponent_et_zero : std_logic;
signal mul_a : std_logic_vector(52 downto 0);
signal mul_b : std_logic_vector(52 downto 0);
signal product_a : std_logic_vector(40 downto 0);
signal product_b : std_logic_vector(40 downto 0);
signal product_c : std_logic_vector(40 downto 0);
signal product_d : std_logic_vector(25 downto 0);
signal product_e : std_logic_vector(33 downto 0);
signal product_f : std_logic_vector(33 downto 0);
signal product_g : std_logic_vector(35 downto 0);
signal product_h : std_logic_vector(28 downto 0);
signal product_i : std_logic_vector(28 downto 0);
signal product_j : std_logic_vector(30 downto 0);
signal sum_0 : std_logic_vector(41 downto 0);
signal sum_1 : std_logic_vector(35 downto 0);
signal sum_2 : std_logic_vector(41 downto 0);
signal sum_3 : std_logic_vector(35 downto 0);
signal sum_4 : std_logic_vector(36 downto 0);
signal sum_5 : std_logic_vector(27 downto 0);
signal sum_6 : std_logic_vector(29 downto 0);
signal sum_7 : std_logic_vector(36 downto 0);
signal sum_8 : std_logic_vector(30 downto 0);
signal product : std_logic_vector(105 downto 0);
signal product_1 : std_logic_vector(105 downto 0);
signal product_2 : std_logic_vector(105 downto 0);
signal product_3 : std_logic_vector(105 downto 0);
signal product_4 : std_logic_vector(105 downto 0);
signal product_5 : std_logic_vector(105 downto 0);
signal product_6 : std_logic_vector(105 downto 0);
signal product_lsb : std_logic;
 
begin
product_7 <= '0' & product_6(105 downto 52) & product_lsb;
exponent <= "000000000000";
process
begin
wait until clk'event and clk = '1';
if (rst = '1') then
sign <= '0';
mantissa_a <= (others =>'0');
mantissa_b <= (others =>'0');
exponent_a <= (others =>'0');
exponent_b <= (others =>'0');
a_is_norm <= '0';
b_is_norm <= '0';
a_is_zero <= '0';
b_is_zero <= '0';
in_zero <= '0';
exponent_terms <= (others =>'0');
exponent_gt_expoffset <= '0';
exponent_under <= (others =>'0');
exponent_1 <= (others =>'0');
exponent_2 <= (others =>'0');
exponent_gt_prodshift <= '0';
exponent_3 <= (others =>'0');
exponent_4 <= (others =>'0');
exponent_et_zero <= '0';
mul_a <= (others =>'0');
mul_b <= (others =>'0');
product_a <= (others =>'0');
product_b <= (others =>'0');
product_c <= (others =>'0');
product_d <= (others =>'0');
product_e <= (others =>'0');
product_f <= (others =>'0');
product_g <= (others =>'0');
product_h <= (others =>'0');
product_i <= (others =>'0');
product_j <= (others =>'0');
sum_0 <= (others =>'0');
sum_1 <= (others =>'0');
sum_2 <= (others =>'0');
sum_3 <= (others =>'0');
sum_4 <= (others =>'0');
sum_5 <= (others =>'0');
sum_6 <= (others =>'0');
sum_7 <= (others =>'0');
sum_8 <= (others =>'0');
product <= (others =>'0');
product_1 <= (others =>'0');
product_2 <= (others =>'0');
product_3 <= (others =>'0');
product_4 <= (others =>'0');
product_5 <= (others =>'0');
product_6 <= (others =>'0');
product_lsb <= '0';
exponent_5 <= (others =>'0');
product_shift <= (others =>'0');
product_shift_2 <= (others =>'0');
elsif (enable = '1') then
sign <= opa(63) xor opb(63);
exponent_a <= '0' & opa(62 downto 52);
exponent_b <= '0' & opb(62 downto 52);
mantissa_a <= opa(51 downto 0);
mantissa_b <= opb(51 downto 0);
a_is_norm <= or_reduce(exponent_a);
b_is_norm <= or_reduce(exponent_b);
a_is_zero <= not or_reduce(opa(62 downto 0));
b_is_zero <= not or_reduce(opb(62 downto 0));
in_zero <= a_is_zero or b_is_zero;
exponent_terms <= exponent_a + exponent_b + ( "0000000000" & not a_is_norm) +
("0000000000" & not b_is_norm);
if (exponent_terms > "001111111101") then
exponent_gt_expoffset <= '1';
else
exponent_gt_expoffset <= '0';
end if;
exponent_under <= "001111111110" - exponent_terms;
exponent_1 <= exponent_terms - "001111111110";
if (exponent_gt_expoffset = '1') then
exponent_2 <= exponent_1;
else
exponent_2 <= exponent;
end if;
if (exponent_2 > product_shift_2) then
exponent_gt_prodshift <= '1';
else
exponent_gt_prodshift <= '0';
end if;
exponent_3 <= exponent_2 - product_shift_2;
if (exponent_gt_prodshift = '1') then
exponent_4 <= exponent_3;
else
exponent_4 <= exponent;
end if;
if (exponent_4 = "000000000000") then
exponent_et_zero <= '1';
else
exponent_et_zero <= '0';
end if;
mul_a <= a_is_norm & mantissa_a;
mul_b <= b_is_norm & mantissa_b;
product_a <= mul_a(23 downto 0) * mul_b(16 downto 0);
product_b <= mul_a(23 downto 0) * mul_b(33 downto 17);
product_c <= mul_a(23 downto 0) * mul_b(50 downto 34);
product_d <= mul_a(23 downto 0) * mul_b(52 downto 51);
product_e <= mul_a(40 downto 24) * mul_b(16 downto 0);
product_f <= mul_a(40 downto 24) * mul_b(33 downto 17);
product_g <= mul_a(40 downto 24) * mul_b(52 downto 34);
product_h <= mul_a(52 downto 41) * mul_b(16 downto 0);
product_i <= mul_a(52 downto 41) * mul_b(33 downto 17);
product_j <= mul_a(52 downto 41) * mul_b(52 downto 34);
sum_0 <= product_a(40 downto 17) + ( '0' & product_b);
sum_1 <= ('0' & sum_0(41 downto 7)) + product_e;
sum_2 <= sum_1(35 downto 10) + ('0' & product_c);
sum_3 <= ( '0' & sum_2(41 downto 7)) + product_h;
sum_4 <= ( '0' & sum_3) + product_f;
sum_5 <= ('0' & sum_4(36 downto 10)) + product_d;
sum_6 <= sum_5(27 downto 7) + ('0' & product_i);
sum_7 <= sum_6 + ('0' & product_g);
sum_8 <= sum_7(36 downto 17) + product_j;
product <= sum_8 & sum_7(16 downto 0) & sum_5(6 downto 0) & sum_4(9 downto 0) & sum_2(6 downto 0) &
sum_1(9 downto 0) & sum_0(6 downto 0) & product_a(16 downto 0);
product_1 <= shr(product, exponent_under);
if (exponent_gt_prodshift = '1') then
product_5 <= product_3;
else
product_5 <= product_4;
end if;
if (exponent_gt_expoffset = '1') then
product_2 <= product;
else
product_2 <= product_1;
end if;
product_3 <= shl(product_2, product_shift_2);
product_4 <= shl(product_2, exponent_2);
if (exponent_gt_prodshift = '1') then
product_5 <= product_3;
else
product_5 <= product_4;
end if;
if (exponent_et_zero = '1') then
product_6 <= shr(product_5, conv_std_logic_vector('1', 106));
else
product_6 <= product_5;
end if;
product_lsb <= or_reduce(product_6(51 downto 0));
if (in_zero = '1') then
exponent_5 <= "000000000000";
else
exponent_5 <= exponent_4;
end if;
product_shift <= count_zeros_mul(product(105 downto 0));
product_shift_2 <= product_shift;
end if;
end process;
end rtl;
/trunk/fpu_double_TB.vhd
0,0 → 1,751
---------------------------------------------------------------------
---- ----
---- FPU ----
---- Floating Point Unit (Double precision) ----
---- ----
---- Author: David Lundgren ----
---- davidklun@gmail.com ----
---- ----
---------------------------------------------------------------------
---- ----
---- Copyright (C) 2009 David Lundgren ----
---- davidklun@gmail.com ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer.----
---- ----
---- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ----
---- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ----
---- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ----
---- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ----
---- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ----
---- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ----
---- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ----
---- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ----
---- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ----
---- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ----
---- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ----
---- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ----
---- POSSIBILITY OF SUCH DAMAGE. ----
---- ----
---------------------------------------------------------------------
 
library ieee;
use work.fpupack.all;
use work.comppack.all;
use ieee.std_logic_misc.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_1164.all;
 
 
entity fpu_double_tb is
end fpu_double_tb;
 
architecture TB_ARCHITECTURE of fpu_double_tb is
 
component fpu_double
port(
clk : in std_logic;
rst : in std_logic;
enable : in std_logic;
rmode : in std_logic_vector(1 downto 0);
fpu_op : in std_logic_vector(2 downto 0);
opa : in std_logic_vector(63 downto 0);
opb : in std_logic_vector(63 downto 0);
out_fp : out std_logic_vector(63 downto 0);
ready : out std_logic;
underflow : out std_logic;
overflow : out std_logic;
inexact : out std_logic;
exception : out std_logic;
invalid : out std_logic );
end component;
 
signal clk : std_logic;
signal rst : std_logic;
signal enable : std_logic;
signal rmode : std_logic_vector(1 downto 0);
signal fpu_op : std_logic_vector(2 downto 0);
signal opa : std_logic_vector(63 downto 0);
signal opb : std_logic_vector(63 downto 0);
signal out_fp : std_logic_vector(63 downto 0);
signal ready : std_logic;
signal underflow : std_logic;
signal overflow : std_logic;
signal inexact : std_logic;
signal exception : std_logic;
signal invalid : std_logic;
 
signal END_SIM: BOOLEAN:=FALSE;
signal out_fp1 : std_logic_vector(63 downto 0);
 
 
begin
out_fp1 <= out_fp;
UUT : fpu_double
port map (
clk => clk,
rst => rst,
enable => enable,
rmode => rmode,
fpu_op => fpu_op,
opa => opa,
opb => opb,
out_fp => out_fp,
ready => ready,
underflow => underflow,
overflow => overflow,
inexact => inexact,
exception => exception,
invalid => invalid
);
 
STIMULUS: process
begin
 
 
 
rst <= '1';
wait for 20 ns;
rst <= '0';
--inputA:4.0000000000e+000
--inputB:-4.0000000000e+000
enable <= '1';
opa <= "0100000000010000000000000000000000000000000000000000000000000000";
opb <= "1100000000010000000000000000000000000000000000000000000000000000";
fpu_op <= "000";
rmode <= "10";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:0.000000000000000e+000
-- out_fp = 0000000000000000
--inputA:3.0000000000e-312
--inputB:1.0000000000e-025
enable <= '1';
opa <= "0000000000000000000000001000110101100000010101111101110111110010";
opb <= "0011101010111110111100101101000011110101110110100111110111011001";
fpu_op <= "011";
rmode <= "10";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:3.000000000000337e-287
-- out_fp = 047245C02F8B68C5
--inputA:4.0000000000e-304
--inputB:2.0000000000e-007
enable <= '1';
opa <= "0000000011110001100011100011101110011011001101110100000101101001";
opb <= "0011111010001010110101111111001010011010101111001010111101001000";
fpu_op <= "010";
rmode <= "00";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:8.000000000000074e-311
-- out_fp = 00000EBA09271E89
--inputA:3.4445600000e+002
--inputB:3.4445599000e+002
enable <= '1';
opa <= "0100000001110101100001110100101111000110101001111110111110011110";
opb <= "0100000001110101100001110100101110111100001010111001010011011001";
fpu_op <= "001";
rmode <= "00";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:1.000000003159585e-005
-- out_fp = 3EE4F8B58A000000
--inputA:-8.8899000000e+002
--inputB:7.8898020000e+002
enable <= '1';
opa <= "1100000010001011110001111110101110000101000111101011100001010010";
opb <= "0100000010001000101001111101011101110011000110001111110001010000";
fpu_op <= "000";
rmode <= "11";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:-1.000098000000000e+002
-- out_fp = C05900A0902DE010
--inputA:4.5600000000e+002
--inputB:2.3700000000e+001
enable <= '1';
opa <= "0100000001111100100000000000000000000000000000000000000000000000";
opb <= "0100000000110111101100110011001100110011001100110011001100110011";
fpu_op <= "011";
rmode <= "00";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:1.924050632911392e+001
-- out_fp = 40333D91D2A2067B
--inputA:4.9990000000e+003
--inputB:0.0000000000e+000
enable <= '1';
opa <= "0100000010110011100001110000000000000000000000000000000000000000";
opb <= "0000000000000000000000000000000000000000000000000000000000000000";
fpu_op <= "010";
rmode <= "10";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:0.000000000000000e+000
-- out_fp = 0000000000000000
--inputA:-9.8883300000e+005
--inputB:4.4444440000e+006
enable <= '1';
opa <= "1100000100101110001011010100001000000000000000000000000000000000";
opb <= "0100000101010000111101000100011100000000000000000000000000000000";
fpu_op <= "001";
rmode <= "10";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:-5.433277000000000e+006
-- out_fp = C154B9EF40000000
--inputA:-4.8000000000e-311
--inputB:4.0000000000e-050
enable <= '1';
opa <= "1000000000000000000010001101011000000101011111011101111100011111";
opb <= "0011010110101101111011100111101001001010110101001011100000011111";
fpu_op <= "011";
rmode <= "00";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:-1.200000000000011e-261
-- out_fp = 89C2E4AE4EAE705E
--inputA:1.9500000000e-308
--inputB:1.8800000000e-308
enable <= '1';
opa <= "0000000000001110000001011010001000110110111111110101001011001101";
opb <= "0000000000001101100001001100011001100110111010010000011110011111";
fpu_op <= "000";
rmode <= "10";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:3.830000000000000e-308
-- out_fp = 001B8A689DE85A6C
--inputA:-3.0000000000e-309
--inputB:9.0000000000e+100
enable <= '1';
opa <= "1000000000000010001010000100000001010111001110101111100100001100";
opb <= "0101010011100100100100101110001011001010010001110101101111101101";
fpu_op <= "010";
rmode <= "11";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:-2.700000000000001e-208
-- out_fp = 94D630F25FC26702
--inputA:3.0000000000e-308
--inputB:2.9900000000e-308
enable <= '1';
opa <= "0000000000010101100100101000001101101000010011011011101001110111";
opb <= "0000000000010101100000000001101011011100110111001101010001001011";
fpu_op <= "001";
rmode <= "10";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:1.000000000000046e-310
-- out_fp = 000012688B70E62C
--inputA:-9.0000000000e-300
--inputB:5.0000000000e+100
enable <= '1';
opa <= "1000000111011000000110111110001110111011010110000001000111000100";
opb <= "0101010011010110110111000001100001101110111110011111010001011100";
fpu_op <= "011";
rmode <= "11";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:-4.940656458412465e-324
-- out_fp = 8000000000000001
--inputA:4.0000000000e+100
--inputB:3.0000000000e-090
enable <= '1';
opa <= "0101010011010010010010011010110100100101100101001100001101111101";
opb <= "0010110101011000011100011100011001000110111001011001010110100111";
fpu_op <= "010";
rmode <= "10";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:1.200000000000000e+011
-- out_fp = 423BF08EB0000001
--inputA:-9.9000000000e-002
--inputB:4.0220000000e+001
enable <= '1';
opa <= "1011111110111001010110000001000001100010010011011101001011110010";
opb <= "0100000001000100000111000010100011110101110000101000111101011100";
fpu_op <= "000";
rmode <= "11";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:4.012100000000000e+001
-- out_fp = 40440F7CED916872
--inputA:9.0770000000e+001
--inputB:-2.0330000000e+001
enable <= '1';
opa <= "0100000001010110101100010100011110101110000101000111101011100001";
opb <= "1100000000110100010101000111101011100001010001111010111000010100";
fpu_op <= "000";
rmode <= "00";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:7.044000000000000e+001
-- out_fp = 40519C28F5C28F5C
--inputA:4.9077000000e+002
--inputB:-3.4434000000e+002
enable <= '1';
opa <= "0100000001111110101011000101000111101011100001010001111010111000";
opb <= "1100000001110101100001010111000010100011110101110000101000111101";
fpu_op <= "001";
rmode <= "00";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:8.351100000000000e+002
-- out_fp = 408A18E147AE147B
--inputA:9.0000000000e+034
--inputB:2.7700000000e+000
enable <= '1';
opa <= "0100011100110001010101010101011110110100000110011100010111000010";
opb <= "0100000000000110001010001111010111000010100011110101110000101001";
fpu_op <= "011";
rmode <= "00";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:3.249097472924188e+034
-- out_fp = 471907B705EBEABE
--inputA:3.9999999989e-315
--inputB:1.0000000000e-002
enable <= '1';
opa <= "0000000000000000000000000000000000110000010000011010011100110101";
opb <= "0011111110000100011110101110000101000111101011100001010001111011";
fpu_op <= "010";
rmode <= "10";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:4.000000428704504e-317
-- out_fp = 00000000007B895B
--inputA:-9.0000000000e+003
--inputB:8.0000000000e+003
enable <= '1';
opa <= "1100000011000001100101000000000000000000000000000000000000000000";
opb <= "0100000010111111010000000000000000000000000000000000000000000000";
fpu_op <= "011";
rmode <= "00";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:-1.125000000000000e+000
-- out_fp = BFF2000000000000
--inputA:9.8440000000e+003
--inputB:0.0000000000e+000
enable <= '1';
opa <= "0100000011000011001110100000000000000000000000000000000000000000";
opb <= "0000000000000000000000000000000000000000000000000000000000000000";
fpu_op <= "011";
rmode <= "10";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:1.#INF00000000000e+000
-- out_fp = 7FF0000000000000
--inputA:4.4440000000e+002
--inputB:-8.8800000000e+002
enable <= '1';
opa <= "0100000001111011110001100110011001100110011001100110011001100110";
opb <= "1100000010001011110000000000000000000000000000000000000000000000";
fpu_op <= "001";
rmode <= "10";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:1.332400000000000e+003
-- out_fp = 4094D1999999999A
--inputA:3.0000000000e-309
--inputB:3.0000000000e+080
enable <= '1';
opa <= "0000000000000010001010000100000001010111001110101111100100001100";
opb <= "0101000010100100001111011011001101111101011101001011110010000111";
fpu_op <= "011";
rmode <= "00";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:0.000000000000000e+000
-- out_fp = 0000000000000000
--inputA:4.9900000000e+002
--inputB:-3.3000000000e-003
enable <= '1';
opa <= "0100000001111111001100000000000000000000000000000000000000000000";
opb <= "1011111101101011000010001001101000000010011101010010010101000110";
fpu_op <= "010";
rmode <= "11";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:-1.646700000000000e+000
-- out_fp = BFFA58E219652BD4
--inputA:9.0000000000e+034
--inputB:4.0000000000e+023
enable <= '1';
opa <= "0100011100110001010101010101011110110100000110011100010111000010";
opb <= "0100010011010101001011010000001011000111111000010100101011110110";
fpu_op <= "000";
rmode <= "10";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:9.000000000040000e+034
-- out_fp = 47315557B41A1A76
--inputA:4.0000000000e+080
--inputB:3.0000000000e-002
enable <= '1';
opa <= "0101000010101010111111001110111101010001111100001111101101011111";
opb <= "0011111110011110101110000101000111101011100001010001111010111000";
fpu_op <= "000";
rmode <= "10";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:4.000000000000001e+080
-- out_fp = 50AAFCEF51F0FB60
--inputA:-5.4770000000e+000
--inputB:-8.9990000000e+000
enable <= '1';
opa <= "1100000000010101111010000111001010110000001000001100010010011100";
opb <= "1100000000100001111111110111110011101101100100010110100001110011";
fpu_op <= "011";
rmode <= "10";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:6.086231803533726e-001
-- out_fp = 3FE379D751E6915E
--inputA:-7.7000000000e+001
--inputB:-8.8400000000e+001
enable <= '1';
opa <= "1100000001010011010000000000000000000000000000000000000000000000";
opb <= "1100000001010110000110011001100110011001100110011001100110011010";
fpu_op <= "010";
rmode <= "10";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:6.806800000000001e+003
-- out_fp = 40BA96CCCCCCCCCE
--inputA:4.0000000000e+009
--inputB:3.0000000000e+008
enable <= '1';
opa <= "0100000111101101110011010110010100000000000000000000000000000000";
opb <= "0100000110110001111000011010001100000000000000000000000000000000";
fpu_op <= "011";
rmode <= "00";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:1.333333333333333e+001
-- out_fp = 402AAAAAAAAAAAAB
--inputA:9.0000000000e-311
--inputB:8.0000000000e-311
enable <= '1';
opa <= "0000000000000000000100001001000101001010010011000000001001011010";
opb <= "0000000000000000000011101011101000001001001001110001111010001001";
fpu_op <= "000";
rmode <= "00";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:1.700000000000010e-310
-- out_fp = 00001F4B537320E3
--inputA:1.9999777344e-320
--inputB:5.0000000000e+099
enable <= '1';
opa <= "0000000000000000000000000000000000000000000000000000111111010000";
opb <= "0101010010100010010010011010110100100101100101001100001101111101";
fpu_op <= "010";
rmode <= "10";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:9.999888671826831e-221
-- out_fp = 124212D01E240533
--inputA:4.4444000000e+004
--inputB:3.3000000000e+001
enable <= '1';
opa <= "0100000011100101101100111000000000000000000000000000000000000000";
opb <= "0100000001000000100000000000000000000000000000000000000000000000";
fpu_op <= "011";
rmode <= "00";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:1.346787878787879e+003
-- out_fp = 40950B26C9B26C9B
--inputA:9.7730000000e+000
--inputB:9.7720000000e+000
enable <= '1';
opa <= "0100000000100011100010111100011010100111111011111001110110110010";
opb <= "0100000000100011100010110100001110010101100000010000011000100101";
fpu_op <= "011";
rmode <= "00";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:1.000102333196889e+000
-- out_fp = 3FF0006B4DDBBE31
--inputA:8.3345700000e+003
--inputB:1.0000000000e+000
enable <= '1';
opa <= "0100000011000000010001110100100011110101110000101000111101011100";
opb <= "0011111111110000000000000000000000000000000000000000000000000000";
fpu_op <= "010";
rmode <= "00";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:8.334570000000000e+003
-- out_fp = 40C04748F5C28F5C
--inputA:-1.0000000000e+000
--inputB:5.8990000000e+003
enable <= '1';
opa <= "1011111111110000000000000000000000000000000000000000000000000000";
opb <= "0100000010110111000010110000000000000000000000000000000000000000";
fpu_op <= "010";
rmode <= "11";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:-5.899000000000000e+003
-- out_fp = C0B70B0000000000
--inputA:6.1000000000e+000
--inputB:-6.0990000000e+000
enable <= '1';
opa <= "0100000000011000011001100110011001100110011001100110011001100110";
opb <= "1100000000011000011001010110000001000001100010010011011101001100";
fpu_op <= "000";
rmode <= "10";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:9.999999999994458e-004
-- out_fp = 3F50624DD2F1A000
--inputA:3.0000000000e-300
--inputB:3.0000000000e-015
enable <= '1';
opa <= "0000000111000000000100101001011111010010001110101011011010000011";
opb <= "0011110011101011000001011000011101101110010110110000000100100000";
fpu_op <= "010";
rmode <= "00";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:9.000000001157124e-315
-- out_fp = 000000006C93B838
--inputA:-9.0000000000e+088
--inputB:4.0000000000e+084
enable <= '1';
opa <= "1101001001100110100111110000000010010101111101001101000000000000";
opb <= "0101000110000000011110001110000100010001110000110101010101101101";
fpu_op <= "000";
rmode <= "00";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:-8.999600000000000e+088
-- out_fp = D2669EBEB27088F3
--inputA:6.6210000000e+001
--inputB:6.9892000000e+001
enable <= '1';
opa <= "0100000001010000100011010111000010100011110101110000101000111101";
opb <= "0100000001010001011110010001011010000111001010110000001000001100";
fpu_op <= "011";
rmode <= "00";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:9.473187203113375e-001
-- out_fp = 3FEE506F59540645
--inputA:-5.0000000000e-309
--inputB:4.0000000000e-310
enable <= '1';
opa <= "1000000000000011100110000110101100111100000011001111010001101001";
opb <= "0000000000000000010010011010001000101101110000111001100010101100";
fpu_op <= "000";
rmode <= "11";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:-4.600000000000001e-309
-- out_fp = 80034EC90E495BBD
--inputA:8.8000000000e+001
--inputB:0.0000000000e+000
enable <= '1';
opa <= "0100000001010110000000000000000000000000000000000000000000000000";
opb <= "0000000000000000000000000000000000000000000000000000000000000000";
fpu_op <= "011";
rmode <= "01";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:1.#INF00000000000e+000
-- out_fp = 7FEFFFFFFFFFFFFF
--inputA:4.5570000000e+002
--inputB:3.4229100000e+003
enable <= '1';
opa <= "0100000001111100011110110011001100110011001100110011001100110011";
opb <= "0100000010101010101111011101000111101011100001010001111010111000";
fpu_op <= "000";
rmode <= "01";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:3.878610000000000e+003
-- out_fp = 40AE4D3851EB851E
--inputA:9.9440000000e+003
--inputB:2.3000000000e+001
enable <= '1';
opa <= "0100000011000011011011000000000000000000000000000000000000000000";
opb <= "0100000000110111000000000000000000000000000000000000000000000000";
fpu_op <= "011";
rmode <= "01";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:4.323478260869565e+002
-- out_fp = 407B0590B21642C8
--inputA:-9.0054400000e+005
--inputB:-3.4445500000e+005
enable <= '1';
opa <= "1100000100101011011110111000000000000000000000000000000000000000";
opb <= "1100000100010101000001100001110000000000000000000000000000000000";
fpu_op <= "001";
rmode <= "01";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:-5.560890000000000e+005
-- out_fp = C120F87200000000
--inputA:5.5500000000e-002
--inputB:3.2444400000e+005
enable <= '1';
opa <= "0011111110101100011010100111111011111001110110110010001011010001";
opb <= "0100000100010011110011010111000000000000000000000000000000000000";
fpu_op <= "011";
rmode <= "00";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:1.710618781669564e-007
-- out_fp = 3E86F5A431628F6D
--inputA:1.2330000000e+000
--inputB:1.5666600000e+000
enable <= '1';
opa <= "0011111111110011101110100101111000110101001111110111110011101110";
opb <= "0011111111111001000100010000101000010011011111110011100011000101";
fpu_op <= "010";
rmode <= "10";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:1.931691780000000e+000
-- out_fp = 3FFEE835A3D0D51B
--inputA:9.7770000000e-001
--inputB:3.0000000000e+099
enable <= '1';
opa <= "0011111111101111010010010101000110000010101010011001001100001100";
opb <= "0101010010010101111100100000001011111001111001011011011101100011";
fpu_op <= "011";
rmode <= "00";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:3.259000000000000e-100
-- out_fp = 2B46CF7665DCED50
--inputA:4.4000000000e+007
--inputB:6.0000000000e+002
enable <= '1';
opa <= "0100000110000100111110110001100000000000000000000000000000000000";
opb <= "0100000010000010110000000000000000000000000000000000000000000000";
fpu_op <= "010";
rmode <= "00";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:2.640000000000000e+010
-- out_fp = 4218964020000000
--inputA:3.9800000000e+000
--inputB:3.7700000000e+000
enable <= '1';
opa <= "0100000000001111110101110000101000111101011100001010001111010111";
opb <= "0100000000001110001010001111010111000010100011110101110000101001";
fpu_op <= "000";
rmode <= "01";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:7.750000000000000e+000
-- out_fp = 401F000000000000
--inputA:8.0400000000e+000
--inputB:8.0395700000e+000
enable <= '1';
opa <= "0100000000100000000101000111101011100001010001111010111000010100";
opb <= "0100000000100000000101000100001010000100110111111100111000110001";
fpu_op <= "001";
rmode <= "01";
wait for 20ns;
enable <= '0';
wait for 800 ns;
--Output:4.299999999997084e-004
-- out_fp = 3F3C2E33EFF18000
 
 
END_SIM <= TRUE;
 
wait;
end process;
CLOCK_clk : process
begin
if END_SIM = FALSE then
clk <= '0';
wait for 5 ns;
else
wait;
end if;
if END_SIM = FALSE then
clk <= '1';
wait for 5 ns;
else
wait;
end if;
end process;
 
 
 
end TB_ARCHITECTURE;
 
configuration TESTBENCH_FOR_fpu_double of fpu_double_tb is
for TB_ARCHITECTURE
for UUT : fpu_double
use entity work.fpu_double(rtl);
end for;
end for;
end TESTBENCH_FOR_fpu_double;
 
/trunk/fpupack.vhd
0,0 → 1,75
---------------------------------------------------------------------
---- ----
---- FPU ----
---- Floating Point Unit (Double precision) ----
---- ----
---- Author: David Lundgren ----
---- davidklun@gmail.com ----
---- ----
---------------------------------------------------------------------
---- ----
---- Copyright (C) 2009 David Lundgren ----
---- davidklun@gmail.com ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer.----
---- ----
---- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ----
---- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ----
---- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ----
---- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ----
---- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ----
---- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ----
---- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ----
---- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ----
---- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ----
---- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ----
---- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ----
---- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ----
---- POSSIBILITY OF SUCH DAMAGE. ----
---- ----
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
 
package fpupack is
 
-- count the number of zeros starting from the left
function count_l_zeros (signal s_vector: std_logic_vector) return std_logic_vector;
function count_zeros_mul (signal s_vector: std_logic_vector) return std_logic_vector;
end fpupack;
 
package body fpupack is
function count_l_zeros (signal s_vector: std_logic_vector) return std_logic_vector is
variable v_count : std_logic_vector(5 downto 0);
begin
v_count := "000000";
for i in s_vector'range loop
case s_vector(i) is
when '0' => v_count := v_count + "000001";
when others => exit;
end case;
end loop;
return v_count;
end count_l_zeros;
-- count the zeros from the left for multiply
function count_zeros_mul (signal s_vector: std_logic_vector) return std_logic_vector is
variable v_count : std_logic_vector(5 downto 0);
begin
v_count := "000000";
for i in 105 downto 52 loop
case s_vector(i) is
when '0' => v_count := v_count + "000001";
when others => exit;
end case;
end loop;
return v_count;
end count_zeros_mul;
end fpupack;
/trunk/Readme.txt
0,0 → 1,161
The following describes the IEEE-Standard-754 compliant, double-precision floating point unit,
written in VHDL. The module consists of the following files:
 
1. fpu_double.vhd (top level)
2. fpu_add.vhd
3. fpu_sub.vhd
4. fpu_mul.vhd
5. fpu_div.vhd
6. fpu_round.vhd
7. fpu_exceptions.vhd
8. fpupack.vhd
9. comppack.vhd
And a testbench file is included, containing 50 test-case operations:
1. fpu_double_TB.vhd
 
This unit has been extensively simulated, covering all 4 operations, rounding modes, exceptions
like underflow and overflow, and even the obscure corner cases, like when overflowing from
denormalized to normalized, and vice-versa.
 
The floating point unit supports denormalized numbers,
4 operations (add, subtract, multiply, divide), and 4 rounding
modes (nearest, zero, + inf, - inf). The unit was synthesized with an
estimated frequency of 185 MHz, for a Virtex5 target device. The synthesis results
are below. fpu_double.vhd is the top-level module, and it contains the input
and output signals from the unit.
 
The input and output signals to the unit are the following:
 
1. clk (global)
2. rst (global)
2. enable (set high, then low, to start operation)
3. rmode (rounding mode, 2 bits, 00 = nearest, 01 = zero,
10 = pos inf, 11 = neg inf)
4. fpu_op (operation code, 3 bits, 000 = add, 001 = subtract,
010 = multiply, 011 = divide, others are not used)
5. opa, opb (input operands, 64 bits, Big-endian order,
bit 63 = sign, bits 62-52 exponent, bits 51-0 mantissa)
6. out_fp (output from operation, 64 bits, Big-endian order,
same ordering as inputs)
7. ready (goes high when output is available)
8. underflow
9. overflow
10. inexact
11. exception - see IEEE 754 definition
12. invalid - see IEEE 754 definition
 
The unit was designed to be synchronous with one global clock, and all of the
registers can be reset with an synchronous global reset.
When the inputs signals (a and b operands, fpu operation code, rounding mode code) are
available, set the enable input high, then set it low after 2 clock cycles. When the
operation is complete and the output is available, the ready signal will go high. To start
the next operation, set the enable input high.
 
Each operation takes the following amount of clock cycles to complete:
1. addition : 20 clock cycles
2. subtraction: 21 clock cycles
3. multiplication: 24 clock cycles
4. division: 71 clock cycles
 
This is longer than other floating point units, but supporting denormalized numbers
requires more signals and logic levels to accommodate gradual underflow. The supported
clock speed of 185 MHz makes up for the large number of clock cycles required for each
operation to complete. If you have a lower clock speed, the code can be changed to
reduce the number of registers and latency of each operation. I purposely increased the
number of logic levels to get the code to synthesize to a faster clock frequency, but of course,
this led to longer latency. I guess it depends on your application what is more important.
 
The following output signals are also available: underflow, overflow, inexact, exception,
and invalid. They are compliant with the IEEE-754 definition of each signal. The unit
will handle QNaN and SNaN inputs per the standard.
 
I'm planning on adding more operations, like square root, sin, cos, tan, etc.,
so check back for updates.
 
Multiply:
The multiply module is written specifically for a Virtex5 target device. The DSP48E slices
can perform a 25-bit by 18-bit Twos-complement multiply (24 by 17 unsigned multiply). I broke up the multiply to
fit these DSP48E slices. The breakdown is similar to the design in Figure 4-15 of the
Xilinx User Guide Document, "Virtex-5 FPGA XtremeDSP Design Considerations", also known as UG193.
You can find this document at xilinx.com by searching for "UG193".
Depending on your device, the multiply can be changed to match the bit-widths of the available
multipliers. A total of 9 DSP48E slices are used to do the 53-bit by 53-bit multiply of 2
floating point numbers.
 
If you have any questions, please email me at: davidklun@gmail.com
 
Thanks,
David Lundgren
 
-----
 
Synthesis Results:
 
 
 
 
Performance Summary
*******************
 
 
Worst slack in design: -2.049
 
 
Requested Estimated Requested Estimated Clock Clock
Starting Clock Frequency Frequency Period Period Slack Type Group
----------------------------------------------------------------------------------------------------------------------
fpu_double|clk 300.0 MHz 185.8 MHz 3.333 5.382 -2.049 inferred Inferred_clkgroup_0
======================================================================================================================
 
 
---------------------------------------
Resource Usage Report for fpu_double
 
Mapping to part: xc5vsx95tff1136-2
Cell usage:
DSP48E 9 uses
FD 3 uses
FDE 21 uses
FDR 587 uses
FDRE 3767 uses
FDRS 8 uses
FDRSE 51 uses
GND 6 uses
MUXCY 20 uses
MUXCY_L 598 uses
MUXF7 2 uses
VCC 6 uses
XORCY 497 uses
XORCY_L 5 uses
LUT1 187 uses
LUT2 742 uses
LUT3 1591 uses
LUT4 847 uses
LUT5 589 uses
LUT6 2613 uses
 
I/O ports: 206
I/O primitives: 205
IBUF 135 uses
OBUF 70 uses
 
BUFGP 1 use
 
I/O Register bits: 0
Register bits not including I/Os: 4437 (7%)
 
Global Clock Buffers: 1 of 32 (3%)
 
Total load per clock:
fpu_double|clk: 4446
 
Mapping Summary:
Total LUTs: 6569 (11%)
 
Mapper successful!
 
 
 
 
 
/trunk/fpu_exceptions.vhd
0,0 → 1,522
---------------------------------------------------------------------
---- ----
---- FPU ----
---- Floating Point Unit (Double precision) ----
---- ----
---- Author: David Lundgren ----
---- davidklun@gmail.com ----
---- ----
---------------------------------------------------------------------
---- ----
---- Copyright (C) 2009 David Lundgren ----
---- davidklun@gmail.com ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer.----
---- ----
---- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ----
---- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ----
---- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ----
---- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ----
---- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ----
---- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ----
---- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ----
---- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ----
---- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ----
---- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ----
---- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ----
---- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ----
---- POSSIBILITY OF SUCH DAMAGE. ----
---- ----
---------------------------------------------------------------------
 
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_misc.all;
ENTITY fpu_exceptions IS
 
PORT(
clk, rst, enable : IN std_logic;
rmode : IN std_logic_vector (1 DOWNTO 0);
opa, opb, in_except : IN std_logic_vector (63 DOWNTO 0);
exponent_in : IN std_logic_vector (11 DOWNTO 0);
mantissa_in : IN std_logic_vector (1 DOWNTO 0);
fpu_op : IN std_logic_vector (2 DOWNTO 0);
out_fp : OUT std_logic_vector (63 DOWNTO 0);
ex_enable, underflow, overflow, inexact : OUT std_logic;
exception, invalid : OUT std_logic
);
 
END fpu_exceptions;
architecture rtl of fpu_exceptions is
signal in_et_zero : std_logic;
signal opa_et_zero : std_logic;
signal opb_et_zero : std_logic;
signal add : std_logic;
signal subtract : std_logic;
signal multiply : std_logic;
signal divide : std_logic;
signal opa_QNaN : std_logic;
signal opb_QNaN : std_logic;
signal opa_SNaN : std_logic;
signal opb_SNaN : std_logic;
signal opa_pos_inf : std_logic;
signal opb_pos_inf : std_logic;
signal opa_neg_inf : std_logic;
signal opb_neg_inf : std_logic;
signal opa_inf : std_logic;
signal opb_inf : std_logic;
signal NaN_input : std_logic;
signal SNaN_input : std_logic;
signal a_NaN : std_logic;
signal div_by_0 : std_logic;
signal div_0_by_0 : std_logic;
signal div_inf_by_inf : std_logic;
signal div_by_inf : std_logic;
signal mul_0_by_inf : std_logic;
signal mul_inf : std_logic;
signal div_inf : std_logic;
signal add_inf : std_logic;
signal sub_inf : std_logic;
signal addsub_inf_invalid : std_logic;
signal addsub_inf : std_logic;
signal out_inf_trigger : std_logic;
signal out_pos_inf : std_logic;
signal out_neg_inf : std_logic;
signal round_nearest : std_logic;
signal round_to_zero : std_logic;
signal round_to_pos_inf : std_logic;
signal round_to_neg_inf : std_logic;
signal inf_round_down_trigger : std_logic;
signal mul_uf : std_logic;
signal div_uf : std_logic;
signal underflow_trigger : std_logic;
signal invalid_trigger : std_logic;
signal overflow_trigger : std_logic;
signal inexact_trigger : std_logic;
signal except_trigger : std_logic;
signal enable_trigger : std_logic;
signal NaN_out_trigger : std_logic;
signal SNaN_trigger : std_logic;
signal exp_2047 : std_logic_vector(10 downto 0);
signal exp_2046 : std_logic_vector(10 downto 0);
signal NaN_output_0 : std_logic_vector(62 downto 0);
signal NaN_output : std_logic_vector(62 downto 0);
signal mantissa_max : std_logic_vector(51 downto 0);
signal inf_round_down : std_logic_vector(62 downto 0);
signal out_inf : std_logic_vector(62 downto 0);
signal out_0 : std_logic_vector(63 downto 0);
signal out_1 : std_logic_vector(63 downto 0);
signal out_2 : std_logic_vector(63 downto 0);
begin
exp_2047 <= "11111111111";
exp_2046 <= "11111111110";
mantissa_max <= "1111111111111111111111111111111111111111111111111111";
process
begin
wait until clk'event and clk = '1';
if (rst = '1') then
in_et_zero <= '0';
opa_et_zero <= '0';
opb_et_zero <= '0';
add <= '0';
subtract <= '0';
multiply <= '0';
divide <= '0';
opa_QNaN <= '0';
opb_QNaN <= '0';
opa_SNaN <= '0';
opb_SNaN <= '0';
opa_pos_inf <= '0';
opb_pos_inf <= '0';
opa_neg_inf <= '0';
opb_neg_inf <= '0';
opa_inf <= '0';
opb_inf <= '0';
NaN_input <= '0';
SNaN_input <= '0';
a_NaN <= '0';
div_by_0 <= '0';
div_0_by_0 <= '0';
div_inf_by_inf <= '0';
div_by_inf <= '0';
mul_0_by_inf <= '0';
mul_inf <= '0';
div_inf <= '0';
add_inf <= '0';
sub_inf <= '0';
addsub_inf_invalid <= '0';
addsub_inf <= '0';
out_inf_trigger <= '0';
out_pos_inf <= '0';
out_neg_inf <= '0';
round_nearest <= '0';
round_to_zero <= '0';
round_to_pos_inf <= '0';
round_to_neg_inf <= '0';
inf_round_down_trigger <= '0';
mul_uf <= '0';
div_uf <= '0';
underflow_trigger <= '0';
invalid_trigger <= '0';
overflow_trigger <= '0';
inexact_trigger <= '0';
except_trigger <= '0';
enable_trigger <= '0';
NaN_out_trigger <= '0';
SNaN_trigger <= '0';
NaN_output_0 <= (others =>'0');
NaN_output <= (others =>'0');
inf_round_down <= (others =>'0');
out_inf <= (others =>'0');
out_0 <= (others =>'0');
out_1 <= (others =>'0');
out_2 <= (others =>'0');
elsif (enable = '1') then
if or_reduce(in_except(62 downto 0)) = '0' then
in_et_zero <= '1';
else
in_et_zero <= '0';
end if;
if or_reduce(opa(62 downto 0)) = '0' then
opa_et_zero <= '1';
else
opa_et_zero <= '0';
end if;
if or_reduce(opb(62 downto 0)) = '0' then
opb_et_zero <= '1';
else
opb_et_zero <= '0';
end if;
if fpu_op = "000" then
add <= '1';
else
add <= '0';
end if;
if fpu_op = "001" then
subtract <= '1';
else
subtract <= '0';
end if;
if fpu_op = "010" then
multiply <= '1';
else
multiply <= '0';
end if;
if fpu_op = "011" then
divide <= '1';
else
divide <= '0';
end if;
if opa(62 downto 52) = "11111111111" and or_reduce(opa(51 downto 0)) = '1' and
opa(51) = '1' then
opa_QNaN <= '1';
else
opa_QNaN <= '0';
end if;
if opb(62 downto 52) = "11111111111" and or_reduce(opb(51 downto 0)) = '1' and
opb(51) = '1' then
opb_QNaN <= '1';
else
opb_QNaN <= '0';
end if;
if opa(62 downto 52) = "11111111111" and or_reduce(opa(51 downto 0)) = '1' and
opa(51) = '0' then
opa_SNaN <= '1';
else
opa_SNaN <= '0';
end if;
if opb(62 downto 52) = "11111111111" and or_reduce(opb(51 downto 0)) = '1' and
opb(51) = '0' then
opb_SNaN <= '1';
else
opb_SNaN <= '0';
end if;
if opa(62 downto 52) = "11111111111" and or_reduce(opa(51 downto 0)) = '0' and
opa(63) = '0' then
opa_pos_inf <= '1';
else
opa_pos_inf <= '0';
end if;
if opb(62 downto 52) = "11111111111" and or_reduce(opb(51 downto 0)) = '0' and
opb(63) = '0' then
opb_pos_inf <= '1';
else
opb_pos_inf <= '0';
end if;
if opa(62 downto 52) = "11111111111" and or_reduce(opa(51 downto 0)) = '0' and
opa(63) = '1' then
opa_neg_inf <= '1';
else
opa_neg_inf <= '0';
end if;
if opb(62 downto 52) = "11111111111" and or_reduce(opb(51 downto 0)) = '0' and
opb(63) = '1' then
opb_neg_inf <= '1';
else
opb_neg_inf <= '0';
end if;
if opa(62 downto 52) = "11111111111" and or_reduce(opa(51 downto 0)) = '0' then
opa_inf <= '1';
else
opa_inf <= '0';
end if;
if opb(62 downto 52) = "11111111111" and or_reduce(opb(51 downto 0)) = '0' then
opb_inf <= '1';
else
opb_inf <= '0';
end if;
if opa_QNaN = '1' or opb_QNaN = '1' or opa_SNaN = '1' or opb_SNaN = '1' then
NaN_input <= '1';
else
NaN_input <= '0';
end if;
if opa_SNaN = '1' or opb_SNaN = '1' then
SNaN_input <= '1';
else
SNaN_input <= '0';
end if;
if opa_SNaN = '1' or opa_QNaN = '1' then
a_NaN <= '1';
else
a_NaN <= '0';
end if;
if divide = '1' and opb_et_zero = '1' and opa_et_zero = '0' then
div_by_0 <= '1';
else
div_by_0 <= '0';
end if;
if divide = '1' and opb_et_zero = '1' and opa_et_zero = '1' then
div_0_by_0 <= '1';
else
div_0_by_0 <= '0';
end if;
if divide = '1' and opa_inf = '1' and opb_inf = '1' then
div_inf_by_inf <= '1';
else
div_inf_by_inf <= '0';
end if;
if divide = '1' and opa_inf = '0' and opb_inf = '1' then
div_by_inf <= '1';
else
div_by_inf <= '0';
end if;
if multiply = '1' and ((opa_inf = '1' and opb_et_zero = '1') or
(opa_et_zero = '1' and opb_inf = '1')) then
mul_0_by_inf <= '1';
else
mul_0_by_inf <= '0';
end if;
if multiply = '1' and (opa_inf = '1' or opb_inf = '1') and
mul_0_by_inf = '0' then
mul_inf <= '1';
else
mul_inf <= '0';
end if;
if divide = '1' and opa_inf = '1' and opb_inf = '0' then
div_inf <= '1';
else
div_inf <= '0';
end if;
if add = '1' and (opa_inf = '1' or opb_inf = '1') then
add_inf <= '1';
else
add_inf <= '0';
end if;
if subtract = '1' and (opa_inf = '1' or opb_inf = '1') then
sub_inf <= '1';
else
sub_inf <= '0';
end if;
if (add = '1' and opa_pos_inf = '1' and opb_neg_inf = '1') or
(add = '1' and opa_neg_inf = '1' and opb_pos_inf = '1') or
(subtract = '1' and opa_pos_inf = '1' and opb_pos_inf = '1') or
(subtract = '1' and opa_neg_inf = '1' and opb_neg_inf = '1') then
addsub_inf_invalid <= '1';
else
addsub_inf_invalid <= '0';
end if;
if (add_inf = '1' or sub_inf = '1') and addsub_inf_invalid = '0' then
addsub_inf <= '1';
else
addsub_inf <= '0';
end if;
if addsub_inf = '1' or mul_inf = '1' or div_inf = '1' or div_by_0 = '1'
or (exponent_in > "011111111110") then -- 2046
out_inf_trigger <= '1';
else
out_inf_trigger <= '0';
end if;
if out_inf_trigger = '1' and in_except(63) = '0' then
out_pos_inf <= '1';
else
out_pos_inf <= '0';
end if;
if out_inf_trigger = '1' and in_except(63) = '1' then
out_neg_inf <= '1';
else
out_neg_inf <= '0';
end if;
if rmode = "00" then
round_nearest <= '1';
else
round_nearest <= '0';
end if;
if rmode = "01" then
round_to_zero <= '1';
else
round_to_zero <= '0';
end if;
if rmode = "10" then
round_to_pos_inf <= '1';
else
round_to_pos_inf <= '0';
end if;
if rmode = "11" then
round_to_neg_inf <= '1';
else
round_to_neg_inf <= '0';
end if;
if (out_pos_inf = '1' and round_to_neg_inf = '1') or
(out_neg_inf = '1' and round_to_pos_inf = '1') or
(out_inf_trigger = '1' and round_to_zero = '1') then
inf_round_down_trigger <= '1';
else
inf_round_down_trigger <= '0';
end if;
if multiply = '1' and opa_et_zero = '0' and opb_et_zero = '0' and
in_et_zero = '1' then
mul_uf <= '1';
else
mul_uf <= '0';
end if;
if divide = '1' and opa_et_zero = '0' and in_et_zero = '1' then
div_uf <= '1';
else
div_uf <= '0';
end if;
if div_by_inf = '1' or mul_uf = '1' or div_uf = '1' then
underflow_trigger <= '1';
else
underflow_trigger <= '0';
end if;
if SNaN_input = '1' or addsub_inf_invalid = '1' or mul_0_by_inf = '1' or
div_0_by_0 = '1' or div_inf_by_inf = '1' then
invalid_trigger <= '1';
else
invalid_trigger <= '0';
end if;
if div_by_inf = '1' or mul_uf = '1' or div_uf = '1' then
underflow_trigger <= '1';
else
underflow_trigger <= '0';
end if;
if out_inf_trigger = '1' and NaN_input = '0' then
overflow_trigger <= '1';
else
overflow_trigger <= '0';
end if;
if (or_reduce(mantissa_in(1 downto 0)) = '1' or out_inf_trigger = '1' or
underflow_trigger = '1') and NaN_input = '0' then
inexact_trigger <= '1';
else
inexact_trigger <= '0';
end if;
if (invalid_trigger = '1' or overflow_trigger = '1' or
underflow_trigger = '1' or inexact_trigger = '1') then
except_trigger <= '1';
else
except_trigger <= '0';
end if;
if (invalid_trigger = '1' or overflow_trigger = '1' or
underflow_trigger = '1' or inexact_trigger = '1') then
except_trigger <= '1';
else
except_trigger <= '0';
end if;
if (except_trigger = '1' or out_inf_trigger = '1' or
NaN_input = '1') then
enable_trigger <= '1';
else
enable_trigger <= '0';
end if;
if (NaN_input = '1' or invalid_trigger = '1') then
NaN_out_trigger <= '1';
else
NaN_out_trigger <= '0';
end if;
if (invalid_trigger = '1' and SNaN_input = '0') then
SNaN_trigger <= '1';
else
SNaN_trigger <= '0';
end if;
if a_NaN = '1' then
NaN_output_0 <= exp_2047 & '1' & opa(50 downto 0);
else
NaN_output_0 <= exp_2047 & '1' & opb(50 downto 0);
end if;
if SNaN_trigger = '1' then
NaN_output <= exp_2047 & "01" & opa(49 downto 0);
else
NaN_output <= NaN_output_0;
end if;
inf_round_down <= exp_2046 & mantissa_max;
if inf_round_down_trigger = '1' then
out_inf <= inf_round_down;
else
out_inf <= exp_2047 & "0000000000000000000000000000000000000000000000000000";
end if;
if underflow_trigger = '1' then
out_0 <= in_except(63) & "000000000000000000000000000000000000000000000000000000000000000";
else
out_0 <= in_except;
end if;
if out_inf_trigger = '1' then
out_1 <= in_except(63) & out_inf;
else
out_1 <= out_0;
end if;
if NaN_out_trigger = '1' then
out_2 <= in_except(63) & NaN_output;
else
out_2 <= out_1;
end if;
end if;
end process;
 
 
process
begin
wait until clk'event and clk = '1';
if (rst = '1') then
ex_enable <= '0';
underflow <= '0';
overflow <= '0';
inexact <= '0';
exception <= '0';
invalid <= '0';
out_fp <= (others =>'0');
elsif (enable = '1') then
ex_enable <= enable_trigger;
underflow <= underflow_trigger;
overflow <= overflow_trigger;
inexact <= inexact_trigger;
exception <= except_trigger;
invalid <= invalid_trigger;
out_fp <= out_2;
end if;
end process;
end rtl;
/trunk/fpu_div.vhd
0,0 → 1,409
---------------------------------------------------------------------
---- ----
---- FPU ----
---- Floating Point Unit (Double precision) ----
---- ----
---- Author: David Lundgren ----
---- davidklun@gmail.com ----
---- ----
---------------------------------------------------------------------
---- ----
---- Copyright (C) 2009 David Lundgren ----
---- davidklun@gmail.com ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer.----
---- ----
---- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ----
---- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ----
---- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ----
---- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ----
---- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ----
---- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ----
---- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ----
---- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ----
---- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ----
---- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ----
---- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ----
---- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ----
---- POSSIBILITY OF SUCH DAMAGE. ----
---- ----
---------------------------------------------------------------------
 
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_misc.all;
use IEEE.numeric_std.all;
library work;
use work.fpupack.all;
ENTITY fpu_div IS
 
PORT(
clk, rst, enable : IN std_logic;
opa, opb : IN std_logic_vector (63 DOWNTO 0);
sign : OUT std_logic;
mantissa_7 : OUT std_logic_vector (55 DOWNTO 0);
exponent_out : OUT std_logic_vector (11 DOWNTO 0)
);
 
END fpu_div;
architecture rtl of fpu_div is
 
signal dividend_signal : std_logic_vector(53 downto 0);
signal divisor_signal : std_logic_vector(53 downto 0);
signal enable_signal : std_logic;
signal enable_signal_2 : std_logic;
signal enable_signal_a : std_logic;
signal enable_signal_b : std_logic;
signal enable_signal_c : std_logic;
signal enable_signal_d : std_logic;
signal enable_signal_e : std_logic;
signal dividend_shift : std_logic_vector(5 downto 0);
signal dividend_shift_2 : std_logic_vector(5 downto 0);
signal divisor_shift : std_logic_vector(5 downto 0);
signal divisor_shift_2 : std_logic_vector(5 downto 0);
signal count_out : std_logic_vector(5 downto 0);
signal mantissa_a : std_logic_vector(51 downto 0);
signal mantissa_b : std_logic_vector(51 downto 0);
signal expon_a : std_logic_vector(10 downto 0);
signal expon_b : std_logic_vector(10 downto 0);
signal a_is_norm : std_logic;
signal b_is_norm : std_logic;
signal a_is_zero : std_logic;
signal exponent_a : std_logic_vector(11 downto 0);
signal exponent_b : std_logic_vector(11 downto 0);
signal dividend_a : std_logic_vector(51 downto 0);
signal dividend_a_shifted : std_logic_vector(51 downto 0);
signal dividend_denorm : std_logic_vector(52 downto 0);
signal dividend_1 : std_logic_vector(53 downto 0);
signal divisor_b : std_logic_vector(51 downto 0);
signal divisor_b_shifted : std_logic_vector(51 downto 0);
signal divisor_denorm : std_logic_vector(52 downto 0);
signal divisor_1 : std_logic_vector(53 downto 0);
signal count_index : std_logic_vector(5 downto 0);
signal count_nonzero : std_logic;
signal quotient : std_logic_vector(53 downto 0);
signal quotient_out : std_logic_vector(53 downto 0);
signal remainder : std_logic_vector(53 downto 0);
signal remainder_out : std_logic_vector(53 downto 0);
signal remainder_msb : std_logic;
signal count_nonzero_signal : std_logic;
signal count_nonzero_signal_2 : std_logic;
signal expon_term : std_logic_vector(11 downto 0);
signal expon_uf_1 : std_logic;
signal expon_uf_term_1 : std_logic_vector(11 downto 0);
signal expon_final_1 : std_logic_vector(11 downto 0);
signal expon_final_2 : std_logic_vector(11 downto 0);
signal expon_shift_a : std_logic_vector(11 downto 0);
signal expon_shift_b : std_logic_vector(11 downto 0);
signal expon_uf_2 : std_logic;
signal expon_uf_term_2 : std_logic_vector(11 downto 0);
signal expon_uf_term_3 : std_logic_vector(11 downto 0);
signal expon_uf_gt_maxshift : std_logic;
signal expon_uf_term_4 : std_logic_vector(11 downto 0);
signal expon_final_3 : std_logic_vector(11 downto 0);
signal expon_final_4 : std_logic_vector(11 downto 0);
signal quotient_msb : std_logic;
signal expon_final_4_et0 : std_logic;
signal expon_final_4_term : std_logic;
signal expon_final_5 : std_logic_vector(11 downto 0);
signal mantissa_1 : std_logic_vector(51 downto 0);
signal mantissa_2 : std_logic_vector(51 downto 0);
signal mantissa_3 : std_logic_vector(51 downto 0);
signal mantissa_4 : std_logic_vector(51 downto 0);
signal mantissa_5 : std_logic_vector(51 downto 0);
signal mantissa_6 : std_logic_vector(51 downto 0);
signal remainder_a : std_logic_vector(107 downto 0);
signal remainder_shift_term : std_logic_vector(11 downto 0);
signal remainder_b : std_logic_vector(107 downto 0);
signal remainder_1 : std_logic_vector(55 downto 0);
signal remainder_2 : std_logic_vector(55 downto 0);
signal remainder_3 : std_logic_vector(55 downto 0);
signal remainder_4 : std_logic_vector(55 downto 0);
signal remainder_5 : std_logic_vector(55 downto 0);
signal remainder_6 : std_logic_vector(55 downto 0);
signal m_norm : std_logic;
signal rem_lsb : std_logic;
begin
sign <= opa(63) xor opb(63);
expon_a <= opa(62 downto 52);
expon_b <= opb(62 downto 52);
a_is_norm <= or_reduce(expon_a);
b_is_norm <= or_reduce(expon_b);
a_is_zero <= not or_reduce(opa(62 downto 0));
exponent_a <= '0' & expon_a;
exponent_b <= '0' & expon_b;
dividend_denorm <= dividend_a_shifted & '0';
dividend_1 <= "01" & dividend_a when a_is_norm = '1' else '0' & dividend_denorm;
divisor_denorm <= divisor_b_shifted & '0';
divisor_1 <= "01" & divisor_b when b_is_norm = '1' else '0' & divisor_denorm;
count_nonzero <= '0' when count_index = "000000" else '1';
count_index <= count_out;
quotient_msb <= quotient_out(53);
mantissa_2 <= quotient_out(52 downto 1);
mantissa_3 <= quotient_out(51 downto 0);
mantissa_4 <= mantissa_2 when quotient_msb = '1' else mantissa_3;
mantissa_5 <= mantissa_2 when expon_final_4 = "000000000001" else mantissa_4;
mantissa_6 <= mantissa_1 when expon_final_4_et0 = '1' else mantissa_5;
remainder_a <= quotient_out(53 downto 0) & remainder_msb & remainder_out(52 downto 0);
remainder_1 <= remainder_b(107 downto 52);
remainder_2 <= quotient_out(0) & remainder_msb & remainder_out(52 downto 0) & '0' ;
remainder_3 <= remainder_msb & remainder_out(52 downto 0) & "00" ;
remainder_4 <= remainder_2 when quotient_msb = '1' else remainder_3;
remainder_5 <= remainder_2 when expon_final_4 = "000000000001" else remainder_4;
remainder_6 <= remainder_1 when expon_final_4_et0 = '1' else remainder_5;
m_norm <= or_reduce(expon_final_5);
rem_lsb <= or_reduce(remainder_6(54 downto 0));
mantissa_7 <= '0' & m_norm & mantissa_6 & remainder_6(55) & rem_lsb ;
process
begin
wait until clk'event and clk = '1';
if (rst = '1') then
exponent_out <= (others =>'0');
else
if (a_is_zero = '1') then
exponent_out <= "000000000000";
else
exponent_out <= expon_final_5;
end if;
end if;
end process;
process
begin
wait until clk'event and clk = '1';
if (rst = '1') then
count_out <= (others =>'0');
elsif (enable_signal = '1') then
count_out <= "110101"; -- 53
elsif (count_nonzero = '1') then
count_out <= count_out - "000001";
end if;
end process;
process
begin
wait until clk'event and clk = '1';
if (rst = '1') then
quotient_out <= (others =>'0');
remainder_out <= (others =>'0');
else
quotient_out <= quotient;
remainder_out <= remainder;
end if;
end process;
 
process
begin
wait until clk'event and clk = '1';
if (rst = '1') then
quotient <= (others =>'0');
elsif (count_nonzero_signal = '1') then
if (divisor_signal > dividend_signal) then
quotient(conv_integer(count_index)) <= '0';
else
quotient(conv_integer(count_index)) <= '1';
end if;
end if;
end process;
 
process
begin
wait until clk'event and clk = '1';
if (rst = '1') then
remainder <= (others =>'0');
remainder_msb <= '0';
elsif ((not count_nonzero_signal and count_nonzero_signal_2) = '1') then
remainder <= dividend_signal;
if (divisor_signal > dividend_signal) then
remainder_msb <= '0';
else
remainder_msb <= '1';
end if;
end if;
end process;
 
process
begin
wait until clk'event and clk = '1';
if (rst = '1') then
dividend_signal <= (others =>'0');
divisor_signal <= (others =>'0');
elsif (enable_signal_e = '1') then
dividend_signal <= dividend_1;
divisor_signal <= divisor_1;
elsif (count_nonzero_signal = '1') then
if (divisor_signal > dividend_signal) then
dividend_signal <= shl(dividend_signal, conv_std_logic_vector('1', 54));
else
dividend_signal <= shl(dividend_signal - divisor_signal, conv_std_logic_vector('1', 54));
end if;
end if;
end process;
 
process
begin
wait until clk'event and clk = '1';
if (rst = '1') then
expon_term <= (others =>'0');
expon_uf_1 <= '0';
expon_uf_term_1 <= (others =>'0');
expon_final_1 <= (others =>'0');
expon_final_2 <= (others =>'0');
expon_shift_a <= (others =>'0');
expon_shift_b <= (others =>'0');
expon_uf_2 <= '0';
expon_uf_term_2 <= (others =>'0');
expon_uf_term_3 <= (others =>'0');
expon_uf_gt_maxshift <= '0';
expon_uf_term_4 <= (others =>'0');
expon_final_3 <= (others =>'0');
expon_final_4 <= (others =>'0');
expon_final_4_et0 <= '0';
expon_final_4_term <= '0';
expon_final_5 <= (others =>'0');
mantissa_a <= (others =>'0');
mantissa_b <= (others =>'0');
dividend_a <= (others =>'0');
divisor_b <= (others =>'0');
dividend_shift <= (others =>'0');
divisor_shift <= (others =>'0');
dividend_shift_2 <= (others =>'0');
divisor_shift_2 <= (others =>'0');
remainder_shift_term <= (others =>'0');
remainder_b <= (others =>'0');
dividend_a_shifted <= (others =>'0');
divisor_b_shifted <= (others =>'0');
mantissa_1 <= (others =>'0');
elsif (enable_signal_2 = '1') then
expon_term <= exponent_a + "001111111111"; -- 1023
if (exponent_b > expon_term) then
expon_uf_1 <= '1';
else
expon_uf_1 <= '0';
end if;
if (expon_uf_1 = '1') then
expon_uf_term_1 <= exponent_b - expon_term;
expon_final_2 <= (others =>'0');
else
expon_uf_term_1 <= (others =>'0');
expon_final_2 <= expon_final_1;
end if;
expon_final_1 <= expon_term - exponent_b;
if (expon_uf_1 = '1') then
expon_uf_term_1 <= exponent_b - expon_term;
else
expon_uf_term_1 <= (others =>'0');
end if;
if (a_is_norm = '1') then
expon_shift_a <= (others =>'0');
else
expon_shift_a <= "000000" & dividend_shift_2;
end if;
if (b_is_norm = '1') then
expon_shift_b <= (others =>'0');
else
expon_shift_b <= "000000" & divisor_shift_2;
end if;
if (expon_shift_a > expon_final_2) then
expon_uf_2 <= '1';
else
expon_uf_2 <= '0';
end if;
if (expon_uf_2 = '1') then
expon_uf_term_2 <= expon_shift_a - expon_final_2;
else
expon_uf_term_2 <= (others =>'0');
end if;
expon_uf_term_3 <= expon_uf_term_2 + expon_uf_term_1;
if (expon_uf_term_3 > "000000110011") then -- 51
expon_uf_gt_maxshift <= '1';
else
expon_uf_gt_maxshift <= '0';
end if;
if (expon_uf_gt_maxshift = '1') then
expon_uf_term_4 <= "000000110100"; --52
else
expon_uf_term_4 <= expon_uf_term_3;
end if;
if (expon_uf_2 = '1') then
expon_final_3 <= (others =>'0');
else
expon_final_3 <= expon_final_2 - expon_shift_a;
end if;
expon_final_4 <= expon_final_3 + expon_shift_b;
if (expon_final_4 = "000000000000") then
expon_final_4_et0 <= '1';
else
expon_final_4_et0 <= '0';
end if;
if (expon_final_4_et0 = '1') then
expon_final_4_term <= '0';
else
expon_final_4_term <= '1';
end if;
if (quotient_msb = '1') then
expon_final_5 <= expon_final_4;
else
expon_final_5 <= expon_final_4 - expon_final_4_term;
end if;
mantissa_a <= opa(51 downto 0);
mantissa_b <= opb(51 downto 0);
dividend_a <= mantissa_a;
divisor_b <= mantissa_b;
dividend_shift <= count_l_zeros(dividend_a);
divisor_shift <= count_l_zeros(divisor_b);
dividend_shift_2 <= dividend_shift;
divisor_shift_2 <= divisor_shift;
remainder_shift_term <= "000000110100" - expon_uf_term_4; -- 52
remainder_b <= shl(remainder_a, remainder_shift_term);
dividend_a_shifted <= shl(dividend_a, dividend_shift_2);
divisor_b_shifted <= shl(divisor_b, divisor_shift_2);
mantissa_1 <= shr(quotient_out(53 downto 2), expon_uf_term_4);
end if;
end process;
 
process
begin
wait until clk'event and clk = '1';
if (rst = '1') then
count_nonzero_signal <= '0';
count_nonzero_signal_2 <= '0';
enable_signal <= '0';
enable_signal_a <= '0';
enable_signal_b <= '0';
enable_signal_c <= '0';
enable_signal_d <= '0';
enable_signal_e <= '0';
else
count_nonzero_signal <= count_nonzero;
count_nonzero_signal_2 <= count_nonzero_signal;
enable_signal <= enable_signal_e;
enable_signal_a <= enable;
enable_signal_b <= enable_signal_a;
enable_signal_c <= enable_signal_b;
enable_signal_d <= enable_signal_c;
enable_signal_e <= enable_signal_d;
end if;
end process;
 
process
begin
wait until clk'event and clk = '1';
if (rst = '1') then
enable_signal_2 <= '0';
elsif (enable = '1') then
enable_signal_2 <= '1';
end if;
end process;
 
end rtl;
/trunk/comppack.vhd
0,0 → 1,125
---------------------------------------------------------------------
---- ----
---- FPU ----
---- Floating Point Unit (Double precision) ----
---- ----
---- Author: David Lundgren ----
---- davidklun@gmail.com ----
---- ----
---------------------------------------------------------------------
---- ----
---- Copyright (C) 2009 David Lundgren ----
---- davidklun@gmail.com ----
---- ----
---- This source file may be used and distributed without ----
---- restriction provided that this copyright statement is not ----
---- removed from the file and that any derivative work contains ----
---- the original copyright notice and the associated disclaimer.----
---- ----
---- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ----
---- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ----
---- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ----
---- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ----
---- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ----
---- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ----
---- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ----
---- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ----
---- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ----
---- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ----
---- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ----
---- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ----
---- POSSIBILITY OF SUCH DAMAGE. ----
---- ----
---------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
 
library work;
use work.fpupack.all;
 
package comppack is
 
 
--- Component Declarations ---
component fpu_add is
PORT(
clk : IN std_logic;
rst : IN std_logic;
enable : IN std_logic;
opa : IN std_logic_vector (63 DOWNTO 0);
opb : IN std_logic_vector (63 DOWNTO 0);
sign : OUT std_logic;
sum_3 : OUT std_logic_vector (55 DOWNTO 0);
exponent_2 : OUT std_logic_vector (10 DOWNTO 0)
);
end component;
component fpu_sub is
PORT(
clk : IN std_logic;
rst : IN std_logic;
enable : IN std_logic;
opa : IN std_logic_vector (63 DOWNTO 0);
opb : IN std_logic_vector (63 DOWNTO 0);
fpu_op : IN std_logic_vector (2 DOWNTO 0);
sign : OUT std_logic;
diff_2 : OUT std_logic_vector (55 DOWNTO 0);
exponent_2 : OUT std_logic_vector (10 DOWNTO 0)
);
end component;
component fpu_mul is
port(
clk : IN std_logic;
rst : IN std_logic;
enable : IN std_logic;
opa : IN std_logic_vector (63 DOWNTO 0);
opb : IN std_logic_vector (63 DOWNTO 0);
sign : OUT std_logic;
product_7 : OUT std_logic_vector (55 DOWNTO 0);
exponent_5 : OUT std_logic_vector (11 DOWNTO 0)
);
end component;
component fpu_div is
port(
clk, rst, enable : IN std_logic;
opa, opb : IN std_logic_vector (63 DOWNTO 0);
sign : OUT std_logic;
mantissa_7 : OUT std_logic_vector (55 DOWNTO 0);
exponent_out : OUT std_logic_vector (11 DOWNTO 0)
);
end component;
component fpu_round is
port(
clk, rst, enable : IN std_logic;
round_mode : IN std_logic_vector (1 DOWNTO 0);
sign_term : IN std_logic;
mantissa_term : IN std_logic_vector (55 DOWNTO 0);
exponent_term : IN std_logic_vector (11 DOWNTO 0);
round_out : OUT std_logic_vector (63 DOWNTO 0);
exponent_final : OUT std_logic_vector (11 DOWNTO 0)
);
end component;
component fpu_exceptions is
port(
clk, rst, enable : IN std_logic;
rmode : IN std_logic_vector (1 DOWNTO 0);
opa, opb, in_except : IN std_logic_vector (63 DOWNTO 0);
exponent_in : IN std_logic_vector (11 DOWNTO 0);
mantissa_in : IN std_logic_vector (1 DOWNTO 0);
fpu_op : IN std_logic_vector (2 DOWNTO 0);
out_fp : OUT std_logic_vector (63 DOWNTO 0);
ex_enable, underflow, overflow, inexact : OUT std_logic;
exception, invalid : OUT std_logic
);
end component;
end comppack;

powered by: WebSVN 2.1.0

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