1)有人可以解释在SystemVerilog中使用虚拟接口的概念。
即使在LRM和其他网站中提到它可用于驱动物理接口等的不同实例,并且由于类是动态的而DUT是静态的,我们需要虚拟接口。
但我仍然不清楚这个概念。请以简单的方式解释为什么我们使用虚拟接口。
2)我们可以在界面内使用动态数组,为什么不呢?如果没有替代方案?
答案 0 :(得分:3)
到目前为止一些好的答案,但似乎在使用 dynamic 这个词及其与虚拟界面的关系时存在一些混淆。
首先有动态大小的类型,如数组,字符串和队列。这些是通用数据类型,通常无法合成。但如果供应商有足够的动力,他们可能就是这样。这些类型可以在module
,interface
或class
内声明,但与interfaces
和virtual interfaces
的讨论无关。
然后有动态构造的类对象。通过在运行时执行过程代码来构造类对象,而不是在编译时静态地详细说明它们。静态细化还通过展平层次结构并创建对端口连接的信号的直接引用来处理模块之间的端口连接。你不能用类做到这一点,所以你需要除了端口连接之外的另一种机制来在类对象之外进行通信。
一个简单的解决方案是使用分层引用 - 只需使用您想要读取或写入的分层路径到达DUT。然而,由于多种原因,该解决方案很快变得不可行。这对于可重用性是不利的。只要DUT的层次结构发生变化,或者您尝试从块级别转移到SOC验证,就必须更新testbench类中的路径。许多人试图通过使用像
这样的文本宏来管理它`define PATH top.design.block1
然后写`PATH.sig1< = 1;在他们的测试平台上。当有多个testbench对象实例需要通信DUT的多个路径时,此方法不起作用。另一个问题是大多数类都是在SystemVerilog包中编写的,除了其他包导入之外,包不应该有任何外部依赖。
因此SystemVerilog已经对类对象进行了动态引用,它为接口实例添加了动态引用,并将其称为virtual interface
。它与没有继承的抽象类引用非常相似。 virtual interface
变量可以动态接受实际接口实例的句柄。然后,您可以动态引用该接口实例的成员。
答案 1 :(得分:1)
1)将虚拟接口视为指向所述接口的实际实例的指针。
2)接口模拟一组信号。声明动态信号数组没有任何物理意义。可以这样想:设备有一个固定的端口列表,没有一个在构建之后创建。如果要为具有可变数量信号的设备类声明接口,则需要使用参数:
interface some_interface;
parameter int WIDTH = 10;
logic some_signals[WIDTH];
endinterface
module top;
// instantiate an interface with 50 signals
some_interface #(50) my_if();
// the signals can then be referenced with
// my_if.some_signals[0]
// my_if.some_signals[1]
// ...
// my_if.some_signals[49]
endmodule
编辑:正如Greg所说,允许在接口中声明动态数组,但它不可能是可合成的。
答案 2 :(得分:1)
{C} / C ++借用virtual
关键字。 virtual interface
是一种特殊类型,它链接HDL(硬件描述语言)和OOP(面向对象编程)。
引用IEEE Std 1800-2012§25.9虚拟接口:
虚拟接口提供了一种机制,用于将抽象模型和测试程序与构成设计的实际信号分离。虚拟接口允许相同的子程序在设计的不同部分上操作并动态地控制与子程序相关联的信号集。用户可以操纵一组虚拟信号,而不是直接参考实际的信号集。对底层设计的更改不需要重写使用虚拟接口的代码。通过抽象一组块的连接性和功能,虚拟接口可以促进代码重用。
动态数组可以存在于interface
内,这样做的唯一副作用是它不再可合成。要合成的接口必须遵循其他可合成组件的相同要求。当界面不在设计的一部分时(例如,作为测试平台的激励驱动器),动态类型可以存在于界面内。
所有关于IEEE Std 1800-2012§25接口
中的界面下面的示例和可运行的版本here:
interface my_if();
logic [15:0] data;
int payload[];
endinterface : my_if
module my_dut(my_if pif);
initial $monitor("%0t @ %m.pif :: data:%h payload:%p", $time, pif.data, pif.payload);
endmodule : my_dut
module testbench;
class MyClass;
virtual my_if vif;
function new(virtual my_if vif);
this.vif = vif;
endfunction : new
function void init(int size=4);
vif.payload = new [size];
for(int i=0; i<size; i++)
vif.payload[i] = i;
endfunction : init
task send_payload();
for(int i=0; i<vif.payload.size; i++)
#10ns vif.data <= vif.payload[i];
endtask : send_payload
endclass : MyClass
my_if pif();
my_dut dut(pif);
MyClass myc;
initial begin
myc = new(pif);
#10ns myc.init();
#10ns pif.payload.rsort();
#10ns myc.send_payload();
#10ns $finish();
end
endmodule : testbench