当前位置:   article > 正文

数字IC验证面试题

数字ic验证面试题

文章目录

一、systemVerilog数据类型

1.1 队列的操作

  • queue_name.size //返回queue的大小
  • queue_name.insert(index,item) //在index索引处插入item元素
  • queue_name.delete(index) //刪掉某元素或整个queue
  • queue_name.pop_front() //去除第一个元素(队首)
  • queue_name.pop_back() //去除最后一个元素(队尾)
  • queue_name.push_front() //插入元素到queue(0)(队首)
  • queue_name.push_back() //插入元素到queue($)(队尾)

1.2 队列和各种数组之间的关系

数据类型物理内存索引
固定数组编译时创建,之后不能修改数字
动态数组仿真时创建,仿真期间可以改变数字
队列仿真时push-pop可以改变队列大小数字
关联数组仿真时分配内存数字、字符串、类
  • 动态数组:可以在仿真时分配空间或者调整宽度,这样仿真中就可以使用最小的存储空间。
  • 关联数组:用来保存稀疏矩阵的元素,当一个非常大的地址空间进行寻址时,sv只对实际写入的元素分配空间,比定宽数组和动态数组所占用的空间要小得对。
  • 队列:结合了链表和数组的优点,可以在队列的任意位置增加或者删除元素,这类操作在性能上比动态数组小得多,可以通过索引对任意元素进行访问。

1.3 mailbox和queue的关系

  • mailbox必须通过new()例化,而队列只需声明
  • mailbox可存储不同数据类型(不建议),队列只能存储相同类型的数据
  • mailbox中的put()和get()是阻塞方法。而队列对应的存取方式为push_back pop_front()为非阻塞,会立即返回 ,在使用queue取数时应先填写 wait(queue.size()>0)。此外,还需注意,如果调用阻塞方法应使用task,非阻塞方法既可以用task也function
  • 对于变量操作,在传递形式参数时,mailbox传递的是指针。而queue的形式参数声明是ref方向

二、Verilog时序电路

2.1 数字电路主要分为哪几类?为什么使用触发器或锁存器?

数字电路主要分为两类:1)组合逻辑电路;2)时序电路;使用触发器的原因:用触发器是因为触发器能保存数据,保存电路状态;触发器是在时钟边沿触发,用时钟同步是让整个电路能同步整齐划一的工作;乘法器的计算部分是组合逻辑,不需要触发器,计算后的结果可以用触发器保存起来。具体为什么使用触发器?

2.2 setup/hold violation

setup和hold violation

2.3 亚稳态的原因以及消除方法有哪些?

亚稳态以及消除方法

2.4 阻塞赋值与非阻塞赋值的区别与联系是什么?

  • 阻塞赋值:在always块中,后一句赋值要等到前一句执行完成之后才开始。
  • 非阻塞赋值:1)赋值开始时刻,计算所有非阻塞赋值语句右边表达式(RHS)的值。2)赋值结束时刻,更新所有左边表达式(LHS)的值。非阻塞只能用于寄存器的赋值,只能用在initial/always 过程块中。非阻塞不可以用于连续赋值。

2.5 触发器与锁存器的联系与区别?如果锁存器高电平来说建立保持时间是怎么样的?

触发器与锁存器的联系与区别
(1) 寄存器是同步时钟控制,而锁存器是电位信号控制。锁存器一般由电平信号控制,属于电平敏感型。寄存器一般由时钟信号控制,属于边沿敏感型。
(2) 寄存器的输出端平时不随输入端的变化而变化,只有在时钟有效时才将输入端的数据送输出端(打入寄存器),而锁存器的输出端平时总随输入端变化而变化,只有当锁存器信号到达时,才将输出端的状态锁存起来,使其不再随输入端的变化而变化。
可见,寄存器和锁存器具有不同的应用场合,取决于控制方式以及控制信号和数据之间的时间关系:若数据有效一定滞后于控制信号有效(锁存信号(控制信号)来了以后,才将输出端的状态/数据锁存起来),只能使用锁存器;如果数据提前于控制信号而到达且要求同步操作,则可以用寄存器来存放数据。
换言之,控制信号/时钟信号先来,数据后来,用锁存器;
控制信号/时钟信号后来,数据先来,用寄存器。

