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

Subversion Repositories ft816float

[/] [ft816float/] [trunk/] [rtl/] [verilog2/] [i2df96.sv] - Rev 89

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

// ============================================================================
//        __
//   \\__/ o\    (C) 2022  Robert Finch, Waterloo
//    \  __ /    All rights reserved.
//     \/_//     robfinch<remove>@finitron.ca
//       ||
//
//      i2df128.sv
//  - convert integer to decimal floating point
//
// BSD 3-Clause License
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//                                                                          
// ============================================================================

import DFPPkg::*;

module i2df96 (rst, clk, ce, ld, op, rm, i, o, done);
parameter FPWID=96;
input rst;
input clk;
input ce;
input ld;
input op;                                               // 1 = signed, 0 = unsigned
input [2:0] rm;                 // rounding mode
input [95:0] i;         // integer input
output [95:0] o;                // float output
output done;

wire [95:0] i1 = (op & i[95]) ? -i : i;
wire [127:0] bcd;
wire done1, done2;
assign done = done1 & done2;

DDBinToBCD #(.WID(96)) ub2b1
(
        .rst(rst),
        .clk(clk),
        .ld(ld),
        .bin(i1),
        .bcd(bcd),
        .done(done1)
);

DFP96U ui;
wire [11:0] zeroXp = 12'h5FF;

reg iz;                 // zero input ?
wire [7:0] lz;          // count the leading zeros in the number
reg [7:0] lz4;          // leading zero rounded to multiple of four
wire [13:0] wd; // compute number of whole digits
reg so;                 // copy the sign of the input (easy)
reg [2:0] rmd;
wire [127:0] bcd1;
reg [99:0] simag;

always_ff @(posedge clk)
        rmd <= rm;
always_ff @(posedge clk)
        iz <= i==0;
always_ff @(posedge clk)
        so <= i[95];

delay1 #(128) u2 (.clk(clk), .ce(ce), .i(bcd),  .o(bcd1) );
cntlz128Reg   u4 (.clk(clk), .ce(ce), .i(bcd), .o(lz) );

always_comb
        lz4 = lz >> 2'd2;

assign wd = zeroXp - 8'd1 + 8'd25 - lz4 + 8'd7; // constant except for lz

reg [11:0] xo;

always_ff @(posedge clk)
        xo <= iz ? 'd0 : wd;

// left align number
// The number may to too large to represent entirely precisely in which case a
// right shift is required. There are only about 114 bits of precision, but the
// incoming number is allowed to be 128-bit.
// Rounding is required only when the number needs to be right-shifted.

always_ff @(posedge clk)
        if (lz4 < 8'd7) 
                simag = bcd1 >> {8'd7 - lz4,2'd0};
        else
                simag = bcd1 << {lz4 - 8'd7,2'd0};      

wire g =  bcd1[{8'd7 - lz4,2'd0}];      // guard bit (lsb)
wire r =        bcd1[{8'd7 - lz4,2'd0}-1];      // rounding bit
wire s = |(bcd1 & (128'd1 << {8'd7 - lz4,2'd0}-2) - 2'd1);      // "sticky" bit
reg rnd;

// Compute the round bit
always_ff @(posedge clk)
if (lz4 < 8'd7)
        case (rmd)
        3'd0:   rnd = (g & r) | (r & s);        // round to nearest even
        3'd1:   rnd = 0;                                        // round to zero (truncate)
        3'd2:   rnd = (r | s) & !so;            // round towards +infinity
        3'd3:   rnd = (r | s) & so;                     // round towards -infinity
        3'd4:   rnd = (r | s);
        default:        rnd = (g & r) | (r & s);        // round to nearest even
        endcase
else
        rnd = 1'b0;
        
// round the result
assign ui.sig = simag[99:0] + rnd;
assign ui.exp = xo[11:0];
assign ui.sign = op & so;
assign ui.nan = 1'b0;
assign ui.qnan = 1'b0;
assign ui.snan = 1'b0;
assign ui.infinity = 1'b0;

DFPPack96 upk1 (ui, o);

ft_delay #(.WID(1), .DEP(4)) udly1 (.clk(clk), .ce(1'b1), .i(done1), .o(done2));

endmodule

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

powered by: WebSVN 2.1.0

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