I have a SystemVerilog class-based testbench. My DUT has multiple SV interfaces each with it’s own BFM and I have a Driver class which drives all these interfaces through their BFMs in order to generate stimulusto the DUT.
I have a test case in which a bunch of stimulus sent to the DUT (mm writes, triggers, etc…) and then I want to check if the DUT is responding correctly. For this I have to check that after the stimulus has been generated, the DUT generates a series of pulses on one of it’s interfaces.
Right now the code to performe this test is inside a task within the DUT’s driver.
My question is, what is the best way to check such a condition? Should I have assert properties/sequences external to the driver and then enable/disable them when I want to check for them? Should I instead have the checking in the same driver function I mentioned above?
From what I have read I suspect the intended way is to have assertion properties/sequences external to the driver and then enable them or disable them accordingly. I don’t understand how this is supposed to work though… my test task is parametrizable to be able to parametrize the test stimulus, therefore, the DUT’s response will depend on those… Am I supposed to have assertions for each indivifual possible case? As far as I know SV assertion properties/sequences are not parametrizable right?
I am not very experienced in SV assertions so I would appreciate some detailed guidance.
In reply to arquer:
A few comments and remarks. In my career, I have done many designs and verifications and wrote several books on methodologies and assertion languages. Question: what is the best way to check DUT’s compliance to specs?
UVM methodology: has adopted a methodology that requires a separate monitor (a class) that collects the response and compliance to the protocol and a checker (a class) that checks for correctness. The idea of UVM is to bring uniformity in the way things are done and organized, thus allowing any future modifications or changes to be more easily understood.
Concurrent SVA in classes are not allowed. That means that with strict UVM, all assertions must be done in the checker classes. BTW, UVM does not disallow assertions in interfaces or in DUTs or modules and SystemVerilog checkers bound to the DUT.
My take:
[list]
Assertions are statements that properties are met.
Concurrent SVA is just a shorthand language to simplify the writing of assertions. For complex requirements, use tasks. See my paper: PAPER: Understanding the SVA Engine + Simple alternate solutions - SystemVerilog - Verification Academy
Abstract: Understanding the engine behind SVA provides not only a better appreciation and limitations of SVA, but in some situations provide features that cannot be simply implemented with the current definition of SVA. This paper first explains, by example, how a relatively simple assertion example can be written without SVA with the use of SystemVerilog tasks; this provides the basis for understanding the concepts of multithreading and exit of threads upon a condition, such as an error in the assertion. The paper then provides examples that use computational variables within threads; those variables can cause, in some cases, errors in SVA. The strictly emulation model with tasks solves this issue.
I am not particularly fond of the UVM style of MONITOR for collection and checker for verification, except for rare conditions where a lot of data must be collected and analyzed such as image processing, or when a lot of analysis and calculations must be done (FFT?). For protocols type of verifications, I prefer that the checking is done in interfaces and/or in the SystemVerilog checker bound to the interface or DUT.
Right now the code to perform this test is a task within the DUT’s driver.
[/list] I don’t see a big issue here. The only thing though is that you are forced to use tasks instead of SVA, thus making the assertions less readable.
From what I have read I suspect the intended way is to have assertion properties/sequences external to the driver and then enable them or disable them accordingly. I don’t understand how this is supposed to work though… my test task is parametrizable to be able to parametrize the test stimulus, therefore, the DUT’s response will depend on those… Am I supposed to have assertions for each individual possible case? As far as I know, SV assertion properties/sequences are not parametrizable right?
Properties can have arguments. Since properties are written into interfaces/modules/checkers you can pass to the actuals of the arguments the parameters you need. From my paper “Using SVA for scoreboarding and TB designs” I show how you can copy into the interfaces the needed values (such as your parameters) into the interface to be used in the SVA properties.
I would really appreciate it if you could give me a short example. For instance, let’s say one of my tests writes a few registers and then I want to check that, right after the next clock cycle where a certain signal is asserted, another signals is also asserted/deasserted. I would also like to have a timeout so if that the first signal is never asserted an error is thrown after a certain amount of time.
I guess I could do the timeout with some fork/join. What I am more concerned about is how to access my IPs signals from within my SV class.
For the AXI interfaces I have written down a BFM inside a SV interface, as described here: https://www.doulos.com/downloads/events/DVCon_08_abstractBFM_final.pdf
Since all I need to do with the AXI interface is read/write read_burst/write_burst this is fine, as I never have to access an actual interface signal from my class, and I can always go through the BFM.
For the rest of my IPs signals, which are much more custom, I was planning on doing something similar. I created a new interface which groups all those custom signals together and wrote a class inside of it to be able to handle those signals. However I now see it might be tricky to perform all the asserts I want to while going through the BFM…
What do you recommend I do in this case? would it be better to just use a virtual interface and handle the custom interface directly from my class instread of using a BFM?
In reply to arquer:
Per the sayingAll roads lead to Rome*(see all roads lead to rome - Google Search)* all these methodologies that you addressed lead to the defitions of interactive stimulus drivers and verification for/of the DUT.
These methodologies have evolved as a result of lessons and learnings in the software developments, specifically in how to group and encapsulate related items so as to enable better software development and maintenance; the more complex the software is, the greater the need for this encapsulation. Specifically:
virtual classes and tasks: Here you have a template of the tasks interfaces without the implementation, thus allowing the compilation (no elaboration) of code without the need to know the contents, which may exist at a later time. Is that needed? Fro very complex problems, most likely yes. For small designs, not really.
virutal SystemVerilog interfaces: Enables the separation of actual interface from the working one until later on when they are linked.
classes: Enables the grouping of inter-related items and methods, and the extension and updates to those items and methods. really needed? Yes, for complex designs.
Going back to the referred paper and your designs, what is the best solution?
That depends on the problem and style you wish to use. Ben’s points:
That methodology, maybe OK for small designs, but is different than UVM. Tere are good things in UVM that I like:
- transaction class where the definition of items (e,g, variables) needed to create the types of transactions and data is defined, along with the needed constraints.
- driver class that identifies the execution tasks of those transactions, typically after a call to randomization, The driver talks to the virtual interface.
> For the rest of my IPs signals, which are much more custom, I was planning on doing something similar. I created a new interface which groups all those custom signals together and wrote a class inside of it to be able to handle those signals. However, I now see it might be tricky to perform all the asserts I want to while going through the BFM…
What do you recommend I do in this case? would it be better to just use a virtual interface and handle the custom interface directly from my class instead of using a BFM?
I think its an OK approach. On the verification with assertions, you can group those assertions in a SystemVerilog checkerand then bound that (or those) checkers to the interface at the top level (my preference).
> let’s say one of my tests writes a few registers and then I want to check that, right after the next clock cycle where a certain signal is asserted, another signals is also asserted/deasserted. I would also like to have a timeout so if that the first signal is never asserted an error is thrown after a certain amount of time.
What you defined as an assertion is not what you described above, which is temporal. A better definition of the requirements is needed to write a good set of assertions