数字IC验证及设计问题汇总


日常遇到的问题及相应解决方法。

验证问题总结

uvm约束冲突问题

问题描述:case中采用randomize()with对激励进行随机化,但是会提示激励冲突。
问题原因:case中的为外部约束,而transaction属于内部冲突。外部所加约束与内部约束冲突,则看内部约束是否加了soft关键字,若加了则以外部约束为准,若没加则报错。
解决方法:需要外部约束是内部约束的子集来避免冲突,或需要外部约束覆盖内部约束则在内部加上soft关键字。

uvm_info基本用法

`uvm_info("ADDR", $sformatf("R addr = %0h", regmodel.R.get_address()), UVM_LOW);		//打印某个变量值,具体的格式为“%0h”定义的,可根据所需格式进行调整
`uvm_info("ADDR",{"\n",req.sprint()},UVM_LOW);   //可进行数据包的打印

uvm中的宏定义

`define val 10				//定义常数宏
var = `val +45;				//调用宏  sv中调用需要使用“`val”,

linux删除文件时提示占用,无法删除

问题描述:在跑case时,手动终止运行。再次跑case时需要删除之前的旧文件,会提示文件被占用。
问题原因:由于VCS仿真时需要对部分文件进行写操作,而手动ctrl+z后,这些文件仍然被占用,从而导致无法删除被进程占用的文件,也便无法执行新的操作。
解决方法:方法1:使用lsof + 报错提示的被占用的文件名;kill -9 +进程id 来解除占用;之后从新跑case即可。方法2:避免使用ctrl+z 此时会将进程挂起,而不是停止。应使用ctrl+c q来杀掉进程。

SV的repeat使用注意点

用法:repeat(n) begin coding end
说明:重复执行n次coding
例1如下,重复执行n次“@(posedge clk) cnt++;”
repeat(n) @(posedge clk) cnt++;

例2如下,重复执行n次“@(posedge clk);”然后再执行一次cnt++。
repeat(n) @(posedge clk); cnt++;

注意点:可以使用分号来划分需要重复执行的代码块,但是推荐使用begin end显示指定需要重复执行的代码块。单条语句可使用分号,多条则使用begin end。如例1和例2,很容易使人误解。

SV数据采集问题

UVM验证时,出现有参考模型的输出数据,但是采集不到DUT的输出数据(部分能采到,部分采不到)。
处理思路:1.查看DUT输入数据是否缺失(通常不会缺失);2.monitor中数据采集的条件是否和DUT对应,保证完成计算后能采集到结果。

多信号采同一数据

多个信号中任意一个的上升沿采集数据
处理思路:采用fork join_any将多个信号的上升沿触发事件写入不同的分支,当任意一个触发则跳出,执行后续的数据采集操作即可。

批量kill进程

进行case回归时,若出现case一直running无法正常结束。可通过强制杀死进程后对相应case进行调试。
命令如下:
ps -ef | grep username | grep progressname | grep -v grep | cut -c 9-15 | xargs kill -9

说明:
ps -ef :用标准的格式显示进程
grep username |grep progressname | grep -v grep:搜索username起的progressname的部分,且排除grep命令的那个进程
cut -c 9-15: 选取grep结果的9-15列,具体根据username的长度,保证截取到pid那一部分
xargs kill -9 :对选取到的pid对应进程进行kill操作

注意:
由于可能出现多个running,kill掉当前的几个后其余的也会逐次拉起,可通过统计running的个数,然后循环执行该命令。采用shell脚本实现,效率更高。

带看门狗的wait

问题描述:wait用来等待事件,case跑飞。
问题原因:当直接使用wait,若出现事件等待不到的情况则case无法执行下去,出现异常!
处理思路:在wait时加入看门狗,设置等待时间,若超时无法等到则打印错误并结束case。
示例:

  task wait_with_watch_dog;
    fork
    	begin
    		wait(dut_if.signal);
    		disable wait_with_watch_dog;
    	end
    	begin
    		#10ms;
    		`uvm_fatal(“message_id”, “message_string”) 
    	end
    join_any 
  endtask wait_with_watch_dog

task注意点

问题描述:采用带输入的task来检测信号变化时,信号变化但是无法传入。
问题原因:task调用时,传入的信号值为task起来时那个时刻的值信号值,在task内部是保持不变的,因此若task起来时的值不满足等待条件,则时钟无法等到。
处理思路:参考带看门狗的wait部分,直接将信号在task内部调用,则该值会随着信号变化而变化,不会出现不变的情况。

verdi查看波形

推荐方式:不同波形在不同波形窗口查看,在同一波形窗口载入不同的波形文件容易搞混,且不利于定位。
示例

通过宏压缩仿真时间

问题描述:进行数模混合混仿时,按照实际时长仿真的结果太慢
处理思路:可采用宏编译进行时间压缩。
示例:原设计需要计数到100需要100个cycle,而通过条件编译,则将计数减少到10。在系统时钟不变情况下,可将仿真时间缩短10倍。

`ifdef FLAG
	parameter cnt=10;
`else
	parameter cnt=100;
`endif

注意:保证设计功能的情况下进行压缩

VUM transaction约束数组

rand byte pload[];
constraint   pload_cons {
    foreach(pload[i]) {
      pload[i] inside {[1:255]};
    }
    pload.sum < 1024;
    pload.size() inside {[1:8]};
  }
  //动态数组pload,可通过foreach约束pload中每个元素的值,和整个数组的sum和还有size大小,条件同时成立

