// ============================================================================
// gs_grad_divider.sv  (Ch352 — sequential signed divider for the triangle-setup gradient solve)
//
// Replaces the single combinational `grad_num_q[grad_step] / grad_det_q` in gs_stub. That combinational
// divider is a ~6700-cell, ~100ns cone at the 25MHz design clock — the worst setup path, and (the real lesson)
// it CANNOT be covered by any SDC timing exception: both a multicycle and a false_path made the Quartus fitter
// grind on its cone indefinitely (Place stuck <1% for hours). A sequential divider has REGISTERED iterations and
// no combinational cone, so every internal path is an ordinary single-cycle path that closes timing normally —
// no exception needed, no grind.
//
// BIT-EXACT to SystemVerilog signed `/`:
//   * truncation toward zero (divide magnitudes, then apply the XOR-of-signs);
//   * den == 0 -> quotient 0 (matches the gs_stub `if (grad_det_q==0) grad_quo=0` guard).
// Restoring division of the W-bit magnitudes (W iterations), one iteration per clock.
//
// Handshake: pulse `start` with num/den stable -> `busy` high for the solve -> `done` pulses for one cycle
// with `quo` valid (and stays valid until the next start). The gs_stub gradient FSM waits on `done`.
// ============================================================================
`timescale 1ns/1ps

module gs_grad_divider #(
    parameter int W = 56                     // operand width (gs_stub: grad_num_q / sign-extended grad_det)
)(
    input  logic                 clk,
    input  logic                 rst_n,
    input  logic                 start,       // pulse: begin a divide (num/den sampled this cycle)
    input  logic signed [W-1:0]  num,
    input  logic signed [W-1:0]  den,
    output logic signed [W-1:0]  quo,         // truncate-toward-zero quotient (== $signed(num)/$signed(den))
    output logic                 busy,
    output logic                 done          // 1-cycle pulse when quo is valid
);
    localparam int CW = $clog2(W+1);

    // magnitude + sign capture
    function automatic logic [W-1:0] absval(input logic signed [W-1:0] v);
        absval = v[W-1] ? (~v + 1'b1) : v;     // |v| (the most-negative wraps to 2^(W-1), which fits unsigned W)
    endfunction

    logic [W:0]    rem;        // remainder, W+1 bits for the compare/subtract
    logic [W-1:0]  qbuild;     // quotient under construction (also shifts the dividend out of its top)
    logic [W-1:0]  den_mag;    // |den|
    logic          qsign;      // result sign = num_sign ^ den_sign
    logic [CW-1:0] iter;
    logic          run;

    // one restoring step: bring the next dividend bit into rem, conditionally subtract |den|.
    wire [W:0]     rem_sh  = {rem[W-1:0], qbuild[W-1]};   // rem<<1 | dividend MSB
    wire           sub_ok  = (rem_sh >= {1'b0, den_mag});
    wire [W:0]     rem_nxt = sub_ok ? (rem_sh - {1'b0, den_mag}) : rem_sh;

    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            rem <= '0; qbuild <= '0; den_mag <= '0; qsign <= 1'b0; iter <= '0;
            run <= 1'b0; busy <= 1'b0; done <= 1'b0; quo <= '0;
        end else begin
            done <= 1'b0;
            if (start && !busy) begin
                if (den == '0) begin
                    // den == 0 -> quotient 0 (matches the gs_stub guard), available next cycle
                    quo  <= '0;
                    done <= 1'b1;
                    busy <= 1'b0;
                    run  <= 1'b0;
                end else begin
                    rem     <= '0;
                    qbuild  <= absval(num);
                    den_mag <= absval(den);
                    qsign   <= num[W-1] ^ den[W-1];
                    iter    <= CW'(W);
                    run     <= 1'b1;
                    busy    <= 1'b1;
                end
            end else if (run) begin
                rem    <= rem_nxt;
                qbuild <= {qbuild[W-2:0], sub_ok};   // shift dividend out, shift quotient bit in
                iter   <= iter - 1'b1;
                if (iter == CW'(1)) begin
                    // final iteration: qbuild now holds the W-bit magnitude quotient -> apply sign
                    run  <= 1'b0;
                    busy <= 1'b0;
                    done <= 1'b1;
                    quo  <= qsign ? (~{qbuild[W-2:0], sub_ok} + 1'b1) : {qbuild[W-2:0], sub_ok};
                end
            end
        end
    end
endmodule