Latch的建立时间与保持时间。
锁存器的建立和保持时间是以最后CLK高电平消失时间点为基准的,如下图所示:

建立时间(tsetup):
建立时间是在CLK高电平消失之前的最小建立时间
保持时间(thold):
建立时间是在CLK高电平消失之后的最小保持时间
TClk-Q:是CLK电平触发时到数据Q改变时的延时。
tD-Q:电平触发期间,输出由数据输入D改变到输出Q改变的延时。

在Latch的输入开关断开和环路开关闭合时,有效的D输入信号在跳变前(建立时间)和跳变后(保持时间)的短时间内不能发生变化。以保证数据被锁存。
寄存器和锁存器的建立保持时间
在这里插入图片描述

2.6 跨时钟同步

添加链接描述

2.7 P_MOS和N Mos晶体管是怎么连接的

三、sv线程通信

3.1 fork…join有哪三种呢?具体的区别和联系是什么?如何关闭fork进程和等待进程?

  • fork...join块内的线程必须执行完才能开始该块后面的语句;
  • fork.....join_none块内、块外同时执行,块后的线程不必等块内线程结束。通常使用该语句来产生线程
  • fork.....join_any只要块内的线程有一个执行结束,就执行块之后的线程,块内的也继续执行。通常使用该语句实现线程同步
    如果想要关闭fork进程可以使用disable fork,下面是使用实例:
initial begin
  fork
    task1; // Process 1
    task2; // Process 2
  join_any
  $display(“One of task1/2 completed ”);
  disable fork;
  $display(“All other tasks disable now”);
end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

3.2 event、mailbox、semaphore的联系与区别?

  • event:最小信息量的触发。可以用作事件的触发,也可以组合多个event做线程之间的同步,控制线程之间的序列;
  • mailbox:类似FIFO,数据传输的媒介,在线程之间做数据通信或内部数据缓存时可以考虑此元素。
  • semaphore:共享资源管理,多个线程访问某一个公共资源时可以使用这个要素;

3.3 event、mailbox、semaphore常见的使用方法?

  • event是静态的同步对象句柄,翻译翻译就是句柄一般可以是不同对象,是一个动态的,这里的even是一个静态的,只是指明一个事件可以用于线程同步,可以被赋值给其他事件,这样两个事件句柄会指向同一个对象,触发任意一个句柄就触发这个事件;可以传递给队列function和task。触发:->even_handle,等待:@ or wait(even_handle.triggered)
  • mailbox的使用方法
Methoddescription
new()creat a mailbox
put()place a message in a mailbox
try_put()try to place a message in a mailbox without blocking
get()/peek()retrieve a message from a mailbox
num()returns the number of messages in the mailbox
try_get()/try_peek()try to retrieve a message from a mailbox without blocking
  • semaphore的使用方法
Methoddescription
new()creat a semaphore with a specified number of keys
get()obtain one or more keys from the bucket
put()obtain one or more keys from the bucket
try_get()try to obtain one or more keys without blocking

四、覆盖率

4.1 覆盖率的分类有哪些?具体都有什么含义?

  • 代码覆盖率:衡量有多少行代码已经被执行过了,和穿过代码和表达式的路径中有哪些已经被执行过了哪些单比特变量的值为0、1,以及状态机中的哪些状态转化已经被访问过;
  • 功能覆盖率:与spec比较发现design是否行为正确,需要按照verification plan来比较进度,用来衡量哪些设计的特征已经被测试程序测试过的一个指标;
  • 断言覆盖率:用于检查几个信号之间的关系,常用于查找错误,主要是检查时序上的错误,测量断言被触发的频繁程度;

