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)
