How to assign a single System Verilog Interface to an array of Interfaces - system-verilog

I am building an AXI arbiter (axiIxc) where it has Master and Slave ports that are arrays of the AXI interface. I then instantiate this in myModule which has a register interface that is an Interface that I defined with the AXI signals. My issue is that I get a compiler error because regIf is a single Interface and mPort on the AXI arbiter is an array of Interfaces of size [0:0]. Is there any way to cast the single interface to an array? The other way works fine...i.e. the sPort is an array and I can specify which element I want to connect to a sub-module.
module myModule
(
myAxiIfType.slave regIf // registers
);
myAxiIfType regIxcSPort [0:3];
axiIxc #(1,4) // MPort Quantity, SPort Quantity
regAxiIxcInst (
.mPort(regIf),
.sPort(regIxcSPort)
);

No. Interfaces are not the best construct for everything.

Related

How to use system Verilog hierarchical interfaces

Can the top module in system verilog have interface ports? I am trying to define a hierarchical interface and then trying to use that interface for the top module.
Please check below example code and let me know if I am missing something
interface bank_inf (
inout logic [20:0] data_io,
inout logic qsb_io,
inout logic ctrl_io);
endinterface
interface channel_inf #(parameter numbanks = 7)
( bank_inf banks[numbanks-1:0] );
endinterface
interface ss1_inf #(parameter numchannels = 8, parameter numbanks = 7)
( channel_inf channels[numchannels-1:0]);
endinterface
module die1 (ss1_inf ss);
endmodule
module die2 (ss1_inf ss);
endmodule
module top (
ss1_inf ss1,
ss1_inf ss2
);
die1 inst1(ss1);
die2 inst2(ss1);
endmodule
I am getting below error:
Error-[SV-UIP] Unconnected interface port
../test.v, 22
"ss1"
The port 'ss1' of top-level module 'top' whose type is interface 'ss1_inf'
is left unconnected. It is illegal to leave the interface ports unconnected.
Please make sure that all the interface ports are connected.
From a language and simulation perspective, the top level module cannot have interface ports. Interface ports represent references to hierarchical interface instances. Those instances are where allocation of variables and other processes exist. Also, interfaces may be parameterized and the only way to specify that parameterization is through an actual instance. There is no syntax that allows parameterization in the port declaration.
But from the synthesis perspective, the highest level you provide to a synthesis tool may allow interface ports. But you should check with the particular synthesis tool vendor you are using.
No, top level module cannot have interface ports.
The reason is that interface ports require connection to an interface instance. Instantiation of an interface can only happen inside a module. So, only modules instantiated in hierarchy can be connected to an instance of an interface.
No interface instance can exist at the $root/$unit level, therefore there is no interface instance top-level module ports can be connected to.

Virtual interface element uses an interface with interface ports [warning from QuestaSIM vlog/vsim]

What is the meaning of the following warning issued by QuestaSIM's vsim? What is the simulator worried about here? I haven't been able to produce an actual simulation error from this yet.
My guess: it has something to do with interface instances vs. virtual interface instances, but my understanding is minimal.
** Warning: (vsim-8887) tests/base_test.svh(28): Virtual interface element 'this.apb_driver_bfm_vi.clk' uses an interface with interface ports.
apb_driver_bfm_vi is a virtual interface handle to the following interface:
interface apb_driver_bfm(
input logic clk,
input logic nrst,
apb_if.apb_s apb_if_i // apb_if is itself an interface, apb_s is a modport.
);
endinterface : apb_driver_bfm
The virtual interface is used as follows: #(posegde apb_driver_bfm_vi.clk); in the run_phase of my testbench. This seems to work fine, despite the warning.
From section 25.9 Virtual interfaces in the IEEE 1800-2017 SystemVerilog LRM
Although an interface may contain hierarchical references to objects outside its body or ports that reference other interfaces, it shall be illegal to use an interface containing those references in the declaration of a virtual interface.
this a problem when the interface port gets connected to a parameterized interface and different instances of the virtual interface have different parameterizations. This is not a problem when the interfaces have the same parameters, but the LRM is overly pessimistic.

Virtual interface between monitor/driver and their BFM ??? What they are actually, can someone explain?

