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

What is the difference between these 2 codes? Are they just the same? Will both codes execute exactly at the posedge of the clk?

// First code
@(posedge clk) begin
// codes here
end

// Second code
@(posedge clk);
// codes here

Description about both the snippets, you have given, is below :

First Snippet :
When the execution flow comes to the ā€œ@(posedge clk) begin-end statementā€, the simulator wait for the triggering event(positive edge) on the clk and when it triggers, the piece of code covered within begin-end block will execute.

Second Snippet :
When the execution flow comes to the ā€œ@(posedge clk) begin-end statementā€, the simulator wait for the triggering event(positive edge) on the clk. Until the triggering even happen, it blocks the following code and when it triggers, the execution flow goes to the next statement.

In reply to Pratik PK:

Hi,

So does it mean that the 2nd code will not actually happen at the posedge of the clk?

You are not allowed to use a @(posedge CLK) unless you are in a procedural
block.

So I guess your question Something like below:

What is the difference between

always@(posedge CLK) begin
/* Some code */
end

and

always begin
@(posedge CLK);
/* Some code */
end

As far as I know there is no behavioral difference between these.
But your synthesizer might not like the last example.

Also,
always@(posedge CLK) is used to describe a D-Flip Flop, while @(posedge
CLK); is used in testbench.

For example,
c = d;
@(posedge CLK);
a = b;

means a = b; will not be executed until there is a posedge CLK(i.e. at
the posedge CLK time slot, simulator will execute a = b) .

Best Regards,
Chetan Shah
Sr. ASIC Verification Engineer

Product Engineering Services
Software | Embedded | Semiconductor
www.einfochips.com
Frost & Sullivan Company of the Year 2013-14

In reply to cashah85:

Hi Chetan,

Thank you for the response. :) But anyway, my question is actually for verification codes, not for RTL. :)
So thatā€™s why I donā€™t need to worry about synthesizable code.

I Think It should work exactly the same from the test bench point of view.
In the first code snippet, the statements inside the beginā€¦end will get triggered at the posedge.

While in the second case, they get triggered 0 time units after the posedge which means the same thing.

Regards,
Durgesh

In reply to Reuben:

I think you mean " always @(posedge clk) begin ā€¦ end "

I think they are different, First code execution depends on whether blocking or non block stmt used inside ā€˜begin-endā€™.
If ā€˜=ā€™ is used then on the same clk edge all code gets executed inside ā€˜begin-endā€™.

But in the second code is always blocks the rest of the code following clkā€™ event for a posedge.

Thanks
/Sachin
But

In reply to Reuben:

Yes, it happen at the posedge of the clk.

An event control like @(ā€¦) or #(ā€¦) is a prefix to any single procedural statement. It is not considered a statement in itself.

The difference between

@(A) somecode;

and

@(A); somecode;

is that the first line is considered one procedural statement and the second line is considered two procedural statements. The first of the two statements in the second line is the null statement, prefixed by an event control @(A).

You might think there is really no behavioral difference between these two lines, but I havenā€™t shown you the complete context of where these statements are located (neither did you in your original question).

If you had

task t1;
  @(A) somecode;
endtask
task t2;
  @(A); somecode;
endtask

I can claim there is no behavioral difference between t1 and t2. However tools may differ in their ability to set breakpoints on individual statements, and code coverage tools may report these as one or two statements respectively.

On the there hand, if you had the following code

task t1;
  if (X)
  @(A) somecode;
endtask
task t2;
  if (X)
  @(A); somecode;
endtask

Now there is a big difference between the two tasks. In t1, the conditional statement is @(A) somecode;. But in t2, only @A; is the conditional statement-- somecode; is executed unconditionally. Of course, you can always wrap multiple statements in an begin/end block, and use that block where one statement is allowed.

task t1;
  if (X)
  @(A) somecode;
endtask
task t2;
  if (X)
  begin @(A); somecode; end
endtask
task t3;
if (X)
  @(A) begin somecode; end
endtask

Now t1 and t2 are now behaviorally the same. t3 is also the same. the event control is a prefix to a single statement, which happens to be a begin/end block.

1 Like

In reply to dave_59:

Hi Dave,

Thanks for the answer. :)

What if the code is like this:

// In the testbench driver
#1 signal = 1;
#1 signal = 0;

// In the testbench monitor
@(posedge clk) begin
if(signal) $display(ā€œsignal assertedā€);
end

In which timestamp does the ā€œsignal assertedā€ will appear? Is it at the same time with the posedge? Or after 1 clock cycle?
Iā€™m asking this because in RTL a register can only sample the signal after 1 clock cycle, not at exactly the same time with the posedge.

What I want my testbench to do is to report only at the time the RTL registers actually see the signal.

In reply to Reuben:

This is a completely different question, but again you have not show enough code to explain. When is the signal written in relation to the time of the posedge clk?

If you have multiple processes where one process is writing to a signal (the driver), and another process is reading the same signal (the monitor) at the same time, then you have a race condition in that you donā€™t know if you are reading the old value or newly written value of the signal. That is why we use non-blocking assignments (NBA) in Verilog. Search for that.

In reply to dave_59:

Hi Dave,

Yes, that will be a race condition.
What if the non-blocking assignment is inside an if-statement? Will it still not cause a race condition?

For example,

//===== Driver ========
forever begin
@(posedge clk);
if(wr_en) d <= 1;
end

//===== Monitor =======
forever begin
@(posedge clk);
if(d) s = 1;
end

If wr_en asserts at 10us, will s also assert at 10us?

Actually I can try to write this code and simulate it to see the effect but Iā€™m thinking that the result may not be the same for larger codes. This example code is only small so that may not result to a race conditionā€¦ Iā€™m wondering what will happen for larger codes.

can we do like this :

always @(posedge clk && (a == 1 || b ==1 ))
begin
t_out = data_in;
t_k = data_k;
end

In reply to mansi m joshi:

Again, a completely new question. In the future please start a new threadā€”it helps people when searching for answers.

What you wrote means "wait for the expression
(clk && (a == 1 || b ==1 ))
to go from 0 to 1.

What you probably wanted is

always @(posedge clk iff (a == 1 || b ==1 ))

which means "wait for clk to from 0 to 1 along with the condtion that the expression
(a == 1 || b ==1 )
is also true.

Hi Dave,
I have a different Question,
whatā€™s the difference between $monitor and $strobe ?
Since both are on postponed region, right ?
I read somewhere single $monitor gives value whenever variable changes throughout simulation, if itā€™s correct can you show code example or snippet for that ?

In reply to abajaj:

It would help if you opened up a new question thread. It helps build the knowledge base when people search for similar issues.

Did you read the definition in the 1800-2017 LRM; there are lots of examples in it. People rarely use $monitor as it only helps with dry simple debugging.