Virtual Interface
Gün 5: Arayüzler, Assertion ve Coverage | Sınıflar içinden fiziksel arayüze erişim
Kaynak Kod
// =============================================================================
// GUN 5 - Konu 3: Virtual Interface (Interface'e Class'tan Erişim)
// =============================================================================
interface simple_if(input logic clk);
logic valid;
logic ready;
logic [7:0] data;
// Clocking block sinyalleri clock edge'i ile senkronize eder
clocking cb @(posedge clk);
default input #1step output #0;
output valid, data;
input ready;
endclocking
modport tb (clocking cb, input clk);
modport dut (input clk, valid, data, output ready);
endinterface
// --- Class: Virtual Interface kullanan Driver ---
class Driver;
virtual simple_if.tb vif; // Virtual interface handle
int txn_count = 0;
function new(virtual simple_if.tb vif);
this.vif = vif;
endfunction
task drive(input logic [7:0] data);
@(vif.cb);
vif.cb.valid <= 1;
vif.cb.data <= data;
// Senkron bir şekilde ready'i bekle
do begin
@(vif.cb);
end while (vif.cb.ready !== 1'b1);
vif.cb.valid <= 0;
txn_count++;
$display(" [%0t][Driver] Sent: data=0x%02h (#%0d)", $time, data, txn_count);
endtask
task reset();
vif.cb.valid <= 0;
vif.cb.data <= 0;
@(vif.cb);
$display(" [%0t][Driver] Reset applied", $time);
endtask
endclass
// --- Class: Monitor ---
class Monitor;
virtual simple_if.tb vif;
int observed_count = 0;
logic [7:0] observed_data [$];
function new(virtual simple_if.tb vif);
this.vif = vif;
endfunction
task run();
$display(" [Monitor] Listening started");
forever begin
@(vif.cb);
// === equality check kullan! X ve Z geldiğinde false positive durum olabilir
if (vif.cb.valid === 1'b1 && vif.cb.ready === 1'b1) begin
observed_count++;
observed_data.push_back(vif.cb.data);
$display(" [%0t][Monitor] Observed: data=0x%02h (#%0d)",
$time, vif.cb.data, observed_count);
end
end
endtask
endclass
// Simple DUT
module simple_dut(simple_if.dut sif);
always @(posedge sif.clk) begin
sif.ready <= sif.valid; // Ready - 1 cycle delay
end
endmodule
// Top-level
module virtual_interface;
logic clk = 0;
always #5 clk = ~clk;
simple_if sif(clk);
simple_dut dut(sif);
Driver drv;
Monitor mon;
initial begin
$dumpfile("dump.vcd"); $dumpvars;
end
initial begin
$display("=== Virtual Interface ===\n");
drv = new(sif);
mon = new(sif);
// Monitor'ü çalıştır
fork
mon.run();
join_none
// Reset sequence
drv.reset();
#20;
// Send data
for (int i = 0; i < 8; i++) begin
drv.drive(i * 16 + 'hA0);
end
// Monitor'un son transaction'ı da algılaması için biraz beklet!
// ÖNEMLİ NOT: Beklesek bile algılamayacak, sizce neden?
// fixed.sv'de cevabı var, bu dosyanın içeriğini silip onu yapıştırabilirsin.
#50;
$display("\n --- Results ---");
$display(" Driver sent : %0d", drv.txn_count);
$display(" Monitor observed: %0d", mon.observed_count);
$display(" Observed data : %p", mon.observed_data);
$display("\n=== End of Virtual Interface ===");
$finish;
end
endmodule