Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

How to give input to a task

Status
Not open for further replies.

Roronoa137

Junior Member level 1
Joined
Jul 26, 2019
Messages
19
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
165
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
 

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.
 

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 - - -

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.
 

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.
 

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
 

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.
 

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

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top