I was reading UVM cookbook and I got confused about virtual interface connection in between monitor, driver and their BFM. Does it mean there could be multiple driver or monitor, or this is independent of interfacing that does not know either its monitor or driver. Can anybody help?
The keyword virtual is re-used a number of times in SystemVerilog. The interface is virtual in the sense that its hierarchical path is set at runtime by passing it through a variable. All other connections in Verilog/SystemVerilog are fixed paths.
This does indeed allow you to have multiple instances of the same driver code connect to multiple interface instances. It also helps in block-to-system reuse so you can change the hierarchical path as the interface gets deeper into your system level.
Verilog was not created as a programming langue, more over, it was not suitable for object oriented programming. On the other hand, System verilog test bench language was created as an object oriented programming language.
One of the issues is to semantically connect HDL verilog with TB. All verilog HDL/RTL objects are statically compiled and cannot be manipulated dynamically (which is needed at TB). You cannot get pointers to modules, variables, ... (well except through some back-door PLI mechanism).
So, System verilog came up with the interface construct, which was intended as a connectivity object in RTL world. It is similar to a module in a sense, that it is a compile-time static object. But, SV also added a trick, which allows you to have a reference to an interface. The trick is called virtual interface.
From the point of view of a programmer, you can think of it as a reference, or a pointer to the static interface object. This gives you an ability to pass this reference to different TB class, or create multiple references tot he same interface.
Here is a schematic example:
class Transaction;
virtual dut_if trans; // <<< virtual interface
function new(virtual dut_if t);
trans = t; // <<<< assign it to trans
endfunction // new
endclass // Transaction
// definition of the interface
interface dut_if import trans_pkg::*;
(input trans_t trans);
endinterface
// instantiate the interface in module 'rtl'
bind rtl dut_if dut_if(data);
program tb;
// pass it to the constructor as a virtual interface pointer.
Transaction trans1 = new (rtl.dut_if);
Transaction trans2 = new (rtl.dut_if);
endprogram // tb

system verilog interface for multiple clocks

My DUT is a memory controller. I have to write a system verilog interface for the DUT.
Memory Controller DUT supports 32 AXI Masters.
When I am writing an AXI interface, it will consist of ACLK which is generated and passed on through the top(verification). When I am connecting this interface to the DUT, will there be 32(AXI ACLK) + 1(clk on which DUT is working) , inall 33 clks to the DUT..
I am quite confused in these.
logically there should be only one clk in the DUT..
Thanks in advance for the answers
Shared interface signals should be declared as input ports to your interface. That way you can tie them all together to make one logical signal.
interface myintf(input wire sig_shared);
wire sig_internal;
endinterface
module top;
wire s1,s2;
myintf i1(s1);
myintf i2(s1);
myintf i[31:0](s2);
endmodule
Now signals i1.sig_internal and i2.sig_internal will be independent, but i1.sig_shared and i2.sig_shared are logically equivalent. Same thing for i[0].sig_shared thru i[31].sig_shared.

system verilog bind used together with interface

I defined an interface in system verilog and use bind statement to bind to internal RTL signals. I want to be able to force internal RTL signals through the interface. However, this is causing the RTL signal to go to 'x' if I don't force these signals explicitly, it seems bind to interface is having driving capability. I don't want RTL signal to change to 'x' when nothing is forcing it in this case, not sure what I am doing wrong here?
my code looks like this with DUT being the design:
interface myInf(
inout RTL_a,
inout RTL_b
);
bind DUT myInf myInf_inst(
.RTL_a(DUT.a),
.RTL_b(DUT.b)
);
bind DUT myDrv(myInf_inst);
where myDrv is a module which drives the ports on myInf.
In this case, DUT.a and DUT.b are internal RTL signals, they have their driver from design, but I want to be able to force them if needed. however, these signals becoming 'x' when I am just binding them to myInf without actually driving them.
The inout signals might be a non-net type. It is better to be explicit in the the declaration and define them as inout wire. Inside the interface, assign the nets to a logic and initialize the logics to z. A non-z value will apply a driver while a z will allow signals to drive. Example:
interface myInf(
inout wire RTL_a,
inout wire RTL_b
);
logic drv_a, drv_b;
initial {drv_a,drv_b} = 'z; // z means not driving
assign RTL_a = drv_a;
assign RTL_b = drv_b;
endinterface
There might be conflicting drivers, such as the normal drivers from the design. In this case you will need to override the driver. Assuming the signal being overrode is a net type, this is done by changing the assign statements to assign (supply1,suppl0) RTL_a = drv_a;. This is utilizing the Verilog concept of drive strength. Assigning to z will still all other drivers. Most nets are driven with a strength of strong1,strong0 which is weaker then supply1,supply0. Drive strength will not work for non-net types (e.g. logic & reg). These register/variable-types use a last-assignment-wins approach. Fore more on drive strength read IEEE Std 1800-2012 sections 28.11 through 28.15
Your sample code has some bugs. The pin connections for myInf_inst should use hierarchical references relative to its target scope. Unless there is an instance called DUT inside module DUT, then the DUT. should be omitted (See IEEE Std 1800-2012 ยง 23.11 Binding auxiliary code to scopes or instances). The bind statement for myDrv is missing an instance name. The code should be:
bind DUT myInf myInf_inst(
.RTL_a(a), // no DUT.
.RTL_b(b) // no DUT.
);
bind DUT myDrv myDrv_inst(myInf_inst);
sample code: http://www.edaplayground.com/x/2NG