Search code examples
verilogsystem-verilogfpga

Task does not pass the output right


I have been trying to design a task for my testbench to make my life easier. The task seems to be doing fine when I check the internal signals using $display. However, when I hook the task up in my initial block, the simulation output shown on the waveform is NOT the same as the display result. Thank you in advance

===========Code===========

`timescale 1ns/1ps

/*----------Macros----------*/
`define FullCycle 20
`define HalfCycle 10
`define CLK_Cycle(CycleNum) (`FullCycle*CycleNum)


module syncronization_tb();

    /*----------DUT I/O----------*/
    logic reset_n, clk4m, ppm_data, output_valid_flag;
    logic [7: 0] data_out_DUT;
    logic flag;
    /*----------TX I/O----------*/
    logic bit_stream, clk50m;
    logic [1: 0] ppm_out;
    
    /*----------RX I/O----------*/
    logic clk50mREC;
    logic  data_out;

    assign ppm_data = data_out;
     
    Syncronization DUT
    (
        reset_n, 
        clk4m_out, 
        ppm_data, 
        data_out_DUT, 
        output_valid_flag
    );

    PPM_top TX
    (
        reset_n, 
        clk50m, 
        bit_stream, 
        ppm_out
    );

    CLK_Recovery RX
    (   
        clk50mREC, 
        reset_n, 
        ppm_out[1], 
        data_out, 
        clk4m_out
    );

    logic [7:0] data;
    logic Taskflag; 
    integer index; 
    initial forever #`HalfCycle clk50m = ~ clk50m;
    initial #17 forever  #`HalfCycle    clk50mREC = ~clk50mREC; 

    initial begin
        {reset_n, clk50m, bit_stream, clk50mREC} = 0; 
        #`CLK_Cycle(5);
        
        {reset_n} = 1; 


        data = 8'haa;
        generateBITstream(.data(data), .bit_stream_out(bit_stream),.index(index));

       // data = 8'he3;
       // generateBITstream(data, bit_stream);

        //data = 8'h5b;
        //generateBITstream(data, bit_stream);
        
         #`CLK_Cycle(800);
        $stop;
    end




task automatic generateBITstream;

    parameter integer width = 8;
    input [width - 1: 0] data;
    output logic bit_stream_out;
    output integer index;
    begin
        for(index = 0; index < width;  index = index + 1 ) begin 
            @(posedge TX.clk1m) bit_stream_out = data[index];
            $display("%d and time is %t with %b",index, $time, bit_stream_out);
            #`CLK_Cycle(10);
        end
    end
endtask 


endmodule

===========Console Display [Correct Result]===========

run -all
#           0 and time is              1870000ps with 0
#           1 and time is              2870000ps with 1
#           2 and time is              3870000ps with 0
#           3 and time is              4870000ps with 1
#           4 and time is              5870000ps with 0
#           5 and time is              6870000ps with 1
#           6 and time is              7870000ps with 0
#           7 and time is              8870000ps with 1
# Break in Module syncronization_tb at G:/Work/PPM/src/Syncronization RTL Simulation/src/syncronization_tb.sv line 74

===========Waveform [Wrong Result]===========

[Waveform]

===========A minimal reproducible example===========

`timescale 1ns/1ps

/*----------Macros----------*/
`define FullCycle 20
`define HalfCycle 10
`define CLK_Cycle(CycleNum) (`FullCycle*CycleNum)


module syncronization_tb();

    logic [7:0] data;
    logic bit_stream, clk50m; 
    integer index; 

    initial forever #`HalfCycle clk50m =~ clk50m;
    initial begin
        clk50m = 0; #`CLK_Cycle(10);
        
        data = 8'haa;
        generateBITstream(.data(data), .bit_stream_out(bit_stream),.index(index));
         #`CLK_Cycle(800);
        $stop;
    end


task automatic generateBITstream;

    parameter integer width = 8;
    input [width - 1: 0] data;
    output logic bit_stream_out;
    output integer index;
    begin
        for(index = 0; index < width;  index = index + 1 ) begin 
            @(posedge clk50m) bit_stream_out = data[index];
            $display("%d and time is %t with %b",index, $time, bit_stream_out);
            #`CLK_Cycle(10);
        end
    end
endtask 

endmodule

===========Console Display [Correct Result]===========

#           0 and time is               210000 with 0
#           1 and time is               410000 with 1
#           2 and time is               610000 with 0
#           3 and time is               810000 with 1
#           4 and time is              1010000 with 0
#           5 and time is              1210000 with 1
#           6 and time is              1410000 with 0
#           7 and time is              1610000 with 1
# Break in Module syncronization_tb at G:/Work/PPM/src/Syncronization RTL Simulation/src/syncronization_tb.sv line 22

Solution

  • The problem is that the signal connected to the task output port (bit_stream) only gets updated in the testbench once the task completes (after the for loop). It does not get updated every time the $display is called in the for loop.

    One way to fix this is to get rid of the task output port, and directly update the bit_stream signal inside the task:

    task automatic generateBITstream;
        parameter integer width = 8;
        input [width - 1: 0] data;
        output integer index;
        begin
            for(index = 0; index < width;  index = index + 1 ) begin 
                @(posedge TX.clk1m) bit_stream = data[index];
                $display("%d and time is %t with %b",index, $time, bit_stream);
                #`CLK_Cycle(10);
            end
        end
    endtask 
    

    Then call the task as:

        generateBITstream(.data(data), .index(index));