// ============================================================================
// lattice_gas_hpp.v - HPP Lattice Gas自动机
// 正方形网格，4速度方向，弹性碰撞
// ============================================================================
module lattice_gas_hpp #(
    parameter WIDTH  = 64,
    parameter HEIGHT = 64
)(
    input  wire             clk,
    input  wire             rst_n,
    input  wire             enable,
    input  wire             init,
    // 4位/格点：位0=东, 位1=南, 位2=西, 位3=北
    output wire [WIDTH*HEIGHT*4-1:0] state,
    output wire [31:0]      step_count,
    output wire [31:0]      total_particles
);

    // 每格点4位状态：[北,西,南,东]
    reg [3:0] grid [0:WIDTH*HEIGHT-1];
    reg [3:0] grid_nxt [0:WIDTH*HEIGHT-1];
    reg [31:0] steps;

    integer idx, x, y;

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

            // ---- 步骤1：碰撞（在同一格点内） ----
            reg [3:0] after_collision;
            case (grid[idx])
                4'b0101: after_collision = 4'b1010;  // 东西→南北
                4'b1010: after_collision = 4'b0101;  // 南北→东西
                default: after_collision = grid[idx];  // 其他不变
            endcase

            // ---- 步骤2：传播（移动到邻居格点） ----
            // 东向粒子(x) → 移到(x+1,y)
            // 南向粒子(y) → 移到(x,y+1)
            // 西向粒子(x) → 移到(x-1,y)
            // 北向粒子(y) → 移到(x,y-1)
            // 即：从邻居接收粒子

            // 来自西邻居的东向粒子
            wire from_west  = (x > 0) ? grid[y*WIDTH+x-1][0] : grid[y*WIDTH+WIDTH-1][0];
            // 来自北邻居的南向粒子
            wire from_north = (y > 0) ? grid[(y-1)*WIDTH+x][1] : grid[(HEIGHT-1)*WIDTH+x][1];
            // 来自东邻居的西向粒子
            wire from_east  = (x < WIDTH-1) ? grid[y*WIDTH+x+1][2] : grid[y*WIDTH][2];
            // 来自南邻居的北向粒子
            wire from_south = (y < HEIGHT-1) ? grid[(y+1)*WIDTH+x][3] : grid[x][3];

            grid_nxt[idx] = {from_south, from_east, from_north, from_west};
        end
    end

    // 状态更新
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            steps <= 32'd0;
            for (idx = 0; idx < WIDTH*HEIGHT; idx = idx + 1)
                grid[idx] <= 4'd0;
        end else if (init) begin
            steps <= 32'd0;
            // 初始配置：随机粒子
            for (idx = 0; idx < WIDTH*HEIGHT; idx = idx + 1)
                grid[idx] <= 4'd0;  // 空白
        end else if (enable) begin
            for (idx = 0; idx < WIDTH*HEIGHT; idx = idx + 1)
                grid[idx] <= grid_nxt[idx];
            steps <= steps + 32'd1;
        end
    end

    // 粒子总数
    reg [31:0] total;
    always @(*) begin
        total = 0;
        for (idx = 0; idx < WIDTH*HEIGHT; idx = idx + 1)
            total = total + grid[idx][0] + grid[idx][1] +
                    grid[idx][2] + grid[idx][3];
    end

    // 输出
    genvar gi;
    generate
        for (gi = 0; gi < WIDTH*HEIGHT; gi = gi + 1)
            assign state[gi*4 +: 4] = grid[gi];
    endgenerate
    assign step_count = steps;
    assign total_particles = total;

endmodule