EE5530 Lecture16 Complete SV TestBench
EE5530 Lecture16 Complete SV TestBench
Complete SV TestBench
Memory Read
Courtesy: www.verificationguide.com
Verification Process
Before writing/creating the verification plan, need to know about design, so will go through
the design specification.
Operations:
Write Operation:
address, wr_en, and wdata should be driven at the same clock cycle.
Read Operation:
address and rd_en should be driven on the same clock cycle, Design will respond with the data in the
next clock cycle.
Design Features,
The Memory model is capable of storing 8bits of data per address location
Reset values of each address memory location is ‘hFF
Memory DUT
module memory
#(
parameter ADDR_WIDTH = 2, //Memory
parameter DATA_WIDTH = 8 reg [DATA_WIDTH-1:0] mem [2**ADDR_WIDTH];
)
( //Reset
input clk, always @(posedge reset)
input reset, for(int i=0;i<2**ADDR_WIDTH;i++) mem[i]=8'hFF;
Perform write to any memory location, read from the same memory location, read data should be the same
as written data
Perform write and read to all the memory locations (as the address is 2bit width the possible address are
2‘b00, 2’b01, 2’b10, and 2’b11)
Check default memory values. (before writing any locations, do read operation we should get default values
as ‘hFF)
Assert reset in between write/read operation and check for default values. (after writing to few locations
assert the reset and perform read operation, we should get default memory location value ‘hFF)
TestBench Hierarchy
TestBench Architecture
TestBench Without Monitor, Agent, and Scoreboard
Transaction Class
Fields required to generate the stimulus are declared in the transaction class. Transaction class can
also be used as a placeholder for the activity monitored by the monitor on DUT signals. So, the first
step is to declare the Fields‘ in the transaction class
class transaction;
endclass
Generator Class
Generator class is responsible for,
class generator;
//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);
endtask
endclass
Generator Class
class generator;
//constructor
function new(mailbox gen2driv,event ended);
//getting the mailbox handle from env
this.gen2driv = gen2driv;
this.ended = ended;
endfunction
Interface
Will group the signals, specifies the direction (Modport)
endclocking endclocking
Complete Interface
//constructor
function new(virtual mem_intf mem_vif,mailbox gen2driv);
//getting the interface
this.mem_vif = mem_vif;
//getting the mailbox handle from environment
this.gen2driv = gen2driv;
endfunction
Reset Task
For simplicity, define is used to access interface signals.
gen2driv.get(trans);
$display("--------- [DRIVER-TRANSFER: %0d] ---------",no_transactions);
@(posedge mem_vif.DRIVER.clk);
`DRIV_IF.addr <= trans.addr;
if(trans.wr_en) begin
`DRIV_IF.wr_en <= trans.wr_en;
`DRIV_IF.wdata <= trans.wdata;
$display("\tADDR = %0h \tWDATA = %0h",trans.addr,trans.wdata);
@(posedge mem_vif.DRIVER.clk);
end
Drive Task (contd..)
if(trans.rd_en) begin
`DRIV_IF.rd_en <= trans.rd_en;
@(posedge mem_vif.DRIVER.clk);
`DRIV_IF.rd_en <= 0;
@(posedge mem_vif.DRIVER.clk);
trans.rdata = `DRIV_IF.rdata;
$display("\tADDR = %0h \tRDATA = %0h",trans.addr,`DRIV_IF.rdata);
end
$display("-----------------------------------------");
no_transactions++;
end
endtask
class driver;
//mailbox handle's
mailbox gen2driv;
//virtual interface
virtual mem_intf mem_vif;
Environment Constructor
Create Mailbox, Generator, Driver and pass the interface handle through the new() method.
//constructor
function new(virtual mem_intf mem_vif);
//get the interface from test
this.mem_vif = mem_vif;
//creating the mailbox (Same handle will be shared across generator and driver)
gen2driv = new();
task post_test();
task pre_test(); wait(gen_ended.triggered);
driv.reset(); wait(gen.repeat_count == driv.no_transactions);
endtask endtask
task test();
fork task run;
gen.main(); pre_test();
driv.main(); test();
join_any post_test();
endtask $finish;
endtask
`include "transaction.sv"
Complete Environment Code
`include "generator.sv"
`include "driver.sv"
class environment; //creating the mailbox
//(Same handle will be shared
//generator and driver instance //across generator and driver)
generator gen; gen2driv = new();
driver driv; task post_test();
//creating generator and driver wait(gen_ended.triggered);
//mailbox handle's gen = new(gen2driv,gen_ended); wait(gen.repeat_count ==
mailbox gen2driv; driv = new(mem_vif,gen2driv); driv.no_transactions);
endfunction endtask
//event for synchronization
//between generator and test task pre_test(); //run task
event gen_ended; driv.reset(); task run;
endtask pre_test();
//virtual interface test();
virtual mem_intf mem_vif; task test(); post_test();
fork $finish;
//constructor gen.main(); endtask
function new(virtual mem_intf mem_vif); driv.main();
//get the interface from test join_any endclass
this.mem_vif = mem_vif; endtask
Test
Test is written with program construct and is responsible for,
`include "environment.sv"
program test(mem_intf intf);
initial begin
//creating environment
env = new(intf);
//calling run of env, it interns calls generator and driver main tasks.
env.run();
end
endprogram
`include "interface.sv"
TestBench Top
`include "random_test.sv"
endclass