UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Explorer
Explorer
12,728 Views
Registered: ‎08-23-2011

Reg: interpreting @ posedge clk in verilog testbench from HW point of view ...

Jump to solution

hi, ive read and observed on actual hardware that the data/control lines settle before the clock edge.

 

now when we generally simulate designs, in the functional-sim testbench, we always write something like - 

always @ (posedge clk or negedge rst)

if (!rst) begin

  addr <= 0;   wr <= 0; data <= 0;

  end

else begin

  addr <= addr + 1;

  data <= <whatever data we want to write into our DUT>

 wr <= 1

end 

end

 

when we run a simulation for the DUT using the above TB, the addr, data, wr lines assert at the posedge of the clk (which is expected). however functionally, would this not indicate a race condition because the data/addr lines change on the clk edge?

 

i guess what im trying to ask is - what is the physical interpretation of the above TB? does the above still mean that the clock edge comes AFTER the data/addr/wr have been put on the bus (even though it is not evident in the functional sim)?

0 Kudos
1 Solution

Accepted Solutions
Historian
Historian
22,922 Views
Registered: ‎01-23-2009

Re: Reg: interpreting @ posedge clk in verilog testbench from HW point of view ...

Jump to solution

First, what you did in your new code is not good - as you coded it, addr will update 2ns after the clock, data will update 2ns after that, and wr 2ns after that - you coded procedural blocking delays - they "block" the execution of the procedure for the duration of the delay... Effectively they become cumulative

 

If, however, you do

 

always @ (posedge clk or negedge rst)

if (!rst) begin

  addr <= 0;   wr <= 0; data <= 0;

  end

else begin

  addr <= #2 addr + 1;

  data <= #2 <whatever data we want to write into our DUT>

  wr <= #2 1;

end 

end

 

These are delayed non-blocking assignments, so all the signals update 2ns after the rising edge of the clock.

 

As for your question #2, it is answered by my description of non-blocking assignments - but, yes, as coded in your original code, that is true.

 

As for #3, that is a style thing. The NBAs with or without delay will function the same in RTL simulation (as long as you don't do something nasty with your clock as it goes into/out of your testbench). All internal signals will use non-delayed non-blocking assignements, so internally, all waveforms will look like the one you showed - all registers will do their calculations on the values just "before" the rising edge of clock, and all new states will happen just "after" the rising edge of clock (due to the non-blocking assignments).

 

If you do delays on your testbench driven signals, then they will change 2ns after the edge, which does look more like what we expect to see as a "clock to q" delay - but that doesn't change the functionality of the simulation.

 

By the way, I have seen people (and I was one of those people in the WAY olden days) that used delayed non-blocking assignments for all their registers (in the DUT and testbench) - simply to make the waveforms look pretty (to see the "clock to q" delays). While this is harmless to the synthesis tool, it does have the effect of slowing down RTL simulations (by a fair bit - like 30%) - so isn't really worth it.

 

Avrum

5 Replies
Moderator
Moderator
12,722 Views
Registered: ‎07-01-2015

Re: Reg: interpreting @ posedge clk in verilog testbench from HW point of view ...

Jump to solution

Hi @zubin_kumar31,

 

Yes you are right, it won't be evident in functional simulation.

Please try post-route timing simulation to get more insight on this.

 

Thanks,
Arpan

Thanks,
Arpan
----------------------------------------------------------------------------------------------
Kindly note- Please mark the Answer as "Accept as solution" if information provided is helpful.

Give Kudos to a post which you think is helpful and reply oriented.
----------------------------------------------------------------------------------------------
0 Kudos
Historian
Historian
12,712 Views
Registered: ‎01-23-2009

Re: Reg: interpreting @ posedge clk in verilog testbench from HW point of view ...

Jump to solution

When we are working with RTL, we are really working with "cycle accurate" descriptions of our design.

 

The construction of your "testbench" is using a style that is completely similar to what we do in the synthesizable portion of the design (the "Device Under Test" or DUT). This is actually not the "standard" way of doing things - most people intentionally code their testbenches in "non-synthesizable" constructs - for example (and I am not proposing this as the "right" way to do testbenches, just illustrating that we have more freedom)

 

initial

begin

  @(posedge clk); #2;

  for (addr = 0; addr < MAX_ADDR; addr = addr + 1)

  begin

     data = <whatever we want>

     @(posedge clk); #2;

  end

end

 

Done this way, we are explicitly controlling when signals from the testbench change within a clock cycle.

 

So, going back to your example, where your testbench is written like synthesizable code - the problem is the same as any synthesizable code blocks - how are we sure that all updates happen after the rising edge of clock, based on the values that were in effect before the rising edge of clock?

 

