I'm including my own updates, although several unfixed denormal bugs have
been found, and we have some clever hacks to make multiply handle denormal
as well. More code in next two emails
/*
Copyright 2013, Timothy Normand Miller, all rights reserved.
*/
`include "defines.v"
// 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:0] difA, difB;
assign difA = expA - expB;
assign difB = expB - expA;
always @(posedge clock) begin
expA_m_expB <= difA[EXPONENT_SIZE-1:0];
expB_m_expA <= difB[EXPONENT_SIZE-1:0];
A_lt_B <= difA[EXPONENT_SIZE];
B_lt_A <= difB[EXPONENT_SIZE];
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:0] dif;
assign dif = mantA - mantB;
always @(posedge clock) begin
AltB <= dif[MANTISSA_SIZE];
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.
// Also, mux in integer operands
// So that the multiplier can be used for both int and float,
// the mantissa is represented as 33 bits here to distinglish signed
// from unsigned mul.
module swap_mux(
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,
input integer_op,
input [32:0] intA,
input [32:0] intB,
output reg [32:0] mantA,
output reg [32:0] mantB,
output reg signA,
output reg signB,
output reg [DEN_EXPONENT_SIZE-1:0] expA,
output reg [DEN_EXPONENT_SIZE-1:0] expB);
wire do_swap = expA_lt_expB || (!expB_lt_expA && mantA_lt_mantB);
always @(posedge clock) begin
if (integer_op) begin
// For integer op, substitute integer operands for multiply
mantA <= intA;
mantB <= intB;
end else begin
mantA <= do_swap ? inB[DEN_MANTISSA] : inA[DEN_MANTISSA];
mantB <= do_swap ? inA[DEN_MANTISSA] : inB[DEN_MANTISSA];
end
signA <= do_swap ? inB[DEN_SIGN] : inA[DEN_SIGN];
signB <= do_swap ? inA[DEN_SIGN] : inB[DEN_SIGN];
expA <= do_swap ? inB[DEN_EXPONENT] : inA[DEN_EXPONENT];
expB <= do_swap ? inA[DEN_EXPONENT] : inB[DEN_EXPONENT];
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 [EXPONENT_SIZE-1:0] shift_amt,
input [EXPONENT_SIZE-1:0] expA,
output reg [GRS_MANTISSA_SIZE-1:0] mantB,
output reg signB);
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
// Probably not the best way to compute this
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
mantB <= {shifted[GRS_MANTISSA_SIZE-1:1], sticky_bit};
signB <= 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,
input [7:0] max_shift,
output reg [4:0] left,
output reg right);
integer i, shift;
// Need a better way to implement priority encoder with maximum result
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 > max_shift) ? max_shift : 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-1:4];
expAout <= expAin + 1;
end else begin
mantAout <= mantAin[GRS_MANTISSA_SIZE-2:3];
expAout <= expAin;
end
end
endmodule
// Finally, renormalize the result. No special handling for denormalized
// numbers, but will turn overflows into infinities.
module renormalize(
input clock,
input [DEN_MANTISSA_SIZE-1:0] mantAin,
input [DEN_EXPONENT_SIZE-1:0] expAin,
input underflow,
output reg [MANTISSA_SIZE-1:0] mantAout
output reg [EXPONENT_SIZE-1:0] expAout,
output reg overflow,
output reg zero);
wire ovl = expAin >= 255;
always @(posedge clock) begin
overflow <= ovl;
if (underflow) begin
mantAout <= 0;
expAout <= 0;
zero <= 1;
end
if (ovl) begin
mantAout <= 0;
expAout <= 255;
zero <= 0;
end else begin
mantAout <= mantAin;
expAout <= expAin;
zero <= 0 == expAin[EXPONENT_SIZE-1:0];
end
end
endmodule
--
Timothy Normand Miller, PhD
Assistant Professor of Computer Science, Binghamton University
http://www.cs.binghamton.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)