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

Subversion Repositories ft816float

[/] [ft816float/] [trunk/] [rtl/] [verilog2/] [i2f.sv] - Blame information for rev 88

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 48 robfinch
// ============================================================================
2
//        __
3
//   \\__/ o\    (C) 2006-2020  Robert Finch, Waterloo
4
//    \  __ /    All rights reserved.
5
//     \/_//     robfinch@finitron.ca
6
//       ||
7
//
8
//      i2f.sv
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 .
27
//
28
// ============================================================================
29
 
30
import fp::*;
31
 
32
module i2f (clk, ce, op, rm, i, o);
33
input clk;
34
input ce;
35
input op;                                               // 1 = signed, 0 = unsigned
36
input [2:0] rm;                 // rounding mode
37
input [FPWID-1:0] i;            // integer input
38
output [FPWID-1:0] o;           // float output
39
 
40
wire [EMSB:0] zeroXp = {EMSB{1'b1}};
41
 
42
wire iz;                        // zero input ?
43
wire [MSB:0] imag;      // get magnitude of i
44
wire [MSB:0] imag1 = (op & i[MSB]) ? -i : i;
45
wire [7:0] lz;          // count the leading zeros in the number
46
wire [EMSB:0] wd;       // compute number of whole digits
47
wire so;                        // copy the sign of the input (easy)
48
wire [2:0] rmd;
49
 
50
delay1 #(3)   u0 (.clk(clk), .ce(ce), .i(rm),     .o(rmd) );
51
delay1 #(1)   u1 (.clk(clk), .ce(ce), .i(i==0),   .o(iz) );
52
delay1 #(FPWID) u2 (.clk(clk), .ce(ce), .i(imag1),  .o(imag) );
53
delay1 #(1)   u3 (.clk(clk), .ce(ce), .i(i[MSB]), .o(so) );
54
generate
55
if (FPWID==128) begin
56
cntlz128Reg    u4 (.clk(clk), .ce(ce), .i(imag1), .o(lz) );
57
end else if (FPWID==96) begin
58
cntlz96Reg    u4 (.clk(clk), .ce(ce), .i(imag1), .o(lz[6:0]) );
59
assign lz[7]=1'b0;
60
end else if (FPWID==84) begin
61
cntlz96Reg    u4 (.clk(clk), .ce(ce), .i({imag1,12'hfff}), .o(lz[6:0]) );
62
assign lz[7]=1'b0;
63
end else if (FPWID==80) begin
64
cntlz80Reg    u4 (.clk(clk), .ce(ce), .i(imag1), .o(lz[6:0]) );
65
assign lz[7]=1'b0;
66
end else if (FPWID==64) begin
67
cntlz64Reg    u4 (.clk(clk), .ce(ce), .i(imag1), .o(lz[6:0]) );
68
assign lz[7]=1'b0;
69
end else if (FPWID==32) begin
70
cntlz32Reg    u4 (.clk(clk), .ce(ce), .i(imag1), .o(lz[5:0]) );
71
assign lz[7:6]=2'b00;
72
end else begin
73
        always @* begin
74
        $display("Uncoded leading zero count in i2f");
75
        $finish;
76
  end
77
end
78
endgenerate
79
 
80
assign wd = zeroXp - 1 + FPWID - lz;    // constant except for lz
81
 
82
wire [EMSB:0] xo = iz ? 0 : wd;
83
wire [MSB:0] simag = imag << lz;                // left align number
84
 
85
wire g =  simag[EMSB+2];        // guard bit (lsb)
86
wire r =  simag[EMSB+1];        // rounding bit
87
wire s = |simag[EMSB:0];        // "sticky" bit
88
reg rnd;
89
 
90
// Compute the round bit
91
always @(rmd,g,r,s,so)
92
        case (rmd)
93
        3'd0:   rnd = (g & r) | (r & s);      // round to nearest even
94
        3'd1:   rnd = 0;                                        // round to zero (truncate)
95
        3'd2:   rnd = (r | s) & !so;         // round towards +infinity
96
        3'd3:   rnd = (r | s) & so;                 // round towards -infinity
97
        3'd4:   rnd = (r | s);
98
        default:        rnd = (g & r) | (r & s);      // round to nearest even
99
        endcase
100
 
101
// "hide" the leading one bit = MSB-1
102
// round the result
103
wire [FMSB:0] mo = simag[MSB-1:EMSB+1]+rnd;
104
 
105
assign o = {op & so,xo,mo};
106
 
107
endmodule

powered by: WebSVN 2.1.0

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