// ============================================================================
// life_vonneumann.v - Von Neumann邻域生命游戏引擎
// 只考虑上下左右4个正交邻居
// 默认规则: B2/S234（适应4邻居的计数范围0-4）
// ============================================================================
module life_vonneumann #(
    parameter WIDTH  = 64,
    parameter HEIGHT = 64,
    parameter BORN    = 5'b00100,   // B2: 位2=1表示2个邻居出生
    parameter SURVIVE = 5'b01110    // S123: 位1,2,3=1
)(
    input  wire                     clk,
    input  wire                     rst_n,
    input  wire                     enable,
    input  wire                     init,
    input  wire [WIDTH*HEIGHT-1:0]  seed,
    output wire [WIDTH*HEIGHT-1:0]  state,
    output wire [31:0]              generation,
    output wire [31:0]              population
);

    reg [WIDTH*HEIGHT-1:0] curr;
    wire [WIDTH*HEIGHT-1:0] nxt;

    genvar gx, gy;
    generate
        for (gy = 0; gy < HEIGHT; gy = gy + 1) begin : gen_row
            for (gx = 0; gx < WIDTH; gx = gx + 1) begin : gen_col
                localparam integer idx = gy * WIDTH + gx;
                localparam integer xm = (gx == 0) ? WIDTH-1 : gx-1;
                localparam integer xp = (gx == WIDTH-1) ? 0 : gx+1;
                localparam integer ym = (gy == 0) ? HEIGHT-1 : gy-1;
                localparam integer yp = (gy == HEIGHT-1) ? 0 : gy+1;

                // Von Neumann邻域：仅4个正交邻居
                wire [2:0] ncount = curr[ym*WIDTH+gx] +  // 上
                                    curr[gy*WIDTH+xm] +  // 左
                                    curr[gy*WIDTH+xp] +  // 右
                                    curr[yp*WIDTH+gx];   // 下

                wire self = curr[idx];
                assign nxt[idx] = self ? SURVIVE[ncount] : BORN[ncount];
            end
        end
    endgenerate

    reg [31:0] gen_reg;
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            curr    <= {WIDTH*HEIGHT{1'b0}};
            gen_reg <= 32'd0;
        end else if (init) begin
            curr    <= seed;
            gen_reg <= 32'd0;
        end else if (enable) begin
            curr    <= nxt;
            gen_reg <= gen_reg + 32'd1;
        end
    end

    assign state = curr;
    assign generation = gen_reg;

    integer p;
    reg [31:0] pop_reg;
    always @(*) begin
        pop_reg = 32'd0;
        for (p = 0; p < WIDTH*HEIGHT; p = p + 1)
            pop_reg = pop_reg + curr[p];
    end
    assign population = pop_reg;

endmodule