4.2 为什么会出现代码(功能)覆盖率低的现象?

  • function coverage高,code coverage低:可能因为验证计划不完整,测试没有执行设计的所有代码,应该回到硬件的设计spec并且更新验证计划,然后需要增加更多针对为测试功能的功能覆盖点;
  • function coverage低,code coverage高:即使测试平台很好地执行了设计地所有代码,但是没有把它定位到所有有兴趣的状态上;首先,查看design是否实现了所有功能,如果功能有了,但是测试不到,可能需要一个形式验证工具来提取设计状态并创建适当的激励

五、SVA断言

5.1断言有哪几类?它们的联系与区别是什么?

  • 立即断言:在当前仿真时间检查条件,类似于if…else语句,单数断言带有控制,立即断言必须放在过程快定义中。
    关于他们的联系与区别
  • 并行断言:可以认为是一个连续运行的模块,在整个仿真过程检查信号,所以需要在并发断言内指定一个采样的时钟。并发断言旨在时钟沿才会执行;可以在过程块、module、interface和program块内定义并发断言。
    序列sequence编写,将多个信号的关系用断言中特定的操作符进行表示;
    属性property的编写,它可以将多个sequence和多个property进行嵌套,外加上触发事件;
    assert的编写,调用property就可以。编写完断言后我们可以将它用在很多地方,比如DUT内部,或者在top层嵌入DUT 中,还可以在interface处进行编写,基本能够检测到信号的地方都可以进行断言检测。

六、面向对象OOP

6.1 在SV中体现OOP在哪里?

  • 封装:类的封装特性使得类可以根据需要来确定外部访问的权限级别,一般可以将变量声明为以下三种形式:1)public:子类和外部均可以访问(默认);2)protected:只有当前类或者子类可以访问,外部无法访问;3)local:只有当前类可以访问,子类和外部均无法访问;
  • 继承:类的继承特性使得子类可以使用父类的成员变量(variable)或方法(method),当我们在子类实例上调用某一个变量或者方法时,分两种情况说明:1)子类中没有同名的变量或方法,那么编译器会去父类中查找该变量或方法并且使用它。也就是说:在子类中可以直接使用父类的变量和方法。2)子类中有同名的变量或方法,那么在子类中通过super.value或者super.method的方法才能使用父类的变量或方法。如果不使用super., 会默认使用子类中的变量或方法,那么相当于父类中的变量或方法会被子类覆盖掉
  • 多态:多态是为了实现接口的重用。在SystemVerilog中,子类和父类之间多个子程序使用同一个名字的现象
    关于OOP

6.2 浅拷贝(shallow copy)和深拷贝(deep copy)

浅拷贝可以使用列表自带的copy()函数(如list.copy()),或者使用copy模块的copy()函数。深拷贝只能使用copy模块的deepcopy(),所以使用前要导入:from copy import deepcopy
如果拷贝的对象里的元素只有值,没有引用,那浅拷贝和深拷贝没有差别,都会将原有对象复制一份,产生一个新对象,对新对象里的值进行修改不会影响原有对象,新对象和原对象完全分离开。
如果拷贝的对象里的元素包含引用(像一个列表里储存着另一个列表,存的就是另一个列表的引用),那浅拷贝和深拷贝是不同的,浅拷贝虽然将原有对象复制一份,但是依然保存的是引用,所以对新对象里的引用里的值进行修改,依然会改变原对象里的列表的值,新对象和原对象完全分离开并没有完全分离开。而深拷贝则不同,它会将原对象里的引用也新创建一个,即新建一个列表,然后放的是新列表的引用,这样就可以将新对象和原对象完全分离开。

6.3 virtual的作用以及

七、随机化

7.1 rand与randc有什么区别与联系?

  • rand:随机变量的值在指定范围内均匀分布,如果不添加约束,随机变量的值可以是指定范围内的任何值。;
  • randc:随机变量重复出现范围内的所有值,在一次循环过程中不会出现相同的数值。类比抽扑克牌。

7.2 常用随机化约束有哪些?

  • $random —— 系统随机化调用函数,返回32bit有符号数;
  • $urandom() —— 系统随机化调用函数,返回32bit无符号数;
  • $urandom_range()—— 系统随机化调用函数,返回指定范围内的无符号随机整数;
  • srandom() —— 对象和线程(手动添加种子seed)的随机化方法;
  • randomize() —— 对象的随机化方法;
    常用随机化约束

