// ============================================================================
|
// ============================================================================
|
// __
|
// __
|
// \\__/ o\ (C) 2006-2016 Robert Finch, Waterloo
|
// \\__/ o\ (C) 2006-2019 Robert Finch, Waterloo
|
// \ __ / All rights reserved.
|
// \ __ / All rights reserved.
|
// \/_// robfinch<remove>@finitron.ca
|
// \/_// robfinch<remove>@finitron.ca
|
// ||
|
// ||
|
//
|
//
|
// f2i.v
|
// f2i.v
|
// - convert floating point to integer
|
// - convert floating point to integer
|
// - single cycle latency floating point unit
|
// - single cycle latency floating point unit
|
// - parameterized width
|
// - parameterized width
|
// - IEEE 754 representation
|
// - IEEE 754 representation
|
//
|
//
|
//
|
//
|
// This source file is free software: you can redistribute it and/or modify
|
// This source file is free software: you can redistribute it and/or modify
|
// it under the terms of the GNU Lesser General Public License as published
|
// it under the terms of the GNU Lesser General Public License as published
|
// by the Free Software Foundation, either version 3 of the License, or
|
// by the Free Software Foundation, either version 3 of the License, or
|
// (at your option) any later version.
|
// (at your option) any later version.
|
//
|
//
|
// This source file is distributed in the hope that it will be useful,
|
// This source file is distributed in the hope that it will be useful,
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
//
|
//
|
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
//
|
//
|
// i2f - convert integer to floating point
|
// i2f - convert integer to floating point
|
// f2i - convert floating point to integer
|
// f2i - convert floating point to integer
|
//
|
//
|
// ============================================================================
|
// ============================================================================
|
|
|
module f2i
|
module f2i
|
#( parameter WID = 32)
|
#( parameter WID = 32)
|
(
|
(
|
input clk,
|
input clk,
|
input ce,
|
input ce,
|
input [WID-1:0] i,
|
input [WID-1:0] i,
|
output [WID-1:0] o,
|
output [WID-1:0] o,
|
output overflow
|
output overflow
|
);
|
);
|
localparam MSB = WID-1;
|
`include "fpSize.sv"
|
localparam EMSB = WID==128 ? 14 :
|
|
WID==96 ? 14 :
|
|
WID==80 ? 14 :
|
|
WID==64 ? 10 :
|
|
WID==52 ? 10 :
|
|
WID==48 ? 10 :
|
|
WID==44 ? 10 :
|
|
WID==42 ? 10 :
|
|
WID==40 ? 9 :
|
|
WID==32 ? 7 :
|
|
WID==24 ? 6 : 4;
|
|
localparam FMSB = WID==128 ? 111 :
|
|
WID==96 ? 79 :
|
|
WID==80 ? 63 :
|
|
WID==64 ? 51 :
|
|
WID==52 ? 39 :
|
|
WID==48 ? 35 :
|
|
WID==44 ? 31 :
|
|
WID==42 ? 29 :
|
|
WID==40 ? 28 :
|
|
WID==32 ? 22 :
|
|
WID==24 ? 15 : 9;
|
|
|
|
|
|
wire [MSB:0] maxInt = {MSB{1'b1}}; // maximum unsigned integer value
|
wire [MSB:0] maxInt = {MSB{1'b1}}; // maximum unsigned integer value
|
wire [EMSB:0] zeroXp = {EMSB{1'b1}}; // simple constant - value of exp for zero
|
wire [EMSB:0] zeroXp = {EMSB{1'b1}}; // simple constant - value of exp for zero
|
|
|
// Decompose fp value
|
// Decompose fp value
|
reg sgn; // sign
|
reg sgn; // sign
|
always @(posedge clk)
|
always @(posedge clk)
|
if (ce) sgn = i[MSB];
|
if (ce) sgn = i[MSB];
|
wire [EMSB:0] exp = i[MSB-1:FMSB+1]; // exponent
|
wire [EMSB:0] exp = i[MSB-1:FMSB+1]; // exponent
|
wire [FMSB+1:0] man = {exp!=0,i[FMSB:0]}; // mantissa including recreate hidden bit
|
wire [FMSB+1:0] man = {exp!=0,i[FMSB:0]}; // mantissa including recreate hidden bit
|
|
|
wire iz = i[MSB-1:0]==0; // zero value (special)
|
wire iz = i[MSB-1:0]==0; // zero value (special)
|
|
|
assign overflow = exp - zeroXp > MSB; // lots of numbers are too big - don't forget one less bit is available due to signed values
|
assign overflow = exp - zeroXp > MSB; // lots of numbers are too big - don't forget one less bit is available due to signed values
|
wire underflow = exp < zeroXp - 1; // value less than 1/2
|
wire underflow = exp < zeroXp - 1; // value less than 1/2
|
|
|
wire [7:0] shamt = MSB - (exp - zeroXp); // exp - zeroXp will be <= MSB
|
wire [7:0] shamt = MSB - (exp - zeroXp); // exp - zeroXp will be <= MSB
|
|
|
wire [MSB+1:0] o1 = {man,{EMSB+1{1'b0}},1'b0} >> shamt; // keep an extra bit for rounding
|
wire [MSB+1:0] o1 = {man,{EMSB+1{1'b0}},1'b0} >> shamt; // keep an extra bit for rounding
|
wire [MSB:0] o2 = o1[MSB+1:1] + o1[0]; // round up
|
wire [MSB:0] o2 = o1[MSB+1:1] + o1[0]; // round up
|
reg [MSB:0] o3;
|
reg [MSB:0] o3;
|
|
|
always @(posedge clk)
|
always @(posedge clk)
|
if (ce) begin
|
if (ce) begin
|
if (underflow|iz)
|
if (underflow|iz)
|
o3 <= 0;
|
o3 <= 0;
|
else if (overflow)
|
else if (overflow)
|
o3 <= maxInt;
|
o3 <= maxInt;
|
// value between 1/2 and 1 - round up
|
// value between 1/2 and 1 - round up
|
else if (exp==zeroXp-1)
|
else if (exp==zeroXp-1)
|
o3 <= 1;
|
o3 <= 1;
|
// value > 1
|
// value > 1
|
else
|
else
|
o3 <= o2;
|
o3 <= o2;
|
end
|
end
|
|
|
assign o = sgn ? -o3 : o3; // adjust output for correct signed value
|
assign o = sgn ? -o3 : o3; // adjust output for correct signed value
|
|
|
endmodule
|
endmodule
|
|
|
module f2i_tb();
|
module f2i_tb();
|
|
|
wire ov0,ov1;
|
wire ov0,ov1;
|
wire [31:0] io0,io1;
|
wire [31:0] io0,io1;
|
reg clk;
|
reg clk;
|
|
|
initial begin
|
initial begin
|
clk = 0;
|
clk = 0;
|
end
|
end
|
|
|
always #10 clk = ~clk;
|
always #10 clk = ~clk;
|
|
|
f2i #(32) u1 (.clk(clk), .ce(1'b1), .i(32'h3F800000), .o(io1), .overflow(ov1) );
|
f2i #(32) u1 (.clk(clk), .ce(1'b1), .i(32'h3F800000), .o(io1), .overflow(ov1) );
|
f2i #(32) u2 (.clk(clk), .ce(1'b1), .i(32'h00000000), .o(io0), .overflow(ov0) );
|
f2i #(32) u2 (.clk(clk), .ce(1'b1), .i(32'h00000000), .o(io0), .overflow(ov0) );
|
f2i #(80) u3 (.clk(clk), .ce(1'b1), .i(80'h3FF80000000000000000), .o(io1), .overflow(ov1) );
|
f2i #(80) u3 (.clk(clk), .ce(1'b1), .i(80'h3FF80000000000000000), .o(io1), .overflow(ov1) );
|
|
|
endmodule
|
endmodule
|
|
|