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