// ============================================================================
// lattice_gas_fhp.v - FHP-II模型Lattice Gas引擎
// 7速度方向：6个运动方向(0-5,间隔60°) + 1个静止粒子(6)
// 三角形网格用"奇偶行偏移"编码
// ============================================================================
module lattice_gas_fhp #(
    parameter WIDTH  = 64,
    parameter HEIGHT = 64
)(
    input  wire              clk,
    input  wire              rst_n,
    input  wire              enable,
    input  wire              init,
    output wire [6:0]        grid_out [0:WIDTH*HEIGHT-1],
    output wire [31:0]       step_count,
    output wire [31:0]       density,      // 宏观密度
    output wire signed [31:0] velocity_x,  // 宏观速度x
    output wire signed [31:0] velocity_y   // 宏观速度y
);

    // ---- 网格存储：7位/格点 ----
    // bit[5:0] = 6个运动方向粒子
    // bit[6]   = 静止粒子
    // 方向编码: 0=右(0°) 1=右上(60°) 2=左上(120°)
    //           3=左(180°) 4=左下(240°) 5=右下(300°)
    reg [6:0] grid [0:WIDTH*HEIGHT-1];
    reg [6:0] grid_nxt [0:WIDTH*HEIGHT-1];
    reg [31:0] steps;

    // ---- 伪随机数（用于碰撞选择的随机性） ----
    reg [15:0] rng;
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) rng <= 16'hCAFE;
        else rng <= {rng[14:0], rng[15] ^ rng[14] ^ rng[12] ^ rng[3]};
    end

    // ---- 碰撞规则 ----
    function [6:0] collide;
        input [6:0] state;
        input rand_bit;
        begin
            collide = state;  // 默认不变
            // 二体碰撞：对头粒子
            case (state[5:0])
                6'b100001: collide = rand_bit ? 6'b010010 : 6'b001100;  // 0+3
                6'b010010: collide = rand_bit ? 6'b100001 : 6'b001100;  // 1+4
                6'b001100: collide = rand_bit ? 6'b100001 : 6'b010010;  // 2+5
                default: collide = state[5:0];
            endcase
            collide[6] = state[6];  // 静止粒子不变
        end
    endfunction

    // ---- 邻居计算（三角形网格） ----
    // 偶数行和奇数行偏移不同
    integer idx, x, y;
    reg is_odd_row;
    reg [6:0] after_col;

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

            // 步骤1：碰撞
            after_col = collide(grid[idx], rng[0]);

            // 步骤2：传播（根据方向移动到邻居）
            // 方向0(右): 从(x-1,y)接收
            // 方向1(右上): 从左下邻居接收
            // 方向2(左上): 从左下邻居接收
            // 方向3(左): 从(x+1,y)接收
            // 方向4(左下): 从右上邻居接收
            // 方向5(右下): 从右上邻居接收
            // 方向6(静止): 本格点

            // 简化实现：环形边界
            grid_nxt[idx][0] = grid[(y)*WIDTH + (x==0?WIDTH-1:x-1)][0];  // 右向来自左边
            grid_nxt[idx][3] = grid[(y)*WIDTH + (x==WIDTH-1?0:x+1)][3];  // 左向来自右边
            // 对角方向需要考虑奇偶行
            if (is_odd_row) begin
                grid_nxt[idx][1] = (y==0)?1'b0 : grid[(y-1)*WIDTH+x][1];
                grid_nxt[idx][2] = (y==0)?1'b0 : grid[(y-1)*WIDTH+(x==0?WIDTH-1:x-1)][2];
                grid_nxt[idx][4] = (y==HEIGHT-1)?1'b0 : grid[(y+1)*WIDTH+x][4];
                grid_nxt[idx][5] = (y==HEIGHT-1)?1'b0 : grid[(y+1)*WIDTH+(x==0?WIDTH-1:x-1)][5];
            end else begin
                grid_nxt[idx][1] = (y==0)?1'b0 : grid[(y-1)*WIDTH+(x==WIDTH-1?0:x+1)][1];
                grid_nxt[idx][2] = (y==0)?1'b0 : grid[(y-1)*WIDTH+x][2];
                grid_nxt[idx][4] = (y==HEIGHT-1)?1'b0 : grid[(y+1)*WIDTH+(x==WIDTH-1?0:x+1)][4];
                grid_nxt[idx][5] = (y==HEIGHT-1)?1'b0 : grid[(y+1)*WIDTH+x][5];
            end
            grid_nxt[idx][6] = after_col[6];  // 静止粒子不移动
        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] <= 7'd0;
        end else if (init) begin
            steps <= 32'd0;
            for (idx = 0; idx < WIDTH*HEIGHT; idx = idx + 1)
                grid[idx] <= 7'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] dens; reg signed [31:0] vx, vy;
    always @(*) begin
        dens = 0; vx = 0; vy = 0;
        for (idx = 0; idx < WIDTH*HEIGHT; idx = idx + 1) begin
            dens = dens + grid[idx][0]+grid[idx][1]+grid[idx][2]+
                   grid[idx][3]+grid[idx][4]+grid[idx][5]+grid[idx][6];
            // x方向动量: 方向0(+) 方向3(-) 方向1,5(+0.5) 方向2,4(-0.5)
            vx = vx + grid[idx][0] - grid[idx][3] +
                  (grid[idx][1]+grid[idx][5])/2 - (grid[idx][2]+grid[idx][4])/2;
            // y方向动量: 方向1,2(+) 方向4,5(-)
            vy = vy + (grid[idx][1]+grid[idx][2]) - (grid[idx][4]+grid[idx][5]);
        end
    end

    genvar gi;
    generate
        for (gi = 0; gi < WIDTH*HEIGHT; gi = gi + 1)
            assign grid_out[gi] = grid[gi];
    endgenerate
    assign step_count = steps;
    assign density = dens;
    assign velocity_x = vx;
    assign velocity_y = vy;

endmodule