八、interface

8.1 使用interface的好处有哪些?

  • 接口便于设计重用,当两个块之间有两个以上的信号需要连接,并且使用特定的协议进行通信时应该使用接口;
  • 接口可以用于替代原来需要在模块或者程序中反复声明并且位于代码内部的一系列信号,减少连接错误的可能性;
  • 要增加新的信号时,只需要在接口中声明一次,不需要再更高层的模块中共声明,减少错误;
  • modport允许一个模块很方便的将接口的一系列信号捆绑在一起,也可以为信号指定方向以便工具自动检查;

8.2 clocking block用法是怎么样的?它跟setup/hold time violation 有什么不一样?

clocking block用法

8.3 关于@(posedge clk)和@(itf.cb)的区别

关于@(posedge clk)和@(itf.cb)的区别

8.4 virtual interface的好处,与virtual sequencer的区别

virtual interface是在仿真运行时才连接到DUT上,如果只是interface,在编译时就必须进行连 接,在class中时是automatic,在运行的时候产生; virtual interface主要完成接口的动态分配,只要在top层定义virtual interface,其他层不需要 改变,直接通过interface传递参数即可; 消除绝对路径,避免修改的时候改很多东西## 九、常见代码学习

9.1 return、continue、break的用法?

return:function返回值,task返回控制,
continue:本次循环后面的语句不执行,执行下一次的循环
break:循环会不继续进行了。具体

9.2 task和function的区别

  • function能调用另一个function,但不能调用task。task能调用另一个task,也能调用另一个function
  • function总是在仿真时刻0就开始执行 task可以在非零时刻执行;
  • function一定不能包含任何延迟、事件或者时序控制声明语句。task可以包含延迟、事件或者时序控制声明语句
  • function至少有一个输入变量,可以有多个输入变量。task可以没有或者多个输入(input)、输出(output)和双向(inout)变量
  • function只能返回一个值,function不能有输出(output)或者双向(inout)变量 task不返回任何值,任务可以通过输出(output)或者双向(inout)变量传递多个值

9.3 automatic与static的区别与联系

automatic与static的区别与联系

9.4 如何使用ref

如何使用ref

十、验证思想

10.1 debug的常用手段

通过断言、verdi查看波形、log打印等进行debug;

10.2 验证的完备性

  • 首先不可能百分百完全完备,即遍历所有信号的组合,这既不经济也不现实。
  • 所以只能通过多种验证方法一起验证尽可能减少潜在风险,一般有这些验证流程:ip级验证、子系统级验证、soc级验证,除这些以外,还有upf验证、fpga原型验证等多种手段。
  • 前端每走完一个阶段都需要跟设计以及系统一起review验证功能点,测试用例,以及特殊情况下的波形等。
  • 芯片后端也会做一些检查,像sta、formality、DFM、DRC检查等,也会插入一些DFT逻辑供流片回来测试用。流片归来进行测试,有些bug可以软件规避,有些不能规避,只能重新投片

10.3 验证流程,验证环境怎么搭

  • 看spec文档和协议,将DUT的功能和接口总线时序搞明白
  • 制定验证计划和测试点分解
  • 写VIP或者是用别人给的VIP,搭建验证环境和TB,包括各种组件,各个模块的pkg,基础的 sequence还有test,暂时先就写一两个基础的 sequence,然后还有一些环境配置参数的确定等,最后能够将TB正常运行,保证无误;
  • 根据测试点编写sequence和 case,然后去仿真,保证仿真正确性,收集覆盖率;
  • 分析收集的覆盖率,然后查看覆盖率报告去分析还有哪些没有被覆盖,去写一些定向case,和更换不同的seed去仿真;
    回归测试regression,通过不同的seed去跑,收集覆盖率和检测是否有其它bug;

十一、sequence

11.1 m_sequencer和p_sequencer的关系

添加链接描述

(持续更新…)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/938685
推荐阅读
相关标签
  

闽ICP备14008679号