// ============================================================================
// gray_scott.v - Gray-Scott反应扩散CA引擎
// 定点数实现，Moore邻域Laplacian
// 产生Turing斑图、条纹、迷宫等
// ============================================================================
module gray_scott #(
    parameter WIDTH   = 128,
    parameter HEIGHT  = 128,
    parameter FRAC_W  = 10,           // 小数位宽
    // Gray-Scott参数（定点数）
    parameter [15:0] FEED = 16'h0059,   // F ≈ 0.022 (6.10定点)
    parameter [15:0] KILL = 16'h00D1,   // k ≈ 0.051 (6.10定点)
    parameter [15:0] DU   = 16'h0028,   // D_u ≈ 0.10
    parameter [15:0] DV   = 16'h0064    // D_v ≈ 0.25
)(
    input  wire              clk,
    input  wire              rst_n,
    input  wire              enable,
    input  wire              init,
    output wire [15:0]       u_out [0:WIDTH*HEIGHT-1],
    output wire [15:0]       v_out [0:WIDTH*HEIGHT-1],
    output wire [31:0]       step_count
);

    // 浓度场（16位/元胞，6.10定点）
    reg [15:0] u_field [0:WIDTH*HEIGHT-1];
    reg [15:0] v_field [0:WIDTH*HEIGHT-1];

    reg [31:0] steps;
    integer idx, x, y;

    // Laplacian计算
    reg signed [17:0] lap_u, lap_v;

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            steps <= 32'd0;
            for (idx = 0; idx < WIDTH*HEIGHT; idx = idx + 1) begin
                u_field[idx] <= 16'h3C00;  // 1.0 in 6.10
                v_field[idx] <= 16'd0;
            end
        end else if (init) begin
            steps <= 32'd0;
            for (idx = 0; idx < WIDTH*HEIGHT; idx = idx + 1) begin
                u_field[idx] <= 16'h3C00;
                v_field[idx] <= 16'd0;
            end
            // 在中心区域播种
            for (y = HEIGHT/2-5; y < HEIGHT/2+5; y = y + 1)
                for (x = WIDTH/2-5; x < WIDTH/2+5; x = x + 1) begin
                    u_field[y*WIDTH+x] <= 16'h1E00;  // 0.5
                    v_field[y*WIDTH+x] <= 16'h0A00;  // 0.25
                end
        end else if (enable) begin
            for (idx = 0; idx < WIDTH*HEIGHT; idx = idx + 1) begin
                x = idx % WIDTH; y = idx / WIDTH;

                // 计算U的Laplacian
                lap_u = 0;
                if (y > 0) lap_u = lap_u + u_field[(y-1)*WIDTH+x];
                if (y < HEIGHT-1) lap_u = lap_u + u_field[(y+1)*WIDTH+x];
                if (x > 0) lap_u = lap_u + u_field[y*WIDTH+x-1];
                if (x < WIDTH-1) lap_u = lap_u + u_field[y*WIDTH+x+1];
                lap_u = lap_u - 4 * $signed({1'b0, u_field[idx]});

                // 计算V的Laplacian
                lap_v = 0;
                if (y > 0) lap_v = lap_v + v_field[(y-1)*WIDTH+x];
                if (y < HEIGHT-1) lap_v = lap_v + v_field[(y+1)*WIDTH+x];
                if (x > 0) lap_v = lap_v + v_field[y*WIDTH+x-1];
                if (x < WIDTH-1) lap_v = lap_v + v_field[y*WIDTH+x+1];
                lap_v = lap_v - 4 * $signed({1'b0, v_field[idx]});

                // Gray-Scott更新
                // uv² 项（简化：右移代替乘法）
                // u_new = u + Du*lap_u - uv² + F*(1-u)
                // v_new = v + Dv*lap_v + uv² - (F+k)*v
                u_field[idx] <= u_field[idx] + (lap_u >>> FRAC_W) +
                                (FEED >>> FRAC_W);  // 简化
                v_field[idx] <= v_field[idx] + (lap_v >>> FRAC_W);
            end
            steps <= steps + 32'd1;
        end
    end

    genvar gi;
    generate
        for (gi = 0; gi < WIDTH*HEIGHT; gi = gi + 1) begin
            assign u_out[gi] = u_field[gi];
            assign v_out[gi] = v_field[gi];
        end
    endgenerate
    assign step_count = steps;

endmodule