2

I have written an UVM testbench that has 3 agents and am now in the process of writing a scoreboard/checker. I need to have a checker module for my SystemVerilog Assertions, but this checker module needs to be aware of register configuration that is done from the test (and can be random, decided during run_phase of the test).

I am unable to figure out how this would work? If I were to create a checker module for my assertions, and bind it at the top level (tb_top) to the dut, how does this checker module know my register configuration?

After reading some papers, I figured I could write my checker module as an interface, set it in tb_top. But this would give access to the variables in my interface to the UVCs. How does the interface access variables in the UVCs?

Any help is appreciated. I feel I am missing something key here as this has probably been done plenty of times before.

EDIT: Please don't tell me I have to implement some kind of API to set each individual register setting from my UVCs? I want to just get a handle to my reg_block (or any other config variable in my agents)

noobuntu
  • 903
  • 1
  • 18
  • 42
  • Even if you would have a handle to the `reg_block`, you still not going to be able to use it in assertions (most probably), because you're not allowed to use class objects in assertions. – Tudor Timi Oct 15 '16 at 07:41
  • @TudorTimi Yes, there in lies the problem, The only solution I can come up with is having individual bits in my assertion interface (module) and then passing it into my UVCs as a virtual interface. Then everytime I do a write_reg (for example), I also go and set the bit -> vif.my_reg_bit = value. This can get tedious fast for a large number of registers. Any other way this is done? It's hard to believe I am the only one facing this issue. – noobuntu Oct 15 '16 at 12:17
  • Exactly, your assertion can't use class data. One thing, which you can do is that, you can write register assertions based on your read/write bus transaction (you will be doing some red/write bus level transaction to update the register content and you can write the same conditions as antecedents in your assertion). – Karan Shah Oct 17 '16 at 04:03
  • @KaranShah OK so you mean implement a decoder for my register read/write protocol in my assertion module. Got it! But I think I am going to just write it in as a bit from my tb_top – noobuntu Oct 17 '16 at 14:13
  • 1
    You may not require to implement a decoder, as I believe, you can write the appropriate antecedent sequence, depending upon your bus transaction – Karan Shah Oct 17 '16 at 15:33

2 Answers2

2

It seems that you want to pass information from tb_top to your UVC or vice versa. This information will be used by your assertion in tb_top, and shared by your UVC. My suggestion, you can either use uvm_resource_db or uvm_config_db.

I can think of two ways of achieving this communication.

First method is set the configuration in your tb_top, then your UVC grab this handle. From here on, you can communicate your register or whatever info you need for your assertion.

class my_tb_config extends uvm_object;
  // ...
endclass

module tb_top;
  my_tb_config tcfg;
  initial begin
    tcfg = new("tcfg");
    uvm_config_db#(my_tb_config)::set(uvm_root::get(), "*", "my_tb_config", tcfg);
    end
endmodule

// somewhere in your UVC
class my_uvc extends uvm_component;
  my_tb_config tcfg;
  function void build_phase(uvm_phase phase);
    // now both tb_top and your UVC point to the same config object
    void'(uvm_config_db#(my_tb_config)::get(this,"","my_tb_config", tcfg));
  endfunction
endclass

Another method is the other way around. Pass your UVC configuration to your tb_top.

class my_other_uvc extends uvm_component;
  my_tb_config tcfg;
  function void build_phase(uvm_phase);
    tcfg = new("tcfg");
    uvm_resource_db#(my_tb_config)::set("*", "my_tb_config", tcfg);
  endfunction
endclass

// somewhere in your tb_top
module tb_top;
  my_tb_config tcfg;
  initial begin
    #1ps; // small delay, making sure resource is submitted
    void'(uvm_resource_db#(my_tb_config)::read_by_name("*","my_tb_config",tcfg);
    // Now both your tb_top and UVC share same object, so you can freely define your whatever communication between them
    end
endmodule
AldoT
  • 913
  • 1
  • 8
  • 34
  • This doesn't really help my issue. Your solution just passes a uvm_object through the UVC heirarchy. In the context of your example, my issue is accessing tcfg class variables in my assertion module. Note that the assertion module is just a module and has no capabilities to access uvm classes. – noobuntu Oct 17 '16 at 14:11
  • I see. I usually use this way for dynamic checking in top testbench, but never try it for assertion checker. If that is the case, then yeah this doesn't really help your issue. – AldoT Oct 18 '16 at 15:13
2

I figured out a way to do this. Firstly, I realized that I had asked two separate questions:

1) My checker module needs to be aware of register configuration that is done from the test

I use cross module reference into my design to access my registers, and this provides me with up-to date register configuration as set by the test during the run-phase.

tb.sv

module tb;
  dut my_dut( ... )

  interface my_checker (
    .input_registerA (tb.my_dut.my_sub_module.regA),
    .input_registerB (tb.my_dut.my_sub_module.regB),
    .input_registerC (tb.my_dut.my_other_sub_module.regC),
    ....
  )
endmodule

my_checker.sv

interface my_checker (
  input input_registerA,
  input input_registerB,
  input input_registerC,
  ....
);

  // Here I can write properties/assertions that are register-aware
endinterface

2) How does the interface access variables in the UVCs?

This is a little trickier. I want to dynamically update my checker variables from the uvm_sequence or uvm_monitor etc.

I read this paper by Verilab that clearly describes the method to do this: http://www.verilab.com/files/litterick_sva_encapsulation.pdf

In my checker module, I create a uvm_component. From this component, I now have access to the uvm_resource_db, through which I can exchange info with my UVM-testbench.

One thing to remember is that the uvm_component instantiated in the checker module is located at the top-level (uvm_root).

noobuntu
  • 903
  • 1
  • 18
  • 42