Monday, August 18, 2014

SystemVerilog: transaction class with virtual interface

Another place to put a clocking block is inside the interface. The direction of signals is with respect to testcase.

interface switch_interface(input clk);
logic [47:0] src_addr;
logic [31:0] src_data;
logic [47:0] dst_addr;
logic [31:0] dst_data;
bit sop, eop, valid;

default clocking cb @(posedge clk);
output #1 src_addr, src_data, sop, eop;
input #2 dst_addr, dst_data, valid;
endclocking

modport testcase_port (input clk, clocking cb);

modport switch_port (input clk, src_addr, src_data, sop, eop);

endinterface


//using vi + clocking block
class packet;
rand bit [47:0] src_addr;
rand bit [31:0] src_data;
 //signal unrelated to rtl
static bit [15:0] pkt_id;
virtual switch_interface vi;

function new(input virtual switch_interface vif);
this.vi = vif; //vi now pointing to actual interface passed in new
pkt_id++;
endfunction

task send_packet();
@(posedge vi.clk);
vi.cb.sop <= 1'b1;
@(posedge vi.clk);
vi.cb.src_addr <= this.src_addr;
vi.cb.sop <= 1'b0;
repeat(6)@(posedge vi.clk);
vi.cb.src_data <= this.src_data;
repeat(4)@(posedge vi.clk);
vi.cb.eop <= 1'b1;
@(posedge vi.clk);
vi.cb.eop <= 1'b0;
endtask
endclass


`include "packet.sv"
program testcase(switch_interface tcif);
packet testcasepacket;

initial begin
testcasepacket = new();
testcasepacket.randomize();
testcasepacket.send_packet();
#100 $finish;
end
endprogram


module testbench();
bit clk;
always #10 clk = ~clk;

switch_interface sif (.clk (clk));

switch sw0 (
.clk (clk),
.src_addr (sif.src_addr),
.src_data (sif.src_data),
.sop(sif.sop),
.eop(sif.eop),
.valid(sif.valid),
.dst_addr (sif.dst_addr),
.dst_data (sif.dst_data)
);

testcase itest (.tcif (sif.testcase_port));

endmodule

No comments:

Post a Comment