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

Subversion Repositories ft816float

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 39 to Rev 40
    Reverse comparison

Rev 39 → Rev 40

/ft816float/trunk/rtl/positVerilog/isqrt2.v
0,0 → 1,172
`timescale 1ns / 1ps
// ============================================================================
// __
// \\__/ o\ (C) 2010-2020 Robert Finch, Waterloo
// \ __ / All rights reserved.
// \/_// robfinch<remove>@finitron.ca
// ||
//
// isqrt.v
// - integer square root
// - uses the standard long form calc.
// - geared towards use in an floating point unit
// - calculates to WID fractional precision (double width output)
//
//
// 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 isqrt2(rst, clk, ce, ld, a, o, done, lzcnt);
parameter WID = 32;
localparam MSB = WID-1;
parameter IDLE=3'd0;
parameter CALC=3'd1;
parameter DONE=3'd2;
input rst;
input clk;
input ce;
input ld;
input [MSB:0] a;
output [WID*2-1:0] o;
output done;
output reg [$clog2(WID*2-1):0] lzcnt;
 
reg [2:0] state;
reg [WID*2:0] root;
wire [WID*2-1:0] testDiv;
reg [WID*2-1:0] remLo;
reg [WID*2-1:0] remHi;
reg gotnz;
 
wire cnt_done;
assign testDiv = {root[WID*2-2:0],1'b1};
wire [WID*2-1:0] remHiShift = {remHi[WID*2-3:0],remLo[WID*2-1:WID*2-2]};
wire doesGoInto = remHiShift >= testDiv;
assign o = root[WID*2:1];
 
// Iteration counter
reg [7:0] cnt;
 
always @(posedge clk)
if (rst) begin
cnt <= WID*2;
remLo <= {WID*2{1'b0}};
remHi <= {WID*2{1'b0}};
root <= {WID*2+1{1'b0}};
lzcnt <= 8'd0;
gotnz <= 1'b0;
state <= IDLE;
end
else
begin
if (ce) begin
if (!cnt_done)
cnt <= cnt + 8'd1;
case(state)
IDLE: ;
CALC:
if (!cnt_done) begin
// Shift the remainder low
remLo <= {remLo[WID*2-3:0],2'd0};
// Shift the remainder high
remHi <= doesGoInto ? remHiShift - testDiv: remHiShift;
// Shift the root
root <= {root+doesGoInto,1'b0}; // root * 2 + 1/0
if (doesGoInto)
gotnz <= 1'b1;
else if (!gotnz)
lzcnt <= lzcnt + 2'd1;
end
else begin
cnt <= 8'h00;
state <= DONE;
end
DONE:
begin
if (root[WID*2]) begin
cnt <= cnt + 8'd1;
if (cnt == 8'd6)
state <= IDLE;
end
else begin
root <= {root,1'b0};
cnt <= 8'd0;
end
end
default: state <= IDLE;
endcase
if (ld) begin
cnt <= 8'd0;
state <= CALC;
remLo <= {a,32'd0};
remHi <= {WID*2{1'b0}};
root <= {WID*2+1{1'b0}};
gotnz <= 1'b0;
lzcnt <= 8'd0;
end
end
end
assign cnt_done = (cnt==WID);
assign done = state==DONE && cnt > 8'd0;
 
endmodule
 
 
module isqrt_tb();
 
reg clk;
reg rst;
reg [31:0] a;
wire [63:0] o;
reg ld;
wire done;
reg [7:0] state;
 
initial begin
clk = 1;
rst = 0;
#100 rst = 1;
#100 rst = 0;
end
 
always #10 clk = ~clk; // 50 MHz
 
always @(posedge clk)
if (rst) begin
state <= 8'd0;
a <= 32'h912345;
end
else
begin
ld <= 1'b0;
case(state)
8'd0:
begin
a <= 32'h9123456;
ld <= 1'b1;
state <= 8'd1;
end
8'd1:
if (done) begin
$display("i=%h o=%h", a, o);
end
endcase
end
 
isqrt #(32) u1 (.rst(rst), .clk(clk), .ce(1'b1), .ld(ld), .a(a), .o(o), .done(done));
 
endmodule
 
 

powered by: WebSVN 2.1.0

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