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 |