以下の内容はhttps://msyksphinz.hatenablog.com/entry/2025/08/11/040000より取得しました。


Verilog 2001で実装されたBooth乗算器を調査する (4. SystemVerilogテストベンチの設計: tb_mul)

前章で解析したmul_1.vの実装に対して、 tb_mul を作成して検証することにした。

msyksphinz.hatenablog.com

リファレンスモデルの実装

function automatic logic [63:0] model_mul(
    bit s1, bit s2, logic [31:0] a, logic [31:0] b
);
    logic        [63:0] A_u, B_u;
    logic signed [63:0] A_s, B_s;
    logic signed [63:0] P_s;

    // Sign-extend or zero-extend to 64 bits
    A_u = {32'b0, a};
    B_u = {32'b0, b};
    A_s = s1 ? $signed({{32{a[31]}}, a}) : $signed(A_u);
    B_s = s2 ? $signed({{32{b[31]}}, b}) : $signed(B_u);

    P_s = A_s * B_s; // 64-bit multiply
    return P_s;
endfunction

スコアボードによる検証

typedef struct packed {
    int          due_cycle;
    logic [63:0] exp;
} exp_t;

exp_t exp_q[$]; // Queue of expected results

always_ff @(posedge clk) begin
    if (reset) begin
        cycle <= 0;
        exp_q.delete();
    end else begin
        cycle <= cycle + 1;
        
        // Compare when due_cycle is reached
        if (exp_q.size() != 0 && (exp_q[0].due_cycle == cycle)) begin
            if (resp_result !== exp_q[0].exp) begin
                $display("[TIME %0t] MISMATCH at cycle %0d:", $time, cycle);
                $fatal(1, "Result mismatch.");
            end
            exp_q.pop_front();
        end
    end
end

ドライバーの設計

task automatic drive_and_expect(
    bit s1, bit s2, logic [31:0] a, logic [31:0] b
);
    logic [63:0] expected = model_mul(s1, s2, a, b);

    @(posedge clk);
    req_in_1_signed = s1;
    req_in_2_signed = s2;
    req_in_1        = a;
    req_in_2        = b;
    req_valid       = 1'b1;

    // Push expected result into queue
    exp_q.push_back({cycle+RESP_LATENCY+1, expected});

    @(posedge clk);
    req_valid = 1'b0;
endtask

ダイレクト・テスト

task automatic run_directed();
    // Corner cases
    drive_and_expect(0,0, 32'd0,         32'd0);           // ゼロ乗算
    drive_and_expect(1,1, 32'h8000_0000, 32'd2);          // INT_MIN * 2
    drive_and_expect(1,1, 32'h8000_0000, 32'hFFFF_FFFF);  // INT_MIN * -1
    drive_and_expect(0,0, 32'hFFFF_FFFF, 32'hFFFF_FFFF);  // 最大値同士
    // ... その他の境界条件
endtask

ランダムテスト

task automatic run_random(int n);
    for (int i = 0; i < n; i++) begin
        bit s1 = $urandom_range(0,1);
        bit s2 = $urandom_range(0,1);
        logic [31:0] a = $urandom();
        logic [31:0] b = $urandom();
        drive_and_expect(s1, s2, a, b);
    end
endtask



以上の内容はhttps://msyksphinz.hatenablog.com/entry/2025/08/11/040000より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14