Compile ordering of `defines and package types

I have a a number of UVC’s in my design. As part of the uvc_pkg.sv I have a set of defines that are the default values for some elements of the UVC - cover groups bin ranges etc.

I also define a top level params_pkg.sv. The aim of this is to group together multi-uvc parameters. params_pkg contains parameters that have types that come from the uvc packages.
As a result of this arrangement i compile my uvc packages before my parameters package.

However i have one particular uvc that i want to redefine the defines from the UVC. Naturally i would want to put the new defines in the params_pkg as well. However i can’t because i need to compile the uvc_pkg before the params_pkg.

How can i have my type cake and eat it? Have i miss used `defines? I can’t use a forward declaration of the types from the UVC because they are using a scoping operator.

The usual way of working with defines for UVCs (or any reusable code) is to first check if they weren’t previously defined before doing a define:


// defines.svh

`ifndef SOME_DEFINE
`define SOME_DEFINE 1
`endif

This way you can set the defines from the compiler command line without having to edit the file in any way. This way you can keep your UVC package consistent with your params package.

I take the approach of not using any defines at all. Each level of my environment will have the required parameters defined at the top of its package file which are used in place of defines. Since agents are DUT agnostic, the parameters will be generic to the standard interface.

If you need to pass a parameter from a higher level to a lower level due to specialization, you can utilize a parameterized class or the appropriate agent’s configuration object, passed down from the environment or test.

Thanks for the answer guys, you’ve highlighted that i need to be more specific in my example discussion.
I am very comfortable with defines, parameterisation and config objections. All go on in my UVC’s.
I have written up the following example as per my description above.


// uvc_defines.svh
// included in uvc_pkg.sv
 
`ifndef UVC_DEFINE
`define UVC_SETUP 1
`endif


// params_pkg.sv

// redefine the default uvc defines
// meaning the params_pkg must be compiled before the uvc package. 
`define UVC_DEFINE
`define UVC_SETUP 1

// import the type from the UVC package
// this means the uvc_pkg must be compiled before the params_pkg
import uvc_pkg::sequence_mode_e;

	typedef struct {
		string				agentName	;
		int unsigned			framesPerBlock	;
		sequence_mode_e			sequenceMode	;
     } agent_test_param_s;

localparam agent_test_param_s topTestParams [] = '{
//	  |agentName            |framesPerBlock	|sequenceMode
	'{"HISTORY_RD_A0"      ,256 ,		MODE_BFiRC}	, // [0]
	'{"HISTORY_RD_A1"      ,256 ,		MODE_BFiRC}	, // [1]
	'{"HISTORY_RD_A2"      ,256 ,		MODE_BFiRC}	, // [2]

};

So here is the rub, the structure of parameters used in the top level Test is just an easy way to reference a significant amount of parameters and stuff them into config objects quickly and easily. That is test specific and is where it should be.
I am thinking that now i need another defines file for my testbench, but this seems silly as all of my other parameters etc are in the params_pkg.

In reply to Phill_Ferg:

hmmm, i wonder if i am using defines correctly? Am i better going with cgales approach, turning my defines into parameters, and overwriting them with defparam?
This would allow me to main the compile order of uvc_pkg and then params_pkg?

In reply to Phill_Ferg:

In my environments, I always ensure that lower level components have no outside dependencies but are configurable from components above them in the hierarchy. This allows the bottom-up compilation flow from agents → environments → tests.

It’s not clear where you expect to be able to use your params_pkg. I would expect it to be DUT specific, so compiling the uvc_pkg (which should be DUT agnostic) first shouldn’t be an issue.

In reply to cgales:

agreed chuck!

Apart from this scenario that is my approach as well. My params_pkg was intended to hold values that are shared between the the DUT and the top level dut module. These parameters are relevant to both, however the DUT sources them from a VHDL package instead. So i have already lost the intention of the contents.

I think the positioning of the defines above is incorrect. The parameters within the struct are in the correct place, they are shared between the top level dut and the test.
My mistake has been attempting to combine the defines and parameters into one params_pkg file. I have now separated the defines into a separate file. My compile order is now:

  1. Test level defines to overwrite the UVC defines
  2. The UVC’s
  3. The params_pkg which used UVC types.
  4. the tests_pkg which used all of the above