module cordic_sincos_perf (
    input wire clk,
    input wire rst,
    input wire [15:0] angle_in,
    input wire in_valid,
    output reg [15:0] sin_out,
    output reg [15:0] cos_out,
    output reg out_valid
);

    // Fixed-point Parameters
    // Angle: Q2.14, Sin/Cos: Q1.15 Output, Q2.14 Internal
    localparam signed [15:0] INIT_X = 16'h26DD; // 0.60725 in Q2.14

    // Pipeline Depth
    localparam DEPTH = 16;
    
    // Pipeline Registers
    // x_pipe[i] is the output of stage i, input to stage i+1
    // We need indices 0 to DEPTH-1?
    // Let's index such that pipe[0] is input to stage 0.
    // pipe[1] is output of stage 0.
    reg signed [15:0] x_pipe [0:DEPTH];
    reg signed [15:0] y_pipe [0:DEPTH];
    reg signed [15:0] z_pipe [0:DEPTH];
    reg               v_pipe [0:DEPTH];
    
    // ATAN Table
    reg signed [15:0] atan_table [0:15];
    initial begin
        atan_table[0] = 16'h3244;
        atan_table[1] = 16'h1DAC;
        atan_table[2] = 16'h0FAE;
        atan_table[3] = 16'h07F5;
        atan_table[4] = 16'h03FF;
        atan_table[5] = 16'h0200;
        atan_table[6] = 16'h0100;
        atan_table[7] = 16'h0080;
        atan_table[8] = 16'h0040;
        atan_table[9] = 16'h0020;
        atan_table[10] = 16'h0010;
        atan_table[11] = 16'h0008;
        atan_table[12] = 16'h0004;
        atan_table[13] = 16'h0002;
        atan_table[14] = 16'h0001;
        atan_table[15] = 16'h0000;
    end

    integer i;
    
    always @(posedge clk) begin
        if (rst) begin
            for (i = 0; i <= DEPTH; i = i + 1) begin
                v_pipe[i] <= 0;
                x_pipe[i] <= 0;
                y_pipe[i] <= 0;
                z_pipe[i] <= 0;
            end
            out_valid <= 0;
            sin_out <= 0;
            cos_out <= 0;
        end else begin
            // Stage 0 Input
            v_pipe[0] <= in_valid;
            if (in_valid) begin
                x_pipe[0] <= INIT_X;
                y_pipe[0] <= 0;
                z_pipe[0] <= angle_in;
            end
            
            // Pipelined Stages 0 to 15
            for (i = 0; i < DEPTH; i = i + 1) begin
                // Logic for stage i -> produces pipe[i+1]
                if (v_pipe[i]) begin
                     // Determine direction: z >= 0 ? 1 : -1
                     // Logic: if z >= 0, rotate pos (sub angle)
                     if (!z_pipe[i][15]) begin
                         // Positive Z: x' = x - y>>i, y' = y + x>>i, z' = z - atan
                         x_pipe[i+1] <= x_pipe[i] - (y_pipe[i] >>> i);
                         y_pipe[i+1] <= y_pipe[i] + (x_pipe[i] >>> i);
                         z_pipe[i+1] <= z_pipe[i] - atan_table[i];
                     end else begin
                         // Negative Z: x' = x + y>>i, y' = y - x>>i, z' = z + atan
                         x_pipe[i+1] <= x_pipe[i] + (y_pipe[i] >>> i);
                         y_pipe[i+1] <= y_pipe[i] - (x_pipe[i] >>> i);
                         z_pipe[i+1] <= z_pipe[i] + atan_table[i];
                     end
                end
                v_pipe[i+1] <= v_pipe[i];
            end
            
            // Output Stage (from pipe[16])
            out_valid <= v_pipe[DEPTH];
            if (v_pipe[DEPTH]) begin
                // Saturation logic (Q2.14 -> Q1.15)
                // Y (Sin)
                if (y_pipe[DEPTH] >= $signed(16'h4000)) 
                    sin_out <= 16'h7FFF;
                else if (y_pipe[DEPTH] < $signed(16'hC000))
                    sin_out <= 16'h8000;
                else 
                    sin_out <= (y_pipe[DEPTH] <<< 1);

                // X (Cos)
                if (x_pipe[DEPTH] >= $signed(16'h4000)) 
                    cos_out <= 16'h7FFF;
                else if (x_pipe[DEPTH] < $signed(16'hC000))
                    cos_out <= 16'h8000;
                else 
                    cos_out <= (x_pipe[DEPTH] <<< 1);
            end else begin
                out_valid <= 0;
            end
        end
    end

endmodule
