aboutsummaryrefslogtreecommitdiff
path: root/design/div.v
diff options
context:
space:
mode:
authorWojciech Kosior <kwojtus@protonmail.com>2020-09-01 10:54:59 +0200
committerWojciech Kosior <kwojtus@protonmail.com>2020-09-01 11:04:22 +0200
commitee1f6c47e1eff920068f4bceaf604f9535a2e8a9 (patch)
tree580eb001a72601d254bb29cc348a529490f84808 /design/div.v
parentcd02ddff8886aa1db29f80d3cc5cf99a349d8258 (diff)
downloadAGH-engineering-thesis-ee1f6c47e1eff920068f4bceaf604f9535a2e8a9.tar.gz
AGH-engineering-thesis-ee1f6c47e1eff920068f4bceaf604f9535a2e8a9.zip
start anew
Diffstat (limited to 'design/div.v')
-rw-r--r--design/div.v70
1 files changed, 70 insertions, 0 deletions
diff --git a/design/div.v b/design/div.v
new file mode 100644
index 0000000..10db627
--- /dev/null
+++ b/design/div.v
@@ -0,0 +1,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