`timescale 1ns/1ps

module tb_array_status_ctrl();

// 时钟与复位信号
reg                 clk;
reg                 rst_n;

// AXI 到数组的帧信号
reg                 axi2array_frame_valid;
reg [152:0]         axi2array_frame_data;
wire                axi2array_frame_ready;

// 数组读写信号
wire                array_wr_frame_valid;
wire [151:0]        array_wr_frame_data;
reg                 array_wr_frame_ready;
reg                 array_wr_done;

wire                array_rd_frame_valid;
wire [151:0]        array_rd_frame_data;
reg                 array_rd_frame_ready;
reg                 array_rd_done;

// 数组刷新信号
wire                array_ref_start;
reg                 array_ref_done;

// 其他控制信号
wire [1:0]          array_mux_sel;
reg                 mc_work_en;
reg                 array_ref_en;
reg [24:0]          array_inner_tref0;
reg [24:0]          array_inner_tref1;
reg                 array_inner_ref_sel;

// 例化被测试模块
array_status_ctrl uut (
    .clk                    (clk),
    .rst_n                  (rst_n),
    .axi2array_frame_valid  (axi2array_frame_valid),
    .axi2array_frame_data   (axi2array_frame_data),
    .axi2array_frame_ready  (axi2array_frame_ready),
    .array_wr_frame_valid   (array_wr_frame_valid),
    .array_wr_frame_data    (array_wr_frame_data),
    .array_wr_frame_ready   (array_wr_frame_ready),
    .array_wr_done          (array_wr_done),
    .array_rd_frame_valid   (array_rd_frame_valid),
    .array_rd_frame_data    (array_rd_frame_data),
    .array_rd_frame_ready   (array_rd_frame_ready),
    .array_rd_done          (array_rd_done),
    .array_ref_start        (array_ref_start),
    .array_ref_done         (array_ref_done),
    .array_mux_sel          (array_mux_sel),
    .mc_work_en             (mc_work_en),
    .array_ref_en           (array_ref_en),
    .array_inner_tref0      (array_inner_tref0),
    .array_inner_tref1      (array_inner_tref1),
    .array_inner_ref_sel    (array_inner_ref_sel)
);

// 生成时钟（50MHz，周期20ns）
initial begin
    clk = 0;
    forever #10 clk = ~clk;
end

// 主测试流程
initial begin
    // 初始化信号
    rst_n                  = 0;
    axi2array_frame_valid  = 0;
    axi2array_frame_data   = 0;
    array_wr_frame_ready   = 0;
    array_wr_done          = 0;
    array_rd_frame_ready   = 0;
    array_rd_done          = 0;
    array_ref_done         = 0;
    mc_work_en             = 0;
    array_ref_en           = 0;
    array_inner_tref0      = 25'd5;  // 刷新计数阈值
    array_inner_tref1      = 25'd10;
    array_inner_ref_sel    = 0;

    // 释放复位
    #100 rst_n = 1;
    #20;

    // 测试场景1：写操作
    $display("Test Case 1: Write Operation");
    mc_work_en = 1;  // 使能工作模式
    #20;
    // 发送写请求（bit152=1）
    axi2array_frame_data = {1'b1, 152'h123456};  // 写数据
    axi2array_frame_valid = 1;
    array_wr_frame_ready = 1;  // 准备接收写数据
    #20;
    array_wr_done = 1;  // 写完成
    #20;
    axi2array_frame_valid = 0;
    array_wr_done = 0;
    #100;

    // 测试场景2：读操作
    $display("Test Case 2: Read Operation");
    // 发送读请求（bit152=0）
    axi2array_frame_data = {1'b0, 152'hABCDEF};  // 读数据
    axi2array_frame_valid = 1;
    array_rd_frame_ready = 1;  // 准备接收读数据
    #20;
    array_rd_done = 1;  // 读完成
    #20;
    axi2array_frame_valid = 0;
    array_rd_done = 0;
    #100;

    // 测试场景3：刷新操作（达到计数阈值）
    $display("Test Case 3: Refresh Operation (by counter)");
    array_ref_en = 1;  // 使能刷新
    #200;  // 等待刷新计数器达到阈值（tref0=5，约100ns后触发）
    array_ref_done = 1;  // 刷新完成
    #20;
    array_ref_done = 0;
    array_ref_en = 0;
    #100;

    // 测试场景4：状态优先级（刷新 > 写 > 读）
    $display("Test Case 4: State Priority (Refresh > Write > Read)");
    array_ref_en = 1;
    mc_work_en = 1;
    // 同时触发刷新请求、写请求和读请求
    axi2array_frame_data = {1'b1, 152'hFEDCBA};  // 写请求
    axi2array_frame_valid = 1;
    #20;
    array_ref_done = 1;  // 先完成刷新
    #20;
    array_ref_done = 0;
    #20;
    array_wr_done = 1;  // 再完成写操作
    #20;
    axi2array_frame_valid = 0;
    array_wr_done = 0;
    #100;

    // 结束测试
    $display("All Test Cases Completed!");
    $finish;
end

// 监控状态变化
always @(posedge clk) begin
    if (rst_n) begin
        case (uut.cur_state)
            2'b00: $display("[%0t] State: IDLE", $time);
            2'b01: $display("[%0t] State: WRITE", $time);
            2'b10: $display("[%0t] State: READ", $time);
            2'b11: $display("[%0t] State: REFRESH", $time);
        endcase
    end
end

    initial begin
        $fsdbDumpfile("tb.fsdb");
        $fsdbDumpvars(0,tb_array_status_ctrl,"+all");
        $vcdpluson;
        $vcdplusmemon;
    end

// 监控关键信号
always @(posedge clk) begin
    if (array_ref_start) begin
        $display("[%0t] Refresh Start Triggered", $time);
    end
    if (array_wr_frame_valid && array_wr_frame_ready) begin
        $display("[%0t] Write Data Transferred: %h", $time, array_wr_frame_data);
    end
    if (array_rd_frame_valid && array_rd_frame_ready) begin
        $display("[%0t] Read Data Transferred: %h", $time, array_rd_frame_data);
    end
end

endmodule