0

I'm trying to verify a pretty simple handshake between two modules. One module is on a slow clock and raises "req", the faster module should raise "ack" on the next fast clock and hold it until the next slow clock posedge. The end result looks like this:

req-ack wave diagram example

This is how I wrote the expect:

expect expect_ack_when_req_go is
      (@req_rise_e) => @ack_rise_e
      else dut_error("ERROR: ack expected to be asserted when req rises!");

*both @req_rise_e and @ack_rise_e are sampled on slow clock.

Running the simulator yields the error as the first expression seems to succeed but the second one does not. This is despite the fact that when tracing events to the wave, I can see both events occur together (as seen in the wave: event_req, event_ack).

Shay Golan
  • 89
  • 7
  • I would first try to add a sampling clock to the TE, i.e. `expect ... (@req_rise_e => @ack_rise_e)@slow_clk;` – Thorsten Sep 26 '17 at 07:05
  • Already tried it, and it didn't do any good... Also, I think it's redundant, since both events are already sampled by slow clock: `event req_rise_e is rise (smp.port_req$) @slow_clk_e;` `event ack_rise_e is rise (smp.port_ack$) @slow_clk_e;` – Shay Golan Sep 26 '17 at 08:06
  • Ok,@Thorsten it appears you were right! It appears that adding a sampling clock on **both** signals together changes something in the way the simulator understands the check expression. I changed it in the way you suggested and it worked... I can't explain it though... If you can understand it maybe you should post it as a solution? – Shay Golan Sep 26 '17 at 10:59
  • Correction: @Thorsten it appears you were partially right! I first changed the ack_event to be true (ack$ == 1), instead of rise (ack$). It still didn't work, but once I added the sampling clock in the way you suggested it solved it. I still can't explain it though. – Shay Golan Sep 26 '17 at 11:07
  • One more thought: `ack` changes twice during a `slow_clk` period, maybe that's an issue solvable by using an event port. Could you change `smp.port_ack` to be an event port that triggers on rising? – Thorsten Sep 26 '17 at 11:22

1 Answers1

3

You're trying to do overlapped implication, i.e. both your events happen in the same cycle. What the => operator does is check that the consequent happens on the next sampling event, in this case the next slow clock edge. This is called non-overlapped implication in SystemVerilog assertion parlance.

You can get your desired behavior by writing the following:

expect expect_ack_when_req_go is
  (@req_rise_e) => detach({@ack_rise_e; ~[1]})
  else dut_error("ERROR: ack expected to be asserted when req rises!");

Full explanation here.

On a methodological note, I would recommend against writing the temporal expression in a different way. I'm assuming that you are verifying the module that is driving ack and this module works on both clocks. I would also assume that this module samples req with the fast clock. It would be clearer to formulate your check as:

expect expect_ack_when_req_go is
  (@req_rise_at_fast_clock_e) => @ack_rise_at_slow_clock_e
  else dut_error("ERROR: ack expected to be asserted when req rises!");

This way you don't have to mess around with detach(...) and the expect more closely matches the natural language description of your desired behavior.

Tudor Timi
  • 7,453
  • 1
  • 24
  • 53
  • OK, great answer! I vaguely remembered that there are two implication operators on SVA, but it's been a while since I handled any SystemVerilog code. Also nice technical explanation on your blog. Moreover, you are also correct on the methodological note, and this is the fix I'll make. THX. – Shay Golan Sep 27 '17 at 09:11