URL
https://opencores.org/ocsvn/ft816float/ft816float/trunk
Subversion Repositories ft816float
Compare Revisions
- This comparison shows the changes necessary to convert path
/ft816float/trunk/rtl/verilog2
- from Rev 34 to Rev 35
- ↔ Reverse comparison
Rev 34 → Rev 35
/fpConfig.sv
2,7 → 2,7
|
// ============================================================================ |
// __ |
// \\__/ o\ (C) 2019 Robert Finch, Waterloo |
// \\__/ o\ (C) 2019-2020 Robert Finch, Waterloo |
// \ __ / All rights reserved. |
// \/_// robfinch<remove>@finitron.ca |
// || |
27,9 → 27,25
// calculations are performed in one long clock cycle. This will result in |
// the maximum clock rate being really low. |
|
//`define MIN_LATENCY 1'b1 |
`define MIN_LATENCY 1'b1 |
|
// Number of bits extra beyond specified FPWIDth for calculation results |
// should be a multiple of four |
`define EXTRA_BITS 0 |
|
`define FPWID 80 |
|
// This file contains defintions for fields to ease dealing with different fp |
// FPWIDths. Some of the code still needs to be modified to support FPWIDths |
// other than standard 32,64 or 80 bit. |
`define MSB (`FPWID-1) |
`define EMSB (`FPWID==128 ? 14 : `FPWID==96 ? 14 : `FPWID==80 ? 14 : `FPWID==64 ? 10 : `FPWID==52 ? 10 : `FPWID==48 ? 10 : `FPWID==44 ? 10 : `FPWID==42 ? 10 : `FPWID==40 ? 9 : `FPWID==32 ? 7 : `FPWID==24 ? 6 : 49) |
`define FMSB (`FPWID==128 ? (111) : `FPWID==96 ? (79) : `FPWID==80 ? (63) : `FPWID==64 ? (51) : `FPWID==52 ? (39) : `FPWID==48 ? (35) : `FPWID==44 ? (31) : `FPWID==42 ? (29) : `FPWID==40 ? (28) : `FPWID==32 ? (22) : `FPWID==24 ? (15) : (9)) |
`define FX ((`FMSB+2)*2) // the MSB of the expanded fraction |
`define EX (`FX + 1 + `EMSB + 1 + 1 - 1) |
|
// Only uncomment one of the following for the divider |
// radix four has a faster cycle time |
// radix sixteen uses fewer clock cycles |
`define DIV_RADIX4 1'b1 |
//`define DIV_RADIX16 1'b1 |
/fpDiv.v
87,7 → 87,7
wire [FMSB:0] qNaN = {1'b1,{FMSB{1'b0}}}; |
|
// variables |
wire [EMSB+2:0] ex1; // sum of exponents |
reg [EMSB+2:0] ex1; // sum of exponents |
`ifndef GOLDSCHMIDT |
wire [(FMSB+FADD)*2-1:0] divo; |
`else |
112,19 → 112,27
// - calculate fraction |
// ----------------------------------------------------------- |
|
fpDecomp #(FPWID) u1a (.i(a), .sgn(sa), .exp(xa), .fract(fracta), .xz(a_dn), .vz(az), .inf(aInf), .nan(aNan) ); |
fpDecomp #(FPWID) u1b (.i(b), .sgn(sb), .exp(xb), .fract(fractb), .xz(b_dn), .vz(bz), .inf(bInf), .nan(bNan) ); |
wire ld1; |
fpDecompReg #(FPWID) u1a (.clk(clk), .ce(ce), .i(a), .sgn(sa), .exp(xa), .fract(fracta), .xz(a_dn), .vz(az), .inf(aInf), .nan(aNan) ); |
fpDecompReg #(FPWID) u1b (.clk(clk), .ce(ce), .i(b), .sgn(sb), .exp(xb), .fract(fractb), .xz(b_dn), .vz(bz), .inf(bInf), .nan(bNan) ); |
delay1 #(1) u5 (.clk(clk), .ce(ce), .i(ld), .o(ld1)); |
|
// Compute the exponent. |
// - correct the exponent for denormalized operands |
// - adjust the difference by the bias (add 127) |
// - also factor in the different decimal position for division |
reg [EMSB+2:0] ex1a; |
always @(posedge clk) |
if (ce) ex1a = (xa|a_dn) - (xb|b_dn) + bias; |
|
`ifndef GOLDSCHMIDT |
assign ex1 = (xa|a_dn) - (xb|b_dn) + bias + FMSB + (FADD-1) - lzcnt - 8'd1; |
always @(posedge clk) |
if (ce) ex1 = ex1a + FMSB + (FADD-1) - lzcnt - 8'd1; |
`else |
assign ex1 = (xa|a_dn) - (xb|b_dn) + bias + FMSB - lzcnt + 8'd4; |
if (ce) ex1 = ex1a + FMSB - lzcnt + 8'd4; |
`endif |
|
|
// check for exponent underflow/overflow |
wire under = ex1[EMSB+2]; // MSB set = negative exponent |
wire over = (&ex1[EMSB:0] | ex1[EMSB+1]) & !ex1[EMSB+2]; |
132,23 → 140,36
// Perform divide |
// Divider width must be a multiple of four |
`ifndef GOLDSCHMIDT |
fpdivr16 #(FMSB+FADD) u2 (.clk(clk), .ld(ld), .a({3'b0,fracta,8'b0}), .b({3'b0,fractb,8'b0}), .q(divo), .r(), .done(done1), .lzcnt(lzcnt)); |
`ifdef DIV_RADIX4 |
fpdivr4 #(FMSB+FADD) u2 (.clk(clk), .ld(ld1), .a({3'b0,fracta,8'b0}), .b({3'b0,fractb,8'b0}), .q(divo), .r(), .done(done1), .lzcnt(lzcnt)); |
`endif |
`ifdef DIV_RADIX16 |
fpdivr16 #(FMSB+FADD) u2 (.clk(clk), .ld(ld1), .a({3'b0,fracta,8'b0}), .b({3'b0,fractb,8'b0}), .q(divo), .r(), .done(done1), .lzcnt(lzcnt)); |
`endif |
//fpdivr2 #(FMSB+FADD) u2 (.clk4x(clk4x), .ld(ld), .a({3'b0,fracta,8'b0}), .b({3'b0,fractb,8'b0}), .q(divo), .r(), .done(done1), .lzcnt(lzcnt)); |
reg [(FMSB+FADD)*2-1:0] divo1; |
reg [(FMSB+FADD)*2-1:0] divo1, divo2; |
reg [7:0] lzcnts; |
always @(posedge clk) |
if (ce) divo1 = divo[(FMSB+FADD)*2-1:0] << (lzcnt-2); |
if (ce) lzcnts = lzcnt - 2; |
always @(posedge clk) |
if (ce) divo2 = divo[(FMSB+FADD)*2-1:0]; |
|
always @(posedge clk) |
if (ce) divo1 = divo2 << lzcnts; |
`else |
DivGoldschmidt #(.FPWID(FMSB+6),.WHOLE(1),.POINTS(FMSB+5)) |
u2 (.rst(rst), .clk(clk), .ld(ld), .a({fracta,4'b0}), .b({fractb,4'b0}), .q(divo), .done(done1), .lzcnt(lzcnt)); |
reg [(FMSB+6)*2+1:0] divo1; |
u2 (.rst(rst), .clk(clk), .ld(ld1), .a({fracta,4'b0}), .b({fractb,4'b0}), .q(divo), .done(done1), .lzcnt(lzcnt)); |
reg [(FMSB+6)*2+1:0] divo1, divo2; |
always @(posedge clk) |
if (ce) divo2 = divo; |
always @(posedge clk) |
if (ce) divo1 = |
lzcnt > 8'd5 ? divo << (lzcnt-8'd6) : |
divo >> (8'd6-lzcnt); |
lzcnt > 8'd5 ? divo2 << (lzcnt-8'd6) : |
divo2 >> (8'd6-lzcnt); |
; |
`endif |
delay1 #(1) u3 (.clk(clk), .ce(ce), .i(done1), .o(done2)); |
delay2 #(1) u4 (.clk(clk), .ce(ce), .i(done1), .o(done)); |
delay2 #(1) u3 (.clk(clk), .ce(ce), .i(done1), .o(done2)); |
delay3 #(1) u4 (.clk(clk), .ce(ce), .i(done1), .o(done)); |
|
|
// determine when a NaN is output |
/fpdivr4.v
0,0 → 1,118
// ============================================================================ |
// __ |
// \\__/ o\ (C) 2006-2020 Robert Finch, Waterloo |
// \ __ / All rights reserved. |
// \/_// robfinch<remove>@finitron.ca |
// || |
// |
// fpdivr16.v |
// Radix 16 floating point divider primitive |
// |
// |
// 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 |
// by the Free Software Foundation, either version 3 of the License, or |
// (at your option) any later version. |
// |
// This source file is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// You should have received a copy of the GNU General Public License |
// along with this program. If not, see <http://www.gnu.org/licenses/>. |
// |
// ============================================================================ |
|
module fpdivr4(clk, ld, a, b, q, r, done, lzcnt); |
parameter WID1 = 112; |
localparam REM = WID1 % 2; |
localparam WID = ((WID1*2)+1)/2; |
localparam DMSB = WID-1; |
input clk; |
input ld; |
input [WID-1:0] a; |
input [WID-1:0] b; |
output reg [WID*2-1:0] q = 1'd0; |
output reg [WID-1:0] r = 1'd0; |
output reg done = 1'd0; |
output reg [7:0] lzcnt = 1'd0; |
|
initial begin |
if (WID % 2) begin |
$display("fpdvir4: Width must be a multiple of two."); |
$finish; |
end |
end |
|
wire [7:0] maxcnt; |
reg [DMSB:0] rxx = 1'd0; |
reg [8:0] cnt = 1'd0; // iteration count |
// Simulation didn't like all the wiring. |
reg [DMSB+1:0] ri = 1'd0; |
reg b0 = 1'd0,b1 = 1'd0,b2 = 1'd0,b3 = 1'd0; |
reg [DMSB+1:0] r1 = 1'd0,r2 = 1'd0,r3 = 1'd0,r4 = 1'd0; |
reg gotnz = 0; |
|
assign maxcnt = WID*2/2-1; |
always @* |
b0 = b <= {rxx,q[WID*2-1]}; |
always @* |
r1 = b0 ? {rxx,q[WID*2-1]} - b : {rxx,q[WID*2-1]}; |
always @* |
b1 = b <= {r1,q[WID*2-2]}; |
always @* |
r2 = b1 ? {r1,q[WID*2-2]} - b : {r1,q[WID*2-2]}; |
|
reg [2:0] state = 0; |
always @(posedge clk) |
begin |
if (ld) state <= 3'd1; |
case(state) |
3'd0: ; |
3'd1: if (cnt[8]) state <= 3'd2; |
3'd2: state <= 3'd0; |
default: state <= 3'd0; |
endcase |
end |
|
always @(posedge clk) |
begin |
done <= 1'b0; |
case(state) |
3'd0: ; |
3'd1: |
if (!cnt[8]) begin |
q[WID*2-1:2] <= q[WID*2-3:0]; |
q[1] <= b0; |
q[0] <= b1; |
if (!gotnz) |
casez({b0,b1}) |
2'b1?: ; |
2'b01: lzcnt <= lzcnt + 8'd1; |
2'b00: lzcnt <= lzcnt + 8'd2; |
endcase |
if ({b0,b1} != 2'h0 && !gotnz) begin |
gotnz <= 3'd1; |
end |
rxx <= r2; |
cnt <= cnt - 3'd1; |
end |
3'd2: |
begin |
r <= r2; |
done <= 1'b1; |
end |
default: ; |
endcase |
if (ld) begin |
lzcnt <= 0; |
gotnz <= 1'b0; |
cnt <= {1'b0,maxcnt}; |
q <= {(a << REM),{WID{1'b0}}}; |
rxx <= {WID{1'b0}}; |
end |
end |
|
endmodule |
|