Clock generator task - forever statement makes the simulator hang

In reply to dave_59:

Hi Dave, thanks for the reply. That did not fix my issue unfortunately, so I am going to post the testbench code below. I am going to try and delete out the irrelevant stuff to make it easier to read.

TB Module:

timescale 1ns/1ns

import header_pkg::*;
import common_pkg::*;
import testcase_pattern_generator_pkg::*;

module tb_fpga();

	// Pattern Generator interface
    pattgen_if          pattgen_if();

    // Group: Class Constructs
    //////////////////////////////////////////////////////

    // Contains misc tools to add wait states and monitor interrupt on a signal
    common_pkg::events #(`CLOCK_PARAM) ev;    // task_wait_x_seconds, task_wait_clock_cycles

    // Class used to validate the test results.
    common_pkg::scoreboard scrb;

    // Testcases
	testcase_pattern_generator_pkg::class_testcase_pattern_generator #(`CLOCK_PARAM) testcase_pattern_gen;

// instantiate the pattern_gen_v1_0 for the pattern generator test
pattern_gen_v1_0 #(
    .C_AXIS_TDATA_WIDTH(24),
	.C_S_AXI_DATA_WIDTH(32),
	.C_S_AXI_ADDR_WIDTH(32)
)	
	pattern_gen_inst
(
	.i_video_vsync(pattgen_if.video_vsync),
	.o_vsync_int(pattgen_if.vsync_int),
	.i_axis_aclk(pattgen_if.axis_aclk),
	.i_axis_aresetn(pattgen_if.axis_aresetn),
	.s_axis_tdata(pattgen_if.s_axis_tdata),
	.s_axis_tvalid(pattgen_if.s_axis_tvalid),
	.s_axis_tready(pattgen_if.s_axis_tready),
	.s_axis_tuser_sof(pattgen_if.s_axis_tuser_sof),
	.s_axis_tlast(pattgen_if.s_axis_tlast),
	.m_axis_tdata(pattgen_if.m_axis_tdata),
	.m_axis_tvalid(pattgen_if.m_axis_tvalid),
	.m_axis_tready(pattgen_if.m_axis_tready),
	.m_axis_tuser_sof(pattgen_if.m_axis_tuser_sof),
	.m_axis_tlast(pattgen_if.m_axis_tlast),
	.s_axi_aclk(pattgen_if.s_axi_aclk),
	.s_axi_aresetn(pattgen_if.s_axi_aresetn),
	.s_axi_awaddr(pattgen_if.s_axi_awaddr),
	.s_axi_awprot(pattgen_if.s_axi_awprot),
	.s_axi_awvalid(pattgen_if.s_axi_awvalid),
	.s_axi_awready(pattgen_if.s_axi_awready),
	.s_axi_wdata(pattgen_if.s_axi_wdata),
	.s_axi_wstrb(pattgen_if.s_axi_wstrb),
	.s_axi_wvalid(pattgen_if.s_axi_wvalid),
	.s_axi_wready(pattgen_if.s_axi_wready),
	.s_axi_bresp(pattgen_if.s_axi_bresp),
	.s_axi_bvalid(pattgen_if.s_axi_bvalid),
	.s_axi_bready(pattgen_if.s_axi_bready),
	.s_axi_araddr(pattgen_if.s_axi_araddr),
	.s_axi_arprot(pattgen_if.s_axi_arprot),
	.s_axi_arvalid(pattgen_if.s_axi_arvalid),
	.s_axi_arready(pattgen_if.s_axi_arready),
	.s_axi_rdata(pattgen_if.s_axi_rdata),
	.s_axi_rresp(pattgen_if.s_axi_rresp),
	.s_axi_rvalid(pattgen_if.s_axi_rvalid),
	.s_axi_rready(pattgen_if.s_axi_rready)
); 
	
endmodule

Interface:

/////////////////////////////////////////////////////////////
// Pattern Generator Interface
/////////////////////////////////////////////////////////////
interface pattgen_if;	

	// all the pattern generator IOs are connectd to the interface:
	logic video_vsync;
	logic vsync_int;
	bit axis_aclk;
	logic axis_aresetn;
	logic [23:0] s_axis_tdata;
	logic s_axis_tvalid;
	logic s_axis_tready;
	logic s_axis_tuser_sof;
	logic s_axis_tlast;
	logic [23:0] m_axis_tdata;
	logic m_axis_tvalid;
	logic m_axis_tready;
	logic m_axis_tuser_sof;
	logic m_axis_tlast;
	bit s_axi_aclk;
	logic s_axi_aresetn;
	logic [31:0] s_axi_awaddr;
	logic [2:0] s_axi_awprot;
	logic s_axi_awvalid;
	logic s_axi_awready;
	logic [31:0] s_axi_wdata;
	logic [3:0] s_axi_wstrb;
	logic s_axi_wvalid;
	logic s_axi_wready;
	logic [1:0] s_axi_bresp;
	logic s_axi_bvalid;
	logic s_axi_bready;
	logic [31:0] s_axi_araddr;
	logic [2:0] s_axi_arprot;
	logic s_axi_arvalid;
	logic s_axi_arready;
	logic [31:0] s_axi_rdata;
	logic [1:0] s_axi_rresp;
	logic s_axi_rvalid;
	logic s_axi_rready;
	
