// ============================================================================
// prng_rule30_stat_tb.v - 规则30 PRNG统计测试
// 验证输出序列的频率分布和自相关性
// ============================================================================
\`timescale 1ns/1ps

module prng_rule30_stat_tb;

    parameter WIDTH = 64;
    parameter OUT_W = 8;
    parameter SAMPLES = 10000;  // 采样数

    reg  clk, rst_n, enable, init;
    reg  [WIDTH-1:0] seed;
    wire [OUT_W-1:0] rand_out;
    wire valid;
    wire [WIDTH-1:0] debug;

    prng_rule30 #(.WIDTH(WIDTH), .OUT_WIDTH(OUT_W)) dut (
        .clk(clk), .rst_n(rst_n), .enable(enable),
        .init(init), .seed(seed),
        .random_out(rand_out), .valid(valid), .state_debug(debug)
    );

    initial clk = 0;
    always #5 clk = ~clk;

    // 统计计数器
    integer counts [0:255];  // 对8位输出的256种值计数
    integer total;
    real    chi_square;
    real    expected;

    integer n;

    initial begin
        // 初始化计数器
        for (n = 0; n < 256; n = n + 1) counts[n] = 0;
        total = 0;

        $dumpfile("prng_rule30.vcd");
        $dumpvars(0, prng_rule30_stat_tb);

        // 复位
        rst_n = 0; enable = 0; init = 0;
        #50 rst_n = 1;

        // 初始化：中心位为1
        seed = 64'h1 << 31;
        init = 1; #10; init = 0;

        // 采集样本
        enable = 1;
        for (n = 0; n < SAMPLES; n = n + 1) begin
            @(posedge clk);
            counts[rand_out] = counts[rand_out] + 1;
            total = total + 1;
        end

        // 计算卡方统计量
        expected = real'(total) / 256.0;
        chi_square = 0.0;
        for (n = 0; n < 256; n = n + 1) begin
            chi_square = chi_square +
                ((real'(counts[n]) - expected) *
                 (real'(counts[n]) - expected)) / expected;
        end

        $display("=== Rule 30 PRNG Statistics ===");
        $display("Samples: %0d", total);
        $display("Expected per bin: %0.1f", expected);
        $display("Chi-square: %0.2f", chi_square);
        $display("Chi-square critical (df=255, p=0.05): 293.25");
        if (chi_square < 293.25)
            $display("✅ PASSED: Distribution appears uniform");
        else
            $display("❌ FAILED: Distribution may be non-uniform");

        $finish;
    end

endmodule