+ Post New Thread
Results 1 to 7 of 7
  1. #1
    Junior Member level 1
    Points: 107, Level: 1

    Join Date
    Jul 2019
    Posts
    17
    Helped
    0 / 0
    Points
    107
    Level
    1

    How to give input to a task

    I've created a task in my testbench which takes 3 inputs, but it seems that the value of one of them is wrong.

    Below there is my code. I already know that s has the same value of dut.r.f, but when I run the simulation it's not like this.

    MAIN:
    Code:
    module main(
      input  logic        clk,
      input logic         vaux2_p,
      input logic         vaux2_n,
      output  logic        gpio1,
    );
    
      logic [8:0] f;
    
    inst r(
        .clk                    (clk),
        .f                      (f),
      );
    
    endmodule
    R:

    Code:
    module inst(
      input  logic         clk,
    output logic [ 8:0] f
    );
    
    always_ff @(posedge clk) begin
        f <= 8'h0_F0;
    end
    
    endmodule
    TESTBENCH:

    Code:
    module m();
      logic        clk;
      logic        vaux2_p;
      logic        vaux2_n;
      logic        gpio1;
    
      main dut(
        .clk(clk),
        .vaux12_p (vaux2_p),
        .vaux12_n (vaux2_n),
        .gpio1 (gpio1)
        );
    
      task test;
        input [ 7:0] a;
        input [8:0] v;
        input [8:0] s;
        integer f1;
           begin
              f1 = $fopen("file.txt","w");
                 if (!f1) begin
                   $display("File \"file.txt\" cannot be opened!");
                 end else begin
                 //this part of code is just for test what I'm reading
                                          $fdisplay(f1," f: %0h %0b %0d", dut.r.f,dut.r.f,dut.r.f);
                                                                                $fdisplay(f1,"s: %0h %0b %0d", s,s,s);
                                                                                $fdisplay(f1,"v: %0h %0b %0d", v,v,v);
              $fclose(f1);            
         end
      endtask
    
      initial begin
    
        test(8'h19,24'hFF00, dut.r.f);
    $finish;
      end
    endmodule
    If I run this code and then I open the file.txt what I can read is this:
    Code:
    f: f0 11110000 240
    s: xxxxxx xxxxxxxxxxxxxxxxxxxxxxxx x
    v: f0 11110000 240
    I was thinking that this can be due to the fact that at the beginning of the simulation dut.r.f=xxxxxx and only after few ns it turns in f0, but then I realized that this cannot be the problem for two reasons: the first one is that if the value of the signals is taken at the beginning of the simulation, also f should be equal to xxxxxx, the second one is that even if I introduce a delay before I display the signal values, the problem still exists. Do you know if there is any issue in passing a variable from main as input for the task? If yes, it's the same also with functions? Can anyone kindly help me, please? Thanks!
    verilog system-verilog

    •   AltAdvertisement

        
       

  2. #2
    Junior Member level 1
    Points: 107, Level: 1

    Join Date
    Jul 2019
    Posts
    17
    Helped
    0 / 0
    Points
    107
    Level
    1

    Re: How to give input to a task

    Quote Originally Posted by ads-ee View Post
    try m.dut.r.f
    I don't think this is the problem: I tried to remove dut.r.f from thetask input and to print its value inside the task (recalling it with the same syntax: dut.r.f) and it seems to work correctly.
    I think it is more a problem of syntax for which it is not possible to pass a hierarchical variable as input for a task, but I am not 100% sure.
    However I managed to do what I wanted, but I had to change strategy.
    Thank you very much for your reply.



    •   AltAdvertisement

        
       

  3. #3
    Super Moderator
    Points: 31,314, Level: 43
    ads-ee's Avatar
    Join Date
    Sep 2013
    Location
    USA
    Posts
    7,231
    Helped
    1710 / 1710
    Points
    31,314
    Level
    43

    Re: How to give input to a task

    try m.dut.r.f

    - - - Updated - - -

    Your posted code has errors...your code also doesn't have a clock in module m so f stays x. Changing the always_ff code to use assign f = 9'h 0f0; shows that f can be passed to the task.

    Note: passing the variable f to the task using either dut.r.f or m.dut.r.f both work (from current level or full path, respectively). I've used hierarchical paths many times in my testbenches.

    The root cause of the problem is the lack of a testbench clock to clock the value F0 into the variable f.

    - - - Updated - - -

    Quote Originally Posted by Roronoa137 View Post
    However I managed to do what I wanted, but I had to change strategy.
    Thank you very much for your reply.
    If you find a solution to a problem you should really post that solution so the thread can be helpful to someone else that may run into the same issue.



    •   AltAdvertisement

        
       

  4. #4
    Junior Member level 1
    Points: 107, Level: 1

    Join Date
    Jul 2019
    Posts
    17
    Helped
    0 / 0
    Points
    107
    Level
    1

    Re: How to give input to a task

    Thanks for your help. I'm sorry but probably I delated the clock from the module m, actually I have it in my original code, so the problem should be something else, but at the moment I don't have any idea, for sure if I will find the error I will update this post.

    Then, can you kidly explain me what you mean with "changing the always_ff"?

    I know I should post the solution for the problem I proposed, but since I have changed strategy, I haven't use anymore the variable dut.r.f as input to the task, so I don't think this is the right post to write it.



  5. #5
    Super Moderator
    Points: 31,314, Level: 43
    ads-ee's Avatar
    Join Date
    Sep 2013
    Location
    USA
    Posts
    7,231
    Helped
    1710 / 1710
    Points
    31,314
    Level
    43

    Re: How to give input to a task

    I just substituted the always_ff block with an assign so f would get assigned something. Given the clocked assignment is with a constant the assign is pretty much equivalent.

    The passing of the dut.r.f to the task works as it should, I don't know why you can't do it in your version of the testbench. Given you didn't post the exact code that produces the problem, I can't help you fix something I don't see in the posted code.

    Right now besides the clock and the syntax errors in the posted code there isn't anything wrong with the value passed to the task.

    Here is the file I created and modified. Minor stuff that won't change the variable passing to the task.
    Code Verilog - [expand]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    
    module main(
      input  logic        clk,
      input logic         vaux2_p,
      input logic         vaux2_n,
      output  logic        gpio1
    );
     
      logic [8:0] f;
     
    inst r(
        .clk                    (clk),
        .f                      (f)
      );
     
    endmodule
     
     
    module inst(
      input  logic         clk,
    output logic [ 8:0] f
    );
     
    assign f = 9'h 0f0;
    //always_ff @(posedge clk) begin
    //    f <= 8'h F0;
    //end
     
    endmodule
     
     
     
    module m();
      logic        clk;
      logic        vaux2_p;
      logic        vaux2_n;
      logic        gpio1;
     
      main dut(
        .clk(clk),
        .vaux2_p (vaux2_p),
        .vaux2_n (vaux2_n),
        .gpio1 (gpio1)
        );
     
      task test;
        input [ 7:0] a;
        input [8:0] v;
        input [8:0] s;
        integer f1;
     
        f1 = $fopen("file.txt","w");
        if (!f1) begin
            $display("File "file.txt" cannot be opened!");
        end else begin
          //this part of code is just for test what I'm reading
          $display("f: %0h %0b %0d", dut.r.f,dut.r.f,dut.r.f);
          $display("s: %0h %0b %0d", s,s,s);
          $display("v: %0h %0b %0d", v,v,v);
    //      $fclose(f1);            
        end
      endtask
     
      initial begin
        #1;
        test(8'h19,24'hFF00, dut.r.f);
        test(8'h19,24'hFF00, m.dut.r.f);
        $stop;
    //    $finish;
      end
     
    endmodule

    and this is the simulation output:
    Code:
    # f: f0 11110000 240
    # s: f0 11110000 240
    # v: 100 100000000 256
    # f: f0 11110000 240
    # s: f0 11110000 240
    # v: 100 100000000 256
    # ** Note: $stop    : m.sv(68)
    #    Time: 1 ns  Iteration: 0  Instance: /m
    # Break in Module m at m.sv line 68



    •   AltAdvertisement

        
       

  6. #6
    Super Moderator
    Points: 31,314, Level: 43
    ads-ee's Avatar
    Join Date
    Sep 2013
    Location
    USA
    Posts
    7,231
    Helped
    1710 / 1710
    Points
    31,314
    Level
    43

    Re: How to give input to a task

    Started playing around more with this and noticed if the clock is added to the testbench then the output produces x's for both f and s, if the #1 I added before the task call is removed (which I added prior to noticing the missing clock and neglected to remove).

    Regardless if you even add a @(posedge clk); before the task call you still end up with x's for f and s. As far as I can determine this is due to the event queue processing and results in a non-deterministic ordering between the always_ff block that updates f and the task call. If a blocking assignment is used instead of the standard non-blocking assignment in the always_ff block then the assignment to f occurs before the task call (not a fix I would recommend using, as it would cause event queue problems elsewhere).

    I normally have some sort of scheduling events in all my testbench task so I seldom run into these types of race condition issues. The easiest way around such issues is to add a #l1 delay before calling a task that is passing a hierarchical referenced variable to move the scheduler past the timestep that is assigning the variable. Another option is to synchronize to the opposite edge of the clock before calling the task. A third option is to wait for an event on dut.r.f with @(dut.r.f); prior to the task call then the task call occurs after the update of f.

    Of the three I like the @(dut.r.f); as it seems more elegant than the other two methods, but I don't know if this is truly the preferred method. I also like this method as it will still work if you use code which contains a bunch of #1 delays to shift the synchronous outputs off the clock edge.



  7. #7
    Junior Member level 1
    Points: 107, Level: 1

    Join Date
    Jul 2019
    Posts
    17
    Helped
    0 / 0
    Points
    107
    Level
    1

    Re: How to give input to a task

    Thanks, the solution you provided are very useful, I will try to implement them!



--[[ ]]--