📄 floating_point.v.bak
字号:
// floating point system devised by Bruce Land for ECE 5760
//////////////////////////////////////////////////////////
// floating point multiply
// -- sign bit -- 8-bit exponent -- 9-bit mantissa
// Similar to fp_mult from altera
// NO denorms, no flags, no NAN, no infinity, no rounding!
//////////////////////////////////////////////////////////
// f1 = {s1, e1, m1), f2 = {s2, e2, m2)
// If either is zero (zero MSB of mantissa) then output is zero
// If e1+e2<129 the result is zero (underflow)
///////////////////////////////////////////////////////////
module fpmult (fout, f1, f2);
input [17:0] f1, f2 ;
output [17:0] fout ;
wire [17:0] fout ;
reg sout ;
reg [8:0] mout ;
reg [8:0] eout ; // 9-bits for overflow
wire s1, s2;
wire [8:0] m1, m2 ;
wire [8:0] e1, e2, sum_e1_e2 ; // extend to 9 bits to avoid overflow
wire [17:0] mult_out ; // raw multiplier output
// parse f1
assign s1 = f1[17]; // sign
assign e1 = {1'b0, f1[16:9]}; // exponent
assign m1 = f1[8:0] ; // mantissa
// parse f2
assign s2 = f2[17];
assign e2 = {1'b0, f2[16:9]};
assign m2 = f2[8:0] ;
// first step in mult is to add extended exponents
assign sum_e1_e2 = e1 + e2 ;
// build output
// raw integer multiply
unsigned_mult mm(mult_out, m1, m2);
// assemble output bits
assign fout = {sout, eout[7:0], mout} ;
always @(*)
begin
// if either is denormed or exponents are too small
if ((m1[8]==1'd0) || (m2[8]==1'd0) || (sum_e1_e2 < 9'h82))
begin
mout = 0;
eout = 0;
sout = 0; // output sign
end
else // both inputs are nonzero and no exponent underflow
begin
sout = s1 ^ s2 ; // output sign
if (mult_out[17]==1)
begin // MSB of product==1 implies normalized -- result >=0.5
eout = sum_e1_e2 - 9'h80;
mout = mult_out[17:9] ;
end
else // MSB of product==0 implies result <0.5, so shift ome left
begin
eout = sum_e1_e2 - 9'h81;
mout = mult_out[16:8] ;
end
end // nonzero mult logic
end // always @(*)
endmodule
///////////////////////////////////////
// low level integer multiply
// From Altera HDL style manual
///////////////////////////////////////
module unsigned_mult (out, a, b);
output [17:0] out;
input [8:0] a;
input [8:0] b;
assign out = a * b;
endmodule
/////////////////////////////////////////////////////////////////////////////
// floating point Add
// -- sign bit -- 8-bit exponent -- 9-bit mantissa
// NO denorms, no flags, no NAN, no infinity, no rounding!
/////////////////////////////////////////////////////////////////////////////
// f1 = {s1, e1, m1), f2 = {s2, e2, m2)
// If either input is zero (zero MSB of mantissa) then output is the remaining input.
// If either input is <(other input)/2**9 then output is the remaining input.
// Sign of the output is the sign of the greater magnitude input
// Add the two inputs if their signs are the same.
// Subtract the two inputs (bigger-smaller) if their signs are different
//////////////////////////////////////////////////////////////////////////////
module fpadd (fout, f1, f2);
input [17:0] f1, f2 ;
output [17:0] fout ;
wire [17:0] fout ;
wire sout ;
reg [8:0] mout ;
reg [7:0] eout ;
reg [9:0] shift_small, denorm_mout ; //9th bit is overflow bit
wire s1, s2 ; // input signs
reg sb, ss ; // signs of bigger and smaller
wire [8:0] m1, m2 ; // input mantissas
reg [8:0] mb, ms ; // mantissas of bigger and smaller
wire [7:0] e1, e2 ; // input exp
wire [7:0] ediff ; // exponent difference
reg [7:0] eb, es ; // exp of bigger and smaller
reg [7:0] num_zeros ; // high order zeros in the difference calc
// parse f1
assign s1 = f1[17]; // sign
assign e1 = f1[16:9]; // exponent
assign m1 = f1[8:0] ; // mantissa
// parse f2
assign s2 = f2[17];
assign e2 = f2[16:9];
assign m2 = f2[8:0] ;
// find biggest magnitude
always @(*)
begin
if (e1>e2) // f1 is bigger
begin
sb = s1 ; // the bigger number (absolute value)
eb = e1 ;
mb = m1 ;
ss = s2 ; // the smaller number
es = e2 ;
ms = m2 ;
end
else if (e2>e1) //f2 is bigger
begin
sb = s2 ; // the bigger number (absolute value)
eb = e2 ;
mb = m2 ;
ss = s1 ; // the smaller number
es = e1 ;
ms = m1 ;
end
else // e1==e2, so need to look at mantissa to determine bigger/smaller
begin
if (m1>m2) // f1 is bigger
begin
sb = s1 ; // the bigger number (absolute value)
eb = e1 ;
mb = m1 ;
ss = s2 ; // the smaller number
es = e2 ;
ms = m2 ;
end
else // f2 is bigger or same size
begin
sb = s2 ; // the bigger number (absolute value)
eb = e2 ;
mb = m2 ;
ss = s1 ; // the smaller number
es = e1 ;
ms = m1 ;
end
end
end //found the bigger number
// sign of output is the sign of the bigger (magnitude) input
assign sout = (f1[8:0] == 0 && f2[8:0] == 0) ? 0 : sb ;
// form the output
assign fout = {sout, eout, mout} ;
// do the actual add:
// -- equalize exponents
// -- add/sub
// -- normalize
assign ediff = eb - es ; // the actual difference in exponents
always @(*)
begin
if ((ms[8]==0) && (mb[8]==0)) // both inputs are zero
begin
mout = 9'b0 ;
eout = 8'b0 ;
end
else if ((ms[8]==0) || ediff>8) // smaller is too small to matter
begin
mout = mb ;
eout = eb ;
end
else // shift/add/normalize
begin
// now shift but save the low order bits by extending the registers
// need a high order bit for 1.0<sum<2.0
shift_small = {1'b0, ms} >> ediff ;
// same signs means add -- different means subtract
if (sb==ss) //do the add
begin
denorm_mout = {1'b0, mb} + shift_small ;
// normalize --
// when adding result has to be 0.5<sum<2.0
if (denorm_mout[9]==1) // sum bigger than 1
begin
mout = denorm_mout[9:1] ; // take the top bits (shift-right)
eout = eb + 1 ; // compensate for the shift-right
end
else //0.5<sum<1.0
begin
mout = denorm_mout[8:0] ; // drop the top bit (no-shift-right)
eout = eb ; //
end
end // end add logic
else // otherwise sb!=ss, so subtract
begin
denorm_mout = {1'b0, mb} - shift_small ;
// the denorm_mout is always smaller then the bigger input
// (and never an overflow, so bit 9 is always zero)
// and can be as low as zero! Thus up to 8 shifts may be necessary
// to normalize denorm_mout
if (denorm_mout[8:0]==9'd0)
begin
mout = 9'b0 ;
eout = 8'b0 ;
end
else
begin
// detect leading zeros
casex (denorm_mout[8:0])
9'b1xxxxxxxx: num_zeros = 8'd0 ;
9'b01xxxxxxx: num_zeros = 8'd1 ;
9'b001xxxxxx: num_zeros = 8'd2 ;
9'b0001xxxxx: num_zeros = 8'd3 ;
9'b00001xxxx: num_zeros = 8'd4 ;
9'b000001xxx: num_zeros = 8'd5 ;
9'b0000001xx: num_zeros = 8'd6 ;
9'b00000001x: num_zeros = 8'd7 ;
9'b000000001: num_zeros = 8'd8 ;
default: num_zeros = 8'd9 ;
endcase
// shift out leading zeros
// and adjust exponent
eout = eb - num_zeros ;
mout = denorm_mout[8:0] << num_zeros ;
end
end // end subtract logic
// format the output
//fout = {sout, eout, mout} ;
end // end shift/add(sub)/normailize/
end // always @(*) to compute sum/diff
endmodule
/////////////////////////////////////////////////////////////////////////////
// integer to floating point
// input: 10-bit signed integer and scale factor (-100 to +100) powers of 2
// output: -- sign bit -- 8-bit exponent -- 9-bit mantissa
// fp_out = {sign, exp, mantissa}
// NO denorms, no flags, no NAN, no infinity, no rounding!
/////////////////////////////////////////////////////////////////////////////
module int2fp(fp_out, int_in, scale_in) ;
input signed [9:0] int_in ;
input signed [7:0] scale_in ;
output wire [17:0] fp_out ;
wire [9:0] abs_int ;
reg sign ;
reg [8:0] mout ; // mantissa
reg [7:0] eout ; // exponent
reg [7:0] num_zeros ; // count leading zeros in input integer
// get absolute value of int_in
assign abs_int = (int_in[9])? (~int_in)+10'd1 : int_in ;
// build output
assign fp_out = {sign, eout, mout} ;
// detect leading zeros of absolute value
// detect leading zeros
// normalize and form exponent including leading zero shift and scaling
always @(*)
begin
if (abs_int[8:0] == 0)
begin // zero value
eout = 0 ;
mout = 0 ;
sign = 0 ;
num_zeros = 8'd0 ;
end
else // not zero
begin
casex (abs_int[8:0])
9'b1xxxxxxxx: num_zeros = 8'd0 ;
9'b01xxxxxxx: num_zeros = 8'd1 ;
9'b001xxxxxx: num_zeros = 8'd2 ;
9'b0001xxxxx: num_zeros = 8'd3 ;
9'b00001xxxx: num_zeros = 8'd4 ;
9'b000001xxx: num_zeros = 8'd5 ;
9'b0000001xx: num_zeros = 8'd6 ;
9'b00000001x: num_zeros = 8'd7 ;
9'b000000001: num_zeros = 8'd8 ;
default: num_zeros = 8'd9 ;
endcase
mout = abs_int[8:0] << num_zeros ;
eout = scale_in + (8'h89 - num_zeros) ; // h80 is offset, h09 normalizes
sign = int_in[9] ;
end // if int_in!=0
end // always @
endmodule
/////////////////////////////////////////////////////////////////////////////
// floating point to integer
// output: 10-bit signed integer
// input: -- sign bit -- 8-bit exponent -- 9-bit mantissa
// and scale factor (-100 to +100) powers of 2
// fp_out = {sign, exp, mantissa}
// NO denorms, no flags, no NAN, no infinity, no rounding!
/////////////////////////////////////////////////////////////////////////////
module fp2int(int_out, fp_in, scale_in) ;
output signed [9:0] int_out ;
input signed [7:0] scale_in ;
input wire [17:0] fp_in ;
wire [9:0] abs_int ;
wire sign ;
wire [8:0] m_in ; // mantissa
wire [7:0] e_in ; // exponent
//reg [7:0] num_zeros ; // count leading zeros in input integer
assign sign = (m_in[8])? fp_in[17] : 1'h0 ;
assign m_in = fp_in[8:0] ;
assign e_in = fp_in[16:9] ;
//
assign abs_int = (e_in>8'h80)? (m_in >> (8'h89 - e_in)) : 10'd0 ;
//assign int_out = (m_in[8])? {sign, (sign? (~abs_int)+9'd1 : abs_int)} : 10'd0 ;
assign int_out = (sign? (~abs_int)+10'd1 : abs_int) ;
//assign int_out = {sign, sign? (~abs_int)+9'd1 : abs_int} ;
endmodule
/////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -