For some comparisons, check out: http://www.gaisler.com/doc/grfpu_dasia.pdf
http://opencores.org/project,fpu Are we looking to have full IEEE floating point, or a subset of IEEE? Once there is enough code to do add/subtract/multiply I'd like to write a regression test that runs a couple of floating point validation tools. On Mon, Jan 07, 2013 at 03:58:12PM +0100, Mark Marshall wrote: > Hi. > > I've only had a quick scan of this code, but I'm not sure I agree with it. > > I thought that the exponent was an 8-bit unsigned number? In that case > sub_exponent is wrong - it should extend the exponents to 9 bits before > doing the subtraction. For example: > > A = 0x88 > B = 0x03 > > A - B = 0x85 > > (A - B)[7] is 1, so your routine would report this as A < B. > > Best regards, > > Mark M. > > On 6 January 2013 21:30, Timothy Normand Miller <[email protected]> wrote: > > > I'll check this into the git repo when we have the IP stuff worked out. > > I've got most of the add/sub stuff worked out and some of multiply. The > > multiplier itself is in another module already. I just need to wrap all > > this into another level of hierarchy. > > > > Let's have a contest to see who can find the most mistakes. :) > > > > > > > > > > /* > > Copyright 2013, Timothy Normand Miller, all rights reserved. > > For now. > > */ > > > > > > // Fields for normalized numbers > > `define MANTISSA_SIZE 23 > > `define EXPONENT_SIZE 8 > > `define MANTISSA 22:0 > > `define EXPONENT 30:23 > > `define SIGN 31 > > `define FP_SIZE 32 > > > > // Fields for denormalized numbers > > // One extra exponent bit for exponent overflow > > `define DEN_MANTISSA_SIZE 24 > > `define DEN_MANTISSA 23:0 > > `define DEN_EXPONENT 32:24 > > `define DEN_EXPONENT_SIZE 9 > > `define DEN_SIGN 33 > > `define DEN_FP_SIZE 34 > > > > // Fields for denormalized numbers with GRS and overflow bits > > `define GRS_MANTISSA_SIZE 28 > > `define GRS_MANTISSA 27:0 > > `define GRS_EXPONENT 36:28 > > `define GRS_EXPONENT_SIZE 9 > > `define GRS_SIGN 37 > > `define GRS_FP_SIZE 38 > > > > > > // Compare exponents and compute differences. When subtracting, we need > > // to know which operand is greater, so we always subtract smaller from > > // greater. We compare exponents by subtracting. Which difference is > > // negative tells us whether or not to swap, while the other difference > > // indicates how far right to shift the lesser mantissa. > > module sub_exponent( > > input clock, > > input [EXPONENT_SIZE-1:0] expA, > > input [EXPONENT_SIZE-1:0] expB, > > output reg [EXPONENT_SIZE-1:0] expA_m_expB, > > output reg [EXPONENT_SIZE-1:0] expB_m_expA, > > output reg A_lt_B, > > output reg B_lt_A); > > > > wire [EXPONENT_SIZE-1:0] difA, difB; > > assign difA = expA - expB; > > assign difB = expB - expA; > > > > always @(posedge clock) begin > > expA_m_expB <= difA; > > expB_m_expA <= difB; > > A_lt_B <= difA[EXPONENT_SIZE-1]; > > B_lt_A <= difB[EXPONENT_SIZE-1]; > > end > > > > endmodule > > > > > > > > > > // Compare mantissas. If the exponents are equal, then we need to compare > > // the mantissas to see which operand is smaller. We only need one > > difference, > > // because we're not going to reuse the number for any other purpose. > > module lt_mantissa( > > input clock, > > input [MANTISSA_SIZE-1:0] mantA, > > input [MANTISSA_SIZE-1:0] mantB, > > output reg AltB); > > > > wire [MANTISSA_SIZE-1:0] dif; > > assign dif = mantA - mantB; > > > > always @(posedge clock) begin > > AltB <= dif[MANTISSA_SIZE-1]; > > end > > > > endmodule > > > > > > > > > > // For products, need to compute new exponents and signs. > > // We compute a 10-bit signed exponent, to detect underflow > > module product_exponents( > > input clock, > > input [EXPONENT_SIZE-1:0] expA, > > input [EXPONENT_SIZE-1:0] expB, > > input signA, > > input signB, > > output reg [DEN_EXPONENT_SIZE-1:0] expC, > > output reg signC, > > output reg underflow); > > > > always @(posedge clock) begin > > {underflow, expC} <= (expA + expB) - 127; > > signC <= signA ^ signB; > > end > > > > endmodule > > > > > > > > > > // The mantissa has a hidden bit. If the exponent is zero, that bit is > > zero; > > // if the exponent is nonzero, that bit is 1. > > module denormalize( > > input clock, > > input [31:0] A, > > output reg signA, > > output reg [EXPONENT_SIZE-1:0] expA, > > output reg [DEN_MANTISSA_SIZE-1:0] mantA); > > > > wire high_bit = (0 != A[EXPONENT]); > > > > always @(posedge clock) begin > > signA <= A[SIGN]; > > expA <= A[EXPONENT]; > > mantA <= {high_bit, A[MANTISSA]}; > > end > > > > endmodule > > > > > > > > > > // If the "B" operand is greater, need to swap the values for stages > > // down in the pipeline. > > module swap( > > input clock, > > input [DEN_FP_SIZE-1:0] inA, > > input [DEN_FP_SIZE-1:0] inB, > > input expA_lt_expB, > > input expB_lt_expA, > > input mantA_lt_mantB, > > output reg [DEN_FP_SIZE-1:0] outA, > > output reg [DEN_FP_SIZE-1:0] outB); > > > > wire do_swap = expA_lt_expB || (!expB_lt_expA && mantA_lt_mantB); > > > > always @(posedge clock) begin > > outA <= do_swap ? inB : inA; > > outB <= do_swap ? inA : inB; > > end > > > > endmodule > > > > > > > > // Based on the differences calculated earlier, shift the B mantissa > > // right. Now, both exponents are the same, so we keep track of only one. > > module right_shift_mantissa( > > input clock, > > input [DEN_FP_SIZE-1:0] inB, > > input [4:0] shift_amt, > > input [EXPONENT_SIZE-1] expA, > > output reg [GRS_FP_SIZE-1:0] outB); > > > > wire [GRS_MANTISSA_SIZE-1:0] mantissa = {inB[DEN_MANTISSA], 3'b0}; > > wire [GRS_MANTISSA_SIZE-1:0] shifted = mantissa >> shift_amt; > > > > reg sticky_bit; > > integer i; > > > > always @(mantissa or shift_amt) begin > > sticky_bit = 0; > > for (i=0; i<shift_amt; i=i+1) begin > > if (mantissa[i]) sticky_bit = 1; > > end > > end > > > > always @(posedge clock) begin > > outB[GRS_MANTISSA] <= {shifted[GRS_MANTISSA_SIZE-1:1], sticky_bit}; > > outB[GRS_EXPONENT] <= expA; > > outB[GRS_SIGN] <= inB[DEN_SIGN]; > > end > > > > endmodule > > > > > > > > // Depending on signs and the operation, we'll add or subtract the > > // operands. > > module addsub_mantissas( > > input clock, > > input [GRS_MANTISSA_SIZE-1:0] mantA, > > input [GRS_MANTISSA_SIZE-1:0] mantB, > > input sub, > > output reg [GRS_MANTISSA_SIZE-1:0] sum); > > > > wire [GRS_MANTISSA_SIZE-1:0] subtrahend; > > assign subtrahend = {GRS_MANTISSA_SIZE{sub}} ^ mantB; > > > > wire [GRS_MANTISSA_SIZE:0] dif; > > assign dif = {mantA, 1'b1} + {subtrahend, sub}; > > > > always @(posedge clock) begin > > sum <= dif[GRS_MANTISSA_SIZE:1]; > > end > > > > endmodule > > > > > > // Compute the left or right shift necessary to get the highest 1 bit > > // one to the right of the overflow bit. On right shift, left will be > > // invalid. > > module compute_shift( > > input clock, > > input [GRS_MANTISSA_SIZE-1:0] inA, > > output reg [4:0] left, > > output reg right); > > > > integer i, shift; > > > > always @(inA) begin > > shift = 0; > > for (i=0; i<GRS_MANTISSA_SIZE-1; i=i+1) begin > > if (inA[i]) shift = GRS_MANTISSA_SIZE - 2 - i; > > end > > end > > > > always @(posedge clock) begin > > right <= inA[GRS_MANTISSA_SIZE-1]; > > left <= shift; > > end > > > > endmodule > > > > > > > > // Clamp the shift amount so that we don't get a negative exponent. > > module clamp_shift( > > input clock, > > input [4:0] left_in, > > input [7:0] exp_in, > > output [4:0] left_out); > > > > always @(posedge clock) begin > > if (left_in <= exp_in) begin > > left_out <= left_in; > > end else begin > > left_out <= exp_in; > > end > > end > > > > endmodule > > > > > > > > // Shift the mantissa right or left to get highest bit into denormalization > > // bit position. > > module perform_shift( > > input clock, > > input [GRS_MANTISSA_SIZE-1:0] mantAin, > > input [GRS_EXPONENT_SIZE-1:0] expAin, > > input [4:0] left, > > input right, > > output reg [GRS_MANTISSA_SIZE-1:0] mantAout > > output reg [GRS_EXPONENT_SIZE-1:0] expAout); > > > > always @(posedge clock) begin > > if (right) begin > > mantAout <= mantAin[GRS_MANTISSA_SIZE-1:1]; > > expAout <= expAin + 1; > > end else begin > > mantAout <= mantAin << left; > > expAout <= expAin - left; > > end > > end > > > > endmodule > > > > > > > > // Use the GRS and lowest significant bits to compute rounding. > > module round( > > input clock, > > input [GRS_MANTISSA_SIZE-1:0] inA, > > output reg [GRS_MANTISSA_SIZE-1:0] outA); > > > > // Round up if the GRS bits > 4. If the GRS==4, then break tie using > > // lowest significant bit. > > wire do_round = (inA[2:0] > 4) || (inA[2] && inA[3]); > > > > always @(posedge clock) begin > > outA[2:0] <= 0; > > outA[GRS_MANTISSA_SIZE-1:3] <= inA[GRS_MANTISSA_SIZE-1:3] + do_round; > > end > > > > endmodule > > > > > > > > // Rounding may have a carry out. In this case we have to shift right > > // once more. > > module round_overflow_shift( > > input clock, > > input [GRS_MANTISSA_SIZE-1:0] mantAin, > > input [GRS_EXPONENT_SIZE-1:0] expAin, > > output reg [DEN_MANTISSA_SIZE-1:0] mantAout > > output reg [DEN_EXPONENT_SIZE-1:0] expAout); > > > > always @(posedge clock) begin > > if (mantAin[GRS_MANTISSA_SIZE-1]) begin > > mantAout <= mantAin[GRS_MANTISSA_SIZE-2:3]; > > expAout <= expAin + 1; > > end else begin > > mantAout <= mantAin[GRS_MANTISSA_SIZE-1:4]; > > expAout <= expAin; > > end > > end > > > > endmodule > > > > > > > > // Finally, renormalize the result. No special handling for denormalized > > // numbers, but well turn overflows into infinities. > > module renormalize( > > input clock, > > input [DEN_MANTISSA_SIZE-1:0] mantAin, > > input [DEN_EXPONENT_SIZE-1:0] expAin, > > output reg [MANTISSA_SIZE-1:0] mantAout > > output reg [EXPONENT_SIZE-1:0] expAout, > > output reg overflow); > > > > wire ovl = expAin >= 255; > > > > always @(posedge clock) begin > > overflow <= ovl; > > if (ovl) begin > > mantAout <= 0; > > expAout <= 255; > > end else begin > > mantAout <= mantAin; > > expAout <= expAin; > > end > > end > > > > endmodule > > > > > > > > -- > > Timothy Normand Miller, PhD > > Assistant Professor of Computer Science, Binghamton University > > http://www.cs.binghamton.edu/~millerti/<http://www.cse.ohio-state.edu/~millerti> > > Open Graphics Project > > > > _______________________________________________ > > Open-graphics mailing list > > [email protected] > > http://lists.duskglow.com/mailman/listinfo/open-graphics > > List service provided by Duskglow Consulting, LLC (www.duskglow.com) > > > _______________________________________________ > Open-graphics mailing list > [email protected] > http://lists.duskglow.com/mailman/listinfo/open-graphics > List service provided by Duskglow Consulting, LLC (www.duskglow.com) -- -------------------------------------------------------------------------- Troy Benjegerdes 'da hozer' [email protected] Somone asked my why I work on this free (http://www.fsf.org/philosophy/) software & hardware (http://q3u.be) stuff and not get a real job. Charles Shultz had the best answer: "Why do musicians compose symphonies and poets write poems? They do it because life wouldn't have any meaning for them if they didn't. That's why I draw cartoons. It's my life." -- Charles Shultz _______________________________________________ Open-graphics mailing list [email protected] http://lists.duskglow.com/mailman/listinfo/open-graphics List service provided by Duskglow Consulting, LLC (www.duskglow.com)
