OpenCores
URL https://opencores.org/ocsvn/thor/thor/trunk

Subversion Repositories thor

[/] [thor/] [trunk/] [FT64v5/] [rtl/] [fpUnit/] [i2f.v] - Blame information for rev 51

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 51 robfinch
// ============================================================================
2
//        __
3
//   \\__/ o\    (C) 2006-2016  Robert Finch, Waterloo
4
//    \  __ /    All rights reserved.
5
//     \/_//     robfinch<remove>@finitron.ca
6
//       ||
7
//
8
//      i2f.v
9
//  - convert integer to floating point
10
//  - parameterized width
11
//  - IEEE 754 representation
12
//  - pipelineable
13
//  - single cycle latency
14
//
15
// This source file is free software: you can redistribute it and/or modify 
16
// it under the terms of the GNU Lesser General Public License as published 
17
// by the Free Software Foundation, either version 3 of the License, or     
18
// (at your option) any later version.                                      
19
//                                                                          
20
// This source file is distributed in the hope that it will be useful,      
21
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
22
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
23
// GNU General Public License for more details.                             
24
//                                                                          
25
// You should have received a copy of the GNU General Public License        
26
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
27
//                                                                          
28
// ============================================================================
29
 
30
module i2f
31
#(      parameter WID = 32)
32
(
33
        input clk,
34
        input ce,
35
        input [2:0] rm,                  // rounding mode
36
        input [WID-1:0] i,               // integer input
37
        output [WID-1:0] o               // float output
38
);
39
localparam MSB = WID-1;
40
localparam EMSB = WID==128 ? 14 :
41
                  WID==96 ? 14 :
42
                  WID==80 ? 14 :
43
                  WID==64 ? 10 :
44
                                  WID==52 ? 10 :
45
                                  WID==48 ? 11 :
46
                                  WID==44 ? 10 :
47
                                  WID==42 ? 10 :
48
                                  WID==40 ?  9 :
49
                                  WID==32 ?  7 :
50
                                  WID==24 ?  6 : 4;
51
localparam FMSB = WID==128 ? 111 :
52
                  WID==96 ? 79 :
53
                  WID==80 ? 63 :
54
                  WID==64 ? 51 :
55
                                  WID==52 ? 39 :
56
                                  WID==48 ? 34 :
57
                                  WID==44 ? 31 :
58
                                  WID==42 ? 29 :
59
                                  WID==40 ? 28 :
60
                                  WID==32 ? 22 :
61
                                  WID==24 ? 15 : 9;
62
 
63
wire [EMSB:0] zeroXp = {EMSB{1'b1}};
64
 
65
wire iz;                        // zero input ?
66
wire [MSB:0] imag;       // get magnitude of i
67
wire [MSB:0] imag1 = i[MSB] ? -i : i;
68
wire [7:0] lz;           // count the leading zeros in the number
69
wire [EMSB:0] wd;        // compute number of whole digits
70
wire so;                        // copy the sign of the input (easy)
71
wire [2:0] rmd;
72
 
73
delay1 #(3)   u0 (.clk(clk), .ce(ce), .i(rm),     .o(rmd) );
74
delay1 #(1)   u1 (.clk(clk), .ce(ce), .i(i==0),   .o(iz) );
75
delay1 #(WID) u2 (.clk(clk), .ce(ce), .i(imag1),  .o(imag) );
76
delay1 #(1)   u3 (.clk(clk), .ce(ce), .i(i[MSB]), .o(so) );
77
generate
78
if (WID==128) begin
79
cntlz128Reg    u4 (.clk(clk), .ce(ce), .i(imag1), .o(lz) );
80
end else if (WID==96) begin
81
cntlz96Reg    u4 (.clk(clk), .ce(ce), .i(imag1), .o(lz[6:0]) );
82
assign lz[7]=1'b0;
83
end else if (WID==80) begin
84
cntlz80Reg    u4 (.clk(clk), .ce(ce), .i(imag1), .o(lz[6:0]) );
85
assign lz[7]=1'b0;
86
end else if (WID==64) begin
87
cntlz64Reg    u4 (.clk(clk), .ce(ce), .i(imag1), .o(lz[6:0]) );
88
assign lz[7]=1'b0;
89
end else begin
90
cntlz32Reg    u4 (.clk(clk), .ce(ce), .i(imag1), .o(lz[5:0]) );
91
assign lz[7:6]=2'b00;
92
end
93
endgenerate
94
 
95
assign wd = zeroXp - 1 + WID - lz;      // constant except for lz
96
 
97
wire [EMSB:0] xo = iz ? 0 : wd;
98
wire [MSB:0] simag = imag << lz;         // left align number
99
 
100
wire g =  simag[EMSB+2];        // guard bit (lsb)
101
wire r =  simag[EMSB+1];        // rounding bit
102
wire s = |simag[EMSB:0]; // "sticky" bit
103
reg rnd;
104
 
105
// Compute the round bit
106
always @(rmd,g,r,s,so)
107
        case (rmd)
108
        3'd0:   rnd = (g & r) | (r & s);        // round to nearest even
109
        3'd1:   rnd = 0;                                 // round to zero (truncate)
110
        3'd2:   rnd = (r | s) & !so;            // round towards +infinity
111
        3'd3:   rnd = (r | s) & so;                     // round towards -infinity
112
        3'd4:   rnd = (r | s);
113
        endcase
114
 
115
// "hide" the leading one bit = MSB-1
116
// round the result
117
wire [FMSB:0] mo = simag[MSB-1:EMSB+1]+rnd;
118
 
119
assign o = {so,xo,mo};
120
 
121
endmodule
122
 
123
 
124
module i2f_tb();
125
 
126
reg clk;
127
reg [7:0] cnt;
128
wire [31:0] fo;
129
reg [31:0] i;
130
wire [79:0] fo80;
131
initial begin
132
clk = 1'b0;
133
cnt = 0;
134
end
135
always #10 clk=!clk;
136
 
137
always @(posedge clk)
138
        cnt = cnt + 1;
139
 
140
always @(cnt)
141
case(cnt)
142
8'd0:   i <= 32'd0;
143
8'd1:   i <= 32'd16777226;
144
endcase
145
 
146
i2f #(32) u1 (.clk(clk), .ce(1), .rm(2'd0), .i(i), .o(fo) );
147
i2f #(80) u2 (.clk(clk), .ce(1), .rm(2'd0), .i({{48{i[31]}},i}), .o(fo80) );
148
 
149
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.