constant BIN_ZERO : std_ulogic_vector(1 downto 0) := "00";
constant BIN_R : std_ulogic_vector(1 downto 0) := "01";
- constant BIN_MASK : std_ulogic_vector(1 downto 0) := "10";
+ constant BIN_RND : std_ulogic_vector(1 downto 0) := "10";
constant BIN_PS6 : std_ulogic_vector(1 downto 0) := "11";
constant RES_SUM : std_ulogic_vector(1 downto 0) := "00";
variable mulexp : signed(EXP_BITS-1 downto 0);
variable maddend : std_ulogic_vector(127 downto 0);
variable sum : std_ulogic_vector(63 downto 0);
+ variable round_inc : std_ulogic_vector(63 downto 0);
begin
v := r;
illegal := '0';
elsif r.b.exponent > to_signed(127, EXP_BITS) then
v.state := ROUND_OFLOW;
else
- v.shift := to_signed(-2, EXP_BITS);
v.state := ROUNDING;
end if;
else
-- sum overflowed, shift right
opsel_r <= RES_SHIFT;
set_x := '1';
- v.shift := to_signed(-2, EXP_BITS);
if exp_huge = '1' then
v.state := ROUND_OFLOW;
else
end if;
elsif r.r(54) = '1' then
set_x := '1';
- v.shift := to_signed(-2, EXP_BITS);
v.state := ROUNDING;
elsif (r_hi_nz or r_lo_nz or r.r(1) or r.r(0)) = '0' then
-- r.x must be zero at this point
-- r.shift = b.exponent - 52
opsel_r <= RES_SHIFT;
set_x := '1';
- v.shift := to_signed(-2, EXP_BITS);
v.state := ROUNDING;
when FINISH =>
elsif exp_huge = '1' then
v.state := ROUND_OFLOW;
else
- v.shift := to_signed(-2, EXP_BITS);
v.state := ROUNDING;
end if;
end if;
elsif exp_huge = '1' then
v.state := ROUND_OFLOW;
else
- v.shift := to_signed(-2, EXP_BITS);
v.state := ROUNDING;
end if;
-- have to denormalize before rounding
opsel_r <= RES_SHIFT;
set_x := '1';
- v.shift := to_signed(-2, EXP_BITS);
v.state := ROUNDING;
else
-- enabled underflow exception case
renormalize := '1';
v.state := NORMALIZE;
else
- v.shift := to_signed(-2, EXP_BITS);
v.state := ROUNDING;
end if;
end if;
else
-- enabled overflow exception
v.result_exp := r.result_exp - bias_exp;
- v.shift := to_signed(-2, EXP_BITS);
v.state := ROUNDING;
end if;
round := fp_rounding(r.r, r.x, r.single_prec, r.round_mode, r.result_sign);
v.fpscr(FPSCR_FR downto FPSCR_FI) := round;
if round(1) = '1' then
- -- set mask to increment the LSB for the precision
- opsel_b <= BIN_MASK;
- carry_in <= '1';
+ -- increment the LSB for the precision
+ opsel_b <= BIN_RND;
v.shift := to_signed(-1, EXP_BITS);
v.state := ROUNDING_2;
else
in_b0 := (others => '0');
when BIN_R =>
in_b0 := r.r;
- when BIN_MASK =>
- in_b0 := mask;
+ when BIN_RND =>
+ round_inc := (31 => r.single_prec, 2 => not r.single_prec, others => '0');
+ in_b0 := round_inc;
when others =>
-- BIN_PS6, 6 LSBs of P/4 sign-extended to 64
in_b0 := std_ulogic_vector(resize(signed(r.p(7 downto 2)), 64));
end if;
sum := std_ulogic_vector(unsigned(in_a) + unsigned(in_b) + carry_in);
if opsel_mask = '1' then
- sum := sum and not mask;
+ sum(1 downto 0) := "00";
+ if r.single_prec = '1' then
+ sum(30 downto 2) := (others => '0');
+ end if;
end if;
case opsel_r is
when RES_SUM =>