module div_pipelined
  (
   input                 clk,
   input                 rst_n,
   input                 start,
   input [BITS-1:0]      dividend,
   input [BITS-1:0]      divisor,
   output reg            data_valid,
   output reg            div_by_zero,
   output reg [STAGES-1:0] quotient
   //   output reg [7:0]      quotient_correct
   );

  // WARNING!!! THESE PARAMETERS ARE INTENDED TO BE MODIFIED IN A TOP
  // LEVEL MODULE. LOCAL CHANGES HERE WILL, MOST LIKELY, BE
  // OVERWRITTEN!
  parameter
    BITS  = 8,
    STAGES  = BITS;

  // y = a/bQ

  reg [STAGES-1:0]       start_gen, negative_quotient_gen, div_by_zero_gen;
  reg [BITS*2*(STAGES-1)-1:0] dividend_gen, divisor_gen, quotient_gen;
  wire [BITS-1:0]             pad_dividend;
  wire [BITS-2:0]             pad_divisor;

  assign pad_dividend  = 0;
  assign pad_divisor  = 0;

  // sign conversion stage
  always @ (posedge clk or negedge rst_n)
    begin
      if (!rst_n) begin
        div_by_zero_gen[0] <= 0;
        start_gen[0] <=0;
        negative_quotient_gen[0] <= 0;
        dividend_gen[BITS*2-1:0] <= 0;
        divisor_gen[BITS*2-1:0] <= 0; end
      else begin
        div_by_zero_gen[0]       <= (divisor == 0);
        start_gen[0]             <= start;
        negative_quotient_gen[0] <= dividend[BITS-1] ^ divisor[BITS-1];
        dividend_gen[BITS*2-1:0] <= (dividend[BITS-1]) ? ~{dividend,pad_dividend} + 1 : {dividend,pad_dividend};
        divisor_gen[BITS*2-1:0]  <= (divisor [BITS-1]) ? ~{1'b1,divisor, pad_divisor} + 1 : {1'b0,divisor, pad_divisor};
      end
    end

  // first computation stage
  always @ (posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      div_by_zero_gen[1]              <= 0;
      start_gen[1]                    <= 0;
      negative_quotient_gen[1]        <= 0;
      divisor_gen[BITS*2*2-1:BITS*2]  <= 0;
      quotient_gen[BITS*2-1:0]        <= 0;
      dividend_gen[BITS*2*2-1:BITS*2] <= 0;
    end
    else begin
      div_by_zero_gen[1]             <= div_by_zero_gen[0];
      start_gen[1]                   <= start_gen[0];
      negative_quotient_gen[1]       <= negative_quotient_gen[0];
      divisor_gen[BITS*2*2-1:BITS*2] <= divisor_gen[BITS*2-1:0] >> 1;
      if ( dividend_gen[BITS*2-1:0] >= divisor_gen[BITS*2-1:0]) begin
        quotient_gen[BITS*2-1:0] <= 1 << STAGES - 2;
        dividend_gen[BITS*2*2-1:BITS*2] <= dividend_gen[BITS*2-1:0] - divisor_gen[BITS*2-1:0];
      end
      else begin
        quotient_gen[BITS*2-1:0] <= 0;
        dividend_gen[BITS*2*2-1:BITS*2] <= dividend_gen[BITS*2-1:0];
      end
    end // else: !if(!rst_n)
  end // always @ (posedge clk)

  generate
    genvar            i;
    for (i = 1; i < STAGES - 2; i = i + 1) begin : pipeline
      always @ (posedge clk or negedge rst_n) begin
        if (!rst_n) begin
          div_by_zero_gen[i+1]                     <= 0;
          start_gen[i+1]                           <= 0;
          negative_quotient_gen[i+1]               <= 0;
          divisor_gen[BITS*2*(i+2)-1:BITS*2*(i+1)] <= 0;
          quotient_gen[BITS*2*(i+1)-1:BITS*2*i]     <= 0;
          dividend_gen[BITS*2*(i+2)-1:BITS*2*(i+1)] <= 0;
        end
        else begin
          div_by_zero_gen[i+1]                     <= div_by_zero_gen[i];
          start_gen[i+1]                           <= start_gen[i];
          negative_quotient_gen[i+1]               <= negative_quotient_gen[i];
          divisor_gen[BITS*2*(i+2)-1:BITS*2*(i+1)] <= divisor_gen[BITS*2*(i+1)-1:BITS*2*i] >> 1;
          if (dividend_gen[BITS*2*(i+1)-1:BITS*2*i] >= divisor_gen[BITS*2*(i+1)-1:BITS*2*i]) begin
            quotient_gen[BITS*2*(i+1)-1:BITS*2*i] <= quotient_gen[BITS*2*i-1:BITS*2*(i-1)] | (1 << (STAGES-2-i));
            dividend_gen[BITS*2*(i+2)-1:BITS*2*(i+1)] <= dividend_gen[BITS*2*(i+1)-1:BITS*2*i] - divisor_gen[BITS*2*(i+1)-1:BITS*2*i];
          end
          else begin
            quotient_gen[BITS*2*(i+1)-1:BITS*2*i]     <= quotient_gen[BITS*2*i-1:BITS*2*(i-1)];
            dividend_gen[BITS*2*(i+2)-1:BITS*2*(i+1)] <= dividend_gen[BITS*2*(i+1)-1:BITS*2*i];
          end
        end // else: !if(!rst_n)
      end // always @ (posedge clk or negedge rst_n)
    end // block: pipeline
  endgenerate

  // last computation stage
  always @ (posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      div_by_zero_gen[STAGES-1]                           <= 0;
      start_gen[STAGES-1]                                 <= 0;
      negative_quotient_gen[STAGES-1]                     <= 0;
      quotient_gen[BITS*2*(STAGES-1)-1:BITS*2*(STAGES-2)] <= 0;
    end
    else begin
      div_by_zero_gen[STAGES-1]       <= div_by_zero_gen[STAGES-2];
      start_gen[STAGES-1]             <= start_gen[STAGES-2];
      negative_quotient_gen[STAGES-1] <= negative_quotient_gen[STAGES-2];
      if ( dividend_gen[BITS*2*(STAGES-1)-1:BITS*2*(STAGES-2)] >= divisor_gen[BITS*2*(STAGES-1)-1:BITS*2*(STAGES-2)] )
        quotient_gen[BITS*2*(STAGES-1)-1:BITS*2*(STAGES-2)] <= quotient_gen[BITS*2*(STAGES-2)-1:BITS*2*(STAGES-3)] | 1;
      else
        quotient_gen[BITS*2*(STAGES-1)-1:BITS*2*(STAGES-2)] <= quotient_gen[BITS*2*(STAGES-2)-1:BITS*2*(STAGES-3)];
    end // else: !if(!rst_n)
  end // always @ (posedge clk)

  // sign conversion stage
  always @ (posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      div_by_zero <= 0;
      data_valid  <= 0;
      quotient    <= 0;
    end
    else begin
      div_by_zero <= div_by_zero_gen[STAGES-1];
      data_valid  <= start_gen[STAGES-1];
      quotient    <= (negative_quotient_gen[STAGES-1]) ? ~quotient_gen[BITS*2*(STAGES-1)-1:BITS*2*(STAGES-2)] + 1 : quotient_gen[BITS*2*(STAGES-1)-1:BITS*2*(STAGES-2)];
    end
  end

endmodule