FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训
登录
首页-所有问题-其他-正文

使用SystemVerilog编写验证平台时,`interface`和`virtual interface`在实际应用场景中有何区别?什么时候必须用后者?

单片机爱好者单片机爱好者
其他
12小时前
0
0
2
学习SystemVerilog和UVM,对`interface`和`virtual interface`的概念有点混淆。知道`interface`是连接DUT和TB的物理接口,`virtual interface`是一个句柄。但在实际构建验证环境时,什么情况下可以只用`interface`?什么场景下必须使用`virtual interface`(比如在class里)?能结合一个简单的例子说明其必要性和好处吗?
单片机爱好者

单片机爱好者

这家伙真懒,几个字都不愿写!
12600
分享:
想用FPGA实现一个‘轻量级CNN加速器’作为毕设,在资源有限的Artix-7上,如何对卷积层进行高效的循环展开和数据复用设计?上一篇
数字IC后端面试中,关于‘功耗分析(Power Analysis)’通常会问哪些问题?如何从报告中分析出功耗热点和优化方向?下一篇
回答列表总数:5
  • Verilog小白学编程

    Verilog小白学编程

    聊点实际的坑。区别都知道,但用的时候容易出错。

    只用interface的场景:你的testbench非常非常简单,所有激励生成、驱动、监测都写在module里,用initial块和always块搞定。或者,你把一些简单的任务(task)和函数(function)直接定义在interface内部。这种情况下,interface本身就能提供连接和封装,不需要virtual interface。但这不是现代验证的方法。

    必须用virtual interface的场景:只要你用了UVM,或者任何基于class的验证结构,就是必须的。因为UVM的组件(uvm_driver, uvm_monitor等)都是class,这是铁律。

    关键步骤:
    1. 在interface里定义好clocking block和modport,规范时序域和方向。
    2. 在顶层TB module里例化interface,连接DUT。
    3. 声明virtual interface并赋值:`virtual my_if vif = my_if_inst;`
    4. 使用 `uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.env.agent.drv", "vif", vif);` 将其放入数据库。
    5. 在driver的class里,声明 `virtual my_if vif;`,并在build_phase用 `uvm_config_db#(virtual my_if)::get(this, "", "vif", vif);` 获取。
    6. 一定要检查get是否成功!if(!vif) `uvm_fatal("NOVIF", "vif not set")`。这是最常见的坑,仿真跑起来发现信号没驱动,多半是vif是null。
    7. 在run_phase里,通过vif.clocking_block来驱动和采样信号,保证时序正确。

    好处除了复用性,还有利于封装。interface里可以定义协议检查的assertion,而virtual interface让这些assertion在class控制的交易中也能被关联触发,使得验证更严密。

    11小时前
  • Verilog小白学逻辑

    Verilog小白学逻辑

    我当初也卡在这里。给你打个比方:interface就像一台具体的电视机(有实体),virtual interface就像电视机的遥控器。你人(class)不能直接钻进电视机里调台,但你可以用遥控器(virtual interface)来控制它。

    什么时候必须用遥控器?当你在另一个房间(class)的时候!也就是说,你的代码逻辑在class里时,就必须通过virtual interface这个“遥控器”来操作interface“电视机”。

    一个简单的例子:假设你写了一个SPI驱动的任务(task),如果这个任务直接写在interface里或者module里,它可以直接操作interface内部的信号,比如直接写 `cs_n = 1'b0;`。但是,如果你希望把这个驱动任务封装到一个可重用的driver class里,你就不能在这个class里直接写 `cs_n = 1'b0;` 了,因为class找不到cs_n这根线。此时,你必须在class内部声明一个 `virtual spi_interface vif;`,然后在驱动任务里写 `vif.cs_n = 1'b0;`。在仿真开始前,你需要将顶层的实际interface“绑定”到这个vif上。这样,class里的代码就能通过vif间接控制真实的信号了。

    好处很明显:driver class变得独立了,它不关心具体的interface实例叫什么名字,在哪个模块,它只认vif这个通用接口。这样,同一个driver class可以轻松复用于不同的项目、甚至同一个DUT的不同接口实例(例如两个相同的SPI外设)。如果不用virtual interface,你的验证组件就和硬件绑定死了,基本没有可移植性。

    11小时前
  • 芯片验证新人

    芯片验证新人

    从复用性和灵活性的角度来理解会更深。Interface定义了信号的集合和协议,它本身是静态的、与具体实例绑定的。而Virtual Interface提供了对Interface实例的动态引用,这是构建可重用验证组件(VC)的关键。

    必须使用Virtual Interface的核心场景是:当你希望你的验证组件(例如一个AXI Master Driver的类)独立于任何特定的Interface实例或顶层模块时。这样,这个Driver类就可以被实例化多次,用于驱动系统中不同的AXI接口(比如连接到DUT的AXI端口1和端口2),只需将不同的Virtual Interface句柄传递给它们即可。

    步骤很清晰:
    1. 定义interface(如axi_if),包含信号、clocking block、modport。
    2. 在顶层测试平台(top module)中例化该interface的实际实例(如axi_if axi0(.);),并将其连接到DUT的对应端口。
    3. 在顶层module中,声明一个virtual interface的变量(virtual axi_if v_axi0),并将其指向刚才例化的实例(v_axi0 = axi0;)。
    4. 通过UVM配置机制(uvm_config_db)将v_axi0传递给验证环境。
    5. 在验证组件的类(如axi_driver)中,声明一个virtual interface的成员变量(virtual axi_if vif;)。
    6. 在build_phase中,使用uvm_config_db::get获取传递过来的virtual interface句柄。
    7. 此后,driver中的所有操作都基于vif进行(例如 @(vif.cb); vif.cb.addr <= 'h10;)。

    注意事项:Virtual Interface的传递必须在仿真开始前完成,通常是在build阶段。另外,要确保在class中使用virtual interface驱动或采样信号时,其指向的实际interface实例是有效的,避免出现空指针(null)引用。这种设计模式使得验证组件完全与顶层连接关系解耦,极大地提升了代码的可重用性。

    11小时前
  • 逻辑综合学习者

    逻辑综合学习者

    老铁,我刚搞明白这个。你就记住一点:class里不能放硬件的东西,interface是硬件,所以进不去。virtual interface就是个门票,让class能进场操作硬件。

    必须用virtual interface的场景,就是你的验证平台用了OOP(面向对象)那套东西,比如UVM。你的driver, monitor, scoreboard都是class。这些class在仿真开始前就建好了,但实际的interface信号线是跟硬件一起的。virtual interface就是在这两者之间搭桥。

    不用virtual interface行不行?如果你整个TB都用module写,不用class,那可能可以。但那样写又累又难复用,现在没人这么干了。

    一个小例子:你在testbench顶层有个interface叫bus_if,连着DUT。你还有个driver的class。在top里,你写个 virtual bus_if vif = bus_if_inst; 然后把vif传给driver。driver里用vif.sig来读写。如果直接写bus_if_inst.sig,编译器会报错,告诉你class里找不到这个硬件。

    11小时前
  • EE学生一枚

    EE学生一枚

    简单来说,interface是硬件,virtual interface是指向硬件的指针。在module里可以直接用interface,但在class这种软件域里,必须通过virtual interface这个指针来间接访问硬件接口。

    最典型的必须用virtual interface的场景,就是你的driver、monitor这些验证组件是用class写的。因为SystemVerilog的class是动态的、软件的概念,它不能直接包含或例化一个硬件interface。所以你需要先在顶层module里把实际的interface例化好,然后通过uvm_config_db或者直接赋值,把这个interface的指针(即virtual interface)传递给class里的virtual interface变量。这样class里的代码就能通过这个指针去驱动和采样信号了。

    举个例子,假设你有个APB接口。你定义了一个apb_if interface,里面有时钟、复位、地址、数据等信号。在top_tb模块里,你会例化这个apb_if,并连接到DUT和时钟发生器。同时,你需要声明一个virtual apb_if vif; 并把它通过uvm_config_db::set(...)设置进去。在你的apb_driver class里,会声明一个virtual apb_if vif; 然后在build_phase通过uvm_config_db::get(...)拿到这个指针。之后driver里写驱动波形时,用的就是vif.paddr, vif.pwdata这些信号了。如果不用virtual interface,你的class里根本没法直接接触到真实的硬件信号线。

    所以,规则就是:在module里,用interface。在class里,用virtual interface。

    11小时前
我要回答answer.notCanPublish
回答被采纳奖励100个积分
FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训
请先登录