// ============================================================================
// life_variable_rule.v - 支持任意Born/Survive规则的生命游戏
// 规则通过9位寄存器配置：born[0:8] + survive[0:8]
// ============================================================================
module life_variable_rule #(
    parameter WIDTH  = 64,
    parameter HEIGHT = 64
)(
    input  wire                     clk,
    input  wire                     rst_n,
    input  wire                     enable,
    input  wire                     init,
    input  wire [WIDTH*HEIGHT-1:0]  seed,
    input  wire [8:0]               born,       // born[i]=1: i个邻居时出生
    input  wire [8:0]               survive,    // survive[i]=1: i个邻居时存活
    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;

                wire [7:0] nb;
                assign nb[0] = curr[ym*WIDTH+xm];
                assign nb[1] = curr[ym*WIDTH+gx];
                assign nb[2] = curr[ym*WIDTH+xp];
                assign nb[3] = curr[gy*WIDTH+xm];
                assign nb[4] = curr[gy*WIDTH+xp];
                assign nb[5] = curr[yp*WIDTH+xm];
                assign nb[6] = curr[yp*WIDTH+gx];
                assign nb[7] = curr[yp*WIDTH+xp];

                wire [3:0] ncount = nb[0]+nb[1]+nb[2]+nb[3]+
                                    nb[4]+nb[5]+nb[6]+nb[7];
                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