Combinationally sampling an input in clocking block

Let’s say I have a simple fifo-like interface that I’m driving with a clocking block:

clocking cb @ (posedge clk);
   default input #1step output #1step
   output wren, data;
   input ready
endclocking

I’m driving this with a task, but with variable amount of delay after each drive

task automatic send();
   forever begin
       cb.wren <= 0;
       while (!cb.ready) @cb; // Wait until ready
       cb.wren <= 1;
       cb.data <= some_data;
       @cb;
       cb.wren <= 0; // Clear
       // Insert some random delay
       repeat($urandom_range(0, 10)) @cb;
   end
endtask

The issue I have is that when cb.ready is asserted, it takes the testbench at least one cycle to respond. I want to be able to cover the case where wren is asserted combinationally in the same cycle as ready.

One way to overcome this, is to use “input #0 ready” in the clocking block. However, I’ve been told that this is a bad idea.
What’s the correct way to do this? Even better, what’s the right way to insert randomized delays of >=0 cycles while driving the dut?

Much appreciated!

In reply to bitfiddler0:

Hi,

I doubt you can overcome this situation with “One way to overcome this, is to use “input #0 ready” in the clocking block. However, I’ve been told that this is a bad idea.” this. Have you tried this?

To drive wren signal on same cycle where ready is asserted, you’ll have to bypass clocking block. And use wait construct for ready high condition. However if your spec refers to synchronous signals, you might be missing something in driving protocol. As for synchronous designs you should be able to achieve handshakes through clocking block, which is not case here.

Also, your randomized delay approach works ok, but if you want control on randomization as well, use packet based delays with constraint randomization.

In reply to MayurKubavat:

In reply to bitfiddler0:
Hi,
I doubt you can overcome this situation with “One way to overcome this, is to use “input #0 ready” in the clocking block. However, I’ve been told that this is a bad idea.” this. Have you tried this?
To drive wren signal on same cycle where ready is asserted, you’ll have to bypass clocking block. And use wait construct for ready high condition. However if your spec refers to synchronous signals, you might be missing something in driving protocol. As for synchronous designs you should be able to achieve handshakes through clocking block, which is not case here.
Also, your randomized delay approach works ok, but if you want control on randomization as well, use packet based delays with constraint randomization.

Yes I have tried “input #0 ready” and it works for this particular circuit I’m testing.
Can you elaborate on what you mean by “However if your spec refers to synchronous signals, you might be missing something in driving protocol” ?

Really appreciate your help.

In reply to bitfiddler0:

Not sure how making input skew Zero for ready signal solves the problem, as clocking block will sample 0step before clock edge or 1step based on input skew. But still there no way to achieve driving of ready/wren at same point where both the signal comes from two opposite blocks, testbench and design.

For synchronous handshakes either your testbench environment should wait for ready signal(sampled in testbench on clock edge, using clocking block). In which there will be a One cycle delay between ready/wren. Or testbench drives wren independently regardless of ready signal, but needs to hold wren until ready high is sampled, which means design accepted the wren signal. This is similar to AHB protocol minus pipeline.

In reply to MayurKubavat:
You should not be using any input or output skews unless your DUT is a gate-level design with timing. Use the implicit default, or write

default input #1step output #0;

Your while loop is effectively double sampling ready. Try

cb.wren <= 0;
@(cb iff ready); // Wait until ready
cb.wren <= 1;

In reply to dave_59:

Thanks for the info. Can you comment on how I can get the behavior I want? (asserting wren in the same cycle as ready)

In reply to MayurKubavat:

In reply to bitfiddler0:
Not sure how making input skew Zero for ready signal solves the problem, as clocking block will sample 0step before clock edge or 1step based on input skew. But still there no way to achieve driving of ready/wren at same point where both the signal comes from two opposite blocks, testbench and design.
For synchronous handshakes either your testbench environment should wait for ready signal(sampled in testbench on clock edge, using clocking block). In which there will be a One cycle delay between ready/wren. Or testbench drives wren independently regardless of ready signal, but needs to hold wren until ready high is sampled, which means design accepted the wren signal. This is similar to AHB protocol minus pipeline.

It’s because skew of #0 is sampled in the observed region (see SystemVerilog Clocking Block:Input and Output Skews)

Yes I understand how a handshake would work with clocking blocks, but in this module (it’s just a fifo), it is illegal to assert wren unless the DUT is ready.

In reply to bitfiddler0:

Thanks for the information. I think I have never tried #0 input skew, and misinterpreted the behavior! Also I don’t see any reason to not use #0 skew with RTL.

//Try this,

clocking cb @ (posedge clk);
   default input #1step output #1step
   output wren, data;
   input negedge ready;
endclocking

//Or 
wait(ready); //Without the CB

In reply to MayurKubavat:


wait(ready); //Without the CB

Do not to that! Never mix blocking event statements that are not synchronized to the clocking block event with the clocking block event. Another way to put that is once your process is synchronized to a clocking block event, only use the clocking block event. Otherwise you can easily get race conditions when waiting for the first @cb event after an unsynchronized event.

This should work for you:

  cb.wren <= 0;
@(cb iff ready) // Wait until ready
  cb.wren <= 1;
  cb.data <= some_data;
@cb 
  cb.wren <= 0; // Clear

In reply to dave_59:

As far as I understand, the OP wants this:

What you proposed is fully synchronous and can only do is:

You can also click on the images to see the waves.

Hi…i am a new user here. As per my knowledge it takes the testbench at least one cycle to respond. I want to be able to cover the case where wren is asserted combinationally in the same cycle as ready. Use “input #0 ready” in the clocking block.

multilayer pcb