//==============================================================================
// Enhanced PCILeech TLP 128-bit BAR Controller
// Generated by PCILeech Firmware Generator
//
// This module implements an advanced memory region management system with:
// - Custom PIO regions for PCILeech operations
// - Device Control Region (0x0000-0x00FF)
// - Status Registers (0x0100-0x01FF) 
// - Data Buffer (0x0200-0x03FF)
// - MSI-X Table and PBA region handling
// - Integration with existing BAR controller functionality
// - Device-specific timing and behavior patterns
//
// Features:
// - 128-bit TLP interface for high-performance data transfer
// - Dynamic memory region configuration based on device profiling
// - Advanced error detection and recovery mechanisms
// - PCILeech command processing and response generation
// - Manufacturing variance simulation support
// - Comprehensive interrupt handling with MSI-X integration
//==============================================================================

module pcileech_tlps128_bar_controller #(
    // BAR Configuration Parameters
    parameter BAR_APERTURE_SIZE = {{ bar_config.aperture_size | default(65536) }},
    parameter BAR_INDEX = {{ bar_config.bar_index | default(0) }},
    parameter BAR_TYPE = {{ bar_config.bar_type | default(0) }}, // 0=32-bit, 1=64-bit
    parameter BAR_PREFETCHABLE = {{ '1\'b1' if bar_config.prefetchable else '1\'b0' }},
    
    // MSI-X Configuration
    parameter NUM_MSIX = {{ msix_config.num_vectors | default(4) }},
    parameter MSIX_TABLE_BIR = {{ msix_config.table_bir | default(0) }},
    parameter MSIX_TABLE_OFFSET = {{ msix_config.table_offset | default('h1000') }},
    parameter MSIX_PBA_BIR = {{ msix_config.pba_bir | default(0) }},
    parameter MSIX_PBA_OFFSET = {{ msix_config.pba_offset | default('h2000') }},
    
    // PCILeech Memory Layout
    parameter DEVICE_CTRL_BASE = 32'h00000000,  // Device Control Region
    parameter DEVICE_CTRL_SIZE = 32'h00000100,  // 256 bytes
    parameter STATUS_REG_BASE = 32'h00000100,   // Status Registers
    parameter STATUS_REG_SIZE = 32'h00000100,   // 256 bytes
    parameter DATA_BUFFER_BASE = 32'h00000200,  // Data Buffer
    parameter DATA_BUFFER_SIZE = 32'h00000200,  // 512 bytes
    parameter CUSTOM_REGION_BASE = 32'h00000400, // Custom PIO Region
    parameter CUSTOM_REGION_SIZE = 32'h00000C00, // 3KB
    
    // Device-Specific Timing Parameters
    parameter READ_LATENCY = {{ timing_config.read_latency | default(4) }},
    parameter WRITE_LATENCY = {{ timing_config.write_latency | default(2) }},
    parameter BURST_LENGTH = {{ timing_config.burst_length | default(16) }},
    parameter INTER_BURST_GAP = {{ timing_config.inter_burst_gap | default(8) }},
    
    // Performance and Error Handling
    parameter ENABLE_ERROR_INJECTION = {{ '1\'b1' if device_config.enable_error_injection else '1\'b0'  }},
    parameter ENABLE_PERFORMANCE_COUNTERS = {{ '1\'b1' if device_config.enable_perf_counters else '1\'b0' }},
    parameter TIMEOUT_CYCLES = {{ timing_config.timeout_cycles | default(1024) }}
) (
    // Clock and Reset
    input  logic                clk,
    input  logic                reset_n,
    
    // PCIe TLP 128-bit Interface
    input  logic                tlp_rx_valid,
    input  logic [127:0]        tlp_rx_data,
    input  logic                tlp_rx_sop,
    input  logic                tlp_rx_eop,
    input  logic [3:0]          tlp_rx_empty,
    input  logic                tlp_rx_err,
    output logic                tlp_rx_ready,
    
    output logic                tlp_tx_valid,
    output logic [127:0]        tlp_tx_data,
    output logic                tlp_tx_sop,
    output logic                tlp_tx_eop,
    output logic [3:0]          tlp_tx_empty,
    input  logic                tlp_tx_ready,
    output logic                tlp_tx_err,
    
    // BAR Access Interface
    input  logic [31:0]         bar_addr,
    input  logic [31:0]         bar_wr_data,
    input  logic [3:0]          bar_wr_be,
    input  logic                bar_wr_en,
    input  logic                bar_rd_en,
    output logic [31:0]         bar_rd_data,
    output logic                bar_rd_valid,
    
    // Configuration Space Interface
    input  logic                cfg_ext_read_received,
    input  logic                cfg_ext_write_received,
    input  logic [9:0]          cfg_ext_register_number,
    input  logic [3:0]          cfg_ext_function_number,
    input  logic [31:0]         cfg_ext_write_data,
    input  logic [3:0]          cfg_ext_write_byte_enable,
    output logic [31:0]         cfg_ext_read_data,
    output logic                cfg_ext_read_data_valid,
    
    // MSI-X Interrupt Interface
    output logic                msix_interrupt,
    output logic [10:0]         msix_vector,
    input  logic                msix_interrupt_ack,
    
    // PCILeech Control Interface
    input  logic                pcileech_enable,
    input  logic [31:0]         pcileech_command,
    input  logic [63:0]         pcileech_address,
    input  logic [31:0]         pcileech_length,
    output logic [31:0]         pcileech_status,
    output logic                pcileech_ready,
    
    // DMA Interface
    output logic                dma_read_req,
    output logic [63:0]         dma_read_addr,
    output logic [31:0]         dma_read_len,
    input  logic                dma_read_ack,
    input  logic [127:0]        dma_read_data,
    input  logic                dma_read_valid,
    
    output logic                dma_write_req,
    output logic [63:0]         dma_write_addr,
    output logic [31:0]         dma_write_len,
    output logic [127:0]        dma_write_data,
    input  logic                dma_write_ack,
    
    // Status and Debug
    output logic [31:0]         error_status,
    output logic [31:0]         performance_counter_0,
    output logic [31:0]         performance_counter_1,
    output logic [7:0]          debug_state
);

    // ========================================================================
    // Local Parameters and Type Definitions
    // ========================================================================
    
    // TLP Types
    localparam [4:0] TLP_MEM_READ_32    = 5'b00000;
    localparam [4:0] TLP_MEM_READ_64    = 5'b00001;
    localparam [4:0] TLP_MEM_WRITE_32   = 5'b01000;
    localparam [4:0] TLP_MEM_WRITE_64   = 5'b01001;
    localparam [4:0] TLP_COMPLETION     = 5'b01010;
    localparam [4:0] TLP_COMPLETION_DATA = 5'b01011;
    
    // PCILeech Command Opcodes
    localparam [7:0] PCILEECH_CMD_READ      = 8'h01;
    localparam [7:0] PCILEECH_CMD_WRITE     = 8'h02;
    localparam [7:0] PCILEECH_CMD_PROBE     = 8'h03;
    localparam [7:0] PCILEECH_CMD_WRITE_SCATTER = 8'h04;
    localparam [7:0] PCILEECH_CMD_READ_SCATTER  = 8'h05;
    localparam [7:0] PCILEECH_CMD_EXEC      = 8'h06;
    localparam [7:0] PCILEECH_CMD_STATUS    = 8'h07;
    
    // Memory Region Selectors
    typedef enum logic [3:0] {
        REGION_DEVICE_CTRL,
        REGION_STATUS_REG,
        REGION_DATA_BUFFER,
        REGION_CUSTOM_PIO,
        REGION_MSIX_TABLE,
        REGION_MSIX_PBA,
        REGION_CONFIG_SHADOW,
        REGION_GENERAL_MEM,
        REGION_INVALID
    } region_select_t;
    
    // State Machine States
    typedef enum logic [3:0] {
        STATE_IDLE,
        STATE_TLP_DECODE,
        STATE_ADDRESS_DECODE,
        STATE_READ_PROCESS,
        STATE_WRITE_PROCESS,
        STATE_COMPLETION_GEN,
        STATE_DMA_READ,
        STATE_DMA_WRITE,
        STATE_ERROR_HANDLE,
        STATE_PCILEECH_EXEC
    } controller_state_t;
    
    // ========================================================================
    // Internal Signal Declarations
    // ========================================================================
    
    // State Machine
    controller_state_t current_state, next_state;
    
    // TLP Parsing
    logic [127:0]       tlp_header;
    logic [4:0]         tlp_type;
    logic [2:0]         tlp_tc;
    logic               tlp_td, tlp_ep, tlp_attr, tlp_th;
    logic [9:0]         tlp_length;
    logic [15:0]        tlp_requester_id;
    logic [7:0]         tlp_tag;
    logic [3:0]         tlp_first_be, tlp_last_be;
    logic [63:0]        tlp_address;
    logic [127:0]       tlp_data;
    
    // Address Decoding
    region_select_t     target_region;
    logic [31:0]        region_offset;
    logic               address_valid;
    
    // Memory Regions
    (* ram_style = "block" *) logic [31:0] device_ctrl_mem [0:(DEVICE_CTRL_SIZE/4)-1];
    (* ram_style = "block" *) logic [31:0] status_reg_mem [0:(STATUS_REG_SIZE/4)-1];
    (* ram_style = "block" *) logic [31:0] data_buffer_mem [0:(DATA_BUFFER_SIZE/4)-1];
    (* ram_style = "block" *) logic [31:0] custom_region_mem [0:(CUSTOM_REGION_SIZE/4)-1];
    
    // PCILeech Control Registers
    logic [31:0]        pcileech_ctrl_reg;
    logic [31:0]        pcileech_stat_reg;
    logic [63:0]        pcileech_addr_reg;
    logic [31:0]        pcileech_len_reg;
    logic [31:0]        pcileech_data_reg;
    
    // Performance Counters
    logic [31:0]        perf_counter_0;
    logic [31:0]        perf_counter_1;
    logic [31:0]        read_count;
    logic [31:0]        write_count;
    logic [31:0]        error_count;
    
    // Timing Control
    logic [15:0]        timing_counter;
    logic [7:0]         burst_counter;
    logic               timing_active;
    logic               burst_in_progress;
    
    // Error Handling
    logic [31:0]        error_status_reg;
    logic               timeout_error;
    logic               address_error;
    logic               tlp_error;
    logic [15:0]        timeout_counter;
    
    // MSI-X Integration
    logic               msix_table_access;
    logic               msix_pba_access;
    logic [31:0]        msix_table_data;
    logic [31:0]        msix_pba_data;
    
    // Configuration Space Shadow
    logic               cfg_shadow_access;
    logic [31:0]        cfg_shadow_data;
    
    // ========================================================================
    // TLP Parsing and Decoding
    // ========================================================================
    
    // TLP Header Parsing
    always_ff @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            tlp_header <= '0;
            tlp_type <= '0;
            tlp_tc <= '0;
            tlp_td <= '0;
            tlp_ep <= '0;
            tlp_attr <= '0;
            tlp_th <= '0;
            tlp_length <= '0;
            tlp_requester_id <= '0;
            tlp_tag <= '0;
            tlp_first_be <= '0;
            tlp_last_be <= '0;
            tlp_address <= '0;
            tlp_data <= '0;
        end else if (tlp_rx_valid && tlp_rx_ready && tlp_rx_sop) begin
            tlp_header <= tlp_rx_data;
            
            // Parse TLP header fields
            tlp_type <= tlp_rx_data[127:123];
            tlp_tc <= tlp_rx_data[122:120];
            tlp_td <= tlp_rx_data[119];
            tlp_ep <= tlp_rx_data[118];
            tlp_attr <= tlp_rx_data[117];
            tlp_th <= tlp_rx_data[116];
            tlp_length <= tlp_rx_data[105:96];
            tlp_requester_id <= tlp_rx_data[95:80];
            tlp_tag <= tlp_rx_data[79:72];
            tlp_first_be <= tlp_rx_data[71:68];
            tlp_last_be <= tlp_rx_data[67:64];
            
            // Extract address based on TLP type
            if (tlp_rx_data[127:123] == TLP_MEM_READ_64 || tlp_rx_data[127:123] == TLP_MEM_WRITE_64) begin
                tlp_address <= {tlp_rx_data[63:32], tlp_rx_data[31:2], 2'b00};
            end else begin
                tlp_address <= {32'h00000000, tlp_rx_data[63:34], 2'b00};
            end
        end else if (tlp_rx_valid && tlp_rx_ready && !tlp_rx_sop) begin
            tlp_data <= tlp_rx_data;
        end
    end
    
    // ========================================================================
    // Address Decoding and Region Selection
    // ========================================================================
    
    always_comb begin
        target_region = REGION_INVALID;
        region_offset = '0;
        address_valid = 1'b0;
        
        if (tlp_address >= DEVICE_CTRL_BASE && 
            tlp_address < (DEVICE_CTRL_BASE + DEVICE_CTRL_SIZE)) begin
            target_region = REGION_DEVICE_CTRL;
            region_offset = tlp_address - DEVICE_CTRL_BASE;
            address_valid = 1'b1;
        end else if (tlp_address >= STATUS_REG_BASE && 
                     tlp_address < (STATUS_REG_BASE + STATUS_REG_SIZE)) begin
            target_region = REGION_STATUS_REG;
            region_offset = tlp_address - STATUS_REG_BASE;
            address_valid = 1'b1;
        end else if (tlp_address >= DATA_BUFFER_BASE && 
                     tlp_address < (DATA_BUFFER_BASE + DATA_BUFFER_SIZE)) begin
            target_region = REGION_DATA_BUFFER;
            region_offset = tlp_address - DATA_BUFFER_BASE;
            address_valid = 1'b1;
        end else if (tlp_address >= CUSTOM_REGION_BASE && 
                     tlp_address < (CUSTOM_REGION_BASE + CUSTOM_REGION_SIZE)) begin
            target_region = REGION_CUSTOM_PIO;
            region_offset = tlp_address - CUSTOM_REGION_BASE;
            address_valid = 1'b1;
        end else if (tlp_address >= MSIX_TABLE_OFFSET && 
                     tlp_address < (MSIX_TABLE_OFFSET + NUM_MSIX * 16)) begin
            target_region = REGION_MSIX_TABLE;
            region_offset = tlp_address - MSIX_TABLE_OFFSET;
            address_valid = 1'b1;
        end else if (tlp_address >= MSIX_PBA_OFFSET && 
                     tlp_address < (MSIX_PBA_OFFSET + ((NUM_MSIX + 31) / 32) * 4)) begin
            target_region = REGION_MSIX_PBA;
            region_offset = tlp_address - MSIX_PBA_OFFSET;
            address_valid = 1'b1;
        end else if (tlp_address < BAR_APERTURE_SIZE) begin
            target_region = REGION_GENERAL_MEM;
            region_offset = tlp_address;
            address_valid = 1'b1;
        end
    end
    
    // ========================================================================
    // Main Controller State Machine
    // ========================================================================
    
    always_ff @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            current_state <= STATE_IDLE;
        end else begin
            current_state <= next_state;
        end
    end
    
    always_comb begin
        next_state = current_state;
        tlp_rx_ready = 1'b0;
        tlp_tx_valid = 1'b0;
        tlp_tx_data = '0;
        tlp_tx_sop = 1'b0;
        tlp_tx_eop = 1'b0;
        tlp_tx_empty = '0;
        tlp_tx_err = 1'b0;
        
        case (current_state)
            STATE_IDLE: begin
                tlp_rx_ready = 1'b1;
                if (tlp_rx_valid && tlp_rx_sop) begin
                    next_state = STATE_TLP_DECODE;
                end
            end
            
            STATE_TLP_DECODE: begin
                tlp_rx_ready = 1'b1;
                next_state = STATE_ADDRESS_DECODE;
            end
            
            STATE_ADDRESS_DECODE: begin
                if (address_valid) begin
                    if (tlp_type == TLP_MEM_READ_32 || tlp_type == TLP_MEM_READ_64) begin
                        next_state = STATE_READ_PROCESS;
                    end else if (tlp_type == TLP_MEM_WRITE_32 || tlp_type == TLP_MEM_WRITE_64) begin
                        next_state = STATE_WRITE_PROCESS;
                    end else begin
                        next_state = STATE_ERROR_HANDLE;
                    end
                end else begin
                    next_state = STATE_ERROR_HANDLE;
                end
            end
            
            STATE_READ_PROCESS: begin
                // Process read based on target region
                next_state = STATE_COMPLETION_GEN;
            end
            
            STATE_WRITE_PROCESS: begin
                tlp_rx_ready = 1'b1;
                if (tlp_rx_valid && tlp_rx_eop) begin
                    next_state = STATE_COMPLETION_GEN;
                end
            end
            
            STATE_COMPLETION_GEN: begin
                tlp_tx_valid = 1'b1;
                tlp_tx_sop = 1'b1;
                tlp_tx_eop = 1'b1;
                if (tlp_tx_ready) begin
                    next_state = STATE_IDLE;
                end
            end
            
            STATE_DMA_READ: begin
                // Handle DMA read operations
                if (dma_read_ack) begin
                    next_state = STATE_COMPLETION_GEN;
                end
            end
            
            STATE_DMA_WRITE: begin
                // Handle DMA write operations
                if (dma_write_ack) begin
                    next_state = STATE_COMPLETION_GEN;
                end
            end
            
            STATE_ERROR_HANDLE: begin
                // Generate error completion
                tlp_tx_valid = 1'b1;
                tlp_tx_sop = 1'b1;
                tlp_tx_eop = 1'b1;
                tlp_tx_err = 1'b1;
                if (tlp_tx_ready) begin
                    next_state = STATE_IDLE;
                end
            end
            
            STATE_PCILEECH_EXEC: begin
                // Execute PCILeech commands
                if (pcileech_ready) begin
                    next_state = STATE_COMPLETION_GEN;
                end
            end
        endcase
    end
    
    // ========================================================================
    // Memory Region Access Logic
    // ========================================================================
    
    // Device Control Region Access
    logic [31:0] device_ctrl_rdata;
    always_ff @(posedge clk) begin
        if (current_state == STATE_WRITE_PROCESS && target_region == REGION_DEVICE_CTRL) begin
            if (region_offset[31:2] < (DEVICE_CTRL_SIZE/4)) begin
                device_ctrl_mem[region_offset[31:2]] <= tlp_data[31:0];
            end
        end
    end
    
    always_comb begin
        device_ctrl_rdata = '0;
        if (target_region == REGION_DEVICE_CTRL && region_offset[31:2] < (DEVICE_CTRL_SIZE/4)) begin
            device_ctrl_rdata = device_ctrl_mem[region_offset[31:2]];
        end
    end
    
    // Status Register Region Access
    logic [31:0] status_reg_rdata;
    always_ff @(posedge clk) begin
        if (current_state == STATE_WRITE_PROCESS && target_region == REGION_STATUS_REG) begin
            if (region_offset[31:2] < (STATUS_REG_SIZE/4)) begin
                status_reg_mem[region_offset[31:2]] <= tlp_data[31:0];
            end
        end
    end
    
    always_comb begin
        status_reg_rdata = '0;
        if (target_region == REGION_STATUS_REG) begin
            case (region_offset[7:2])
                6'h00: status_reg_rdata = pcileech_stat_reg;
                6'h01: status_reg_rdata = error_status_reg;
                6'h02: status_reg_rdata = perf_counter_0;
                6'h03: status_reg_rdata = perf_counter_1;
                6'h04: status_reg_rdata = read_count;
                6'h05: status_reg_rdata = write_count;
                6'h06: status_reg_rdata = error_count;
                6'h07: status_reg_rdata = {{ device_config.device_signature | default('32\'hDEADBEEF') }};
                default: begin
                    if (region_offset[31:2] < (STATUS_REG_SIZE/4)) begin
                        status_reg_rdata = status_reg_mem[region_offset[31:2]];
                    end
                end
            endcase
        end
    end
    
    // Data Buffer Region Access
    logic [31:0] data_buffer_rdata;
    always_ff @(posedge clk) begin
        if (current_state == STATE_WRITE_PROCESS && target_region == REGION_DATA_BUFFER) begin
            if (region_offset[31:2] < (DATA_BUFFER_SIZE/4)) begin
                data_buffer_mem[region_offset[31:2]] <= tlp_data[31:0];
            end
        end
    end
    
    always_comb begin
        data_buffer_rdata = '0;
        if (target_region == REGION_DATA_BUFFER && region_offset[31:2] < (DATA_BUFFER_SIZE/4)) begin
            data_buffer_rdata = data_buffer_mem[region_offset[31:2]];
        end
    end
    
    // ========================================================================
    // Device-Specific Timing Pattern Implementation
    // ========================================================================
    
    always_ff @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            timing_counter <= '0;
            burst_counter <= '0;
            timing_active <= 1'b1;
            burst_in_progress <= 1'b0;
        end else begin
            // Implement device-specific timing patterns from behavior profiler
            if (timing_active) begin
                if (burst_in_progress) begin
                    if (burst_counter < BURST_LENGTH-1) begin
                        burst_counter <= burst_counter + 1;
                    end else begin
                        burst_in_progress <= 1'b0;
                        burst_counter <= '0;
                        timing_counter <= '0;
                    end
                end else begin
                    if (timing_counter < INTER_BURST_GAP-1) begin
                        timing_counter <= timing_counter + 1;
                    end else begin
                        burst_in_progress <= 1'b1;
                        timing_counter <= '0;
                    end
                end
            end
        end
    end
    
    // ========================================================================
    // PCILeech Command Processing
    // ========================================================================
    
    always_ff @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            pcileech_ctrl_reg <= '0;
            pcileech_stat_reg <= '0;
            pcileech_addr_reg <= '0;
            pcileech_len_reg <= '0;
            pcileech_data_reg <= '0;
        end else begin
            // Update PCILeech control registers based on commands
            if (pcileech_enable && current_state == STATE_PCILEECH_EXEC) begin
                case (pcileech_command[7:0])
                    PCILEECH_CMD_READ: begin
                        pcileech_addr_reg <= pcileech_address;
                        pcileech_len_reg <= pcileech_length;
                        pcileech_stat_reg[0] <= 1'b1; // Busy
                    end
                    PCILEECH_CMD_WRITE: begin
                        pcileech_addr_reg <= pcileech_address;
                        pcileech_len_reg <= pcileech_length;
                        pcileech_stat_reg[0] <= 1'b1; // Busy
                    end
                    PCILEECH_CMD_PROBE: begin
                        pcileech_data_reg <= {{ device_config.device_signature | default('32\'hDEADBEEF') }};
                        pcileech_stat_reg[1] <= 1'b1; // Ready
                    end
                    PCILEECH_CMD_STATUS: begin
                        pcileech_stat_reg[2] <= 1'b1; // Status available
                    end
                endcase
            end
        end
    end
    
    assign pcileech_status = pcileech_stat_reg;
    assign pcileech_ready = pcileech_stat_reg[1];
    
    // ========================================================================
    // MSI-X Integration
    // ========================================================================
    
    // MSI-X Table Access
    msix_table #(
        .NUM_MSIX(NUM_MSIX),
        .MSIX_TABLE_BIR(MSIX_TABLE_BIR),
        .MSIX_TABLE_OFFSET(MSIX_TABLE_OFFSET),
        .MSIX_PBA_BIR(MSIX_PBA_BIR),
        .MSIX_PBA_OFFSET(MSIX_PBA_OFFSET)
    ) msix_table_inst (
        .clk(clk),
        .reset_n(reset_n),
        .bar_addr(tlp_address[31:0]),
        .bar_index(BAR_INDEX[2:0]),
        .bar_wr_data(tlp_data[31:0]),
        .bar_wr_en(current_state == STATE_WRITE_PROCESS && target_region == REGION_MSIX_TABLE),
        .bar_wr_be(tlp_first_be),
        .bar_rd_en(current_state == STATE_READ_PROCESS && target_region == REGION_MSIX_TABLE),
        .bar_rd_data(msix_table_data),
        .bar_access_match(msix_table_access),
        .msix_enable(device_ctrl_mem[0][0]), // MSI-X enable from control register
        .msix_function_mask(device_ctrl_mem[0][1]), // Function mask from control register
        .msix_interrupt(msix_interrupt),
        .msix_vector(msix_vector),
        .msix_interrupt_ack(msix_interrupt_ack)
    );
    
    // ========================================================================
    // Performance Counters and Error Handling
    // ========================================================================
    
    always_ff @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            perf_counter_0 <= '0;
            perf_counter_1 <= '0;
            read_count <= '0;
            write_count <= '0;
            error_count <= '0;
            error_status_reg <= '0;
            timeout_counter <= '0;
        end else begin
            // Performance counters
            if (ENABLE_PERFORMANCE_COUNTERS) begin
                if (current_state == STATE_READ_PROCESS) begin
                    read_count <= read_count + 1;
                    perf_counter_0 <= perf_counter_0 + 1;
                end
                if (current_state == STATE_WRITE_PROCESS) begin
                    write_count <= write_count + 1;
                    perf_counter_1 <= perf_counter_1 + 1;
                end
            end
            
            // Error detection
            if (current_state == STATE_ERROR_HANDLE) begin
                error_count <= error_count + 1;
                error_status_reg[0] <= 1'b1; // Address error
            end
            
            if (tlp_rx_err) begin
                error_status_reg[1] <= 1'b1; // TLP error
                error_count <= error_count + 1;
            end
            
            // Timeout detection
            if (current_state != STATE_IDLE) begin
                if (timeout_counter < TIMEOUT_CYCLES-1) begin
                    timeout_counter <= timeout_counter + 1;
                end else begin
                    error_status_reg[2] <= 1'b1; // Timeout error
                    error_count <= error_count + 1;
                    timeout_counter <= '0;
                end
            end else begin
                timeout_counter <= '0;
            end
            
            // Clear errors on write to error status register
            if (current_state == STATE_WRITE_PROCESS && target_region == REGION_STATUS_REG && 
                region_offset[7:2] == 6'h01 && tlp_data[31]) begin
                error_status_reg <= '0;
            end
        end
    end
    
    assign error_status = error_status_reg;
    assign performance_counter_0 = perf_counter_0;
    assign performance_counter_1 = perf_counter_1;
    
    // ========================================================================
    // BAR Interface Logic
    // ========================================================================
    
    always_comb begin
        bar_rd_data = '0;
        bar_rd_valid = 1'b0;
        
        if (bar_rd_en) begin
            bar_rd_valid = 1'b1;
            case (target_region)
                REGION_DEVICE_CTRL: bar_rd_data = device_ctrl_rdata;
                REGION_STATUS_REG:  bar_rd_data = status_reg_rdata;
                REGION_DATA_BUFFER: bar_rd_data = data_buffer_rdata;
                REGION_MSIX_TABLE:  bar_rd_data = msix_table_data;
                REGION_MSIX_PBA:    bar_rd_data = msix_pba_data;
                default:            bar_rd_data = 32'hDEADBEEF;
            endcase
        end
    end
    
    // ========================================================================
    // Configuration Space Interface
    // ========================================================================
    
    always_comb begin
        cfg_ext_read_data = '0;
        cfg_ext_read_data_valid = 1'b0;
        
        if (cfg_ext_read_received) begin
            cfg_ext_read_data_valid = 1'b1;
            case (cfg_ext_register_number)
                10'h000: cfg_ext_read_data = 32'h{{ "%04X%04X" | format(config_space.device_id | default(0x1234) | int, config_space.vendor_id | default(0x5678) | int) }};
                10'h001: cfg_ext_read_data = 32'h{{ "%04X%04X" | format(config_space.status | default(0x0010) | int, config_space.command | default(0x0000) | int) }};
                10'h002: cfg_ext_read_data = 32'h{{ "%06X%02X" | format(config_space.class_code | default(0x020000) | int, config_space.revision_id | default(0x01) | int) }};
                10'h040: cfg_ext_read_data = pcileech_ctrl_reg; // PCILeech control register
                10'h041: cfg_ext_read_data = pcileech_stat_reg; // PCILeech status register
                10'h042: cfg_ext_read_data = error_status_reg;  // Error status register
                default: cfg_ext_read_data = 32'h00000000;
            endcase
        end
    end
    
    // Configuration space write handling
    always_ff @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            // Initialize configuration space registers
        end else if (cfg_ext_write_received) begin
            case (cfg_ext_register_number)
                10'h040: begin // PCILeech control register
                    if (cfg_ext_write_byte_enable[0]) pcileech_ctrl_reg[7:0] <= cfg_ext_write_data[7:0];
                    if (cfg_ext_write_byte_enable[1]) pcileech_ctrl_reg[15:8] <= cfg_ext_write_data[15:8];
                    if (cfg_ext_write_byte_enable[2]) pcileech_ctrl_reg[23:16] <= cfg_ext_write_data[23:16];
                    if (cfg_ext_write_byte_enable[3]) pcileech_ctrl_reg[31:24] <= cfg_ext_write_data[31:24];
                end
                10'h042: begin // Error status register (write-1-to-clear)
                    if (cfg_ext_write_byte_enable[0]) error_status_reg[7:0] <= error_status_reg[7:0] & ~cfg_ext_write_data[7:0];
                    if (cfg_ext_write_byte_enable[1]) error_status_reg[15:8] <= error_status_reg[15:8] & ~cfg_ext_write_data[15:8];
                    if (cfg_ext_write_byte_enable[2]) error_status_reg[23:16] <= error_status_reg[23:16] & ~cfg_ext_write_data[23:16];
                    if (cfg_ext_write_byte_enable[3]) error_status_reg[31:24] <= error_status_reg[31:24] & ~cfg_ext_write_data[31:24];
                end
            endcase
        end
    end
    
    // ========================================================================
    // DMA Interface Logic
    // ========================================================================
    
    always_comb begin
        dma_read_req = 1'b0;
        dma_read_addr = '0;
        dma_read_len = '0;
        dma_write_req = 1'b0;
        dma_write_addr = '0;
        dma_write_len = '0;
        dma_write_data = '0;
        
        if (current_state == STATE_DMA_READ) begin
            dma_read_req = 1'b1;
            dma_read_addr = pcileech_addr_reg;
            dma_read_len = pcileech_len_reg;
        end else if (current_state == STATE_DMA_WRITE) begin
            dma_write_req = 1'b1;
            dma_write_addr = pcileech_addr_reg;
            dma_write_len = pcileech_len_reg;
            dma_write_data = {96'h0, pcileech_data_reg}; // Extend to 128-bit
        end
    end
    
    // ========================================================================
    // Debug and Status Output
    // ========================================================================
    
    assign debug_state = {4'h0, current_state};
    
    // ========================================================================
    // Error Injection for Testing (if enabled)
    // ========================================================================
    
    {% if device_config.enable_error_injection | default(false) %}
    // Error injection logic for testing and validation
    logic [31:0] error_inject_counter;
    logic        inject_address_error;
    logic        inject_tlp_error;
    logic        inject_timeout_error;
    
    always_ff @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            error_inject_counter <= '0;
            inject_address_error <= 1'b0;
            inject_tlp_error <= 1'b0;
            inject_timeout_error <= 1'b0;
        end else begin
            error_inject_counter <= error_inject_counter + 1;
            
            // Inject errors based on counter patterns (for testing)
            inject_address_error <= (error_inject_counter[15:0] == 16'hAAAA);
            inject_tlp_error <= (error_inject_counter[15:0] == 16'h5555);
            inject_timeout_error <= (error_inject_counter[15:0] == 16'hCCCC);
        end
    end
    {% endif %}
    
    // ========================================================================
    // Simulation and Debug Support
    // ========================================================================
    
    {% if device_config.enable_simulation_support | default(true) %}
`ifdef XILINX_SIMULATOR
    // Initialize memory regions for simulation
    initial begin
        for (int i = 0; i < (DEVICE_CTRL_SIZE/4); i++) device_ctrl_mem[i] = 32'h0;
        for (int i = 0; i < (STATUS_REG_SIZE/4); i++) status_reg_mem[i] = 32'h0;
        for (int i = 0; i < (DATA_BUFFER_SIZE/4); i++) data_buffer_mem[i] = 32'h0;
        for (int i = 0; i < (CUSTOM_REGION_SIZE/4); i++) custom_region_mem[i] = 32'h0;
        
        // Initialize PCILeech control registers
        device_ctrl_mem[0] = 32'h00000001; // Enable PCILeech by default
        device_ctrl_mem[1] = {{ device_config.device_signature | default('32\'hDEADBEEF') }};
        device_ctrl_mem[2] = {{ device_config.firmware_version | default('32\'h00010000') }};
    end
    
    // Debug tasks for software models
    task automatic inject_tlp(input logic [127:0] tlp_data, input logic sop, input logic eop);
        @(posedge clk);
        tlp_rx_valid = 1'b1;
        tlp_rx_data = tlp_data;
        tlp_rx_sop = sop;
        tlp_rx_eop = eop;
        @(posedge clk);
        tlp_rx_valid = 1'b0;
        tlp_rx_sop = 1'b0;
        tlp_rx_eop = 1'b0;
    endtask
    
    // Debug function to read memory region
    function automatic logic [31:0] read_memory_region(input region_select_t region, input logic [31:0] offset);
        case (region)
            REGION_DEVICE_CTRL: return device_ctrl_mem[offset[31:2]];
            REGION_STATUS_REG:  return status_reg_mem[offset[31:2]];
            REGION_DATA_BUFFER: return data_buffer_mem[offset[31:2]];
            REGION_CUSTOM_PIO:  return custom_region_mem[offset[31:2]];
            default:            return 32'hDEADBEEF;
        endcase
    endfunction
    
    // Debug function to get controller status
    function automatic logic [31:0] get_controller_status();
        return {24'h0, current_state, 4'h0};
    endfunction
    
    // Performance monitoring
    always @(posedge clk) begin
        if (current_state == STATE_READ_PROCESS) begin
            $display("[PCILeech BAR Controller] Read access to region %0d, offset 0x%08X at time %0t", 
                     target_region, region_offset, $time);
        end
        if (current_state == STATE_WRITE_PROCESS) begin
            $display("[PCILeech BAR Controller] Write access to region %0d, offset 0x%08X, data 0x%08X at time %0t", 
                     target_region, region_offset, tlp_data[31:0], $time);
        end
        if (current_state == STATE_ERROR_HANDLE) begin
            $display("[PCILeech BAR Controller] Error condition detected at time %0t", $time);
        end
    end
`endif
    {% endif %}

endmodule