endinterface

Testcase Class:

// CONTENTS
// ===========================
// 43  : ____
// 44  : Functions

// 143 : TestCases
// ---------------------------

package testcase_pattern_generator_pkg;

// Import common tools (scoreboard, events, ...)
import common_pkg::*;

class class_testcase_pattern_generator #(MONITOR_CLOCKS=0, NUM_CLOCKS=1) extends common_pkg::test_base #(.NUM_OF_TESTS(1));
	
		// Verification class used to monitor testcases. <scoreboard>
    common_pkg::scoreboard  scrb;

    // Used tp monitor interrupts and clocks. <events>
    // System Clock
    common_pkg::events #( .MONITOR_CLOCKS(MONITOR_CLOCKS), .NUM_CLOCKS(NUM_CLOCKS)) ev;
	
	virtual ps_if vps_if;
	//module interfaces
    virtual pattgen_if vpattgen_if;
   
    // INDEX:   .new(clock_if, ps_if)
    function new(
        virtual clock_if #(MONITOR_CLOCKS, NUM_CLOCKS) vclock_if,
        virtual ps_if vps_if,
        virtual pattgen_if vpattgen_if
    );
        super.new("Pattern Generator");
        scrb = new();
        ev   = new(vclock_if, 0);
        this.vps_if = vps_if;
        this.vpattgen_if = vpattgen_if;
    endfunction
	
    // INDEX:   .task_call_testcase(num)
    task task_call_testcase(input int num, output error);
        case(num)
            'd0:    input_stimulus();
        endcase
    endtask
    
	//----------------------------------------------------------------------------------------------------
    // INDEX: ____
    // INDEX: Functions
    //----------------------------------------------------------------------------------------------------
    
    //reset generation
    task reset_gen();
        $display("[%0t]: Reseting TPG", $time);
		vpattgen_if.axis_aresetn = 0;
        vpattgen_if.s_axi_aresetn = 0;
        #340;  //toggle the reset lines (active low) - need to be held for 16 clock cycles  = 340ns               
        vpattgen_if.axis_aresetn = 1;
        vpattgen_if.s_axi_aresetn = 1;
    endtask
    
    //50 MHz clock signal generation
    task clock_gen();
		fork
			vpattgen_if.axis_aclk = 0;
			vpattgen_if.s_axi_aclk = 0;
            forever #10 vpattgen_if.axis_aclk <= ~vpattgen_if.axis_aclk;
            forever #10 vpattgen_if.s_axi_aclk <= ~vpattgen_if.s_axi_aclk;
			
        join   
    endtask
    
    task signal_init();
        //Video signals     
        vpattgen_if.video_vsync = 0;             // vsync from slave video stream
        vpattgen_if.s_axis_tvalid = 0;           // input video valid signal
        vpattgen_if.s_axis_tuser_sof = 0;        // input video start of frame
        vpattgen_if.s_axis_tlast = 0;            // input video end of line
        vpattgen_if.m_axis_tready = 1;           // output ready signal
        
        //AXI signals
        vpattgen_if.s_axi_awprot = "000";        // defines the access permissions for write accesses (3 bit)
        vpattgen_if.s_axi_arprot = "000";        // defines the access permissions for read accesses(3 bit)
        vpattgen_if.s_axi_wstrb = 4'b1111;       // write strobes - not used(4 bit)
        vpattgen_if.s_axi_arvalid = 0;           // read address valid
        vpattgen_if.s_axi_rready = 0;            // read address ready
        vpattgen_if.s_axi_bready = 1;            // response ready - indicates that the master can accept a write response
        vpattgen_if.s_axi_awvalid = 1;           // write address valid
        vpattgen_if.s_axi_wvalid = 1;            // write data valid
    endtask
    
    task write_reg(input int wsize, input int addr);//, output int error);
        wait (vpattgen_if.s_axi_wready == 1'b1); //wait for wready signal
        vpattgen_if.s_axi_awaddr = addr;
        vpattgen_if.s_axi_wdata = wsize;
        wait (vpattgen_if.s_axi_bvalid == 1'b1); //wait for write successful confirmation
        //TO DO: display error message here if o_s_axi_bvali does not go high, indicating failed axi write 
        //#80;
    endtask
    
task input_stimulus();
      begin
		
		$display("Test has started");
		fork
			reset_gen();
            clock_gen(); 	//forever statements causing simulation to hang
            signal_init();
        join 
		
		#2000;
		//$finish;
      end
   endtask
	
endclass
endpackage