赞
踩
常见的仿真工具如下:
补充:综合工具:
逻辑综合就是把设计实现的RTL代码映射到特定的工艺库(不同的库中门电路的基本标准单元standard cell的面积、时序参数不一样)上,输出成门级网表Netlist。
代码检查工具:nlint, spyglass,Verdi等
知道SOC系统中各个IP的基本功能;
该芯片是一个SOC芯片,主要功能是实现无线通信和数据存储的功能,主要运用场景在数据相机的存储卡。
无线通信功能通过APB总线上的SPI接口外挂一个WiFi芯片与手机相连,实现无线通信和数据传输功能。
数据存储功能主要通过NandFlash控制器,实现存储功能。但是该芯片采用了替换方案,使用了SD_Host接口,外接SD卡的方式进行数据存储。
典型的应用场景:数码相机拍照时,将照片通过SDC(SD memory Controller)控制器接口,放入SRAM暂存,最后通过SD Host接口,将照片存储到外接的SD卡中。然后,手机或PC端用户可以连接到WiFi上,通过手机下载SD memory存储卡中存放的视屏或照片到手机或者电脑上。
名词解释:MCU、IRQ、USB、BIOS等
WDT:Watchingdog Timer,中文名看门狗,是一个定时器电路,一般有一个输入,俗称喂狗,一个输出到MCU的RST(复位)端,MCU正常工作的时候,每隔一段时间输出一个信号到喂狗端,给WDT清零,如果超过规定的时间不喂狗(一般在程序跑飞时),WDT定时超出,就会给出一个RST信号到MCU,使MCU复位,防止MCU死机,看门狗的作用就是防止程序发生死循环,或者说程序跑飞。
工作原理:在系统运行以后也就启动了看门狗的计数器,看门狗就开始自动计数,如果到了一定的时间还不去清看门狗,那么看门狗计数器就会溢出从而引起看门狗中断,造成系统复位。所以在使用有看门狗的芯片时要注意清看门狗。
DMA:DMA(Direct Memory Access,直接内存存取),一个完整的DMA传输过程必须经过DMA请求、DMA响应、DMA传输、DMA结束4个步骤。
1)请求:CPU对DMA控制器初始化,并向I/O接口发出操作命令,I/O接口提出DMA请求。
2) 响应:DMA控制器对DMA请求判别优先级及屏蔽,向总线裁决逻辑提出总线请求。总线裁决逻辑输出总线应答,表示DMA已经响应
3)传输:DMA控制器获得总线控制权后,CPU即刻挂起,由DMA控制器输出读写命令,直接控制RAM与I/O接口进行DMA传输。
3)结束:当完成规定的成批数据传送后,DMA控制器即释放总线控制权,并向I/O接口发出结束信号。当I/O接口收到结束信号后,一方面停 止I/O设备的工作,另一方面向CPU提出中断请求,使CPU从不介入的状态解脱,并检查本次DMA传输操作正确性。
DMA传输方式无需CPU直接控制传输,通过硬件为RAM与I/O设备开辟一条直接传送数据的通路,使CPU的效率大为提高。
Timer:SOC内部的时钟由于温度、电磁以及各种自身因素使得其精度很低,所以不适合做计数使用,使用硬件计数电路Timer计数时间精度更高,一般可达到ns级。
整个IC设计流程宏观上主要包括四个阶段:
前端设计:RTL——>Netlist过程大致如下所示:
后端设计:Netlist——>GDSII过程如下:
参考:https://blog.csdn.net/lovenankai/article/details/5894616
在组合电路中,某一输入信号经过不同的途径传播后,由于路径延迟不同,使得到达电路中某一个逻辑门会合点的时间有先有后,这种现象叫做竞争;由于由竞争而产生的尖脉冲或者说毛刺就叫做冒险。
判断方法:1)、代数法:如果布尔表达式中有相反的信号则可能产生竞争和冒险的现象。如果表达式为:F=A+A’,就会产生"1"冒险;F=A*A’,就会产生"0"冒险。
2)、卡诺图:有两个相切的卡诺圈并且相切处没有被其他卡诺圈包围,就有可能出现竞争冒险;
3)、 实验法:示波器观察。
消除方法:1)、接入滤波电容;、消除毛刺影响;
2)、利用可靠性编码;
3)、可以在表达式中添加增加冗余项消除逻辑冒险。
阻塞赋值 | 非阻塞赋值 | |
---|---|---|
符号 | = | <= |
执行顺序 | 顺序执行 | 并发执行 |
应用 | 组合逻辑块 | 时序逻辑块 |
//(1)、0延时非阻塞赋值 -> 并发 initial begin forever begin #10ns clk_3 = ~clk_3; end //等价begin #10ns clk_3 <= ~clk_3 end end integer data,data_1; integer data_2,data_3; always@(posedge clk_3) begin data <= 1'b1; //非阻塞赋值->并发 data_1 <= data; end always@(posedge clk_3) begin data_2 = 1'b1; //阻塞赋值->顺序 data_3 = data_2; end //(2)、带延时非阻塞赋值 -> 顺序 initial begin #20ns data <= 1'b1; //非阻塞赋值-> 顺序 #30ns data_1 <= data; end initial begin #20ns data_2 = 1'b1; //非阻塞赋值-> 顺序 #30ns data_3 = data_2; end
latch的产生代码方式: 方法1 module top_module ( input d, input ena, output q); assign q=(ena)?d:q; endmodule 方法2 module top_module ( input d, input ena, output reg q); always @(*)begin q <= (ena) ? d : q; end endmodule 方法3 module top_module ( input d, input ena, output reg q); always @(*)begin q = (ena) ? d : q; end endmodule
建立时间:触发器(DFF)时钟上升沿到来之前,数据需要保持稳定的最小时间间隙就是建立时间。
保持时间:触发器(DFF)时钟上升沿到来之后,数据需要保持稳定的最小时间间隙就是保持时间。
考虑触发器的结构(会画);
当时钟Cp由0跳变到1,C=1,C`=0,使TG1断开,从而切断了D端与主锁存器的联系,同时TG2导通,将反相器G1的输入端与G2的输出端连通,主锁存器会锁存Cp跳变前D端的数据(如果此时D没有保持稳定,则会造成亚稳态)。这是TG3导通,TG4断开,~Q信号进过反相器G3传送到Q端。
提示:异步时钟域信号的跨时钟域同步。包括单比特和多比特,对于单比特自然用两级寄存器同步最为方便。对于多比特,常考察异步FIFO以及握手方法。要理解亚稳态的概念以及避免亚稳态的方法。
参考CDC章节。
当时钟上升沿检测到复位信号,执行复位操作(有效的时钟沿是前提)。always @ ( posedge clk );
它是指无论时钟沿是否到来,只要复位信号有效,就对系统进行复位。always @ ( posedge clk or negedge rst_n );
时钟门控clock gating(画出电路结构图),了解DVFS,多阈值电压技术,多电压技术等。
参考低功耗章节:
时钟门控(clock gating):在数据无效时,将寄存器时钟关闭的技术,能够有效降低功耗
, 是低功耗设计的重要方法之一。在寄存器的输入数据无效时,将寄存器的输入时钟置为0,而此时寄存器值保持不变,此时没有时钟翻转,避免了动态功耗
。
DVFS(Dynamic Voltage and Frequency Scaling)动态电压频率调节
本质上是一种自适应的电压频率调节技术,目的是根据的芯片当时的实际功耗需要设定工作电压和时钟频率,这样可以保证提供的功率既满足要求又不会性能过剩,从而可以降低功耗。
多阈值电压技术:不同器件阈(yu)值电压Vth对应的器件其漏电流Leakage负相关。低阈值电压标准单元:速度快、泄漏功耗高;高阈值电压标准单元:速度慢、泄漏功耗低。在不同的时序路径上使用不同阈值电压的标准单元来降低漏电流,可以达到降低漏电功耗的目的。
多电压技术:是指将不同逻辑模块处于不同的电源域中,由不同供电电源供电。工作频率要求高的系统或者模块使用高电压,对于工作频率要求不高的相应的低电压也称Normal电压,从而实现低功耗的目的。
Moore状态机的输出只与当前状态有关。
Mealy状态机的输出不仅与当前状态有关,还与当前输入有关。
同步fifo读写时钟相同,异步fifo读写采用不同的时钟
。 FIFO 是一种先进先出的数据交互方式,相当于一个RAM存储模块。同步FIFO的写时钟和读时钟为同一个时钟(同一个时钟域),由三大部分组成:FIFO写逻辑控制、 FIFO读逻辑控制、FIFO存储体(如Memory,reg等)。
FIFO的空满可以通过计数器Counter判断,遵循空不能读、满不能写
的原则。
assign full = (counter == F_DEPTH)?1:0;
assign empty = (counter == 'h0)?1:0;
也可以通过扩展地址最高位判断空满
。
(空:扩展位相同,有效地址位也相同; 满:扩展位不同,有效地址位相同)
assign empty = (w_addr_1==rd_addr_1)?1:0; //地址判断
assign full = ((w_addr_1[ADDR]!=rd_addr_1[ADDR]) && (w_addr_1[ADDR-1:0]==rd_addr_1[ADDR-1:0]))?1:0;
异步FIFO读写时钟不相同
,异步FIFO除了存储体、读写逻辑控制
,还包括了格雷码转换和时钟同步部分。
异步FIFO采用扩展地址位的方式对FIFO进行读写计数,判断空满。因为格雷码是镜像对称的,若只根据最高位是否相同来区分是读空还是写满是有问题的。实际判断空满:
当最高位和次高位相同,其余位相同认为是读空
;当最高位和次高位不同,其余位相同认为是写满
; /*二进制转化为格雷码计数器*/
assign gray_rdaddress = (rdaddress >>1) ^ rdaddress;//(({1'b0,rdaddress[9:1]}) ^ rdaddress);
/*二进制转化为格雷码计数器*/
assign gray_wraddress = (({1'b0,wraddress[9:1]}) ^ wraddress);
assign fifo_empty = (gray_rdaddress == sync_w2r_r2); //1. 格雷码所有bit位均相同
assign fifo_full = (gray_wraddress == {~sync_r2w_r2[9:8],sync_r2w_r2[7:0]}); //高两位不同,其余位相同
空满时的同步问题:
解决方法:两级寄存器同步 + 格雷码转换
(1)将写时钟域的写指针同步到读时钟域
,将同步后的写指针与读时钟域的读指针进行比较产生读空信号
(2)将读时钟域的读指针同步到写时钟域
,将同步后的读指针与写时钟域的写指针进行比较产生写满信号
异步FIFO最小深度计算:(考虑背靠背读写情况进行计算。)
队列的声明采用==[$]符号==,并且队列在声明之后不需要使用new[]函数
来进行分配内存空间;队列中可以采用push和pop的方法
在队列的头尾添加和删除元素,也可以采用insert()方法在中间插入
元素
函数function | 任务task | |
---|---|---|
执行与消耗 | 不消耗仿真时间 | 消耗仿真时间 |
仿真控制语句 | 函数中不能含有控制仿真时间的语句 如时间延迟#100,阻塞语句@(posedge clk)等 | 任务中可以包含仿真时间控制语句 如延迟#100,时钟周期@(),wait()以及事件event等语句 |
形参变量 | 函数中至少包含一个输入变量进行传参 | 任务中可以没有输入、输出变量 |
调用方式 | 函数的调用只能以语句的一部分出现 | 任务的调用通过一条单独的语句实现 |
在仿真过程中,ref型的任务与函数消耗内存资源更少,仿真速度也更快一些。
封装、继承、多态
不会阻塞线程的执行
;通常触发操作在等待事件操作之后(先等待、后触发)总是阻塞线程的执行
,只有当事件发生变化(被触发)时,线程才会继续执行.@(event_name.triggered)
;SV内建的
类,在内存中创建semaphore时,类似于创建了一个篮子(bucket)
,篮中包含一定数量的钥匙(keys)
,要获取共享的资源,必须从篮子中获取一把或多把钥匙,在获取完资源后必须将钥匙放回到篮子中;声明句柄(创建旗语)
,然后通过new( ) - 创建一个包含特定钥匙数的旗语对象;除了new(),函数外semaphore还提供了:get( ) - 从桶中获取一把或多把钥匙;put( ) - 归还一把或多把钥匙到桶中;try_get( ) - 试图获得一把或多把钥匙而不带阻塞;等方法。SV内建的类,类似FIFO,可以设置一定的深度
,当邮箱中的信息数量达到邮箱的深度时,邮箱为满,此时不能在往邮箱中存放信息。声明句柄(创建邮箱)
,然后通过new( ) - 创建一个邮箱对象对象(默认无限深),mailbox也提供了一些内置方法如:put() - 将数据信息存入邮箱;get() - 将数据移出邮箱;num() - 返回邮箱中的数据条目;等方法。此外还有try_get(),try_put()等非阻塞方法。 SV中用来做线程间同步的几种方法,它们分别是semaphore、event和mailbox。
UVM中,同步不再只局限于同一个组件中的各个线程,而是还有各个组件之间的同步问题
。UVM提供了的类:uvm_event,uvm_event_pool;uvm_barrier, uvm_barrier_pool;
UVM中的不同的组件可以共享同一个uvm_event
,这种共享是通过uvm_event_pool这一全局资源池来实现
的。通过唯一的全局资源池对象,在环境中任何一个地方的组件都可以从资源池中获取共同的对象,避免组件之间的互相依赖。uvm_event_pool::get_global("e1")
来获取同一个名称的uvm_event对象。即便该对象不存在,也会在第一次调用get_global()函数时创建
这样一个对象。trigger
(uvm_object data = null)来传递给数据对象。而在等待uvm_event一侧的组件,则需要通过uvm_event::wait_trigger_data
(output uvm_object data)来获取该对象。uvm_barrier用来对多个组件进行同步协调
,同时为了解决组件独立运作的封闭性需要,也定义了新的类uvm_barrier_pool来全局管理这些uvm_barrier对象。同时激活所有正在等待的进程,使得可以继续进行。通过调用
wait_for( )函数阻塞线程,直到到达阈值`,释放线程。 1)、使用随机化产生激励,可以很容易的在短时间内产生大量的随机激励,对于较大的验证空间,这些随机激励可以达到我们工程师可能会忽略的地方。相对于固定的激励(难以覆盖较大的可激励空间),随机化的激励可以简化代码编写,更能验证出DUT可能隐藏的错误,提高验证的完备性
2)、对于较大的验证空间,随机化策略可以使验证有条件趋于量化流程,达到以时间换空间的效果
。
验证的独立性、完备性和正确性
。还需要采用各类先进的验证方法和策略,比如覆盖率驱动的验证策略、随机化验证策略、基于断言的验证策略
。除此之外,为了提高质量和效率,还需要维护regression的流程。验证过程中,哪些设计代码被执行,从而被覆盖到。它与设计的功能没有关系,它会通过仿真工具自动搜集
。衡量设计所实现的各项功能,是否按预想的行为执行,当设计的某些功能被验证到了,我们就说这些功能点被覆盖到
。功能覆盖率需要通过人为定义覆盖点
,与待测功能点进行映射。 行覆盖率(line coverage)
:指程序的每一行代码是否被执行过。
条件覆盖率(condition coverage)
:指每个条件中的逻辑操作数被覆盖的情况。
跳转覆盖率(toggle coverage)
:用来记录某个设计边界信号数据位的0/1跳转情况,如从0到1,或者从1到0的跳转。
决策覆盖率(branch coverage)
:指在if,case,for,forever,while等语句中各个分支的执行情况。
状态机覆盖率(FSM coverage)
:用来记录状态机的各种状态被进入的次数以及状态之间的跳转情况。
面向数据的覆盖率(Data-oriented Coverage)
-对已进行的数据组合检查.我们可以通过编写覆盖组(coverage groups)、覆盖点(coverage points)和交叉覆盖(cross coverage)获得面向数据的覆盖率.
面向控制的覆盖率(Control-oriented Coverage)
-检查行为序列(sequences of
behaviors)是否已经发生.通过编写SVA来获得断言覆盖率(assertion coverage).
-cm_dir CovData/vcs/{TC_name}
:表示将生成的覆盖率数据文件放到CovData/vcs目录中,若果目录不存在,则自动创建。生成的覆盖率文件以.vdb为后缀,名称要求与用例名相关,如:test_1.vdbCopyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。