Scoreboard

Gün 7: Bitirme Projesi - Bölüm 2 | Referans model ile DUT çıkışını karşılaştırma

Kaynak Kod

// =============================================================================
// GUN 7 - Konu 2: Scoreboard - Referans Model ile DUT Karsilastirmasi
// =============================================================================

class ALU_Scoreboard;
  mailbox #(ALU_Transaction) drv2scb;  // Driver'dan beklenen
  mailbox #(ALU_Transaction) mon2scb;  // Monitor'den gercek

  int pass_count = 0;
  int fail_count = 0;
  int total_count = 0;

  function new(mailbox #(ALU_Transaction) drv_mbx, mailbox #(ALU_Transaction) mon_mbx);
    this.drv2scb = drv_mbx;
    this.mon2scb = mon_mbx;
  endfunction

  task run();
    ALU_Transaction expected, actual;
    logic [15:0] ref_result;
    logic [3:0]  ref_flags;

    $display("[Scoreboard] Baslatildi");

    forever begin
      drv2scb.get(expected);
      mon2scb.get(actual);
      total_count++;

      // Referans model hesaplama
      compute_reference(expected.opcode, expected.operand_a, expected.operand_b,
                        ref_result, ref_flags);

      // Karsilastirma
      if (actual.result === ref_result) begin
        pass_count++;
      end else begin
        fail_count++;
        $display("[Scoreboard] HATA #%0d!", total_count);
        $display("  Islem    : %s", expected.opcode.name());
        $display("  A=0x%02h, B=0x%02h", expected.operand_a, expected.operand_b);
        $display("  Beklenen : result=0x%04h, flags=%04b", ref_result, ref_flags);
        $display("  Gercek   : result=0x%04h, flags=%04b", actual.result, actual.flags);
      end
    end
  endtask

  // Referans model: ALU davranisini yazilimda modelle
  function void compute_reference(
    ALU_Transaction::opcode_e opcode,
    logic [7:0] a, logic [7:0] b,
    output logic [15:0] result,
    output logic [3:0] flags
  );
    logic [16:0] temp;
    flags = 0;

    case (opcode)
      ALU_Transaction::OP_ADD: begin
        temp = {1'b0, a} + {1'b0, b};
        result = temp[15:0];
        flags[2] = temp[8];  // carry
        flags[3] = (a[7] == b[7]) && (temp[7] != a[7]);  // overflow
      end
      ALU_Transaction::OP_SUB: begin
        temp = {1'b0, a} - {1'b0, b};
        result = temp[15:0];
        flags[2] = temp[8];  // borrow
        flags[3] = (a[7] != b[7]) && (temp[7] != a[7]);  // overflow
      end
      ALU_Transaction::OP_AND: result = {8'h00, a & b};
      ALU_Transaction::OP_OR:  result = {8'h00, a | b};
      ALU_Transaction::OP_XOR: result = {8'h00, a ^ b};
      ALU_Transaction::OP_NOT: result = {8'h00, ~a};
      ALU_Transaction::OP_SHL: result = a << b[2:0];
      ALU_Transaction::OP_SHR: result = a >> b[2:0];
    endcase

    // Zero & Negative
    if (opcode inside {ALU_Transaction::OP_ADD, ALU_Transaction::OP_SUB})
      flags[0] = (temp[7:0] == 0);
    else
      flags[0] = (result == 0);
    flags[1] = result[15] | result[7];
  endfunction

  function void report();
    $display("\n  ========== SCOREBOARD RAPORU ==========");
    $display("  Toplam  : %0d", total_count);
    $display("  Basarili: %0d", pass_count);
    $display("  Basarisiz: %0d", fail_count);
    if (fail_count == 0)
      $display("  *** TUM TESTLER BASARILI! ***");
    else
      $display("  !!! %0d HATA TESPIT EDILDI !!!", fail_count);
    $display("  ========================================");
  endfunction
endclass