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

Subversion Repositories ft816float

[/] [ft816float/] [trunk/] [rtl/] [verilog2/] [dfisqrt.v] - Rev 56

Compare with Previous | Blame | View Log

`timescale 1ns / 1ps
// ============================================================================
//        __
//   \\__/ o\    (C) 2010-2020  Robert Finch, Waterloo
//    \  __ /    All rights reserved.
//     \/_//     robfinch<remove>@finitron.ca
//       ||
//
//	dfisqrt.v
//	- integer square root
//  - uses the standard long form calc.
//	- geared towards use in an decimal floating point unit
//	- calculates to WID fractional precision (double width output)
//
//
// 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.
//                                                                          
// ============================================================================
 
module dfisqrt(rst, clk, ce, ld, a, o, done);
parameter N=34;
parameter WID = N*4;
localparam MSB = WID-1;
input rst;
input clk;
input ce;
input ld;
input [MSB:0] a;
output reg [WID*2-1:0] o;
output reg done;
 
reg [3:0] state;
parameter SKIPLZ = 4'd1;
parameter A0 = 4'd2;
parameter S3 = 4'd3;
parameter INCJ = 4'd4;
parameter DONE = 4'd5;
parameter S1 = 4'd6;
parameter S4 = 4'd7;
parameter S2 = 4'd8;
 
reg [3:0] tbl [0:255];
reg [7:0] tbl5 [0:9];
reg [7:0] sqra [0:9];
 
initial begin
	sqra[0] = 8'h00;
	sqra[1] = 8'h01;
	sqra[2] = 8'h04;
	sqra[3] = 8'h09;
	sqra[4] = 8'h16;
	sqra[5] = 8'h25;
	sqra[6] = 8'h36;
	sqra[7] = 8'h49;
	sqra[8] = 8'h64;
	sqra[9] = 8'h81;
end
 
genvar g;
generate begin
	for (g = 0; g < 256; g = g + 1)
		initial begin
			if (g >= 8'h81)
				tbl[g] = 4'h9;
			else if (g >= 8'h64)
				tbl[g] = 4'h8;
			else if (g >= 8'h49)
				tbl[g] = 4'h7;
			else if (g >= 8'h36)
				tbl[g] = 4'h6;
			else if (g >= 8'h25)
				tbl[g] = 4'h5;
			else if (g >= 8'h16)
				tbl[g] = 4'h4;
			else if (g >= 8'h09)
				tbl[g] = 4'd3;
			else if (g >= 8'h04)
				tbl[g] = 4'h2;
			else if (g >= 8'h01)
				tbl[g] = 4'h1;
			else
				tbl[g] = 4'h0;
		end
end
endgenerate
 
initial begin
	tbl5[0] = 8'h05;
	tbl5[1] = 8'h15;
	tbl5[2] = 8'h25;
	tbl5[3] = 8'h35;
	tbl5[4] = 8'h45;
	tbl5[5] = 8'h55;
	tbl5[6] = 8'h65;
	tbl5[7] = 8'h75;
	tbl5[8] = 8'h85;
	tbl5[9] = 8'h95;
end
 
 
reg [7:0] dcnt;
reg [7:0] j;
reg [N*2*4-1:0] b;
reg [N*4*2-1:0] ii;
wire [N*4*2-1:0] firstRa;
reg [N*4*2-1+4:0] ai, Rbx5;
wire [(N*2+1)*4-1:0] Rax2, Rax4, Rax5i, newRax5a;
reg [(N*2+1)*4-1:0] Rax5, pRax5, newRax5;
wire tooBig;
 
BCDAddN #(.N(N*2+1)) ua1 (.ci(1'b0), .a({4'h0,firstRa}), .b({4'h0,firstRa}), .o(Rax2), .co());
BCDAddN #(.N(N*2+1)) ua2 (.ci(1'b0), .a(Rax2), .b(Rax2), .o(Rax4), .co());
BCDAddN #(.N(N*2+1)) ua3 (.ci(1'b0), .a({4'h0,firstRa}), .b(Rax4), .o(Rax5i), .co());
 
BCDSubN #(.N(N*2+1)) ua4 (.ci(1'b0), .a(Rax5), .b(Rbx5), .o(newRax5a), .co(tooBig));
 
 
wire [3:0] a0 = tbl[ii[N*4*2-1:N*4*2-8]];
wire [7:0] sqra00 = sqra[a0];
wire [N*2*4+3:0] srqa0 = {4'h0,sqra00,{N*2*4-8{1'b0}}};
 
BCDSubN #(.N(N*2)) ua5 (.ci(1'b0), .a(ii), .b(srqa0), .o(firstRa), .co());
 
wire [WID*2-1:0] tbl5x = {tbl5[b[3:0]],{(N*2-3)*4{1'b0}}};
wire [WID*2-1:0] tbl5s = tbl5x >> {j,2'h0};
 
wire [N*2*4-1:0] sum_ai;
BCDAddN #(.N(N*2)) ua6 (.ci(1'b0), .a(ai), .b(tbl5s), .o(sum_ai), .co());
 
always @(posedge clk)
begin
case(state)
SKIPLZ:
	begin
		Rax5 <= {N*2*4+4{1'd0}};
		Rbx5 <= {N*2*4+4{1'd0}};
		if (ii[N*4*2-1:N*4*2-8]==8'h00) begin
			ii <= {ii[N*4*2-9:0],8'h00};		
			dcnt <= dcnt - 8'd2;
			if (dcnt==8'h00) begin
				o <= {WID*2{1'b0}};
				state <= DONE;
			end
		end
		else
			state <= A0;
	end
	// Get the first digit of the square root.
A0:
	begin
		b <= 4'd0;
		ai <= {4'd0,a0,{(N*2-2)*4{1'b0}}};
		state <= S1;
	end
	// Set initial Ra5
S1:
	begin
		Rax5 <= Rax5i;
		Rbx5 <= {4'h0,sum_ai};
		pRax5 <= Rax5i;
		state <= S2;
	end
S2:
	begin
		newRax5 <= newRax5a;
		if (tooBig) begin
			Rax5 <= {Rax5,4'h0};
			ai <= ai | (b << (N*2-j)*4-8);
			state <= INCJ;
		end
		else begin
			b <= b + 1'd1;
			state <= S3;
		end
	end
S3:
	begin
		pRax5 <= Rax5;
		Rax5 <= newRax5;
		Rbx5 <= {4'h0,sum_ai};
		state <= S2;
	end
INCJ:
	begin
		b <= 4'd0;
		j <= j + 1'd1;
		dcnt <= dcnt - 1'd1;
		if (dcnt==0) begin
			state <= DONE;
			o <= ai;
		end
		else
			state <= S4;
	end
S4:
	begin
		Rbx5 <= {4'h0,sum_ai};
		state <= S2;
	end
DONE:
	begin
		done <= 1'b1;
	end
endcase
if (ld) begin
	state <= SKIPLZ;
	dcnt <= N*2;
	j <= 8'd1;
	b <= 4'd0;
	ii <= {a,{N*4{1'b0}}};
	done <= 1'b0;
end
end
 
endmodule
 
 
module dfisqrt_tb();
parameter N=34;
 
reg clk;
reg rst;
reg [N*4-1:0] a;
wire [N*4*2-1: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 <= 64'h987654321;
end
else
begin
ld <= 1'b0;
case(state)
8'd0:
	begin	
		a <= 64'h987654321;
		ld <= 1'b1;
		state <= 8'd1;
	end
8'd1:
	if (done) begin
		$display("i=%h o=%h", a, o);
	end
endcase
end
 
dfisqrt #(.N(N)) u1 (.rst(rst), .clk(clk), .ce(1'b1), .ld(ld), .a(a), .o(o), .done(done));
 
endmodule
 
 
 

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.