0
\$\begingroup\$

I have a test bench with an event counter that can be triggered by multiple tasks. I want to count all the events - even simultaneous ones.

Something like this:

module top;

  event incr_cnt_now;
  int total_cnt;
  always @ (incr_cnt_now)
    total_cnt++;

// in task a
   @ (posedge clk)
     if (some_condition)
       -> incr_cnt_now;
// in task b
   @ (posedge clk)
     if (some_other_condition)
       -> incr_cnt_now;

The problem is that if the two (or more in the real code) event triggers happen at the exact same time, total_cnt is only incremented once. I've looked at the LRM and some websites and tried .triggered and nonblocking events (->>) but I'm obviously missing something. I have a temporary hack with multiples of #1 (assuming that's the global precision) in the different tasks but that's really ugly.
Please set me straight!

\$\endgroup\$
2
  • \$\begingroup\$ A very warm welcome to the site. I don't know SV well enough to answer but I understand the principle for HDLs. Can you just have a separate event handler for each event that increments a counter, then just have all the counters added together? \$\endgroup\$
    – TonyM
    Commented Nov 8 at 22:01
  • \$\begingroup\$ Possible, but I don't know how many sources of events there might be. I would have to use an associative array where I could dynamically add sources. Interesting, but could get messy. \$\endgroup\$
    – David R
    Commented Nov 10 at 3:01

2 Answers 2

0
\$\begingroup\$

Call a function instead of trying to trigger an event

function void inc_cnt_now;
   total_cnt++;
endfunction
// in task a
   @ (posedge clk)
     if (some_condition)
       incr_cnt_now();
// in task b
   @ (posedge clk)
     if (some_other_condition)
       incr_cnt_now();

If you still need an event for something else, trigger it inside the function.

function void inc_cnt_now;
   total_cnt++;
   ->> my_event; // event gets triggered once per timeslot
 endfunction
\$\endgroup\$
0
\$\begingroup\$

There's only three choices:

  1. One counter that responds to every event.
  2. Separate tracking of events, to spread out the counting work. Each event sets a request flag, later cleared by acknowledge from a master counter-maintaining process.
  3. A separate counter per event, with all counters added up later.

Events can be simultaneous so (1) is out.

Using (2) with the effectively zero time of simulation can be done but depends on the event rates and overlaps If events are continuous and fast, it's also harder to debug and so harder to keep reliable. If there's a burst of events then a period of silence, it's much more practical.

If you can't use (1) and (2) then (3) is all that's left, really. Just adding up all the counters concurrently is reliable and simple. You'll need to know a non-event interval when you can read the counter and get a reliable total. But you'd need to know that to get any scheme to work.

Your testbench architecture is obviously derived from the requirements, such as how event counters must be implemented. If your architecture won't support the scheme, you've got the wrong architecture and it needs redesigning.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.