Covergroups inside VHDL code

Hello people!

First of all I want to say hi as it is my first post. I am trying to learn SystemVerilog using the UVM :)

After this I am going to introduce my problem.
I have a really simple VHDL entity of a tiny scrambler.The shift register of the scrambler is only 7 bits long.
So my entity has a clk, reset,input_data, input_enable, output_data and output_enable:

entity scrambler is
    Port ( clk : in  STD_LOGIC;
           reset : in  STD_LOGIC;
	   d_in: in std_logic;
	   v_in: in std_logic;
	   d_out: out std_logic;
	   v_out: out std_logic		
	   );
end scrambler;

I want to add coverpoints to this DUT but I do not know how to start. I thought about covering the values of the input/output but I find more interesting/useful to cover the values of the shift register inside the DUT.

I was wondering if it was possible to cover the values of the shift register inside the DUT and how can I cover those. I am a beginner in the UVM world.
I thought I could do the covergroups with my scoreboard but that would not be testing the DUT…

Thanks a lot,
Antonio

Antonio,

You want to look at the bind construct of SystemVerilog. This allow you to insert a module instance inside another module instance (or entity in VHDL) without modifying the original module. The bind construct was originally intended to insert assertions into a DUT without modifying the source, but you could certainly do the same for covergroups or any other construct.

When it comes to VHDL<->SystemVerilog inter-operability, there may be specific limitations that may be tool specific. Check you User Manual or vendor for assistance.

Dave

In reply to dave_59:

Sorry for the late reply…
Thank you for your answer, you really guided me!
I found your article which is really good “The Missing Link: The Testbench to DUT
Connection”

About the bind construct, you really pointed me in a great direction but I am still a bit lost. I guess I have to use it in my test module/class with syntax similar to:

bind DUT: InterfaceName InterfaceInstanceNAme
    .InterfaceVariable(DUTSignal_1)
    .InterfaceVariable(DUTSignal_i)
    ....
);

Is there any website/book where I could find how to use most of the SV Syntax aspect?
I am using the Ray Salemi UVM Primer book but there are some aspects like the bind trick I cannot find in it.

Dave the thing you mention about the tool limitations. I am using questasim so I do not have any problems. However I would like to have a code which also could be simulated in a different simulator. If possible…

Thanks,
Antonio

In reply to antonio92m:

Could anyone please help me to find a link or some place to find extra info about how to use bind within VHDL?

Thanks!!

In reply to antonio92m:

If you are using Questa you can find an example in the Questa installation path
…/mixedlang/bind_example

I’d like correct you with your wording: You can bind a SV module/interface to a VHDL component.
It appears in the design browser as the VHDL component contains this SV module. But it ‘appears’ only.

In reply to chr_sue:

Thanks for your answer chr_sue!

Also thanks for my wording.

It is not clear yet for me how to bind a SV block to a VHDL architecture.
The example says:


module bind_wrapper;
	bind send_receive receive_send inst_receive_send (.data_received(data_sent));
endmodule

I guess I can bind my interface to the VHDL architecure, Am I right? But I do not really know how to.
By observing the “bind_wrapper” module and the files it seems the syntax would be:


bind WhereToBind WhatIsBindedToTheData NameOfTheBindInstance (.VariableThatHoldTheDataBinded(SignalIWantToBindInTheVDHLArchitecture));

And then I would need to pass this data to my coverage class, would I send the SV variable binded to the architecture to the monitor that my coverage class is subscribed?

Thank you thank you!!

Antonio

In reply to antonio92m:

