aboutsummaryrefslogtreecommitdiffstats
path: root/ip/div_unsigned.v
diff options
context:
space:
mode:
Diffstat (limited to 'ip/div_unsigned.v')
-rw-r--r--ip/div_unsigned.v146
1 files changed, 146 insertions, 0 deletions
diff --git a/ip/div_unsigned.v b/ip/div_unsigned.v
new file mode 100644
index 0000000..db70758
--- /dev/null
+++ b/ip/div_unsigned.v
@@ -0,0 +1,146 @@
+/////////////////////////////////////////////////////////////////////
+//// ////
+//// Non-restoring unsigned divider ////
+//// ////
+//// Author: Richard Herveille ////
+//// richard@asics.ws ////
+//// www.asics.ws ////
+//// ////
+/////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2002 Richard Herveille ////
+//// richard@asics.ws ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer.////
+//// ////
+//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
+//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
+//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
+//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
+//// 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. ////
+//// ////
+/////////////////////////////////////////////////////////////////////
+
+`timescale 1 ns / 1 ns
+
+module div_unsigned(clock, clken, numer, denom, quotient, remain);
+
+ //
+ // parameters
+ //
+ parameter stages = 32; // controls # of pipeline stages
+ localparam width = stages;
+ parameter z_width = 2*width; // internally used width
+
+ parameter width_n = width; // width of numerator and quotient <= width
+ parameter width_d = width; // width of denominator and remainder <= width
+
+ //
+ // inputs & outputs
+ //
+ input clock; // system clock
+ input clken; // clock enable
+
+ input [width_n -1:0] numer; // dividend
+ input [width_d -1:0] denom; // divisor
+ output [width_n -1:0] quotient; // quotient
+ output [width_d -1:0] remain; // remainder
+ reg [width_n-1:0] quotient = {(width_n){1'b0}};
+ reg [width_d-1:0] remain = {(width_d){1'b0}};
+
+ //
+ // functions
+ //
+ function [z_width:0] gen_s;
+ input [z_width:0] si;
+ input [z_width:0] di;
+ begin
+ if(si[z_width])
+ gen_s = {si[z_width-1:0], 1'b0} + di;
+ else
+ gen_s = {si[z_width-1:0], 1'b0} - di;
+ end
+ endfunction
+
+ function [width-1:0] gen_q;
+ input [width-1:0] qi;
+ input [z_width:0] si;
+ begin
+ gen_q = {qi[width-2:0], ~si[z_width]};
+ end
+ endfunction
+
+ function [width-1:0] assign_s;
+ input [z_width:0] si;
+ input [z_width:0] di;
+ reg [z_width:0] tmp;
+ begin
+ if(si[z_width])
+ tmp = si + di;
+ else
+ tmp = si;
+
+ assign_s = tmp[z_width-1:z_width-width];
+ end
+ endfunction
+
+ //
+ // variables
+ //
+ reg [width-1:0] q_pipe [width-1:0];
+ reg [z_width:0] s_pipe [width:0];
+ reg [z_width:0] d_pipe [width:0];
+
+ integer n0, n1, n2;
+
+ // generate divisor (d) pipe
+ always @(denom)
+ begin
+ d_pipe[0] <= {1'b0, {(width-width_d){1'b0}}, denom, {(z_width-width){1'b0}} };
+ end
+
+ always @(posedge clock)
+ if(clken)
+ for(n0=1; n0 <= width; n0=n0+1)
+ d_pipe[n0] <= d_pipe[n0-1];
+
+ // generate internal remainder pipe
+ always @(numer)
+ begin
+ s_pipe[0] <= {{(width){1'b0}}, {(width-width_d){1'b0}}, numer};
+ end
+
+ always @(posedge clock)
+ if(clken)
+ for(n1=1; n1 <= width; n1=n1+1)
+ s_pipe[n1] <= gen_s(s_pipe[n1-1], d_pipe[n1-1]);
+
+ // generate quotient pipe
+ always @(posedge clock)
+ q_pipe[0] <= 0;
+
+ always @(posedge clock)
+ if(clken)
+ for(n2=1; n2 < width; n2=n2+1)
+ q_pipe[n2] <= gen_q(q_pipe[n2-1], s_pipe[n2]);
+
+
+ always @(posedge clock)
+ if(clken)
+ quotient <= gen_q(q_pipe[width-1], s_pipe[width]);
+
+ always @(posedge clock)
+ if(clken)
+ remain <= assign_s(s_pipe[width], d_pipe[width]);
+endmodule