-
Notifications
You must be signed in to change notification settings - Fork 35
/
qdiv.v
107 lines (94 loc) · 4.08 KB
/
qdiv.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: Burke
// Engineer: Tom Burke
//
// Create Date: 19:39:14 08/24/2011
// Design Name:
// Module Name: qdiv.v
// Project Name: Fixed-point Math Library (Verilog)
// Target Devices:
// Tool versions: Xilinx ISE WebPack v14.7
// Description: Fixed-point division in (Q,N) format
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Revision 0.02 - 25 May 2014
// Updated to fix an error
//
// Additional Comments: Based on my description on youtube:
// http://youtu.be/TEnaPMYiuR8
//
//////////////////////////////////////////////////////////////////////////////////
module qdiv #(
//Parameterized values
parameter Q = 15,
parameter N = 32
)
(
input [N-1:0] i_dividend,
input [N-1:0] i_divisor,
input i_start,
input i_clk,
output [N-1:0] o_quotient_out,
output o_complete,
output o_overflow
);
reg [2*N+Q-3:0] reg_working_quotient; // Our working copy of the quotient
reg [N-1:0] reg_quotient; // Final quotient
reg [N-2+Q:0] reg_working_dividend; // Working copy of the dividend
reg [2*N+Q-3:0] reg_working_divisor; // Working copy of the divisor
reg [N-1:0] reg_count; // This is obviously a lot bigger than it needs to be, as we only need
// count to N-1+Q but, computing that number of bits requires a
// logarithm (base 2), and I don't know how to do that in a
// way that will work for everyone
reg reg_done; // Computation completed flag
reg reg_sign; // The quotient's sign bit
reg reg_overflow; // Overflow flag
initial reg_done = 1'b1; // Initial state is to not be doing anything
initial reg_overflow = 1'b0; // And there should be no woverflow present
initial reg_sign = 1'b0; // And the sign should be positive
initial reg_working_quotient = 0;
initial reg_quotient = 0;
initial reg_working_dividend = 0;
initial reg_working_divisor = 0;
initial reg_count = 0;
assign o_quotient_out[N-2:0] = reg_quotient[N-2:0]; // The division results
assign o_quotient_out[N-1] = reg_sign; // The sign of the quotient
assign o_complete = reg_done;
assign o_overflow = reg_overflow;
always @( posedge i_clk ) begin
if( reg_done && i_start ) begin // This is our startup condition
// Need to check for a divide by zero right here, I think....
reg_done <= 1'b0; // We're not done
reg_count <= N+Q-1; // Set the count
reg_working_quotient <= 0; // Clear out the quotient register
reg_working_dividend <= 0; // Clear out the dividend register
reg_working_divisor <= 0; // Clear out the divisor register
reg_overflow <= 1'b0; // Clear the overflow register
reg_working_dividend[N+Q-2:Q] <= i_dividend[N-2:0]; // Left-align the dividend in its working register
reg_working_divisor[2*N+Q-3:N+Q-1] <= i_divisor[N-2:0]; // Left-align the divisor into its working register
reg_sign <= i_dividend[N-1] ^ i_divisor[N-1]; // Set the sign bit
end
else if(!reg_done) begin
reg_working_divisor <= reg_working_divisor >> 1; // Right shift the divisor (that is, divide it by two - aka reduce the divisor)
reg_count <= reg_count - 1; // Decrement the count
// If the dividend is greater than the divisor
if(reg_working_dividend >= reg_working_divisor) begin
reg_working_quotient[reg_count] <= 1'b1; // Set the quotient bit
reg_working_dividend <= reg_working_dividend - reg_working_divisor; // and subtract the divisor from the dividend
end
//stop condition
if(reg_count == 0) begin
reg_done <= 1'b1; // If we're done, it's time to tell the calling process
reg_quotient <= reg_working_quotient; // Move in our working copy to the outside world
if (reg_working_quotient[2*N+Q-3:N]>0)
reg_overflow <= 1'b1;
end
else
reg_count <= reg_count - 1;
end
end
endmodule