当前位置:网站首页>【数字IC验证快速入门】13、SystemVerilog interface 和 program 学习

【数字IC验证快速入门】13、SystemVerilog interface 和 program 学习

2022-07-07 04:43:00 luoganttcc

导读:作者有幸在中国电子信息领域的排头兵院校“电子科技大学”攻读研究生期间,接触到前沿的数字IC验证知识,旁听到诸如华为海思清华紫光联发科技等业界顶尖集成电路相关企业面授课程,对数字IC验证有了一些知识积累和学习心得。为帮助想入门前端IC验证的朋友,思忱一二后,特开此专栏,以期花最短的时间,走最少的弯路,学最多的IC验证技术知识。

一、内容概述

interface

  • 1、验证平台(TestBench)和待验设计(DUT)的连接
  • 2、Verilog的端口连接方式和缺点
  • 3、SystemVerilog interface
  • 5、SystemVerilog clocking block

program

  • SystemVerilog program block

仿真(了解即可)

  • 1、仿真时间(了解)
    • 我们做EDA验证,更多的是做逻辑功能验证,不会去太多的关注时序(setup、hold等时序,后端STA会更多关心)。
  • 2、仿真时间域:timing region(了解)

二、验证平台与待测设计的连接

2.1、Verilog 连接方式

  • Verilog module ports

在这里插入图片描述

  • Verilog 语言使用端口名字连接各个功能模块
    在这里插入图片描述

在这里插入图片描述

  • 仲裁器:对于某一个东西,资源比较有限,如果多个人来申请,那就需要仲裁器来决定谁可以用!
  • logic 可以当做wire和reg的组合

