blob: 10db627ceee84af69e9211e0115ea3102e65345a (
about) (
plain)
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
|
`default_nettype none
module div
#(
parameter WIDTH = 16
)
(
input wire clock,
input wire start,
input wire [WIDTH-1 : 0] dividend,
input wire [WIDTH-1 : 0] divisor,
output wire [WIDTH-1 : 0] quotient,
output wire [WIDTH-1 : 0] remainder,
output wire done
);
reg [$clog2(WIDTH)-1 : 0] steps;
reg [2*WIDTH : 0] work_reg;
reg [WIDTH-1 : 0] divisor_latched;
wire [WIDTH+1 : 0] work_remainder;
wire work_remainder_sign;
assign work_remainder = work_reg[2*WIDTH : WIDTH-1];
assign work_remainder_sign = work_remainder[WIDTH + 1];
/*
* The following variable represents quotient using digits 1 and -1,
* where -1 is internally represented as 0
*/
`define MINUS_ONE 1'b0
`define PLUS_ONE 1'b1
wire [WIDTH-1 : 0] work_quotient;
assign work_quotient = work_reg[WIDTH-1 : 0];
reg work_quotient_ready;
always @ (posedge clock) begin
if (start) begin
steps <= WIDTH - 1;
work_reg <= dividend;
divisor_latched <= divisor;
work_quotient_ready <= 0;
end else begin
if (steps)
steps <= steps - 1;
else
work_quotient_ready <= 1;
if (!work_quotient_ready) begin
work_reg[WIDTH-1 : 1] <= work_reg[WIDTH-2 : 0];
if (work_remainder_sign) begin /* work remainder negative */
work_reg[0] <= `MINUS_ONE; /* Filling up quotient */
work_reg[2*WIDTH : WIDTH] <= work_remainder + divisor_latched;
end else begin /* work remainder equal 0 or positive */
work_reg[0] <= `PLUS_ONE; /* Filling up quotient */
work_reg[2*WIDTH : WIDTH] <= work_remainder - divisor_latched;
end
end
end
end // always @ (posedge clock)
assign quotient = work_quotient - ~work_quotient - work_remainder_sign;
assign remainder = (work_remainder >> 1) + (work_remainder_sign ? divisor_latched : 0);
assign done = work_quotient_ready && !start;
endmodule // div
|