`timescale 1ns / 1ps
// matched_filter_multi_segment.v
module matched_filter_multi_segment (
    input wire clk,           // 100MHz
    input wire reset_n,
    
    // Input from DDC (100 MSPS)
    input wire signed [17:0] ddc_i,
    input wire signed [17:0] ddc_q,
    input wire ddc_valid,
    
    // Chirp control (from sequence controller)
    input wire use_long_chirp,      // 
    input wire [5:0] chirp_counter, // 
    
    // Microcontroller sync signals
    input wire mc_new_chirp,        // Toggle for new chirp (32)
    input wire mc_new_elevation,    // Toggle for new elevation (32)
    input wire mc_new_azimuth,      // Toggle for new azimuth (50)
    
    input wire [15:0] long_chirp_real,
    input wire [15:0] long_chirp_imag,
    input wire [15:0] short_chirp_real,
    input wire [15:0] short_chirp_imag,
    
    // Memory system interface
    output reg [1:0] segment_request,
    output wire [9:0] sample_addr_out,  // Tell memory which sample we need
    output reg mem_request,
    input wire mem_ready,
    
    // Output: Pulse compressed
    output wire signed [15:0] pc_i_w,
    output wire signed [15:0] pc_q_w,
    output wire pc_valid_w,
    
    // Status
    output reg [3:0] status
);

// ========== FIXED PARAMETERS ==========
parameter BUFFER_SIZE = 1024;
parameter LONG_CHIRP_SAMPLES = 3000;  // Still 3000 samples total
parameter SHORT_CHIRP_SAMPLES = 50;   // 0.5µs @ 100MHz
parameter OVERLAP_SAMPLES = 128;      // Standard for 1024-pt FFT
parameter SEGMENT_ADVANCE = BUFFER_SIZE - OVERLAP_SAMPLES;  // 896 samples
parameter DEBUG = 1;                  // Debug output control

// Calculate segments needed with overlap
// For 3072 samples with 128 overlap: 
// Segments = ceil((3072 - 128) / 896) = ceil(2944/896) = 4
parameter LONG_SEGMENTS = 4;          // Now exactly 4 segments!
parameter SHORT_SEGMENTS = 1;         // 50 samples padded to 1024

// ========== FIXED INTERNAL SIGNALS ==========
reg signed [31:0] pc_i, pc_q;
reg pc_valid;

// Dual buffer for overlap-save
reg signed [15:0] input_buffer_i [0:BUFFER_SIZE-1];
reg signed [15:0] input_buffer_q [0:BUFFER_SIZE-1];
reg [10:0] buffer_write_ptr;
reg [10:0] buffer_read_ptr;
reg buffer_has_data;
reg buffer_processing;
reg [15:0] chirp_samples_collected;

// State machine
reg [3:0] state;
localparam ST_IDLE = 0;
localparam ST_COLLECT_DATA = 1;
localparam ST_ZERO_PAD = 2;
localparam ST_WAIT_REF = 3;
localparam ST_PROCESSING = 4;
localparam ST_WAIT_FFT = 5;
localparam ST_OUTPUT = 6;
localparam ST_NEXT_SEGMENT = 7;

// Segment tracking
reg [2:0] current_segment;        // 0-3
reg [2:0] total_segments;
reg segment_done;
reg chirp_complete;

// Microcontroller sync detection
reg mc_new_chirp_prev, mc_new_elevation_prev, mc_new_azimuth_prev;
wire chirp_start_pulse = mc_new_chirp && !mc_new_chirp_prev;
wire elevation_change_pulse = mc_new_elevation && !mc_new_elevation_prev;
wire azimuth_change_pulse = mc_new_azimuth && !mc_new_azimuth_prev;

// Processing chain signals
wire [15:0] fft_pc_i, fft_pc_q;
wire fft_pc_valid;
wire [3:0] fft_chain_state;

// Buffer for FFT input
reg [15:0] fft_input_i, fft_input_q;
reg fft_input_valid;
reg fft_start;

// ========== SAMPLE ADDRESS OUTPUT ==========
assign sample_addr_out = buffer_read_ptr;

// ========== MICROCONTROLLER SYNC ==========
always @(posedge clk or negedge reset_n) begin
    if (!reset_n) begin
        mc_new_chirp_prev <= 1'b0;
        mc_new_elevation_prev <= 1'b0;
        mc_new_azimuth_prev <= 1'b0;
    end else begin
        mc_new_chirp_prev <= mc_new_chirp;
        mc_new_elevation_prev <= mc_new_elevation;
        mc_new_azimuth_prev <= mc_new_azimuth;
    end
end

// ========== BUFFER INITIALIZATION ==========
integer buf_init;
initial begin
    for (buf_init = 0; buf_init < BUFFER_SIZE; buf_init = buf_init + 1) begin
        input_buffer_i[buf_init] = 16'd0;
        input_buffer_q[buf_init] = 16'd0;
    end
end

// ========== FIXED STATE MACHINE WITH OVERLAP-SAVE ==========
integer i;
always @(posedge clk or negedge reset_n) begin
    if (!reset_n) begin
        state <= ST_IDLE;
        buffer_write_ptr <= 0;
        buffer_read_ptr <= 0;
        buffer_has_data <= 0;
        buffer_processing <= 0;
        current_segment <= 0;
        segment_done <= 0;
        segment_request <= 0;
        mem_request <= 0;
        pc_valid <= 0;
        status <= 0;
        chirp_samples_collected <= 0;
        chirp_complete <= 0;
        fft_input_valid <= 0;
        fft_start <= 0;
    end else begin
        pc_valid <= 0;
        mem_request <= 0;
        fft_input_valid <= 0;
        
        case (state)
            ST_IDLE: begin
                // Reset for new chirp
                buffer_write_ptr <= 0;
                buffer_read_ptr <= 0;
                buffer_has_data <= 0;
                buffer_processing <= 0;
                current_segment <= 0;
                segment_done <= 0;
                chirp_samples_collected <= 0;
                chirp_complete <= 0;
                
                // Wait for chirp start from microcontroller
                if (chirp_start_pulse) begin
                    state <= ST_COLLECT_DATA;
                    total_segments <= use_long_chirp ? LONG_SEGMENTS[2:0] : SHORT_SEGMENTS[2:0];
                    
                    $display("[MULTI_SEG_FIXED] Starting %s chirp, segments: %d",
                             use_long_chirp ? "LONG" : "SHORT", 
                             use_long_chirp ? LONG_SEGMENTS : SHORT_SEGMENTS);
                    $display("[MULTI_SEG_FIXED] Overlap: %d samples, Advance: %d samples",
                             OVERLAP_SAMPLES, SEGMENT_ADVANCE);
                end
            end
            
            ST_COLLECT_DATA: begin
                // Collect samples for current segment with overlap-save
                if (ddc_valid) begin
                    // Store in buffer
                    input_buffer_i[buffer_write_ptr] <= ddc_i[17:2] + ddc_i[1];
                    input_buffer_q[buffer_write_ptr] <= ddc_q[17:2] + ddc_q[1];
                    
                    buffer_write_ptr <= buffer_write_ptr + 1;
                    chirp_samples_collected <= chirp_samples_collected + 1;
                    
                    // Debug: Show first few samples
                    if (chirp_samples_collected < 10 && buffer_write_ptr < 10) begin
                        $display("[MULTI_SEG_FIXED] Store[%0d]: I=%h Q=%h", 
                                 buffer_write_ptr, 
                                 ddc_i[17:2] + ddc_i[1], 
                                 ddc_q[17:2] + ddc_q[1]);
                    end
                    
                    // Check conditions based on chirp type
                    if (use_long_chirp) begin
                        // LONG CHIRP: Process when we have SEGMENT_ADVANCE new samples
                        // (buffer contains overlap from previous segment + new data)
                        
                        // Check if we have enough NEW data to process
                        if (buffer_write_ptr >= SEGMENT_ADVANCE) begin
                            buffer_has_data <= 1;
                            state <= ST_WAIT_REF;
                            segment_request <= current_segment[1:0];  // Use lower 2 bits
                            mem_request <= 1;
                            
                            $display("[MULTI_SEG_FIXED] Segment %d ready: %d samples collected",
                                     current_segment, chirp_samples_collected);
                        end
                        
                        // Check if end of chirp reached
                        if (chirp_samples_collected >= LONG_CHIRP_SAMPLES - 1) begin
                            chirp_complete <= 1;
                            $display("[MULTI_SEG_FIXED] End of long chirp reached");
                        end
                    end else begin
                        // SHORT CHIRP: Only 50 samples, then zero-pad
                        if (chirp_samples_collected >= SHORT_CHIRP_SAMPLES - 1) begin
                            state <= ST_ZERO_PAD;
                            $display("[MULTI_SEG_FIXED] Short chirp: collected %d samples, starting zero-pad",
                                     chirp_samples_collected + 1);
                        end
                    end
                end
            end
            
            ST_ZERO_PAD: begin
                // For short chirp: zero-pad remaining buffer
                input_buffer_i[buffer_write_ptr] <= 16'd0;
                input_buffer_q[buffer_write_ptr] <= 16'd0;
                buffer_write_ptr <= buffer_write_ptr + 1;
                
                if (buffer_write_ptr >= BUFFER_SIZE - 1) begin
                    // Done zero-padding
                    buffer_has_data <= 1;
                    buffer_write_ptr <= 0;
                    state <= ST_WAIT_REF;
                    segment_request <= 0;  // Only one segment for short chirp
                    mem_request <= 1;
                    $display("[MULTI_SEG_FIXED] Zero-pad complete, buffer full");
                end
            end
            
            ST_WAIT_REF: begin
                // Wait for memory to provide reference coefficients
                if (mem_ready) begin
                    // Start processing
                    buffer_processing <= 1;
                    buffer_read_ptr <= 0;
                    fft_start <= 1;
                    state <= ST_PROCESSING;
                    
                    $display("[MULTI_SEG_FIXED] Reference ready, starting processing segment %d",
                             current_segment);
                end
            end
            
            ST_PROCESSING: begin
                // Feed data to FFT chain
                if ((buffer_processing) && (buffer_read_ptr < BUFFER_SIZE)) begin
                    // 1. Feed ADC data to FFT
                    fft_input_i <= input_buffer_i[buffer_read_ptr];
                    fft_input_q <= input_buffer_q[buffer_read_ptr];
                    fft_input_valid <= 1;
                    
                    // 2. Request corresponding reference sample
                    mem_request <= 1'b1;
                    
                    // Debug every 100 samples
                    if (buffer_read_ptr % 100 == 0) begin
                        $display("[MULTI_SEG_FIXED] Processing[%0d]: ADC I=%h Q=%h",
                                buffer_read_ptr,
                                input_buffer_i[buffer_read_ptr],
                                input_buffer_q[buffer_read_ptr]);
                    end
                    
                    buffer_read_ptr <= buffer_read_ptr + 1;
                    
                end else if (buffer_read_ptr >= BUFFER_SIZE) begin
                    // Done feeding buffer
                    fft_input_valid <= 0;
                    mem_request <= 0;
                    buffer_processing <= 0;
                    buffer_has_data <= 0;
                    state <= ST_WAIT_FFT;  // CRITICAL: Wait for FFT completion
                    
                    $display("[MULTI_SEG_FIXED] Finished feeding %d samples to FFT, waiting...",
                             BUFFER_SIZE);
                end
            end
            
            ST_WAIT_FFT: begin
                // Wait for the processing chain to complete (2159 cycles latency)
                if (fft_pc_valid) begin
                    state <= ST_OUTPUT;
                    $display("[MULTI_SEG_FIXED] FFT processing complete for segment %d",
                             current_segment);
                end
            end
            
            ST_OUTPUT: begin
                // Store FFT output
                pc_i <= fft_pc_i;
                pc_q <= fft_pc_q;
                pc_valid <= 1;
                segment_done <= 1;
                
                $display("[MULTI_SEG_FIXED] Output segment %d: I=%h Q=%h",
                         current_segment, fft_pc_i, fft_pc_q);
                
                // Check if we need more segments
                if (current_segment < total_segments - 1 || !chirp_complete) begin
                    state <= ST_NEXT_SEGMENT;
                end else begin
                    // All segments complete
                    state <= ST_IDLE;
                    $display("[MULTI_SEG_FIXED] All %d segments complete",
                             total_segments);
                end
            end
            
            ST_NEXT_SEGMENT: begin
                // Prepare for next segment with OVERLAP-SAVE
                current_segment <= current_segment + 1;
                segment_done <= 0;
                
                if (use_long_chirp) begin
                    // OVERLAP-SAVE: Keep last OVERLAP_SAMPLES for next segment
                    // Shift data in buffer to preserve overlap
                    
                    for (i = 0; i < OVERLAP_SAMPLES; i = i + 1) begin
                        input_buffer_i[i] <= input_buffer_i[i + SEGMENT_ADVANCE];
                        input_buffer_q[i] <= input_buffer_q[i + SEGMENT_ADVANCE];
                    end
                    
                    // Start writing after the overlap
                    buffer_write_ptr <= OVERLAP_SAMPLES;
                    
                    $display("[MULTI_SEG_FIXED] Overlap-save: kept %d samples, write_ptr=%d",
                             OVERLAP_SAMPLES, OVERLAP_SAMPLES);
                end else begin
                    // Short chirp: only one segment
                    buffer_write_ptr <= 0;
                end
                
                // Continue collecting or finish
                if (!chirp_complete) begin
                    state <= ST_COLLECT_DATA;
                    $display("[MULTI_SEG_FIXED] Starting segment %d/%d",
                             current_segment + 1, total_segments);
                end else begin
                    state <= ST_IDLE;
                end
            end
        endcase
        
        // Update status
        status <= {state[2:0], use_long_chirp};
    end
end

// ========== PROCESSING CHAIN INSTANTIATION ==========
matched_filter_processing_chain m_f_p_c(
    .clk(clk),
    .reset_n(reset_n),
    
    // Input ADC Data
    .adc_data_i(fft_input_i),
    .adc_data_q(fft_input_q),
    .adc_valid(fft_input_valid),// && buffer_processing),
    
    // Chirp Selection
    .chirp_counter(chirp_counter),
    
    // Reference Chirp Memory Interfaces
    .long_chirp_real(long_chirp_real),
    .long_chirp_imag(long_chirp_imag),
    .short_chirp_real(short_chirp_real),
    .short_chirp_imag(short_chirp_imag),
    
    // Output
    .range_profile_i(fft_pc_i),
    .range_profile_q(fft_pc_q),
    .range_profile_valid(fft_pc_valid),
    
    // Status
    .chain_state(fft_chain_state)
);

// ========== DEBUG MONITOR ==========
reg [31:0] dbg_cycles;
always @(posedge clk or negedge reset_n) begin
    if (!reset_n) begin
        dbg_cycles <= 0;
    end else begin
        dbg_cycles <= dbg_cycles + 1;
        
        // Monitor state transitions
        if (dbg_cycles % 1000 == 0 && state != ST_IDLE) begin
            $display("[MULTI_SEG_MONITOR @%0d] state=%0d, segment=%0d/%0d, samples=%0d",
                     dbg_cycles, state, current_segment, total_segments,
                     chirp_samples_collected);
        end
    end
end

// ========== OUTPUT CONNECTIONS ==========
assign pc_i_w = fft_pc_i;
assign pc_q_w = fft_pc_q;
assign pc_valid_w = fft_pc_valid;

endmodule