IC面试知识点之SystemVerilog部分

1. $display和$monitor的区别?
   (1) $display:主要起到一个打印数据的作用,将要打印的信息输出在仿真窗口中,可以在任何地方调用,
   (2) $monitor:起到一个监视器的功能,监视要输出的内容,当他有变化时才输出,输出在仿真控制台上创建一个监视器窗口,只能在模块中调用;
   一般使用$display来打印仿真过程中的一些信息,用$monitor来监视调试过程中的变量变化情况;

2. clocking block的作用?
   对于设计中的竞争问题,通常可以使用非阻塞赋值代替阻塞赋值来消除竞争问题。在验证仿真过程中,仍然也会存在时序竞争的问题,以下主要讨论在验证仿真中的时序问题。
   (1) 通过使用clocking block来实现采样和驱动与时钟的同步,消除竞争(这里主要是由于在时钟上升沿采样或者输出一个信号时,没有clocking的规定,系统不知道在上升沿到来之际,
       到底是采样原来的值还是上升沿变化后的值,同理也不知道到底驱动上升沿变化之前的值还是变化之后的值),
   (2) 在时钟边沿前采样(采样原来的值),在时钟边沿后驱动(驱动变化后的值)
   (3) 为什么会有多个时钟块:因为对于不同的组件,他的总线的输入和输出方向有可能是不一致的,因此针对这些不同的组件,应该添加不同的时钟块加以区分,这里的时钟块起到了
       类似modport的功能。
       在定义了clocking block时,需要设置该cb是在时钟上升沿还是下降沿采样,因此在程序中,只需要使用@intf.cb即可实现等待时钟边沿的效果
   (4) 接口中的logic和wire
       一般建议在接口中使用logic数据类型,因为wire类型只能使用连续赋值语句,但是连续赋值是同步的,如果要使用异步的赋值,那么就不能使用wire类型了;
       而logic不能有多个驱动源去驱动,因此,若涉及到多个驱动源驱动同一个信号,则需要使用wire类型
   (5) modport的用法:
       在定义cb时可以将信号进行分组,然后在例化模块传入接口时需要指明传递的是该接口哪一个modport,例如 module1 test(intf.modport1)
   (6) SV中仿真的timeslot,在SV中,数据的采样、驱动以及信号变化等都是在时钟沿上完成的,但是在软件的仿真环境中无法做到真正的并行执行,因此在一个时间片中划分不同的阶段
       来执行不同的操作。
       active区域     :执行设计的事件
       observa区域    :执行断言语句
       reactivate区域 :执行测试平台
       postponed区域  :所有设计都稳定后的信号采样时间
       因此,想要采样到稳定的设计的值,应该在时钟沿的上一个时钟片中的postpone区域采样(使用1step延时),然后在时钟沿后

3. SV中include和import的区别和联系:
   (1) import使用包路径。当某个package编译到lib后,处在同一个lib的文件就可以使用import语句将package里面的内容引用到文件里面(不同lib之间不能import),并且在仿真的过程中还能动态的去使用;
   (2) include使用相对路径或绝对路径,而相当于把外部的文件内容直接复制到当前文件中,不能动态使用

4. SV中的program块
   program是SV为了测试(非UVM环境)而准备的环境外壳。也因此,program中不可以出现硬件行为语句,例如always、module、interface和其它program例化;program对数据的采样会发生在
   reactive阶段即硬件变化后的稳定数据,从而避免采样竞争问题(数据不稳定);program也具备自动结束仿真的隐性方法,这也是module所不具备的。

5. $sformatf() / $sformat()函数
   $sformatf()直接返回一个格式化的字符串
   $sformat()需要传入第一个参数去接收字符串

6. case,casex 以及casez的区别
   (1) 在case语句中,敏感表达式中与各项值之间的比较是一种全等比较,每一位都相同才认为匹配。
   (2) 在casez语句中,如果分支表达式某些位的值为高阻z,那么对这些位的比较就会忽略,不予考虑,而只关注其他位的比较结果。
   (3) 在casex语句中,则把这种处理方式进一步扩展到对x的处理,即如果比较双方有一方的某些位的值是z或x,那么这些位的比较就不予考虑。

7. UVM的factory机制的重载使用的步骤
   factory的实现包含三步
    (1)注册:当定义一个类的时候,必须要对其类型进行注册。`uvm_component_utils()
    (2)实例化对象:在对 component或 object 型对象进行实例化的时候要使用静态方法,不能采用 new()去实例化。也就是要用如下实例化格式:
        object_name = class_type::type_id::create("object_name",this);
    (3)重载override:在需要override的时候,按照类型或者名称去override原来的对象。
         // 注意,这里的class是定义类时定义的类名,比如class my_driver extends uvm_driver,那么class就是my_driver,而不是定义类的构造函数时传进去的name属性;
         set_type_override_by_type(oringin_class::get_type(), new_class::get_type());
         // 以上代码等价于下面代码
         set_type_override("oringin_class_name", "new_class_name")

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值