I am completely new to the SystemVerilog world, and I am trying to verify the asynchronous FIFO made by Cummings.

The goal is to verify this design by using the Tb components, so no UVM at all. I should basically focus on Generator (or sequencer), Driver, Interface, Monitor and Scoreboard.

There are at least 5 situations that I would like to verify which are: read only, write only, read/write at the same time, write when the FIFO is full, and read when the FIFO is empty.

Is it better to use two agents by splitting the write side and read side? If so, how can I realise the communication between the two of them when they need to provide the inputs and outputs to the monitor? Or is it better to use only one agent?

My original idea was to use a transaction with some constraints where I could use a 2-bit mode which is randomized and according to its value, I would have provided a specific stimulus (if mode =2'b00, then {winc, rinc} =2'b00 etc.) so that the Generator could just randomize all the inputs and eventually I should have at least 3 cases covered (write only, read only and write/read at the same time).

For the Write Full and Read Empty: I know the depth of the FIFO, and I would just declare a task that repeats itself one more time after the entire FIFO is filled and etc.

The point of this question is: is there any better way to proceed? Am I going in the wrong way? Maybe it's because I am unexperienced, but by randomizing everything and telling the generator to generate, don't know, 100 transactions, eventually every case will be covered I guess. Is a solution like this wrong?


1 Answer 1


One approach is to create an interface with a set of generic signal names: rstn, clk, inc, data. Also create a generic agent to support a direction (write or read). Then, you can use 2 instances of the same agent/interface pair: one for write and the other for read.

Your generator then controls both agent instances.

Since this is a small design, I recommend not thinking too much more about this, choose an approach, then start coding. It will quickly become obvious to you if the approach is working for you or not. As you are developing your testbench, you will constantly be making refinements and simplifications.

You have identified the most important scenarios, and using code coverage should help you catch any subtle corner cases you are not thinking about.

One important aspect about verifying asynchronous designs is controlling the 2 clocks. Make sure you set the 2 clock periods such that they are actually asynchronous to each other. For example, if one is 10ns, the other could be 11ns. Think about what clock ratios you want to support for your design:

  • wclk faster than rclk
  • rclk faster than wclk
  • wclk same speed as rclk

You should randomize the periods and track the ratios with a coverpoint.


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.