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)

Reply via email to