diff --git a/fpu.vhdl b/fpu.vhdl index a309705..3914a97 100644 --- a/fpu.vhdl +++ b/fpu.vhdl @@ -185,6 +185,7 @@ architecture behaviour of fpu is signal r, rin : reg_type; signal fp_result : std_ulogic_vector(63 downto 0); + signal opsel_a : std_ulogic_vector(1 downto 0); signal opsel_b : std_ulogic_vector(1 downto 0); signal opsel_r : std_ulogic_vector(1 downto 0); signal opsel_s : std_ulogic_vector(1 downto 0); @@ -838,6 +839,7 @@ begin variable set_b_mant : std_ulogic; variable set_c : std_ulogic; variable set_y : std_ulogic; + variable set_r : std_ulogic; variable set_s : std_ulogic; variable qnan_result : std_ulogic; variable invalid_mul : std_ulogic; @@ -1143,6 +1145,7 @@ begin v.first := '0'; v.doing_ftdiv := "00"; v.opsel_a := AIN_R; + opsel_a <= AIN_R; opsel_ainv <= '0'; opsel_mask <= '0'; opsel_b <= BIN_ZERO; @@ -1166,6 +1169,7 @@ begin set_b := '0'; set_b_mant := '0'; set_c := '0'; + set_r := '1'; set_s := '0'; f_to_multiply.is_signed <= '0'; f_to_multiply.valid <= '0'; @@ -1207,12 +1211,7 @@ begin when IDLE => v.invalid := '0'; if e_in.valid = '1' then - v.opsel_a := AIN_B; v.busy := '1'; - if e_in.op = OP_FP_ARITH and e_in.valid_a = '1' and - (e_in.valid_b = '0' or e_in.valid_c = '0') then - v.opsel_a := AIN_A; - end if; v.exec_state := exec_state; if is_nan_inf = '1' then v.state := DO_NAN_INF; @@ -1293,6 +1292,11 @@ begin when DO_ZERO_DEN => -- At least one floating point operand is zero or denormalized + if r.is_addition = '1' then + opsel_a <= AIN_A; + else + opsel_a <= AIN_B; + end if; if (r.use_a = '1' and r.a.class = ZERO) or (r.use_b = '1' and r.b.class = ZERO and r.is_multiply = '0') or (r.use_c = '1' and r.c.class = ZERO) then @@ -1320,7 +1324,7 @@ begin else -- B is zero, other operands are finite if r.int_result = '1' then - -- fcti*, r.opsel_a = AIN_B + -- fcti* arith_done := '1'; elsif r.is_inverse = '1' then -- fdiv, fre, frsqrte @@ -1328,7 +1332,7 @@ begin zero_divide := '1'; arith_done := '1'; elsif r.is_addition = '1' then - -- fadd, r.opsel_a = AIN_A + -- fadd, fsub v.result_class := FINITE; re_sel1 <= REXP1_A; re_set_result <= '1'; @@ -1342,21 +1346,8 @@ begin else -- some operand is denorm, and/or it's fmadd/fmsub with B=0 - -- input selection for denorm cases -- A and C are non-zero if present, -- B is non-zero if present except for multiply-add - if r.a.zeroexp = '1' and (r.is_multiply or r.is_inverse) = '1' then - v.opsel_a := AIN_A; - elsif r.b.zeroexp = '1' and (r.is_inverse or r.is_sqrt) = '1' then - v.opsel_a := AIN_B; - elsif r.c.zeroexp = '1' then - v.opsel_a := AIN_C; - else - v.opsel_a := AIN_B; - if r.use_a = '1' and (r.use_b = '0' or r.use_c = '0' or r.b.class = ZERO) then - v.opsel_a := AIN_A; - end if; - end if; if r.is_multiply = '1' and r.b.class = ZERO then -- This will trigger for fmul as well as fmadd/sub, but -- it doesn't matter since r.is_subtract = 0 for fmul. @@ -1389,7 +1380,7 @@ begin re_sel2 <= REXP2_B; re_set_result <= '1'; if r.a.class = INFINITY or r.b.class = ZERO or r.b.class = INFINITY or - (r.b.class = FINITE and r.b.mantissa(UNIT_BIT) = '0') then + (r.b.class = FINITE and r.b.denorm = '1') then v.cr_result(2) := '1'; end if; if r.a.class = NAN or r.a.class = INFINITY or @@ -1408,7 +1399,7 @@ begin v.instr_done := '1'; v.cr_result := "0000"; if r.b.class = ZERO or r.b.class = INFINITY or - (r.b.class = FINITE and r.b.mantissa(UNIT_BIT) = '0') then + (r.b.class = FINITE and r.b.denorm = '1') then v.cr_result(2) := '1'; end if; if r.b.class = NAN or r.b.class = INFINITY or r.b.class = ZERO @@ -1418,7 +1409,7 @@ begin when DO_FCMP => -- fcmp[uo] - -- r.opsel_a = AIN_B + opsel_a <= AIN_B; v.instr_done := '1'; update_fx := '1'; re_sel2 <= REXP2_B; @@ -1467,7 +1458,6 @@ begin -- Prepare to subtract mantissas, put B in R v.cr_result := "0000"; v.instr_done := '0'; - v.opsel_a := AIN_A; v.state := CMP_1; end if; v.fpscr(FPSCR_FL downto FPSCR_FU) := v.cr_result; @@ -1550,7 +1540,7 @@ begin v.instr_done := '1'; when DO_FMR => - -- r.opsel_a = AIN_B + opsel_a <= AIN_B; v.result_class := r.b.class; re_sel2 <= REXP2_B; re_set_result <= '1'; @@ -1558,7 +1548,7 @@ begin v.instr_done := '1'; when DO_FRI => -- fri[nzpm] - -- r.opsel_a = AIN_B + opsel_a <= AIN_B; v.result_class := r.b.class; re_sel2 <= REXP2_B; re_set_result <= '1'; @@ -1574,14 +1564,15 @@ begin end if; when DO_FRSP => - -- r.opsel_a = AIN_B, r.shift = 0 + -- r.shift = 0 + opsel_a <= AIN_B; v.result_class := r.b.class; re_sel2 <= REXP2_B; re_set_result <= '1'; v.state := DO_FRSP_2; when DO_FRSP_2 => - -- r.opsel_a = AIN_R, r.shift = 0 + -- r.shift = 0 -- set shift to exponent - -126 rs_sel1 <= RSH1_B; rs_con2 <= RSCON2_MINEXP; @@ -1599,7 +1590,7 @@ begin -- instr bit 9: 1=dword 0=word -- instr bit 8: 1=unsigned 0=signed -- instr bit 1: 1=round to zero 0=use fpscr[RN] - -- r.opsel_a = AIN_B + opsel_a <= AIN_B; v.result_class := r.b.class; re_sel2 <= REXP2_B; re_set_result <= '1'; @@ -1626,7 +1617,7 @@ begin end if; when DO_FCFID => - -- r.opsel_a = AIN_B + opsel_a <= AIN_B; if r.insn(8) = '0' and r.b.negative = '1' then -- fcfid[s] with negative operand, set R = -B opsel_ainv <= '1'; @@ -1643,7 +1634,7 @@ begin when DO_FADD => -- fadd[s] and fsub[s] - -- r.opsel_a = AIN_A + opsel_a <= AIN_A; v.result_class := r.a.class; re_sel1 <= REXP1_A; re_set_result <= '1'; @@ -1652,7 +1643,6 @@ begin rs_neg1 <= '1'; rs_sel2 <= RSH2_A; v.add_bsmall := r.exp_cmp; - v.opsel_a := AIN_B; if r.exp_cmp = '0' then if r.a.exponent = r.b.exponent then v.state := ADD_2; @@ -1666,15 +1656,16 @@ begin when DO_FMUL => -- fmul[s] - -- r.opsel_a = AIN_A unless C is denorm and A isn't + opsel_a <= AIN_A; v.result_class := r.a.class; re_sel1 <= REXP1_A; re_sel2 <= REXP2_C; re_set_result <= '1'; -- Renormalize denorm operands - if r.a.mantissa(UNIT_BIT) = '0' then + if r.a.denorm = '1' then v.state := RENORM_A; - elsif r.c.mantissa(UNIT_BIT) = '0' then + elsif r.c.denorm = '1' then + opsel_a <= AIN_C; v.state := RENORM_C; else f_to_multiply.valid <= '1'; @@ -1682,7 +1673,7 @@ begin end if; when DO_FDIV => - -- r.opsel_a = AIN_A unless B is denorm and A isn't + opsel_a <= AIN_A; v.result_class := r.a.class; re_sel1 <= REXP1_A; re_sel2 <= REXP2_B; @@ -1690,9 +1681,10 @@ begin re_set_result <= '1'; v.count := "00"; -- Renormalize denorm operands - if r.a.mantissa(UNIT_BIT) = '0' then + if r.a.denorm = '1' then v.state := RENORM_A; - elsif r.b.mantissa(UNIT_BIT) = '0' then + elsif r.b.denorm = '1' then + opsel_a <= AIN_B; v.state := RENORM_B; else v.first := '1'; @@ -1700,23 +1692,23 @@ begin end if; when DO_FSEL => + rsgn_op := RSGN_SEL; if r.a.class = ZERO or (r.a.negative = '0' and r.a.class /= NAN) then v.opsel_a := AIN_C; - rsgn_op := RSGN_SEL; else v.opsel_a := AIN_B; end if; v.state := EXC_RESULT; when DO_FSQRT => - -- r.opsel_a = AIN_B + opsel_a <= AIN_B; v.result_class := r.b.class; re_sel2 <= REXP2_B; re_set_result <= '1'; if r.b.negative = '1' then v.fpscr(FPSCR_VXSQRT) := '1'; qnan_result := '1'; - elsif r.b.mantissa(UNIT_BIT) = '0' then + elsif r.b.denorm = '1' then v.state := RENORM_B; elsif r.b.exponent(0) = '0' then v.state := SQRT_1; @@ -1727,18 +1719,18 @@ begin end if; when DO_FRE => - -- r.opsel_a = AIN_B + opsel_a <= AIN_B; v.result_class := r.b.class; re_sel2 <= REXP2_B; re_set_result <= '1'; - if r.b.mantissa(UNIT_BIT) = '0' then + if r.b.denorm = '1' then v.state := RENORM_B; else v.state := FRE_1; end if; when DO_FRSQRTE => - -- r.opsel_a = AIN_B + opsel_a <= AIN_B; v.result_class := r.b.class; re_sel2 <= REXP2_B; re_set_result <= '1'; @@ -1747,7 +1739,7 @@ begin if r.b.negative = '1' then v.fpscr(FPSCR_VXSQRT) := '1'; qnan_result := '1'; - elsif r.b.mantissa(UNIT_BIT) = '0' then + elsif r.b.denorm = '1' then v.state := RENORM_B; elsif r.b.exponent(0) = '0' then v.state := RSQRT_1; @@ -1757,8 +1749,7 @@ begin when DO_FMADD => -- fmadd, fmsub, fnmadd, fnmsub - -- r.opsel_a = AIN_A if A is denorm, else AIN_C if C is denorm, - -- else AIN_B + opsel_a <= AIN_B; v.result_class := r.a.class; -- put a.exp + c.exp into result_exp re_sel1 <= REXP1_A; @@ -1767,9 +1758,11 @@ begin -- put b.exp into shift rs_sel1 <= RSH1_B; -- Make sure A and C are normalized - if r.a.mantissa(UNIT_BIT) = '0' then + if r.a.denorm = '1' then + opsel_a <= AIN_A; v.state := RENORM_A; - elsif r.c.mantissa(UNIT_BIT) = '0' then + elsif r.c.denorm = '1' then + opsel_a <= AIN_C; v.state := RENORM_C; elsif r.madd_cmp = '0' then -- addend is bigger, do multiply first @@ -1785,18 +1778,13 @@ begin when RENORM_A => rs_norm <= '1'; v.state := RENORM_A2; - if r.use_c = '1' and r.c.denorm = '1' then - v.opsel_a := AIN_C; - else - v.opsel_a := AIN_B; - end if; when RENORM_A2 => - -- r.opsel_a = AIN_C for fmul/fmadd, AIN_B for fdiv set_a := '1'; re_sel2 <= REXP2_NE; re_set_result <= '1'; if r.is_multiply = '1' then + opsel_a <= AIN_C; if r.c.mantissa(UNIT_BIT) = '1' then if r.is_addition = '0' or r.b.class = ZERO then v.first := '1'; @@ -1806,13 +1794,13 @@ begin if new_exp + 1 >= r.b.exponent then v.madd_cmp := '1'; end if; - v.opsel_a := AIN_B; v.state := DO_FMADD; end if; else v.state := RENORM_C; end if; else + opsel_a <= AIN_B; if r.b.mantissa(UNIT_BIT) = '1' then v.first := '1'; v.state := DIV_2; @@ -1839,7 +1827,6 @@ begin re_sel2 <= REXP2_NE; re_set_result <= '1'; end if; - v.opsel_a := AIN_B; v.state := LOOKUP; when RENORM_C => @@ -1858,12 +1845,12 @@ begin if new_exp + 1 >= r.b.exponent then v.madd_cmp := '1'; end if; - v.opsel_a := AIN_B; v.state := DO_FMADD; end if; when ADD_1 => -- transferring B to R + opsel_a <= AIN_B; re_sel2 <= REXP2_B; re_set_result <= '1'; -- set shift to b.exp - a.exp @@ -1881,15 +1868,14 @@ begin v.x := s_nz; set_x := '1'; v.longmask := r.single_prec; - if r.add_bsmall = '1' then - v.opsel_a := AIN_A; - else - v.opsel_a := AIN_B; - end if; v.state := ADD_2; when ADD_2 => - -- r.opsel_a = AIN_A if r.add_bsmall = 1 else AIN_B + if r.add_bsmall = '1' then + opsel_a <= AIN_A; + else + opsel_a <= AIN_B; + end if; opsel_b <= BIN_R; opsel_binv <= r.is_subtract; carry_in <= r.is_subtract and not r.x; @@ -1931,7 +1917,7 @@ begin end if; when CMP_1 => - -- r.opsel_a = AIN_A + opsel_a <= AIN_A; opsel_b <= BIN_R; opsel_binv <= '1'; carry_in <= '1'; @@ -2033,6 +2019,8 @@ begin when FMADD_6 => -- r.shift = UNIT_BIT (or 0, but only if r is now nonzero) + set_r := '0'; + opsel_r <= RES_SHIFT; re_sel2 <= REXP2_NE; rs_norm <= '1'; if (r.r(UNIT_BIT + 2) or r_hi_nz or r_lo_nz or (or (r.r(DP_LSB - 1 downto 0)))) = '0' then @@ -2043,7 +2031,7 @@ begin else -- R is all zeroes but there are non-zero bits in S -- so shift them into R and set S to 0 - opsel_r <= RES_SHIFT; + set_r := '1'; re_set_result <= '1'; set_s := '1'; v.state := FINISH; @@ -2055,10 +2043,10 @@ begin end if; when LOOKUP => - -- r.opsel_a = AIN_B -- wait one cycle for inverse_table[B] lookup -- if this is a division, compute exponent -- (see comment on RENORM_B2 above) + opsel_a <= AIN_B; if r.use_a = '1' then re_sel2 <= REXP2_NE; re_set_result <= '1'; @@ -2136,15 +2124,15 @@ begin end if; when DIV_6 => - -- r.opsel_a = AIN_R -- test if remainder is 0 or >= B + opsel_b <= BIN_RND; + rbit_inc := '1'; if pcmpb_lt = '1' then -- quotient is correct, set X if remainder non-zero + set_r := '0'; v.x := r.p(UNIT_BIT + 2) or px_nz; else -- quotient needs to be incremented by 1 in R-bit position - rbit_inc := '1'; - opsel_b <= BIN_RND; v.x := not pcmpb_eq; end if; v.state := FINISH; @@ -2575,6 +2563,7 @@ begin when ROUNDING_3 => -- r.shift = clz(r.r) - 9 + opsel_r <= RES_SHIFT; mant_nz := r_hi_nz or (r_lo_nz and not r.single_prec); re_sel2 <= REXP2_NE; -- set shift to new_exp - min_exp (== -1022) @@ -2582,11 +2571,11 @@ begin rs_con2 <= RSCON2_MINEXP; rs_neg2 <= '1'; if mant_nz = '0' then + set_r := '0'; v.result_class := ZERO; arith_done := '1'; else -- Renormalize result after rounding - opsel_r <= RES_SHIFT; re_set_result <= '1'; v.denorm := exp_tiny; if new_exp < to_signed(-1022, EXP_BITS) then @@ -2605,6 +2594,7 @@ begin when EXC_RESULT => -- r.opsel_a = AIN_A, AIN_B or AIN_C according to which input is the result + opsel_a <= r.opsel_a; case r.opsel_a is when AIN_B => re_sel2 <= REXP2_B; @@ -2620,7 +2610,7 @@ begin arith_done := '1'; when DO_IDIVMOD => - -- r.opsel_a = AIN_B + opsel_a <= AIN_B; if r.b.class = ZERO then -- B is zero, signal overflow v.int_ovf := '1'; @@ -2657,21 +2647,19 @@ begin -- add the X bit onto R to round up B carry_in <= r.x; -- prepare to do count-leading-zeroes on A - v.opsel_a := AIN_A; v.state := IDIV_CLZA; when IDIV_CLZA => set_b := '1'; -- put R back into B - -- r.opsel_a = AIN_A + opsel_a <= AIN_A; if r.is_signed = '1' and r.a.negative = '1' then opsel_ainv <= '1'; carry_in <= '1'; end if; re_con2 <= RECON2_UNIT; re_set_result <= '1'; - v.opsel_a := AIN_C; v.state := IDIV_CLZA2; when IDIV_CLZA2 => - -- r.opsel_a = AIN_C + opsel_a <= AIN_C; rs_norm <= '1'; -- write the dividend back into A in case we negated it set_a_mant := '1'; @@ -2720,6 +2708,12 @@ begin msel_inv <= '1'; msel_2 <= MUL2_LUT; set_y := '1'; + -- Get 0.5 into R in case the inverse estimate turns out to be + -- less than 0.5, in which case we want to use 0.5, to avoid + -- infinite loops in some cases. + -- It turns out the generated QNaN mantissa is actually what we want + opsel_r <= RES_MISC; + misc_sel <= "001"; if r.b.mantissa(UNIT_BIT + 1) = '1' then -- rounding up of the mantissa caused overflow, meaning the -- normalized B is 2.0. Since this is outside the range @@ -2740,10 +2734,22 @@ begin msel_2 <= MUL2_P; set_y := r.first; pshift := '1'; - f_to_multiply.valid <= r.first; + -- set shift to 64 + rs_con2 <= RSCON2_64; + if r.first = '1' then + if r.count = "11" then + if r.p(UNIT_BIT) = '0' and r.p(UNIT_BIT - 1) = '0' then + -- inverse estimate is < 0.5, so use 0.5 + v.state := IDIV_USE0_5; + else + v.state := IDIV_DODIV; + end if; + else + f_to_multiply.valid <= r.first; + end if; + end if; if multiply_to_f.valid = '1' then v.first := '1'; - v.count := r.count + 1; v.state := IDIV_NR2; end if; when IDIV_NR2 => @@ -2752,42 +2758,25 @@ begin msel_2 <= MUL2_P; f_to_multiply.valid <= r.first; pshift := '1'; - v.opsel_a := AIN_A; - -- set shift to 64 - rs_con2 <= RSCON2_64; - -- Get 0.5 into R in case the inverse estimate turns out to be - -- less than 0.5, in which case we want to use 0.5, to avoid - -- infinite loops in some cases. - opsel_r <= RES_MISC; - misc_sel <= "001"; + if r.first = '1' then + v.count := r.count + 1; + end if; if multiply_to_f.valid = '1' then v.first := '1'; - if r.count = "11" then - v.state := IDIV_DODIV; - else - v.state := IDIV_NR1; - end if; + v.state := IDIV_NR1; end if; when IDIV_USE0_5 => - -- Get 0.5 into R; it turns out the generated - -- QNaN mantissa is actually what we want - opsel_r <= RES_MISC; - misc_sel <= "001"; - v.opsel_a := AIN_A; + -- Put the 0.5 which is in R into Y as the inverse estimate + set_y := '1'; + msel_2 <= MUL2_R; -- set shift to 64 rs_con2 <= RSCON2_64; v.state := IDIV_DODIV; when IDIV_DODIV => - -- r.opsel_a = AIN_A -- r.shift = 64 - -- inverse estimate is in P or in R; copy it to Y - if r.b.mantissa(UNIT_BIT + 1) = '1' or - (r.p(UNIT_BIT) = '0' and r.p(UNIT_BIT - 1) = '0') then - msel_2 <= MUL2_R; - else - msel_2 <= MUL2_P; - end if; - set_y := '1'; + -- inverse estimate is in Y + -- put A (dividend) into R + opsel_a <= AIN_A; -- shift_res is 0 because r.shift = 64; -- put that into B, which now holds the quotient set_b_mant := '1'; @@ -2809,7 +2798,6 @@ begin else -- handle top bit of quotient specially -- for this we need the divisor left-justified in B - v.opsel_a := AIN_C; v.state := IDIV_EXT_TBH; end if; when IDIV_SH32 => @@ -2864,7 +2852,8 @@ begin msel_2 <= MUL2_P; v.inc_quot := not pcmpc_lt and not r.divmod; if r.divmod = '0' then - v.opsel_a := AIN_B; + -- get B into R for IDIV_DIVADJ state + opsel_a <= AIN_B; end if; -- set shift to UNIT_BIT (== 56) rs_con2 <= RSCON2_UNIT; @@ -2894,12 +2883,11 @@ begin -- r.shift = - b.exponent -- shift the quotient estimate right by b.exponent bits opsel_r <= RES_SHIFT; - v.opsel_a := AIN_B; v.first := '1'; v.state := IDIV_DIV7; when IDIV_DIV7 => - -- r.opsel_a = AIN_B -- add shifted quotient delta onto the total quotient + opsel_a <= AIN_B; opsel_b <= BIN_R; v.first := '1'; v.state := IDIV_DIV8; @@ -2923,12 +2911,11 @@ begin msel_1 <= MUL1_Y; msel_2 <= MUL2_P; v.inc_quot := not pcmpc_lt and not r.divmod; - if r.divmod = '0' then - v.opsel_a := AIN_B; - end if; -- set shift to UNIT_BIT (== 56) rs_con2 <= RSCON2_UNIT; if r.divmod = '0' then + -- get B into R for IDIV_DIVADJ state + opsel_a <= AIN_B; v.state := IDIV_DIVADJ; elsif pcmpc_eq = '1' then v.state := IDIV_ZERO; @@ -2936,16 +2923,17 @@ begin v.state := IDIV_MODADJ; end if; when IDIV_EXT_TBH => - -- r.opsel_a = AIN_C; get divisor into R and prepare to shift left + -- get divisor into R and prepare to shift left -- set shift to 63 - b.exp + opsel_a <= AIN_C; rs_sel1 <= RSH1_B; rs_neg1 <= '1'; rs_con2 <= RSCON2_63; - v.opsel_a := AIN_A; v.state := IDIV_EXT_TBH2; when IDIV_EXT_TBH2 => - -- r.opsel_a = AIN_A; divisor is in R + -- divisor is in R -- r.shift = 63 - b.exponent; shift and put into B + opsel_a <= AIN_A; set_b_mant := '1'; -- set shift to 64 - UNIT_BIT (== 8) rs_con2 <= RSCON2_64_UNIT; @@ -2966,13 +2954,13 @@ begin -- r.shift = 64 - B.exponent, so is at least 1 opsel_r <= RES_SHIFT; -- top bit of A gets lost in the shift, so handle it specially - v.opsel_a := AIN_B; -- set shift to 63 rs_con2 <= RSCON2_63; v.state := IDIV_EXT_TBH5; when IDIV_EXT_TBH5 => - -- r.opsel_a = AIN_B, r.shift = 63 + -- r.shift = 63 -- shifted dividend is in R, subtract left-justified divisor + opsel_a <= AIN_B; opsel_b <= BIN_R; opsel_ainv <= '1'; carry_in <= '1'; @@ -3004,15 +2992,14 @@ begin msel_2 <= MUL2_R; f_to_multiply.valid <= r.first; pshift := '1'; - v.opsel_a := AIN_B; opsel_r <= RES_MULT; if multiply_to_f.valid = '1' then v.first := '1'; v.state := IDIV_EXTDIV3; end if; when IDIV_EXTDIV3 => - -- r.opsel_a = AIN_B -- delta quotient is in R; add it to B + opsel_a <= AIN_B; opsel_b <= BIN_R; v.first := '1'; v.state := IDIV_EXTDIV4; @@ -3040,12 +3027,11 @@ begin opsel_r <= RES_SHIFT; -- test LS 64b of remainder in P against divisor in C v.inc_quot := not pcmpc_lt; - v.opsel_a := AIN_B; v.state := IDIV_EXTDIV6; when IDIV_EXTDIV6 => - -- r.opsel_a = AIN_B -- shifted remainder is in R, see if it is > 1 -- and compute R = R * Y if so + opsel_a <= AIN_B; msel_1 <= MUL1_Y; msel_2 <= MUL2_R; pshift := '1'; @@ -3060,7 +3046,6 @@ begin -- result is in R/S opsel_r <= RES_SHIFT; if pcmpc_lt = '0' then - v.opsel_a := AIN_C; v.state := IDIV_MODSUB; elsif r.result_sign = '0' then v.state := IDIV_DONE; @@ -3068,8 +3053,8 @@ begin v.state := IDIV_DIVADJ; end if; when IDIV_MODSUB => - -- r.opsel_a = AIN_C -- Subtract divisor from remainder + opsel_a <= AIN_C; opsel_ainv <= '1'; carry_in <= '1'; opsel_b <= BIN_R; @@ -3079,7 +3064,7 @@ begin v.state := IDIV_DIVADJ; end if; when IDIV_DIVADJ => - -- result (so far) is on the A input of the adder + -- result (so far) is in R -- set carry to increment quotient if needed -- and also negate R if the answer is negative opsel_ainv <= r.result_sign; @@ -3274,7 +3259,7 @@ begin if (or (mask and r.r)) = '1' and set_x = '1' then v.x := '1'; end if; - case r.opsel_a is + case opsel_a is when AIN_R => in_a0 := r.r; when AIN_A => @@ -3379,7 +3364,9 @@ begin end case; result <= misc; end case; - v.r := result; + if set_r = '1' then + v.r := result; + end if; if set_s = '1' then case opsel_s is when S_NEG =>