// ============================================================================
// ca_margolus.v - Margolus邻域CA引擎
// 2×2块交替更新，支持可逆规则
// 关键：规则必须是双射（可逆），否则会丢失信息
// ============================================================================
module ca_margolus #(
    parameter WIDTH  = 64,
    parameter HEIGHT = 64,
    parameter [15:0] BLOCK_RULE = 16'h6996  // XOR奇偶规则（可逆）
)(
    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
);

    reg [WIDTH*HEIGHT-1:0] curr;
    reg [31:0] gen_reg;
    wire phase = gen_reg[0];  // 偶数步=0, 奇数步=1

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

    genvar bx, by;
    generate
        for (by = 0; by < HEIGHT/2; by = by + 1) begin : gen_brow
            for (bx = 0; bx < WIDTH/2; bx = bx + 1) begin : gen_bcol
                // 根据相位偏移块的起始位置
                wire [6:0] ox = phase ? {1'b0, bx[5:1]} : {1'b0, bx};
                wire [6:0] oy = phase ? {1'b0, by[5:1]} : {1'b0, by};

                // 2×2块的4个元胞索引
                wire [12:0] ul_idx = oy * WIDTH + ox;
                wire [12:0] ur_idx = oy * WIDTH + ox + 1;
                wire [12:0] ll_idx = (oy+1) * WIDTH + ox;
                wire [12:0] lr_idx = (oy+1) * WIDTH + ox + 1;

                // 4位块输入
                wire [3:0] block_in = {curr[ul_idx], curr[ur_idx],
                                       curr[ll_idx], curr[lr_idx]};

                // 规则查找
                wire [3:0] block_out = BLOCK_RULE[block_in * 4 +: 4];

                // 写回
                assign nxt[ul_idx] = block_out[3];
                assign nxt[ur_idx] = block_out[2];
                assign nxt[ll_idx] = block_out[1];
                assign nxt[lr_idx] = block_out[0];
            end
        end
    endgenerate

    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;

endmodule