View difference between Paste ID: 4kv3CTTs and WMT1HKfk
SHOW: | | - or go back to the newest paste.
1
`timescale 1ns / 1ps
2
module div #(
3
    parameter int unsigned DATA_WIDTH = 32
4
) (
5
    input logic clk,
6
    input logic rst_n,
7
    input logic [DATA_WIDTH-1:0] dividend,
8
    input logic [DATA_WIDTH-1:0] divisor,
9
    input logic signed_ope,
10
    input logic start,
11
    input logic flush,
12
    output logic [DATA_WIDTH-1:0] quotient,
13
    output logic [DATA_WIDTH-1:0] remainder,
14
    output logic ready
15
);
16
  localparam int unsigned D1 = 1;
17
  localparam int unsigned COUNT_WIDTH = $clog2(DATA_WIDTH + 1);
18
19
  logic r_ready;
20
  logic r_signed_ope;
21
  logic [COUNT_WIDTH-1:0] r_count;
22
  logic [DATA_WIDTH-1:0] r_quotient;
23
  logic w_dividend_sign;
24
  logic r_dividend_sign;
25
  logic remainder_sign;
26
  logic [DATA_WIDTH:0] r_remainder;
27
  logic [DATA_WIDTH-1:0] r_divisor;
28
  logic [DATA_WIDTH:0] divisor_ext;
29
  logic divisor_sign;
30
  logic [DATA_WIDTH:0] rem_quo;
31
  logic                diff_sign;
32
  logic [DATA_WIDTH:0] sub_add;
33
34
  assign ready = r_ready;
35
36
  assign divisor_sign = r_divisor[DATA_WIDTH-1] & r_signed_ope;
37
  assign divisor_ext = {divisor_sign, r_divisor};
38
  assign remainder_sign = r_remainder[DATA_WIDTH];
39
40
  assign rem_quo = {r_remainder[DATA_WIDTH-1:0], r_quotient[DATA_WIDTH-1]};
41
  assign diff_sign = remainder_sign ^ divisor_sign;
42
  assign sub_add = diff_sign ? rem_quo + divisor_ext :
43
                               rem_quo - divisor_ext;
44
45
  // after process
46
  always_comb begin
47
    quotient  = (r_quotient << 1) | 1;
48
    remainder = r_remainder[DATA_WIDTH-1:0];
49
50
    if (r_remainder == 0) begin
51
      // do nothing
52
    end else if (r_remainder == divisor_ext) begin
53
      quotient  = quotient + 1;
54
      remainder = remainder - r_divisor;
55
    end else if (r_remainder == -divisor_ext) begin
56
      quotient  = quotient - 1;
57
      remainder = remainder + r_divisor;
58
    end else if (remainder_sign ^ r_dividend_sign) begin
59
      if (diff_sign) begin
60
        quotient  = quotient - 1;
61
        remainder = remainder + r_divisor;
62
      end else begin
63
        quotient  = quotient + 1;
64
        remainder = remainder - r_divisor;
65
      end
66
    end
67
  end
68
69
  assign w_dividend_sign = dividend[DATA_WIDTH-1] & signed_ope;
70
71
  always @(posedge clk or negedge rst_n) begin
72
    if (~rst_n) begin
73
      r_quotient      <= #D1 '0;
74
      r_dividend_sign <= #D1 '0;
75
      r_remainder     <= #D1 '0;
76
      r_divisor       <= #D1 '0;
77
      r_count         <= #D1 '0;
78
      r_ready         <= #D1 1'b1;
79
      r_signed_ope    <= #D1 1'b0;
80
    end else begin
81
      if (flush) begin
82
        r_count         <= #D1 '0;
83
        r_ready         <= #D1 1'b1;
84
      end else if (start) begin
85
        // RISC-V's div by 0 spec
86
        if (divisor == '0) begin
87
            r_quotient  <= #D1 '1;
88
            r_remainder <= #D1 {w_dividend_sign, dividend};
89
        end else begin
90
            r_quotient  <= #D1 dividend;
91
            r_remainder <= #D1 {(DATA_WIDTH+1){w_dividend_sign}};
92
            r_ready     <= #D1 1'b0;
93
        end
94
        r_count         <= #D1 '0;
95
        r_dividend_sign <= #D1 w_dividend_sign;
96
        r_divisor       <= #D1 divisor;
97
        r_signed_ope    <= #D1 signed_ope;
98
      end else if (~ready) begin
99
        r_quotient  <= #D1 {r_quotient[DATA_WIDTH-2:0], ~diff_sign};
100
        r_remainder <= #D1 sub_add[DATA_WIDTH:0];
101
        r_count     <= #D1 r_count + 1;
102
        if (r_count == DATA_WIDTH - 1) begin
103
          r_ready <= #D1 1'b1;
104
        end
105
      end
106
    end
107
  end
108
endmodule
109
110