// ============================================================================
// ecosystem_ca.v - 三态捕食-猎物生态系统CA
// 状态: 0=空, 1=猎物(Prey), 2=捕食者(Predator)
// 使用Von Neumann邻域（4邻居），支持概率性规则
// ============================================================================
module ecosystem_ca #(
    parameter WIDTH  = 64,
    parameter HEIGHT = 64,
    parameter PREY_BIRTH_PROB  = 4'd3,   // 猎物繁殖概率 (3/16)
    parameter PRED_DEATH_PROB  = 4'd2,   // 捕食者死亡概率 (2/16)
    parameter PRED_CATCH_RANGE = 4'd1    // 捕食范围
)(
    input  wire             clk,
    input  wire             rst_n,
    input  wire             enable,
    input  wire             init,
    output wire [1:0]       grid_out [0:WIDTH*HEIGHT-1],  // 2位/元胞
    output wire [31:0]      prey_count,
    output wire [31:0]      pred_count,
    output wire [31:0]      empty_count,
    output wire [31:0]      step_count
);

    // ---- 网格状态 ----
    reg [1:0] grid_curr [0:WIDTH*HEIGHT-1];
    reg [1:0] grid_next [0:WIDTH*HEIGHT-1];

    // ---- 伪随机数 ----
    reg [15:0] rng;
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) rng <= 16'hACED;
        else rng <= {rng[14:0], rng[15] ^ rng[14] ^ rng[12] ^ rng[3]};
    end

    // ---- 邻居计数 ----
    integer idx, x, y;
    reg [3:0] prey_nb, pred_nb;

    always @(*) begin
        for (idx = 0; idx < WIDTH*HEIGHT; idx = idx + 1) begin
            x = idx % WIDTH;
            y = idx / WIDTH;
            prey_nb = 0; pred_nb = 0;

            // Von Neumann邻域
            if (y > 0) begin
                prey_nb = prey_nb + (grid_curr[idx-WIDTH] == 2'd1);
                pred_nb = pred_nb + (grid_curr[idx-WIDTH] == 2'd2);
            end
            if (y < HEIGHT-1) begin
                prey_nb = prey_nb + (grid_curr[idx+WIDTH] == 2'd1);
                pred_nb = pred_nb + (grid_curr[idx+WIDTH] == 2'd2);
            end
            if (x > 0) begin
                prey_nb = prey_nb + (grid_curr[idx-1] == 2'd1);
                pred_nb = pred_nb + (grid_curr[idx-1] == 2'd2);
            end
            if (x < WIDTH-1) begin
                prey_nb = prey_nb + (grid_curr[idx+1] == 2'd1);
                pred_nb = pred_nb + (grid_curr[idx+1] == 2'd2);
            end

            // 规则应用
            case (grid_curr[idx])
                2'd0: begin  // 空
                    // 猎物繁殖：邻近有猎物 → 概率性变为猎物
                    if (prey_nb > 0 && rng[3:0] < PREY_BIRTH_PROB)
                        grid_next[idx] = 2'd1;
                    else
                        grid_next[idx] = 2'd0;
                end
                2'd1: begin  // 猎物
                    // 被捕食：邻近有捕食者 → 变为捕食者
                    if (pred_nb > 0)
                        grid_next[idx] = 2'd2;
                    else
                        grid_next[idx] = 2'd1;  // 安全存活
                end
                2'd2: begin  // 捕食者
                    // 饿死：邻近无猎物 → 概率性死亡
                    if (prey_nb == 0 && rng[7:4] < PRED_DEATH_PROB)
                        grid_next[idx] = 2'd0;
                    else
                        grid_next[idx] = 2'd2;  // 存活
                end
            endcase
        end
    end

    // ---- 状态更新 ----
    reg [31:0] step_reg;
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            step_reg <= 32'd0;
        end else if (init) begin
            step_reg <= 32'd0;
            // 随机初始化
            for (idx = 0; idx < WIDTH*HEIGHT; idx = idx + 1)
                grid_curr[idx] <= rng[1:0];  // 0/1/2随机
        end else if (enable) begin
            for (idx = 0; idx < WIDTH*HEIGHT; idx = idx + 1)
                grid_curr[idx] <= grid_next[idx];
            step_reg <= step_reg + 32'd1;
        end
    end

    // ---- 种群计数 ----
    reg [31:0] pc, dc, ec;
    always @(*) begin
        pc = 0; dc = 0; ec = 0;
        for (idx = 0; idx < WIDTH*HEIGHT; idx = idx + 1) begin
            case (grid_curr[idx])
                2'd0: ec = ec + 1;
                2'd1: pc = pc + 1;
                2'd2: dc = dc + 1;
            endcase
        end
    end

    assign prey_count  = pc;
    assign pred_count  = dc;
    assign empty_count = ec;
    assign step_count  = step_reg;

    genvar gi;
    generate
        for (gi = 0; gi < WIDTH*HEIGHT; gi = gi + 1)
            assign grid_out[gi] = grid_curr[gi];
    endgenerate

endmodule