The answer is due to the non-blocking assignments used in the always @(posedge clk). Verilog has a "stratified event queue" - it tracks a number of different events in different queues. Specifically, non-blocking assignment (the <= operation) goes into its own queue (the non-blocking assignment queue) - separate from most other events, which go in the "active" (or inactive for future events) queue. By design, all active events are processed before any non-blocking assignment (NBA) events. This mechanism is what prevents races between the updates of variables in processes. Take for example

 

always @(posedge clk)

  b <= a;

always @(posedge clk)

  c <= b;

 

Without the knowledge that NBA events are processed last, how can we assure that this simulates as two back to back flip-flops (one delaying a to become b and one delaying b to become c)...

 

Specifically a non-blocking assignment says: "Evaluate the value of the right hand side of the non-blocking assignment, and then defer the actual update of the left hand side until all other active events are complete". This way, all NBA right hand side expressions are evaluated before any NBA deferred assignments are completed.

 

[Note - the full event scheduling algorithm in Verilog is a more complex than this, but this description is accurate enough to describe this situation]

 

Avrum

 

 

Explorer
Explorer
12,707 Views
Registered: ‎08-23-2011

Re: Reg: interpreting @ posedge clk in verilog testbench from HW point of view ...

Jump to solution

yes, post par timing sim is an option, 

 

but i guess ill simplify what im asking - 

unless you have all the hardware spec, one cannot be sure what delays to program into the TB for accurate simulation.

 

so in the functional testbench, on the posedge of the clk, if my control signal transitions from 0 to 1, then does the testbench (or DUT) function as per the value 0 or as per the value 1?

 

i have attached a pic to explain my question ...

 

 

tb1.png
0 Kudos
Explorer
Explorer
12,700 Views
Registered: ‎08-23-2011

Re: Reg: interpreting @ posedge clk in verilog testbench from HW point of view ...

Jump to solution

hi avrum,

 

i know another way of making a tb - 

always @ (posedge clk or negedge rst)

if (!rst) begin

  addr <= 0;   wr <= 0; data <= 0;

  end

else begin

  #2 addr <= addr + 1;

  #2 data <= <whatever data we want to write into our DUT>

  #2 wr <= 1

end 

end

 

what the above is doing is, within the clk cycle, it is delaying putting addr/data/wr by 2ns after the posedge of clk.

having the above delay or writing the TB without those delays is showing the same result in functional sim.

 

so my interpretation would be - 

1) having this delay indicates a clk-to-q type of delay which might be present in actual hardware/FFs

2) with/without the #2 delay, the waveforms appear the same, so my understanding would be that if a signal transitions from 0 to 1 on the posedge of the clk, the TB is taking the previous value, i.e. 0 in this case. and sending it to the DUT ... 

3) having the dealys on the data/bram_wr lines is good practice as it is more representative of the clk-to-q delay which would be seen on actual hardware or timing simulations.

 

please let me know if the above interpretations are correct or where i may be going wrong in my understanding ... 

0 Kudos
Historian
Historian
22,923 Views
Registered: ‎01-23-2009

Re: Reg: interpreting @ posedge clk in verilog testbench from HW point of view ...

Jump to solution

First, what you did in your new code is not good - as you coded it, addr will update 2ns after the clock, data will update 2ns after that, and wr 2ns after that - you coded procedural blocking delays - they "block" the execution of the procedure for the duration of the delay... Effectively they become cumulative

 

If, however, you do

 

always @ (posedge clk or negedge rst)

if (!rst) begin

  addr <= 0;   wr <= 0; data <= 0;

  end

else begin

  addr <= #2 addr + 1;

  data <= #2 <whatever data we want to write into our DUT>

  wr <= #2 1;

end 

end

 

These are delayed non-blocking assignments, so all the signals update 2ns after the rising edge of the clock.

 

As for your question #2, it is answered by my description of non-blocking assignments - but, yes, as coded in your original code, that is true.

 

As for #3, that is a style thing. The NBAs with or without delay will function the same in RTL simulation (as long as you don't do something nasty with your clock as it goes into/out of your testbench). All internal signals will use non-delayed non-blocking assignements, so internally, all waveforms will look like the one you showed - all registers will do their calculations on the values just "before" the rising edge of clock, and all new states will happen just "after" the rising edge of clock (due to the non-blocking assignments).

 

If you do delays on your testbench driven signals, then they will change 2ns after the edge, which does look more like what we expect to see as a "clock to q" delay - but that doesn't change the functionality of the simulation.

 

By the way, I have seen people (and I was one of those people in the WAY olden days) that used delayed non-blocking assignments for all their registers (in the DUT and testbench) - simply to make the waveforms look pretty (to see the "clock to q" delays). While this is harmless to the synthesis tool, it does have the effect of slowing down RTL simulations (by a fair bit - like 30%) - so isn't really worth it.

 

Avrum