Ok, I’m starting to explain:

  1. WhereToBind: we can bind to a (1) certain design. This the entity name of a VHDL design or the module name of a Verilog/SV design. If you have more than 1 instances of this design in your DUT. The bind-block appears in all instamces. (2) we can bind to an instance.Then WhereToBind is the instance name of the design we want to bind to (using the dot-notation,i.e. DUT.inst1.inst2)

  2. WhatIsBindedToTheData: this is the module name where you have your coverage model inside (covergroups, cross etc.

  3. NameOfTheBindInstance: This is the instance name of your module holding the coverage model.

  4. SignalIWantToBindInTheVDHLArchitecture: you can connect your bind-module to any signal inside a VHDL instance or design. But you cannot connet to any VHDL variable.

Hope this helps you to better understand what is going on with the bind construct.

In reply to chr_sue:

Thank you Chris!! That was so well explained!
But I still have a couple of doubts.

In numbers (2) and (3) could we say class instead of modules? I say that because the only module I have is the Top module, the rest are interfaces and classes.

Could I bind my coverage class to the DUT? I guess what I should do is to bind my interface to the DUT and then use that interface to pass some data to the coverage class right?

Thank you

In reply to antonio92m:

The best place to implement the bind construct is in the toplevel module where you are instantiating the DUT, because you need the path to the DUT. A coverage module should contain your coverage modee with all your covergroups, crosses etc.

In reply to chr_sue:
Okay, but If I instantiate it in the TOP module, how can the BFM access to the DUT internal signals?


module top;
   import uvm_pkg::*;
   import scrambler_pkg::*;
`include "scrambler_macros.svh"
`include "uvm_macros.svh"


   scrambler_bfm       bfm();
   scrambler DUT (.clk(bfm.clk), .reset(bfm.reset), .d_in(bfm.d_in),
		  .v_in(bfm.v_in), .d_out(bfm.d_out), .v_out(bfm.v_out));

/*The DUT is a single component.
  I'm not sure about the 3rd argument of the construct. I think it should be the coverage class,
  But I'm not sure if a class can have access to bind or has to access through the interface.
*/
   bind DUT scrambler_bfm tb_classes/coverage.svh (.scrambler_reg(registro_act));

/*I guess I have to declare the variable to hold the data binded as well*/
   bit [6:0] scrambler_reg;
/*But even with this I don't know how the coverage class can access to this vector*/

initial begin
   uvm_config_db #(virtual scrambler_bfm)::set(null, "*", "bfm", bfm);
   run_test();
end

endmodule : top

Thanks again Chris. Hope at least this thread also helps other people struggling using the bind construct.

In reply to antonio92m:

For me is not clear what the bfm is. Is it the SV interface the DUt is connected to?
In the bind construct the 3rd argument is definitely wrong. This has to be the instance name of the module which holds the coverage model.
Inmy understanding it does not make any sense to use the consider the bfm as the unit which holds the coverage model. And it is connected to the toplevel of the DUT. Is this really what you want?

In reply to chr_sue:

Yes, the bfm is the interface connected to the DUT.
When you say module do you mean that has to be strictly a module(or interface) or can also be a class?
I asked that because the only module I have is the TOP module. The rest are classes. And the coverage class is within the environment class. That is why I though that the bind construct has to be “linked” to the interface to be able to send the data to the TB.

I totally agree, I do not want to to use the BFM to hold the coverage model but I use the bfm as the thing that drives data to coverage and scoreboard.

Thanks again for all your help Chris!!

In reply to antonio92m:

When I say module, than I mean a static construct like a SV module, SV interface or program and not a class.
When your intention is to put your functional coverage into a class-cased construct, then it has to be part of your class-based env. This is always a good place to have the functional coverage in, especially for the functional coverage of your testbench, bur also for functional coverage for your design.
If you want to calculate functional coverage of a DUt unit the you have to implement in your toplevel module a bind construct for a second interface (an interface which is connected to an internal unit of your DUT. This second interface has to be passed to your env using uvm_config_db.

Do you know the bind example from the Questa examples. You can find it in the installation path
…\examples\mixedlang\bind_example

In reply to chr_sue:

Hello Chris,

Yes at the moment my coverage is within the env, but it does not have enough “coverage” as the most important thing to check are the signals inside the DUT.

Oh that’s great I did not realise about using a different interface using the bind construct


   bind DUT bind_bfm bind_inst (.inputPortOfBindInterface(registro_act));

Where that bind line would be in the top module and where the bind_bfm interface should write the input data to a monitor connected to the coverage class and therefore the coverage class would access to the data with the analysis ports, would not it?

I did have a look at the example that you mentioned above. And thanks to it I “could” guess which the “parameters” (I do not know how are they called) of the construct were.

And now with a 2nd interface I should sync with the “main” interface that is generating the clk in order to send the data to the monitor in the right time, right?

Thanks!!

P.S: Do you know any other source apart from the bind example in the mixedlang folder to learn more about how to use bind? I read the article of Dave Rich: “The Missing Link: The Testbench to DUT Connection” but apart from that I could not find any more information.

In reply to antonio92m:

The bind construct privides you an adapter to internal DUT signals. In the toplevel module you can connect this to a second interface which you can be pass with the uvm_config_db through the class-based testbench. There is nothing magic. It is very simple.This the reason why you do not find articles relating to the bind.

In reply to chr_sue:

Hello Chris,
I have been trying to use the bind construct but I did not succeed.
I have created a new interface that will be registered with the factory and therefore the coverage class will access to it. Then I declared the bind construct in the following way:

bind designEntity NewInterfaceName NewInterfaceInstance (.VariableOfTheNewInterface(DesignSignalIwannaBeBindedTo);


module top;
   import uvm_pkg::*;
   import scrambler_pkg::*;
`include "scrambler_macros.svh"
`include "uvm_macros.svh"


   scrambler_bfm       bfm();
   scrambler DUT (.clk(bfm.clk), .reset(bfm.reset), .d_in(bfm.d_in),
		  .v_in(bfm.v_in), .d_out(bfm.d_out), .v_out(bfm.v_out));

   /*New interface binded to the internal data*/
   bind_bfm bind_bfm_inst();

   bind scrambler bind_bfm bind_bfm_inst(.scrambler_reg(registro_act));

   
initial begin
   uvm_config_db #(virtual scrambler_bfm)::set(null, "*", "bfm", bfm); //Registering the main interface with the factory
   uvm_config_db #(virtual bind_bfm)::set(null,"*","bind_bfm",bind_bfm_inst);//Registering the bind interface with the factory
   run_test();
end

endmodule : top

The new interface is very simple


interface bind_bfm;
   import scrambler_pkg::*;

   bit [6:0] scrambler_reg;
endinterface : bind_bfm



And the signal I want to get is a:


signal registro_act: std_logic_vector( 6 downto 0);

But Questa complains:

** Error: top.sv(13): (vopt-1027) Number of positional association elements (1) exceeds number of formals (0).

I do not know what that error means. Could you please give me a hand?

Thank you!

In reply to antonio92m:

Hello Antonio,

I took my time to investigate soem more details and I found the story with the additional interface is not so easy as I just said. You have now 2 options:
(1) You can implement your design covergroups in the interface/module you are binding to your design. But this is not so nice because you have to take care regarding the sampling of your covergroup.
(2) You spend more effort as explained in a paper presented at DVCon by Dave Rich (Mentor Graphics). If you google ‘missing link dvcon’ you should find it. I can provide you also a code example. I’m working on it and you can get it tomorrow evening. Please contact me through my web-page christoph-suehnel@web.de

In reply to chr_sue:

Hello Chris,

Thanks again, I really appreciate it.

About:

  1. I am not sure about this option because then it would not have an UVM structure and it would be “unreausable and unmanageable code” right?

  2. I have read the article several times and it is not clear yet for me. The code in the appendix A where the bind is.
    I do not understand the meaning of the colon “:”. Would it be the same using VHDL?


bind model : dut.sub1 probe_itf #(.WIDTH(common_pkg::WordSize1)) m1_1(InternalBus);
bind model : dut.sub2 probe_itf #(.WIDTH(common_pkg::WordSize2)) m1_2(InternalBus);
bind model : dut.sub1 probe_itf #(.WIDTH(1)) m1_3(CS);

Also regarding that I do not have submodules, would the structure of the bind construct change? I mean if I do not have a module and submodules compared with the Dave Rich article I think it should be like:


bind scrambler : DUT bind_bfm bind_bfm_inst(.scrambler_reg(registro_act));
/*where the bind_bfm is the interface*/

I have also visited your website. Do you know the link where you will publish it?

I also wanted to ask you. I am trying to learn the UVM because of my final project for uni. Do you mind if I write your name as one of the people that helped me a lot?

In reply to antonio92m:

Hi Antonio,
regarding
(1): It would be still a UVM environment. Because the bind construct is used heavily for SystemVerilog assertions. And it adds in the toplevel module only one additional unit.

(2): common:: indicates that data aree following are defined in the package ‘common_pkg’. It is the resolution operator.
Regarding the code example, please use my email address from my webpage. The I’ll respond to you.
I believe it is not so easy to understand, because it is an apptroach using so-called abstract classes. But I’ll help you and guide through the code.
Finally it is up to you to mention me if you feel I could help you.

In reply to chr_sue:

Hello Chris,

About

  1. I do not understand how can still be an UVM environment. I mean I thought that the top module was where you had to instantiate the DUT and the interfaces to link that DUT to your design. And if you instantiate let’s say the coverage class in your TOP then that would not be within the agent, right?

  2. about the colon “:” I meant the: bind model : dut … Sorry it was not clear.
    Okay, thank you Chris. I am going to email you :)

And yes I want to mention you because you are helping me a lot and I appreciate that!