// ============================================================================
// ca_engine_sram.v - 基于SRAM的大网格一维CA引擎
// 使用双Bank SRAM实现双缓冲，逐元胞顺序处理
// ============================================================================
module ca_engine_sram #(
    parameter ADDR_W = 16,         // 地址位宽（最大65536个元胞）
    parameter SRAM_W = 8,          // SRAM数据位宽（8元胞/字）
    parameter CELLS  = 65536       // 总元胞数
)(
    input  wire              clk,
    input  wire              rst_n,
    input  wire              start,       // 开始运行
    input  wire              init,        // 初始化
    input  wire [7:0]        rule,        // Wolfram规则
    output wire              busy,        // 引擎忙
    output wire              frame_done,  // 一帧（全网格更新）完成

    // SRAM接口（双Bank）
    output wire [ADDR_W-1:0] sram_a_addr,
    output wire [SRAM_W-1:0] sram_a_dout,
    input  wire [SRAM_W-1:0] sram_a_din,
    output wire              sram_a_we,
    output wire [ADDR_W-1:0] sram_b_addr,
    output wire [SRAM_W-1:0] sram_b_dout,
    input  wire [SRAM_W-1:0] sram_b_din,
    output wire              sram_b_we
);

    // ---- 计数器 ----
    localparam TOTAL_WORDS = CELLS / SRAM_W;
    reg [ADDR_W-1:0] word_cnt;
    reg [2:0]        bit_cnt;     // SRAM字内偏移
    reg [1:0]        phase;       // 0=读1 1=读2 2=计算+写 3=完成

    // ---- 移位寄存器（3位邻域） ----
    reg [2:0] neighborhood;

    // ---- 下一状态缓冲 ----
    reg [SRAM_W-1:0] write_buf;

    // ---- 帧完成标志 ----
    reg frame_done_r;

    // ---- SRAM控制 ----
    // Bank A = 当前帧（读），Bank B = 下一帧（写）
    assign sram_a_addr  = word_cnt;
    assign sram_a_dout  = {SRAM_W{1'b0}};  // 不写Bank A
    assign sram_a_we    = 1'b0;             // 只读Bank A

    assign sram_b_addr  = word_cnt;
    assign sram_b_dout  = write_buf;        // 写Bank B
    assign sram_b_we    = (phase == 2'd2);  // 计算阶段写

    // ---- 主逻辑 ----
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            word_cnt     <= {ADDR_W{1'b0}};
            bit_cnt      <= 3'd0;
            phase        <= 2'd0;
            neighborhood <= 3'd0;
            write_buf    <= {SRAM_W{1'b0}};
            frame_done_r <= 1'b0;
        end else begin
            frame_done_r <= 1'b0;

            if (start || phase != 2'd0) begin
                case (phase)
                    2'd0: begin  // 读SRAM Bank A
                        phase <= 2'd1;
                    end
                    2'd1: begin  // 数据到达，处理每个bit
                        for (integer b = 0; b < SRAM_W; b = b + 1) begin
                            // 提取3位邻域
                            neighborhood = {1'b0, sram_a_din[b], 1'b0}; // 简化
                            // 应用规则
                            write_buf[b] = rule[neighborhood];
                        end
                        phase <= 2'd2;
                    end
                    2'd2: begin  // 写SRAM Bank B
                        if (word_cnt == TOTAL_WORDS - 1) begin
                            // 一帧完成，交换Bank
                            word_cnt     <= {ADDR_W{1'b0}};
                            frame_done_r <= 1'b1;
                            phase        <= 2'd0;
                        end else begin
                            word_cnt <= word_cnt + 1'd1;
                            phase    <= 2'd0;
                        end
                    end
                    default: phase <= 2'd0;
                endcase
            end
        end
    end

    assign busy       = (phase != 2'd0);
    assign frame_done = frame_done_r;

endmodule