注意点:
1、对于数组需要foreach来对其中元素进行约束

UVM field autimation常用函数

对于uvm field automation机制,常用的函数包括:
1.uvm_field int:用于注册整型变量
2.uvm field_bool:用于注册布尔型变量
3.uvm_field_enum:用于注册枚举型变量
4.uvm_field_string:用于注册字符串型变量
5.uvm_field_object:用于注册对象型变量
6.uvm field_array:用于注册数组型变量
7.uvm_field_array_int:用于注册整型数组变量
8.uvm_field_array_string:用于注册字符串数组变量
注意:
1、根据变量类型使用对应的注册函数!!
2、定义整型数组时,通过uvm_field_array_int进行注册,只能注册一维数组,多维数组需要手动复制

VUM环境卡在0时刻常见原因

1,使用uvm phase调试功能,看卡在哪个phase的哪个组件; 2,查看各个组件中是否有零延时的无限循环导致无法退出,程序无法向下执行,一般在driver或者monitor的无限循环体中。

uvm_do,uvm_do_with, randomize() with{}的区别

uvm_do:直接发送transaction的包
uvm_do_with:在发送transaction时,进行约束
randomize:对数据进行约束
示例:

bus_trans tmp;	//声明
tmp=new();          //创建对象
tmp.randomize() with{data==10}  //带约束的随机化

event用法注意

作用:通过event进行线程通信
用法:触发: -> (非阻塞);等待:@ or wait(阻塞)
注意:-> 和@搭配,需要先@再->;-> 和wait搭配,先后顺序均可

SV参数传递-ref,input,output

input:不会修改传入参数,仅仅将其传进去。调用结束之后,函数里面的值就被丢弃了。
output:先新建,然后对新建的目标处理,最后将指针指向该目标。将函数里面的值传递到函数外面来,调用结束之后,函数外面的值就丢了。
ref:类似更新(SV中常用该写法),函数内部和外部看到的是同一份值,哪里改都会改。
参考链接:https://blog.csdn.net/qq_41467882/article/details/121684326

UVM验证的前门访问与后门访问

  • 前门访问
    通过正常的总线协议对寄存器进行访问
  • 后门访问
    不通过DUT总线对寄存器活内部存储器进行读取操作都是后门操作。
    优势:所有后门访问操作都是不消耗仿真时间(即$time打印的时间)而只消耗运行时间的。
    劣势:不同于前门访问操作都可以在波形文件中找到总线信号变化的波形及所有操作的记录,后门访问操作则无法在波形文件中找到操作痕迹。调试难度会增加。
    访问方式:1、使用interface进行后门访问操作;2、DPI+VPI;3、UVM提供两类后门访问的函数:一是UVM_BACKDOOR形式的read和write,二是peek和poke。这两类函数的区别是,第一类会在进行操作时模仿DUT的行为,第二类则完全不管DUT的行为。

virtual的task与function

当将子类b的句柄B赋值给父类a的句柄A后,virtual的task/function将会直接索引到子类中同名task/function,而没有virtual的task/function则继续索引父类的。

task的disable注意点

在这里插入图片描述
多次调用的task A中某一个被disable后,所有的task A将会被disable。

子类与父类同名的对象方法的优先级

缺省子类会对其重写,若需要调用父类的同名方法,使用super即可。

event和uvm_event区别

eventuvm_event
类型单纯的一个类型,声明即可类,需要创建或拿到句柄
触发方式->trigger(),若要再次触发则需要先reset()
等待方式@ / waitwait_ptrigger() (电平触发)和wait_trigger()(上升沿触发)
携带信息仅表示事件出发,无额外信息通过方法wait_trigger_data()或wait_ptrigger_data()来获取事件触发时写入的数据对象
等待进程数无法获得get_num_waiters()获取等待它的进程数
句柄获取方式无需通过资源池获取共享的对象句柄,避免依赖
引用方式绝对路径通过资源池

event是uvm_event的基础,并在此基础上进行扩展。

示例链接可参考:https://www.cnblogs.com/csjt/p/15561286.html

设计问题总结

有符号数赋值问题

有符号数进行运算时,结果为有符号数;
无符号数进行运算时,结果为无符号数;
混和运算时,无符号优先级高,结果为无符号数;
在给有符号类型变量赋值无符号数,该有符号类型变量当作无符号数处理。

大端模式与小端模式

硬件存储数据规律:地址递增
大端模式:先存高比特(即高比特存放在低地址)
小端模式:先存低比特(即低比特存放在低地址)

APB基本概念

HBRUST:突发传输,传输的个数。分为单拍突发、未定长度突发、固定长度突发,固定长度突发包括INCR突发(递增)和WRAP突发(回卷),长度有4拍、8拍和16拍。
HSIZE:单个数据传输的大小。计算方式为8*(HSIZE+1)。

设计规范

1、逻辑判断使用单比特!

时序分析

三个有效起点:输入端口,寄存器Q以及黑盒模块的输出端口
三个有效终点:输出端口,寄存器D以及黑盒模块的输入端口
交叉组合为对应的path
时序约束:有时钟则约束时钟频率,无时钟则约束输入输出端口。
set_max_delay x -from [all_inputs ] -to [all_outputs] 常用于纯组合逻辑的时序约束。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值