SystemVerilog TestBench Example - ADDER
Part 1 Transaction
- Fields required to generate the stimulus are declared in the transaction class.
- Transaction class can also be used as the placeholder for the activity monitored by the monitor on DUT signals.
class transaction; //declaring the transaction items rand bit [3:0] a; rand bit [3:0] b; bit [6:0] c; function void display(string name); $display("- %s ",name); $display("- a = %0d, b = %0d",a,b); $display("- c = %0d",c); endfunction endclass
Part 2 Generator
- Generating the stimulus by randomizing the transaction class
- Sending the randomized class to driver
class generator; rand transaction trans; //declaring transaction class mailbox gen2driv; //declaring mailbox event ended; //event, to indicate the end of transaction generation //constructor function new(mailbox gen2driv); this.gen2driv = gen2driv; //getting the mailbox handle from env endfunction //main task, generates(create and randomizes) the packets and puts into mailbox task main(); trans = new(); if( !trans.randomize() ) $fatal("Gen:: trans randomization failed"); gen2driv.put(trans); //put data into mailbox -> ended; //triggering indicatesthe end of generation endtask endclass
Part 3 Interface
- The interface will group the signals
interface myintf(input logic clk,reset); //declaring the signals logic valid; logic [3:0] a; logic [3:0] b; logic [6:0] c; endinterface
Part 4 Driver
- receive the stimulus generated from generator and drive to DUT by assigning transaction class values to interface signals.
class driver; //used to count the number of transactions int no_transactions; //creating virtual interface handle 定义虚接口 virtual myintf vif; //creating mailbox handle mailbox gen2driv; //constructor function new(virtual myintf vif,mailbox gen2driv); //getting the interface this.vif = vif; //getting the mailbox handles from environment this.gen2driv = gen2driv; endfunction //Reset task, Reset the Interface signals to default/initial values task reset; wait(vif.reset); $display("[ DRIVER ] ----- Reset Started -----"); vif.a <= 0; vif.b <= 0; vif.valid <= 0; wait(!vif.reset); $display("[ DRIVER ] ----- Reset Ended -----"); endtask //drivers the transaction items to interface signals task main; forever begin transaction trans; gen2driv.get(trans); @(posedge vif.clk); vif.valid <= 1; vif.a <= trans.a; vif.b <= trans.b; @(posedge vif.clk); vif.valid <= 0; trans.c <= vif.c; @(posedge vif.clk); trans.display("[ Driver ]"); no_transactions++; end endtask endclass
Part 5 Environment
- Environment is container class contains Mailbox, Generator and Driver
class environment; generator gen; //generator and driver instance driver driv; mailbox gen2driv; //mailbox handle's virtual myintf vif; //virtual interface //constructor function new(virtual myintf vif); this.vif = vif; //get the interface from test //creating the mailbox (Same handle will be shared across generator and driver) gen2driv = new(); gen = new(gen2driv); //creating generator and driver driv = new(vif,gen2driv); endfunction // task pre_test(); driv.reset(); //function in driver class endtask task test(); fork gen.main(); driv.main(); join_any endtask task post_test(); wait(gen.ended.triggered); wait(gen.repeat_count == driv.no_transactions); endtask //run task task run; pre_test(); test(); post_test(); $finish; endtask endclass
Part 6 Test
- Creating the environment.
- Configuring the testbench i.e, setting the type and number of transactions to be generated.
- Initiating the stimulus driving.
`include "environment.sv" program test(myintf); environment env; //declaring environment instance initial begin env = new(myintf); //creating environment //setting the repeat count of generator as 10, means to generate 10 packets env.gen.repeat_count = 10; //calling run of env, it interns calls generator and driver main tasks. env.run(); end endprogram
Part 7 Top
- This is the topmost file, which connects the DUT and TestBench.
- TestBench top consists of DUT, Test and Interface instances.
- The interface connects the DUT and TestBench.
`include "interface.sv" `include "random_test.sv" module tbench_top; bit clk; bit reset; always #5 clk = ~clk; //generate clk //reset Generation initial begin reset = 1; #5 reset =0; end //creatinng instance of interface, inorder to connect DUT and testcase 实例interface myintf i_intf(clk,reset); //实例 test class test t1(i_intf); //DUT instance, interface signals are connected to the DUT ports adder DUT ( .clk(i_intf.clk), .reset(i_intf.reset), .a(i_intf.a), .b(i_intf.b), .valid(i_intf.valid), .c(i_intf.c) ); //enabling the wave dump initial begin $dumpfile("dump.vcd"); $dumpvars; end endmodule