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

Subversion Repositories ft816float

[/] [ft816float/] [trunk/] [rtl/] [positVerilog/] [isqrt2.v] - Blame information for rev 88

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

Line No. Rev Author Line
1 40 robfinch
`timescale 1ns / 1ps
2
// ============================================================================
3
//        __
4
//   \\__/ o\    (C) 2010-2020  Robert Finch, Waterloo
5
//    \  __ /    All rights reserved.
6
//     \/_//     robfinch<remove>@finitron.ca
7
//       ||
8
//
9
//      isqrt.v
10
//      - integer square root
11
//  - uses the standard long form calc.
12
//      - geared towards use in an floating point unit
13
//      - calculates to WID fractional precision (double width output)
14
//
15
//
16
// This source file is free software: you can redistribute it and/or modify 
17
// it under the terms of the GNU Lesser General Public License as published 
18
// by the Free Software Foundation, either version 3 of the License, or     
19
// (at your option) any later version.                                      
20
//                                                                          
21
// This source file is distributed in the hope that it will be useful,      
22
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
23
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
24
// GNU General Public License for more details.                             
25
//                                                                          
26
// You should have received a copy of the GNU General Public License        
27
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
28
//                                                                          
29
// ============================================================================
30
 
31
module isqrt2(rst, clk, ce, ld, a, o, done, lzcnt);
32
parameter WID = 32;
33
localparam MSB = WID-1;
34
parameter IDLE=3'd0;
35
parameter CALC=3'd1;
36
parameter DONE=3'd2;
37
input rst;
38
input clk;
39
input ce;
40
input ld;
41
input [MSB:0] a;
42
output [WID*2-1:0] o;
43
output done;
44
output reg [$clog2(WID*2-1):0] lzcnt;
45
 
46
reg [2:0] state;
47
reg [WID*2:0] root;
48
wire [WID*2-1:0] testDiv;
49
reg [WID*2-1:0] remLo;
50
reg [WID*2-1:0] remHi;
51
reg gotnz;
52
 
53
wire cnt_done;
54
assign testDiv = {root[WID*2-2:0],1'b1};
55
wire [WID*2-1:0] remHiShift = {remHi[WID*2-3:0],remLo[WID*2-1:WID*2-2]};
56
wire doesGoInto = remHiShift >= testDiv;
57
assign o = root[WID*2:1];
58
 
59
// Iteration counter
60
reg [7:0] cnt;
61
 
62
always @(posedge clk)
63
if (rst) begin
64
        cnt <= WID*2;
65
        remLo <= {WID*2{1'b0}};
66
        remHi <= {WID*2{1'b0}};
67
        root <= {WID*2+1{1'b0}};
68
        lzcnt <= 8'd0;
69
        gotnz <= 1'b0;
70
        state <= IDLE;
71
end
72
else
73
begin
74
        if (ce) begin
75
                if (!cnt_done)
76
                        cnt <= cnt + 8'd1;
77
                case(state)
78
                IDLE:   ;
79
                CALC:
80
                        if (!cnt_done) begin
81
                                // Shift the remainder low
82
                                remLo <= {remLo[WID*2-3:0],2'd0};
83
                                // Shift the remainder high
84
                                remHi <= doesGoInto ? remHiShift - testDiv: remHiShift;
85
                                // Shift the root
86
                                root <= {root+doesGoInto,1'b0}; // root * 2 + 1/0
87
                                if (doesGoInto)
88
                                  gotnz <= 1'b1;
89
                                else if (!gotnz)
90
                                  lzcnt <= lzcnt + 2'd1;
91
                        end
92
                        else begin
93
                                cnt <= 8'h00;
94
                                state <= DONE;
95
                        end
96
                DONE:
97
                        begin
98
                          if (root[WID*2]) begin
99
                                cnt <= cnt + 8'd1;
100
                                if (cnt == 8'd6)
101
                                        state <= IDLE;
102
                          end
103
                          else begin
104
                            root <= {root,1'b0};
105
                            cnt <= 8'd0;
106
                          end
107
                        end
108
                default: state <= IDLE;
109
                endcase
110
                if (ld) begin
111
                        cnt <= 8'd0;
112
                        state <= CALC;
113
                        remLo <= {a,32'd0};
114
                        remHi <= {WID*2{1'b0}};
115
                        root <= {WID*2+1{1'b0}};
116
        gotnz <= 1'b0;
117
        lzcnt <= 8'd0;
118
                end
119
        end
120
end
121
assign cnt_done = (cnt==WID);
122
assign done = state==DONE && cnt > 8'd0;
123
 
124
endmodule
125
 
126
 
127 42 robfinch
module isqrt2_tb();
128 40 robfinch
 
129
reg clk;
130
reg rst;
131
reg [31:0] a;
132
wire [63:0] o;
133
reg ld;
134
wire done;
135
reg [7:0] state;
136
 
137
initial begin
138
        clk = 1;
139
        rst = 0;
140
        #100 rst = 1;
141
        #100 rst = 0;
142
end
143
 
144
always #10 clk = ~clk;  //  50 MHz
145
 
146
always @(posedge clk)
147
if (rst) begin
148
        state <= 8'd0;
149
        a <= 32'h912345;
150
end
151
else
152
begin
153
ld <= 1'b0;
154
case(state)
155
8'd0:
156
        begin
157
                a <= 32'h9123456;
158
                ld <= 1'b1;
159
                state <= 8'd1;
160
        end
161
8'd1:
162
        if (done) begin
163
                $display("i=%h o=%h", a, o);
164
        end
165
endcase
166
end
167
 
168 42 robfinch
isqrt2 #(32) u1 (.rst(rst), .clk(clk), .ce(1'b1), .ld(ld), .a(a), .o(o), .done(done));
169 40 robfinch
 
170
endmodule
171
 
172
 

powered by: WebSVN 2.1.0

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