Constraint Blokları

Gün 3: Rastgele Üretim ve Kısıtlamalar | inside, dist, if-else, implication (->) kısıtlamaları

Kaynak Kod

// =============================================================================
// GUN 3 - Konu 3: Kisitlama Bloklari: inside, dist, if-else, implication
// =============================================================================

class ConfigPacket;
  typedef enum logic [1:0] {IDLE, READ, WRITE, BURST} cmd_e;

  rand cmd_e         command;
  rand logic [15:0]  address;
  rand logic [31:0]  data;
  rand int unsigned  length;
  rand bit [7:0]     priority;
  rand bit           valid;

  // --- inside: Deger kumesi kisitlamasi ---
  constraint c_addr_inside {
    address inside {[16'h0000:16'h0FFF],    // Bolge 1
                    [16'h2000:16'h2FFF],    // Bolge 2
                    [16'hF000:16'hFFFF]};   // Bolge 3
  }

  // --- dist: Olasilik dagilimi ---
  constraint c_cmd_dist {
    command dist {
      READ   := 40,   // %40 okuma
      WRITE  := 40,   // %40 yazma
      BURST  := 15,   // %15 burst
      IDLE   := 5     // %5  bosta
    };
  }

  constraint c_priority_dist {
    priority dist {
      [0:3]   :/ 60,   // Dusuk oncelik - %60 (/= esit dagilir: her biri %15)
      [4:6]   :/ 30,   // Orta oncelik - %30
      7       := 10    // Yuksek oncelik - %10
    };
  }

  // --- if-else: Kosullu kisitlama ---
  constraint c_data_ifelse {
    if (command == READ) {
      data == 32'h0;                        // Okumada veri sifir
      length inside {[1:4]};
    } else if (command == WRITE) {
      data != 32'h0;                        // Yazmada veri sifir olamaz
      length inside {[1:8]};
    } else if (command == BURST) {
      length inside {[4:16]};               // Burst uzun
    } else {
      length == 0;                          // IDLE
      data == 0;
    }
  }

  // --- implication (->): Sonuc kisitlamasi ---
  constraint c_valid_impl {
    (command != IDLE) -> (valid == 1);      // IDLE degilse gecerli olmali
    (command == IDLE) -> (valid == 0);
  }

  constraint c_burst_addr {
    (command == BURST) -> (address[3:0] == 4'h0);  // Burst hizali adres
  }

  // --- Sabit deger dislama ---
  constraint c_no_zero_addr {
    address != 16'h0000;
  }

  function void display();
    $display("  CMD=%-5s | Addr=0x%04h | Data=0x%08h | Len=%2d | Pri=%0d | V=%0b",
             command.name(), address, data, length, priority, valid);
  endfunction
endclass

module constraint_bloklari;
  initial begin
    ConfigPacket pkt;
    int cmd_counts [string];

    $display("=== Constraint Bloklari ===\n");
    pkt = new();

    // --- Kisitlamali rastgele uretim ---
    $display("--- 20 Rastgele Paket ---");
    cmd_counts["IDLE"]  = 0;
    cmd_counts["READ"]  = 0;
    cmd_counts["WRITE"] = 0;
    cmd_counts["BURST"] = 0;

    repeat (20) begin
      assert(pkt.randomize()) else $fatal(1, "Randomize hata!");
      pkt.display();
      cmd_counts[pkt.command.name()]++;
    end

    // --- Dagilim istatistikleri ---
    $display("\n--- Komut Dagilimi (20 deneme) ---");
    foreach (cmd_counts[key])
      $display("  %s: %0d kez (%%%0d)", key, cmd_counts[key], cmd_counts[key]*5);

    // --- inside dislama (~inside) ---
    $display("\n--- Adres Dislama (~inside) ---");
    repeat (5) begin
      assert(pkt.randomize() with {
        !(address inside {[16'h0000:16'h00FF]});
      });
      $display("  Addr = 0x%04h (0x0000-0x00FF disinda)", pkt.address);
    end

    $display("\n=== Constraint Bloklari Sonu ===");
    $finish;
  end
endmodule