// Code your testbench here
// or browse Examples
module tb;
task my_first_task (input logic [31:0] addr, ref logic [31:0] data);
data = 8'h8;
for (int i=0; i <100; i++) begin
$display ("Entering the loop");
end
for (int i=0; i <100; i++) begin
$display ("Entering the second loop");
end
endtask
logic [31:0] addr, data;
initial begin
data = 'h10;
addr = 'h01;
fork
my_first_task (addr,data);
begin
@data;
$display ("Read from bus %h \n",data);
end join
end
endmodule
I dont see the @data getting triggered when the data is declared as ref.I understand the control will come back when the data is declared as output. Can any one tell me why the data change is not reflected?
In reply to rag123:
You have 2 forked tasks in parallel. The change in data is not detected in the begin-end task.
Try:
fork
my_first_task (addr,data);
begin
#1;
@ $changed(data);
$display ("Read from bus %h \n",data);
end join
Ben SystemVerilog.us
In reply to rag123:
This is a race condition. There is no guarantee if the assignment trigger, or the event control @data executes first. A non-blocking assignment would fix this particular example.
In reply to ben@SystemVerilog.us:
Hi Ben, I really frown upon putting in #1’s to fix race conditions.
In reply to dave_59:
Ben,
I dont see the code getting compiled in. which tool are u using?
Dave,
If i change it to non blocking, it is not compiling.
Error-[DTNBA] Dynamic type in non-blocking assignment
testbench.sv, 7
tb, "data"
Dynamic type (Automatic variable in this case) cannot be used on the
left-hand side of non blocking assignments.
In reply to rag123:
The following worked. Some notes:
- The task or function ‘my_first_task’ with ref arguments must be automatic.
- data <= 8’h1; // non-blocking assignment may not be an automatic variable
- my_first_task needs the #1; Love it or hate it, it’s the nature of the beast.
module tb;
// The task or function 'my_first_task' with ref arguments must be automatic.
task automatic my_first_task (input logic [31:0] addr, ref logic [31:0] data);
#1; // <----------- NEEDED THiS
data = 8'h1; // non-blocking assignment may not be an automatic variable
for (int i=0; i <1; i++) begin
$display ("Entering the loop");
end
for (int i=0; i <1; i++) begin
$display ("Entering the second loop");
end
endtask
logic [31:0] addr, data;
initial begin
data = 'h10;
addr = 'h01;
fork
my_first_task (addr,data);
begin
@ (data); // <-------- $changed requires a cloking event for the past of data
$display ("Read from bus %h \n",data);
end
join
end
endmodule
Entering the loop
# Entering the second loop
# Read from bus 00000001
#
Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us
For training, consulting, services: contact Home - My cvcblr
- SVA Handbook 4th Edition, 2016 ISBN 978-1518681448
- A Pragmatic Approach to VMM Adoption 2006 ISBN 0-9705394-9-5
- Using PSL/SUGAR for Formal and Dynamic Verification 2nd Edition, 2004, ISBN 0-9705394-6-0
- Real Chip Design and Verification Using Verilog and VHDL, 2002 isbn 978-1539769712
- Component Design by Example ", 2001 ISBN 0-9705394-0-1
- VHDL Coding Styles and Methodologies, 2nd Edition, 1999 ISBN 0-7923-8474-1
- VHDL Answers to Frequently Asked Questions, 2nd Edition ISBN 0-7923-8115
- SVA Alternative for Complex Assertions
Verification Horizons - March 2018 Issue | Verification Academy - SVA: Package for dynamic and range delays and repeats | Verification Academy
- SVA in a UVM Class-based Environment
SVA in a UVM Class-based Environment | Verification Horizons | Verification Academy
In reply to ben@SystemVerilog.us:
Typically, one uses clocking events. The following works, regardless of the order of the blocks in the fork-join
module tb;
bit clk;
initial forever #10 clk=!clk;
task automatic my_first_task (input logic [31:0] addr, ref logic [31:0] data);
@(posedge clk);
data = 8'h2; // non-blocking assignment may not be an automatic variable
for (int i=0; i <1; i++) begin
$display ("@ %t Entering the loop ", $realtime);
end
for (int i=0; i <1; i++) begin
$display ("Entering the second loop");
end
endtask
logic [31:0] addr, data;
initial begin
data = 'h10;
addr = 'h01;
fork
begin
// @(posedge clk);
@ (data);
$display ("@ %t Read from bus %h \n", $realtime, data);
end
my_first_task (addr,data);
join
end
endmodule
# @ 10 Entering the loop
# Entering the second loop
# @ 10 Read from bus 00000002
#
****NOTE
The following has a race condition
module tb;
bit clk;
initial forever #10 clk=!clk;
task automatic my_first_task (input logic [31:0] addr, ref logic [31:0] data);
@(posedge clk);
data = 8'h2; // non-blocking assignment may not be an automatic variable
for (int i=0; i <1; i++) begin
$display ("@ %t Entering the loop ", $realtime);
end
for (int i=0; i <1; i++) begin
$display ("Entering the second loop");
end
endtask
logic [31:0] addr, data;
initial begin
data = 'h10;
addr = 'h01;
fork
begin
@(posedge clk);
$display ("@ %t Before the @data %h \n", $realtime, data);
@ (data); // <<< Gets bloked here, waiting for a new change
$display ("@ %t Read from bus %h \n", $realtime, data);
end
my_first_task (addr,data);
join
$display ("@ %t After the joins %h \n", $realtime, data);
end
endmodule
@ 10 Entering the loop
# Entering the second loop
# @ 10 Before the @data 00000002
WIth the #1 as in
@(posedge clk); #1;
data = 8'h2;
It WORKS OK
@ 10 Before the @data 00000010
#
# @ 11 Entering the loop
# Entering the second loop
# @ 11 Read from bus 00000002
#
# @ 11 After the joins 00000002
#
BTW, this forum does not discuss tools. One should ever identify the tool you are using. You can just say “my tool deos this”, but in the this, delete anything that can identify the tool. Your question is Not a tool issue, but a SystemVerilog issue.
Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us
For training, consulting, services: contact Home - My cvcblr
- SVA Handbook 4th Edition, 2016 ISBN 978-1518681448
- A Pragmatic Approach to VMM Adoption 2006 ISBN 0-9705394-9-5
- Using PSL/SUGAR for Formal and Dynamic Verification 2nd Edition, 2004, ISBN 0-9705394-6-0
- Real Chip Design and Verification Using Verilog and VHDL, 2002 isbn 978-1539769712
- Component Design by Example ", 2001 ISBN 0-9705394-0-1
- VHDL Coding Styles and Methodologies, 2nd Edition, 1999 ISBN 0-7923-8474-1
- VHDL Answers to Frequently Asked Questions, 2nd Edition ISBN 0-7923-8115
- SVA Alternative for Complex Assertions
Verification Horizons - March 2018 Issue | Verification Academy - SVA: Package for dynamic and range delays and repeats | Verification Academy
- SVA in a UVM Class-based Environment
SVA in a UVM Class-based Environment | Verification Horizons | Verification Academy
In reply to ben@SystemVerilog.us:
Thanks Ben. I modified the post.
In reply to rag123:
See https://verificationacademy.com/forums/systemverilog/driving-wire-task-interface.
On using nonblocking assignment in tasks
Driving a wire thru a task is illegal.
Quote:
1800-2012 14.3 Clocking block declaration
- A clockvar whose clocking_direction is inout shall behave as if it were two clockvars, one input and one output, having the same name and the same clocking_signal.
- Reading the value of such an inout clockvar shall be equivalent to reading the corresponding input clockvar.
- Writing to such an inout clockvar shall be equivalent to writing to the corresponding output clockvar.
interface dut_mem_if (input logic clk);
wire[31:0] data; // <------------------- the bi-direct
clocking driver_cb @ (posedge clk);
inout data; // <------------------- the bi-direct
endclocking : driver_cb
endinterface : dut_mem_if
class dut_mem_driver;
virtual interface dut_mem_if.drvr_if_mp vif;
// ...
virtual task write_task(logic [31:0] data, address);
this.vif.driver_cb.data <= data;
In reply to ben@SystemVerilog.us:
Making the task NOT automatic and usi G nonblocking assignments works.
.
// Code your testbench here
// or browse Examples
// Code your testbench here
// or browse Examples
module tb;
bit clk;
initial forever #10 clk=!clk;
task my_first_task ();
// @(posedge clk);
data <= 8'h2; // non-blocking assignment may not be an automatic variable
for (int i=0; i <1; i++) begin
$display ("@ %t Entering the loop ", $realtime);
end
for (int i=0; i <1; i++) begin
$display ("Entering the second loop");
end
endtask
logic [31:0] addr, data;
initial begin
data = 'h10;
addr = 'h01;
fork
begin
// @(posedge clk);
@ (data);
$display ("@ %t Read from bus %h \n", $realtime, data);
end
my_first_task ();
join
end
endmodule
KERNEL: @ 0 Entering the loop
KERNEL: Entering the second loop
KERNEL: @ 0 Read from bus 00000002
KERNEL:
In reply to ben@SystemVerilog.us:
There are a number of issues at play here.
A task must have automatic lifetime in order to pass an argument by reference. That argument does not know the lifetime of the actual variable passed to it, so it places the most restrictive rules for assignments and does not allow non-blocking assignments. That was my mistake.
The original question exposes a race condition—there are a many ways of dealing with it. Without knowing the requirements behind what the code was trying to accomplish, it’s difficult to give a best solution.