Mutiple test cases needs to be run sequentially in SV or UVM

i have System verilog framework in which i ave tester, scoreboard interface BFm, and testbench

i have written some tasks(testing different scenarios) in Interface BFM , i am passing random values and inputs rather calling this tasks in tester, i have genearl scoreboard in which i have written tasks to monitor all this outputs. and in testbench i am calling all this tasks.

now the problem is i want to call this task(present in INterface sequentially in tester and check teh output signals of checker

for eg.
Interface has
Task 1
Task 2
task 3

i am passing my values in tester
Tester task 1
Tester task 2
Tester task 3

against which i want to check
scoreboard task 1
scoreboard task 2
scoreboard task 3

in my testbench
i am creating a handle of scoreboard and tester
s i want to work my code like this
tester task 1
scoreboard task 1
tester task 2
scoreboard task 2
tester task 3
scoreboard task 3

can somebody help please its urgent…

i am also open to understand UVM framework
i have build phase and run phase
i want to test this task separately

one more thing
this is UART module in which
i have FIFO and UART basically
1st task test the basic opeartion
2nd task test if FIFO is full or not
so for 1st i am sending the data for teh first time
but for 2nd time i m sending data continously till it exausts the limit

please guide.

In reply to rtawade:

Post your code please. Your description is confusing.

In reply to bmorris:

okay… here it is…

this is interface...
interface UART_bfm;

int tx_counter;
int rx_counter;
int i;
   logic [15:0]   TX_REQ;
   logic		  CLK;
   logic 		  reset;

   logic		  WR;
   logic [3:0] 	  br_sel;
   logic		  RD;
   
   logic		  txclk;
   logic		  rxclk;
   logic		  ld_tx_data;
   logic		  tx_enable;
   logic		  rx_in;
   logic		  uld_rx_data;
   logic		  rx_enable;
   logic [7:0] 	  tx_data;

	logic [2:0] R;   

   //output reg		  tx_full;
   logic		  tx_empty;
   //logic		  rx_full;
   logic		  tx_fifo_empty;
   logic		  tx_out;
   logic		  tx_fifo_full;
   logic [7:0] 	  rx_data;
   logic		  rx_fifo_empty;
   logic		  rx_frame_err_out;
   logic		  rx_over_run_out;
   logic		  rx_busy_out;
   logic		  tx_over_run_out;
   logic [3:0]    rx_cnt_out;
   logic [39:0]   RX_FIFO_DATA;
   logic		  rx_fifo_full;
   logic		  rx_empty;
   logic [39:0]   TX_FIFO_OUT;
   logic [39:0]   RX_FIFO_OUT;
   
   
initial begin 
CLK = 1 ;
forever  #5 CLK=~CLK; end

//*****************Test case1**********************
//RESET Operation 
task reset_UART();
reset =1'b1;
ld_tx_data = 1'b0;
tx_data = 8'h00;
tx_enable = 1'b1;
uld_rx_data = 1'b0;
rx_enable = 1'b1;
#500;
reset =1'b0;
endtask : reset_UART

//*********************test case 2*************************
//basic operation of transmitting and receiving data 
task  TransmitData(input [0:7]itx_data,[0:15] iTX_REQ );	
//BAsic OPeration TX

$display ("Basic Operation ");
br_sel = 2'b00;
WR = 0;
tx_data = itx_data;
TX_REQ = iTX_REQ;
#100;
WR = 1'b1;
#20;
WR = 1'b0;
RD = 1'b0;
#100;
wait (tx_empty == 1);
ld_tx_data = 1'b1;
wait (tx_empty == 0);
$display ($time," Data loaded for send.......lots of love you have reached here..");
ld_tx_data = 1'b0;
wait(tx_empty == 1);
$display ($time, "Data Sent... tx_data = %h", tx_data);

endtask:TransmitData

task ReceiveData( );
//RX UART
$display ("ReceiveData");
tx_enable = 1'b1;
wait (rx_empty == 1'b0);
$display ($time, "RX byte REady....");
uld_rx_data = 1'b1;
$display ($time, "RX byte unloaded.... %h", rx_data);
#100;
RD = 1; // this is not working 
#100;
uld_rx_data = 1'b0;
RD = 0;

endtask :ReceiveData

//*********************test case 3*************************
//UART with TX reset//
task TX_UART_RESET(input bit[7:0] rand_tx_data,input bit[15:0] Tx_request);
begin
	$display ("TX_UART_RESET");
	br_sel = 2'b00;
	tx_data = rand_tx_data;
	TX_REQ = Tx_request;
	#100;
	WR = 1'b1;
	#20;
	WR = 1'b0;
	RD = 1'b0;
	#500;
	ld_tx_data = 1;
	reset = 1'b1;
	#100;
	reset = 1'b0;
	ld_tx_data = 0;
	$display ("Waiting for tx_empty to become 0");
	for ( i=0; i<200; i++)
	begin 
	$display ("after reaset, loading has failed .");	
	end
end
endtask


task RX_UART_WITH_RESET(); 
begin
		$display ("RX_UART_WITH_RESET ");
		tx_enable = 1'b1;
		wait(rx_empty == 0);
		$display ("RX Byte Ready");
		uld_rx_data = 1;
		#100;
		reset = 1'b0;
		for (int i=0; i<500; i++) 
		begin
			$display ("after reaset, loading has failed .");		
		end
end
endtask


//DIFFERENT BAUD RATES
task TX_UART_BAUDRATES(input bit[7:0] rand_tx_data,input bit[15:0] TX_REQUEST, input [0:1] br_select);
begin
	$display ("TX_UART_BAUDRATES ");
	br_sel = br_select;
	tx_data = rand_tx_data;
	TX_REQ = TX_REQUEST;
	#100;
	WR = 1'b1;
	#20;
	WR = 1'b0;
	RD = 1'b0;
	#500;
	wait(tx_empty == 1 ) ;
	ld_tx_data = 1;
	repeat(2) @(negedge txclk);
	ld_tx_data = 0;
	wait (tx_empty == 0);
	$display ("data loaded for send..");
	wait (tx_empty == 1);
	$display ("Data Sent");
end
endtask;

task RX_UART_BAUDRATE();
begin
	$display ("RX_UART_BAUDRATE ");  
	tx_enable = 1'b1;
	wait (rx_empty ==0);
	$display ("RX byte READy");
	uld_rx_data = 1;
	wait (rx_empty == 1);
	$display ("RX BYTE UNLOADED... : %0h", rx_data);
	#100;
	RD = 1;
	#100;
	uld_rx_data = 0;
	RD = 1'b0;
end
endtask

initial 
	begin
      rxclk = 0;
      txclk = 0;
      tx_counter = 0;
      rx_counter = 0;
	end

always @(posedge CLK) 
	begin
	    
    if(br_sel == 2'b00)
	begin
	tx_counter = tx_counter+1;
		if (tx_counter == 1) 
	    begin
			txclk <= ~txclk;
			tx_counter <= 0;
	    end

	    rx_counter = rx_counter + 1;

		if(rx_counter == 1)
	    begin
			rxclk <= ~rxclk;
			rx_counter <= 0;
	    end
	end
	
	else if(br_sel == 2'b01)
	begin
	tx_counter = tx_counter+1;
		if (tx_counter == 2604) 
	    begin
			txclk <= ~txclk;
			tx_counter <= 0;
	    end
		rx_counter = rx_counter + 1;
		if(rx_counter == 163)
	    begin
			rxclk<= ~rxclk;
			rx_counter <= 0;
	    end
	end

    else if(br_sel == 2'b10)
	begin
	tx_counter = tx_counter+1;
		if (tx_counter == 1302) 
	    begin
			txclk <= ~txclk;
			tx_counter <= 0;
	    end
		rx_counter = rx_counter + 1;
		if(rx_counter == 81)
	    begin
			rxclk<= ~rxclk;
			rx_counter <= 0;
	    end
	end
    
	else if(br_sel == 2'b11)
	begin
	tx_counter = tx_counter+1;
		if (tx_counter == 434) 
	    begin
			txclk <= ~txclk;
			tx_counter <= 0;
	    end
		rx_counter = rx_counter + 1;
		if(rx_counter == 27)
	    begin
			rxclk<= ~rxclk;
			rx_counter <= 0;
	    end
	end
      
   end

///////////////////
task transmit_uart_tx_full(input [0:7]itx_data,[0:15] iTX_REQ);
begin
	
	bfm.tx_data=itx_data;
	bfm.br_sel=2'b00;
	bfm.TX_REQ=iTX_REQ;
	#100;
	bfm.WR =1'b1;
	#20;
	bfm.WR=1'b0;
	bfm.RD=1'b0;
		
end
endtask

endinterface 

here i am calling various tasks from bfm to execute, i want to run specific number of scoreboard tasks against each testcase/ task of my tester.
or you can say i want to run each testcase separately.
for eg i want task bfm.TransmitData(tx_data,TX_REQ) to run and then i want to check my scoreboard task named A and check status of signals. get the the test case result and then test another testcase/ task from tester.

class tester;

   virtual UART_bfm bfm;
   
   function new (virtual UART_bfm b);
		bfm = b;
	endfunction : new

      
protected function reg[0:7] get_data();
reg [0:7] transmit_data;
transmit_data = $random;
return transmit_data;
endfunction : get_data


protected function reg[0:1] RANDOMB_RATE();
reg [0:1] BAUD_RATE;
BAUD_RATE = $random;
return BAUD_RATE;
endfunction : RANDOMB_RATE


	logic [0:7] tx_data;
    logic [0:15] TX_REQ;
	logic [0:1] Br_sel;
	
task execute();
	
	bfm.reset_UART();
	tx_data = get_data();
	TX_REQ=16'h01;
        
	bfm.TransmitData(tx_data,TX_REQ);
	bfm.ReceiveData();
	
       
	bfm.TX_UART_RESET(tx_data,TX_REQ);
	bfm.RX_UART_WITH_RESET();
	
	#100;
	tx_data = get_data();
	TX_REQ = 16'h03;
	Br_sel = RANDOMB_RATE();
    
	bfm.TX_UART_BAUDRATES(tx_data, TX_REQ, Br_sel);
	bfm.RX_UART_BAUDRATE(); 
	
	bfm.reset_UART();

	
	
     
endtask : execute
task FIFO_FULL();
begin

	$display("Data started");
	bfm.reset_UART();
	TX_REQ = 16'h00;
	for (int i = 0; i<20; i++)
	begin
	TX_REQ= TX_REQ+1'b1;
	tx_data = get_data();
	bfm.transmit_uart_tx_full(tx_data, TX_REQ);

	end
end
endtask


endclass : tester

---------------------------------------------------------

class scoreboard;

virtual UART_bfm bfm;

function new(virtual UART_bfm b);
	bfm = b;
endfunction : new

logic [0:7] sb_tx_data;
logic [0:7] sb_rx_data;
reg 	     tx_par;
reg 	     rx_par;

task execute();
forever begin @(bfm.uld_rx_data)
	if (bfm.rx_data) 
	begin 
	tx_par = ~(bfm.tx_data[6] ^ bfm.tx_data[5] ^ bfm.tx_data[4] ^ bfm.tx_data[3] ^ bfm.tx_data[2] ^ bfm.tx_data[1] ^ bfm.tx_data[0]);
	rx_par = ~(bfm.rx_data[6] ^ bfm.rx_data[5] ^ bfm.rx_data[4] ^ bfm.rx_data[3] ^ bfm.rx_data[2] ^ bfm.rx_data[1] ^ bfm.rx_data[0]);
		if (rx_par == bfm.rx_data[7]) 
			begin
			$display(" %0d :PARITY CHECK : Good value of data received - CORRECT PARITY,%b, %b,%b ",  $time, tx_par,bfm.tx_data[7],bfm.rx_data[7]);
			end
		
		if (bfm.tx_data == bfm.rx_data)
			begin
			$display ( "success:transmited_data : %0h, recieved_data : %0h",bfm.tx_data,bfm.rx_data);
			end			
		else 
			$display ( "Failed:transmited_data : %0h, recieved_data : %0h",bfm.tx_data,bfm.rx_data);
			
	end
		
end 
	
forever begin @(bfm.uld_rx_data)
	if (bfm.rx_data) 
	begin 
	tx_par = ~(bfm.tx_data[6] ^ bfm.tx_data[5] ^ bfm.tx_data[4] ^ bfm.tx_data[3] ^ bfm.tx_data[2] ^ bfm.tx_data[1] ^ bfm.tx_data[0]);
	if (tx_par == bfm.tx_data[7]) 
			begin
			$display(" %0d :PARITY CHECK : Good value of data tramsmitted - CORRECT PARITY ",$time);
			end

end
end
forever 
begin @(bfm.txclk)
	if (bfm.tx_empty==1)
	begin
	 $display (" TRANSMITTER EMPTY ");
	end
end
forever 
begin @(bfm.rxclk)
	if (bfm.rx_empty==1)
	begin
	 $display ("RECEIVER EMPTY ");
	end
end
endtask : execute 

////////////////////////////SUB TAsks//////////////////////////////

task tx_rx();
$display("tc_rx execution started....");
forever begin @(bfm.ld_tx_data)

	sb_tx_data=bfm.tx_data;
	$display ("%0d :scoreboard : scoreboard recieved trasmitted data from driver :%b",$time,sb_tx_data);
	sb_rx_data=bfm.rx_data;
	$display(" %0d : Scorebooard : Scoreboard received transmitted data from driver:%b ",$time,sb_tx_data);
	
	begin
		if (bfm.tx_data == bfm.rx_data)
		$display ( "success:transmited_data : %0h, recieved_data : %0h",bfm.tx_data,bfm.rx_data);
        else
		$display ( "Failed:transmited_data : %0h, recieved_data : %0h",bfm.tx_data,bfm.rx_data);
	end 
end
endtask : tx_rx 


task tx_rx_empty();
$display ("rx_tx empty started");
forever 
begin @(bfm.txclk)
	if (bfm.tx_empty==1)
	begin
	 $display (" TRANSMITTER EMPTY ");
	end
end
forever 
begin @(bfm.rxclk)
	if (bfm.rx_empty==1)
	begin
	 $display ("RECEIVER EMPTY ");
	end
end

endtask:tx_rx_empty

task tx_rx_en ();
$display ("2 rx_tx empty started");
forever 
	begin @(bfm.txclk)
	if(bfm.tx_enable==1)
		begin
		$display("TRANSMITTER ACTIVE");		
		end
    end
 
forever
begin @(bfm.rxclk)
	if (bfm.rx_enable==1)
		begin
		$display(" RECEIVER ACTIVE");		
		end
    end 
endtask	:tx_rx_en

task tx_rx_full();
$display ("rx_tx full started");
forever 
begin @(bfm.txclk)
	if (bfm.tx_fifo_full==1)
	begin
	 $display (" TRANSMITTER FULL ");
	end
end
forever 
begin @(bfm.rxclk)
	if (bfm.rx_fifo_full==1)
	begin
	 $display ("RECEIVER FULL ");
	end
end

endtask:tx_rx_full

task FIFO_FULL_ERROR();
begin
if (bfm.tx_fifo_full==1)
	begin
	 $display (" TRANSMITTER FULL ");
	end
else 
begin 
	 $display (" TRANSMITTER NOT FULL ");
end
end
endtask

task fr_err(); 
      //packet pkt_rcv,pkt_exp; 
      forever 
	begin
	   if(bfm.rx_frame_err_out == 1)	      
	   begin
	      $display(" %0d : FRAME ERROR : INCORRECT START AND STOP BITS !!!!!",$time);
	   end

	end 
   endtask : fr_err
   
    task tx_rx_overrun_err(); 
      //packet pkt_rcv,pkt_exp; 
      forever 
	begin
	   if(bfm.tx_over_run_out == 1)	      
	     begin
		$display(" %0d : OVERRUN ERROR : SLOW TRANSMIT FAST RECEIVE !!!!!",$time);
	     end
	   if(bfm.rx_over_run_out == 1)	      
	     begin
		$display(" %0d : OVERRUN ERROR : FAST TRANSMIT SLOW RECEIVE !!!!!",$time);
	     end	   
	end 
   endtask : tx_rx_overrun_err
   
   
   task parity_chk(); 
      //packet pkt_rcv,pkt_exp; 
      
      begin
	 if(bfm.ld_tx_data == 1)
	   begin
	      sb_tx_data =  bfm.tx_data;
	      $display(" %0d : Scorebooard : Scoreboard received transmitted data from driver:%b ",$time,sb_tx_data);
	      tx_par = ~(sb_tx_data[6] ^ sb_tx_data[5] ^ sb_tx_data[4] ^ sb_tx_data[3] ^ sb_tx_data[2] ^ sb_tx_data[1] ^ sb_tx_data[0]);
	      if(tx_par == sb_tx_data[7])
		$display(" %0d :PARITY CHECK : Good value of data tramsmitted - CORRECT PARITY ",$time);
	      else
		$display(" %0d :PARITY CHECK : Bad value of data tramsmitted - INCORRECT PARITY",$time);		  
	   end
	 
	 if(bfm.uld_rx_data == 1)	      
	   begin
	      sb_rx_data =  bfm.rx_data; 
	      $display(" %0d : Scorebooard : Scoreboard received a packet from receiver:%b ",$time,sb_rx_data);
	      rx_par = ~(sb_rx_data[6] ^ sb_rx_data[5] ^ sb_rx_data[4] ^ sb_rx_data[3] ^ sb_rx_data[2] ^ sb_rx_data[1] ^ sb_rx_data[0]);
	      if(rx_par == sb_rx_data[7])
		$display(" %0d :PARITY CHECK : Good value of data received - CORRECT PARITY ",$time);
	      else
		$display(" %0d :PARITY CHECK : Bad value of data received - INCORRECT PARITY ",$time);	
	   end

      end
   endtask : parity_chk 
   
endclass :scoreboard 
------------------------------------------------------------------
`include "scoreboard.sv"
`include "tester.sv"
`include "coverage.sv"
class testbench_virtual;

   virtual UART_bfm bfm;


   tester    tester_h;
   scoreboard scoreboard_h;
  coverage coverage_h;
 
   function new (virtual UART_bfm b);
       bfm = b;
   endfunction : new

   task TestCases();
   begin
   tester_h.FIFO_FULL();
   scoreboard_h.FIFO_FULL_ERROR();
   $display("NExt Test case");
   basicOp();
   
   
   end
   
   endtask
   
   task basicOp();
   fork
   tester_h.execute();
   scoreboard_h.execute();
   join_none
   endtask
   
   task execute();
      tester_h    = new(bfm);
      scoreboard_h = new(bfm);
	coverage_h = new(bfm);

      fork      
		TestCases();
		coverage_h.execute();
 /*
	 tester_h.execute();
         scoreboard_h.execute();
         coverage_h.execute();
         scoreboard_h.tx_rx();
scoreboard_h.tx_rx_empty();
scoreboard_h.tx_rx_full();
scoreboard_h.tx_rx_en();
*/
      join_none
   endtask : execute
endclass : testbench_virtual

i have written this testbench as of now to serially execute and check the status as some of the testcases run parallel with scoreboard and some serial with scoreboard.but i am confused to decide hwo the UART has to be tested.

DO i need to monitor all the signals ? if yes then how will kow if my tstecase has been failed or succeed coz all the scoreboard task would run in parallel hence difficult to determine which one has been passed which one doesnt if you think there is something wrong with the approach please suggest how can i do it. i am happy to post more details here.

In reply to rtawade:

oy… ok my first response would be to migrate to UVM.

Since that’s out of the way, I may not be the best to answer this question, but…

I would have SB threads which call monitor tasks in the BFM. E.g. from SB, fork off a forever statement calling bfm.monitor_tx_bus (monitor the serial TX bus). When this task returns, the SB knows a serial transmission just occurred, and it returns the whole dataword it saw off bus. This needs to be compared to a predicted value, which should have ALREADY been generated from your test.

  1. test writes 'hAB to serial TX
  2. SB stores predicted output 'hAB in local fifo
  3. SB bfm.monitor_tx() returns, has data 'hAB.
  4. check passed!

You can queue up several predicted values in a row before actual values appear on bus.

Same deal on RX. Whatever is driving the RX bus can provide the data words for the predicted values. If it’s a loopback, well you already know the answer.

Your forked tasks can also use that time to check parity, whatever.
I think it would only have 2 perpetual tasks tho:
fork
monitor_rx();
monitor_tx();
join_none

task monitor_rx();
forever begin
bfm.monitor_rx();
// got something!
// perform checking…
begin
endtask

task monitor_tx();
forever begin
bfm.monitor_tx();
// got something!
// perform checking…
begin
endtask

task execute();
      tester_h    = new(bfm);
      scoreboard_h = new(bfm);
	coverage_h = new(bfm);
 
      
      fork      
        scoreboard_h.execute(); // start the scoreboard. runs all simulation.
        tester_h.execute(); // start the tests
      join_none


   endtask : execute

if the SB has tasks it needs to fork, it can do that itself.

In reply to bmorris:

thanks for your inputs…

it did work with fork and i am able to do it sequentially.
now i am working to migrate this to UVM in case i face any error which is likely to be (as i am a beginner ) i would post it here.

Thanks once again.