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)