隐式.*端口连接(实际使用还是不推荐使用

  • SystemVerilog .*可以自动匹配具有相同名字的线网和端口(灵活性差)
  • 自动匹配的名字必须具有相同的端口位宽
  • 连接的端口类型必须兼容

在这里插入图片描述

隐式.name连接(实际使用还是不推荐使用

  • .name 是使用端口名字连接的简化形式
  • .name 必须满足端口名字和位宽一致
  • .name 简化实例模块之间的连接

在这里插入图片描述

2.2、Verilog 连接方式

Verilog 的模块端口连接方式比较繁琐!Why?(有点勉强,单纯为了后面引出SV)

比如将一个信号request修改为request1

  • 需要修改所有模块的端口列表
  • 需要修改连接模块的所有端口列表
  • 需要修改所有的模块实例化的端口名字
  • 需要修改所有的层次化的端口的模块端口名字

如果忘记修改所有的端口名字,会出现编译错误。

在这里插入图片描述

  • SoC(System on Chip )大规模设计中Verilog的端口连接方式更加繁杂!
    在这里插入图片描述

  • 在多个模块中都需要声明相应的端口

  • 通信协议接口在多个模块中使用

  • 不匹配的声明会导致编译错误

  • 设计文档修改端口名之后需要修改所有模块

SystemVerilog 引入新的端口类型:interface

:interface更多的用在DUT和TB的连接!

2.3、SystemVerilog Interface

2.3.1、SystemVerilog Interface 简要介绍

  • interface 中集合了多个Verilog类型的信号,是一个独立的端口类型
  • interface 可以是一个独立的文件

在这里插入图片描述

2.3.2、 利用interface简化模块连接

在这里插入图片描述

2.3.3、如何使用interface中信号?

在这里插入图片描述

  • endmodule:test 仅仅是为了写给读代码的人看的,相当于注释!
  • 本身interface定义的信号是没有方向性的,是一个双向信号!

2.3.4、接口与端口的连接

  • 接口通过名字来引用信号

在这里插入图片描述

  • 上述arbitertest的例化方式是等效的!

2.3.5、interface modport

  • module port的简写
  • modport 为接口内部的信号提供不同的视角(DUT,Test Program)
  • 一个interface中可以提供任意数量的modport
  • modport只是声明连接模块的信号的端口方向:inputoutputinout(inout很少用!)

在这里插入图片描述

  • 在interface中声明的时候,位宽不需要只需要声明方向!

2.3.6、SystemVerilog interface 小结

  • interface的功能

    • 一组信号/线网
    • 独立的文件
    • 在interface中定义通信协议(很少用
    • 在interface中定义协议检查和验证函数:task、function、assertion(很少用
  • modport可以定义interface的不同视角(DUT,Test Porgram)

    • input
    • output
  • interface中不能包含设计的层次结构

    • interface中不能包含module模块的实例
  • interface可以用作设计的端口,具有可综合的特性(工程上还是更多的用Verilog综合,当然现在综合工具也在慢慢支持SV)

  • interface中可以包括含多个modport

2.4、Clocking

2.4.1、Clocking:激励的时序(1/8)(了解,不重要)

  • 没太大用,因为我们更多的是做逻辑功能验证,不会过多的关注时序!
  • 时序是跟用的具体器件信息的工艺有关系,这些延时信息在综合过程中才能体现,得到网表之后才会有时序,才会做STA。在RTL阶段不存在进行STA。

在这里插入图片描述

2.4.2、Clocking:激励的时序(2/8)

  • SystemVerilog 中使用clocking模块控制同步信号
  • 在interface中定义clocking模块,将信号同步到某一个特定的时钟
  • Clocking模块中所有信号都是同步驱动或采样,可以确保验证平台可以在正确的时间跟设计进行交互
  • Clocking模块主要使用在验证平台中,不能用作RTL设计
  • 一个interface中可以包含多个clocking模块

2.4.3、Clocking:激励的时序(3/8)(了解,不重要)

  • 当使用interface和clocking模块进行仿真时:
    • 从DUT的输出到TestBench的输入有1个延迟
      • 需要在Testbench的输入端添加一个“虚拟的同步器”
    • 从Testbench的输出到DUT的输入没有延迟

在这里插入图片描述

2.4.4、Clocking Skew(4/8)(skew了解,不重要)(学习下语法,在interface中定义)

  • 定义input和output skew,控制时序
    • input skew表示在时钟有效边沿采样信号的扭斜时间单位
    • output skew 表示在时钟有效边沿驱动信号的扭斜时间单位

在这里插入图片描述

  • 上面的代码是模拟一个D触发器的寄存输出,保证信号是同步的,保证激励是同一个时钟域的。

2.4.5、Clocking Blocks(5/8)(重要,学习下用法)

在这里插入图片描述

  • TEST中的 request 是在时钟的上沿发出来的!(信号同步到时钟的上升沿)
  • TEST中的 grant 是在时钟的上沿去采集,相当于寄存器打了一拍,延后一拍!
  • clk同步,相当于寄存器打了一拍,同步时钟域
  • @arbif.cb等待下一个时钟周期上沿,等效于@(posedge clk)
  • clock本身可以用其他方法替代,不是必须得有,比如上图右下角的写法还可以写成如下
@(posedge clk)
arb.TEST.request <= 2'b01;

 
  
  • 1
  • 2
  • 通常在实际使用中我们用上面这种替代方法更多,切记不要为了炫技而写代码
  • clocking功能其实并没有带来特别大的好处!
  • 一定要记住clockingmodport可选的!了解知识点即可,有其他方式等效替换

2.4.6、Clocking Block:信号同步(6/8)

在这里插入图片描述

  • @arbif.cb等效于@(posedge clk)
  • @等待的是一个信号变化(上下沿用posedgenegedge区分),wait等待的是一个电平
  • ##2等待2个时钟周期等效于repeat(n) @arbif.cb

2.4.7、Clocking Block:信号同步操作 (7/8)

  • 时序逻辑用非阻塞
  • 组合逻辑用阻塞
    在这里插入图片描述

2.4.7、Clocking 总结(8/8)

  • interface 中的clocking只用于验证平台,不能用于RTL设计

  • Clocking的好处

    • 显式指明同步时钟域
    • 验证平台驱动信号符合实际需求,保证同步行为
  • Clocking的功能

    • Interface可以包含多个clocking模块
    • 一个clocking模块只有一个clock
    • Clocking模块中的信号的方向与testbench有关

2.5、Program Block(干货)

2.5.1、Program Block(1/3)

  • Program 语句块执行验证平台代码
    • Program 语句块类似于module语句块,可以包含变量和其他module模块的实例化
    • Program 不能含有层次化的机构,如其他module或interface的实例

在这里插入图片描述

2.5.2、Program Block(2/3)

在这里插入图片描述

  • # 可以自己加时间单位;##x表示x个cb时钟周期,而cb用的posedge。

2.5.3、Program Block(3/3)

  • Program好处

    • 将验证平台和待测设计分隔开
    • Program用于执行测试用例(testcase)【面试重要】
    • Program用于封装与测试用例相关的数据【面试重要】
  • Program功能

    • 可以例化在任意的层次结构中
      • 通常是在最顶层文件中
    • 可以像module一样使用interface和端口进行连接
    • 没有module层次结构,只有class的层次结构
    • 可以有initial、task和function代码,但是不能存在always语句
    • 当Program中的initial语句执行到结束时,隐式执行$finish

注:对于仿真来讲,programmodule一样,唯一区别可能少写一个$finish。还是那句话,这也是可选的!并不是工程上一定会用到,更多的是为了知识体系的完整性!但是interface在工程上还是非常重要的,要特别重视。

2.6、验证平台 - 顶层文件top

  • 顶层示例,与下面的没有大关系
    在这里插入图片描述

2.6.1、RTL Design with Interface

在这里插入图片描述

  • ref 在SV中就是相当于inout
    • ref参数传递变量指针,而不是变量的值,参考C语言的指针,在Interface中用的不多!
  • 在实际中,RTL Design中用的Interface很少,这里仅仅举个例子!

代码示例框图关系:
在这里插入图片描述

2.6.2、Test Program with Interface

在这里插入图片描述

2.6.3、Connection between DUT & test with interface

在这里插入图片描述

  • Q:test和ctrl之间的信号是如何连接的?
    • A:通过在Interface中的modport定义好方向,便可以实现自动连接!

三、实践练习

3.1、编写DUT文件

arb.v

module arb(
  input  wire rst_n,
  input  wire clk,
  input  wire request,
  output reg grant
);

always @(posedge clk or negedge rst_n) begin
if(rst_n 1‘b0) begin
grant <= 1’
b0;
end
else if(request 1‘b1)begin
grant <= 1’
b1;
end
else if(request ==1‘b0)begin
grant <= 1’
b0;
end
end

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

3.2、编写Interface文件

arb_if.sv

interface arb_if(input bit clk);
  logic grant;
  logic request;
  logic rst_n;
  clocking cb @(posedge clk);
    input grant;
    output request;
  endclocking
  modport TB(
    clocking cb,
    output rst_n
  );
  modport dut(
    output grant,
    input request,
    input rst_n
  );
endinterface
  • DUT的port一般不会去用Interface的port,这个clocking只是针对在test环境中使用定义的!
    • clocking本质是模拟时钟沿,把信号打一拍进来。而DUT端口信号实际是不含时序信息的,进来之后如果要用时钟打拍,是用实际的电路,即实际的D触发器去打拍。不需要用模拟的时钟打拍!
    • clocking一般用在环境里面,模拟时钟打拍的同步时序;不是一定在test里面就要用clocking,灵活的应用,可以Interface里面没有clocking,在driver里面去通过时钟沿送数据;仅仅是语法上提供了选择
  • 关于DUT的modport要说的:DUT是不能用clocking block的,DUT是内部使用always逻辑去采的,故在端口上不能用cb。
  • 其实这里的modport dut没太大的用!

3.3、编写test文件

注:作用主要用来发送激励

test.sv

program test(arb_if.TB arbif);
  initial begin
    // Asynch drive rst_n
    arbif.cb.request <= 1'b0; arbif.rst_n <= 1'b1;
    #15 arbif.rst_n <= 1'b0;
    #35 arbif.rst_n <= 1'b1;
    #5;
    // Synch drive request
    arbif.cb.request <= 1'b1; wait(arbif.cb.grant == 1'b1);
    arbif.cb.request <= 1'b0;
    @arbif.cb; //@(posedge clk)
    @arbif.cb;
    @arbif.cb;
  end
endprogram 

3.4、编写TestBench文件

arb_tb.sv

module ARB_TB();
  bit clk;
  arb_if arbif(.*);// arb_if arbif(.clk(clk));
  test u_test(.*);
  arb u_arb(
    .rst_n (arbif.rst_n),
    .clk   (clk),
    .request (arbif.request),
    .grant (arbif.grant)
  );
  initial begin
    clk = 0;
    forever #10 clk = ~clk;
  end 
endmodule 
  • .* 会自动连接Interface里面的信号!

3.5、编译运行

因为只是写了test的激励,没有写monitior,也没有写自动化的比对Makefile,因此使用Questasim 来查看波形,打开命令如下

vsim &

 
  
  • 1

如果Questasim有已经启动工程,需要先关闭,然后使用GUI的方式新建工程。参考:【数字IC验证快速入门】6、Questasim 快速上手使用

按照如上链接新建、编译并开始仿真工程。

添加DUT的的波形,在sim窗口选中u_arb,选择Add Wave或者快捷键ctrl+w,如下图所示:

在这里插入图片描述

随后在Wave栏选择选择Run -ALL,出现是否结束的仿真,一定要选择NO,如下图所示:

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

可以对比DUT代码,查看波形,可以发现满足预期

原网站

版权声明
本文为[luoganttcc]所创,转载请带上原文链接,感谢
https://luogantt.blog.csdn.net/article/details/125637686