Will infinite while loop inside fork-join_any end after exiting? - system-verilog

Will the first while loop continue after I have exited fork/join_any? I see the message "iam here" after the message "after join any".
I expect that the first while loop will stop when I exit fork/join_any.
Is that not the case?
fork
begin
while(1)
begin
#(posedge trigger_clock);
do something
$info("i am here");
end
end
begin
while(1)
begin
#(posedge trigger_clock);
if(condition is true)
begin
break;
end
end
end
join_any
$info("after join any");

As you have observed, the top while loop continues to execute even when you exit the fork when the bottom while loop completes. This is expected.
If you want the top while loop to stop executing when you exit the fork, you can use the disable fork statement:
fork
// ...
join_any
disable fork;
$info("after join any");
Refer to IEEE Std 1800-2017, section 9.6 Process control.

Related

Wait for only some threads to complete after fork join_none in SystemVerilog

In SystemVerilog I need to wait for some threads that have been executed inside a fork join_none structure to finish. But there is another process inside another fork join_none structure that will never end.
My code looks like this:
fork
process_that_will_never_end();
join_none
fork
for(int i = 0; i < 40; i++) begin
fork
process_that_must_end(i);
join_none
end
join
The fork join containing the for loop has no effect (which is what I expected). I thought about using a "wait fork" at the end but this will also wait for process_that_will_never_end(), so it won't work.
Is there any way to wait only for all the process_that_must_end() threads to finish?
You almost had it. You just need to move the scope of the begin/end to outside the for loop. Then the wait fork only applies to the children of the second fork.
fork : first_fork
process_that_will_never_end();
join_none
fork begin : second_fork
for(int i = 0; i < 40; i++)
fork : third_forks
automatic int k = i;
process_that_must_end(k);
join_none
wait fork;
end join

How to prevent new threads of SVA

Lets assume, I have a button in my design. I want to increment counter between next two clock when button has been pressed three times and I want to check this behaviour with SVA.
I have wrote this one:
`timescale 1ns / 1ps
module tb();
parameter NUMBER_OF_PRESSES = 10;
parameter CLK_SEMI_PERIOD = 5;
bit clk;
always #CLK_SEMI_PERIOD clk = ~clk;
bit button_n;
bit reset_n;
logic [7:0] counter;
property p;
logic[7:0] val;
disable iff(!reset_n) #(posedge clk) (($fell(button_n)[=3]),val=counter) |=> ##[0:2] (counter== val+1);
endproperty
assert property(p);
initial begin
automatic bit key_d;
automatic byte key_lat;
automatic byte key_press_count;
reset_n = 1;
button_n = 1;
counter = 0;
fork
begin
repeat(NUMBER_OF_PRESSES) begin
repeat(5)begin
#(negedge clk);
end
button_n = 0;
key_lat = $urandom_range(1,4);
repeat(key_lat) begin
#(negedge clk);
end
button_n = 1;
end
end
begin
forever begin
#(posedge clk);
if(!button_n && key_d) begin
key_press_count++;
end
if(key_press_count == 3) begin
counter++;
key_press_count = 0;
end
key_d = button_n;
end
end
join_any
end
endmodule
This works good at first three press, but then it will always throw assertion error, because it has been started new thread of assertion at each button press. So, I need to prevent testbench from doing this. When repetitition has been started I don't need to start new threads.
How can I do this?
I am not confident I fully understand your question. Let me first state my understanding and where I think your problem is. Apologise if I am mistaken.
You intend to detect negedges on button_n ("presses"), and on the third one, you increment "counter".
The problem here is that your stated objective (which actually matches the SVA) and your design do different things.
Your SVA will check that the counter has the expected value 1-3 cycles after every third negedge. This holds for press 0, 1 and 2. But it must also hold for press 1, 2 and 3. And press 2, 3 and 4 etc. I suspect the assertion passes on press 2 and then fails on press 3. I.e. you check that you increment your counter on every press after the third.
Your design, on the other hand does something different. It counts 3 negedges, increments counter, and it then starts counting from scratch.
I would advise against the use of local variables in assertions unless you are certain that it is what you need - I don't think this is the case here. You can have your SVA trigger on key_press_count == 3 (assuming you ofc define key_press_count appropriately and not as an automatic var).
If you insist on using your local SVA variable you can slightly modify your trigger condition to include counter. For example something along the lines of (though may be slightly wrong, have not tested):
(counter == 0 || $changed(counter)) ##1 ($fell(button_n)[=3], val = counter)
IMO that's a bad idea and having supporting RTL is the better way to go here to document your intention as well as check exactly the behaviour you are after.
Hope this helps

Bus in sensitivity list in SystemVerilog

Is it possible to evaluate statements in an always block when any bit in a bus is toggled(posedge)? e.g. If I have:
input [1:0] a;
always#([what to do here?]) begin
[statements]
end
I have tried
always#(posedge a)
and also
always#(posedge a[1:0])
but simulation shows only on posedge of a[0] are the statements evaluated.
I am not able to use "," or "or" because the width is determined by a parameter.
Thank you in advance!
You need to generate a process for each bit
event ev;
for (genvar ii =0;ii<$bits(a);ii++) begin
always #(posedge a[ii] ) ->>ev;
end
always #ev ...

What is the difference between #(posedge clk) begin end.... and #(posedge clk);?

What is the difference between:
1
forever begin
**#posedge(clk) begin**
if(vif.sof == 1) begin
//some code here
end
end
end
2
forever begin
**#posedge(clk);**
if(vif.sof == 1) begin
//some code here
end
end
Does the begin..end that goes with #(posedge clk) make a difference ?
event_controls like # and # in procedural code are not statement by themselves; they are prefixes to the statements that follow. And a statement can be a simple statement, like an assignment, or a block like begin/end or fork/join. And a block is allowed wherever a single statement is allowed.
When you write #(posedge clk); it is really #(posedge clk) null_statement;
I should have given you enough information to answer your question, but here is another variation:
forever
#posedge(clk)
if(vif.sof == 1) begin
//some code here
end
Now there is a big difference if a semicolon follows #(posedge clk) or not.

Sybase. Break or continue inside of a for loop

I'm writing Sybase procedure and ran into a problem: how to break inside of a for loop. It just gives me syntax error. Is it possible to skip the current row and go to the next one in for loop?
for TmpUserEvents as TmpUserCursorEvents dynamic scroll cursor for
select
*
from
test
do
if flag = 1 then
continue; --break;
end if;
end for;
To answer my own question: it is possible to continue for loop while executing.
for TmpUserEvents as TmpUserCursorEvents dynamic scroll cursor for
select
*
from
test
do
lbl:
loop
if condition = 1 then
leave lbl;
end if;
end loop lbl;
end for;