测试平台:
测试平台是整个验证系统的的总称,包含了各个组件和各个组件之间的连接关系,测试平台的配置和控制。测试平台中各个组件之间是相互独立的,验证组件和设计之间需要进行连接,组件之间也需要连接。
1、组件stimulator :
stimulator (激励发生器)是验证环境的重要部件,在一些场合中,它也被称为driver (驱动器)、BFM (bus function model,总线功能模型),behavioral (行为模型)或者generator (发生器)。Stimulator的主要职责是模拟与DUT相邻设计的接口协议,只需要关注于如何模拟接口信号,使其能够以真实的接口协议来发送激励给DUT。Stimulator不应该违反协议,但不拘束于真实的硬件行为,还可以给出更多丰富的只要协议允许的激励场景。比真实硬件行为更手富的激励,会使得在模块级的验证更加充分,因为它不但验证过了硬件普通的接口协议情景,还模拟出更多复杂的、在更高系统级别无法产生出来的场景。
2、组件monitor:
主要功能是观察DUT 的边界或者内部信号,并且经过打包整理传送给其他验证平台,可以从检测信号的层次来划分monitor的作用,可以分为观察DUT边界信号和内部信号
3、组件checker:
checker主要负责模拟设计行为和功能检查的作用,缓存的从各个monitor里面收集数据,然后汇集到一起输送给reference model,reference model主要作用是模拟硬件的功能,需要设计者提前熟悉硬件的功能和逻辑。然后通过数据比较的方法,检查实际收集到的DUT输出端接口数据是否和reference model产生的一致,检查过程中无论正确与否都要把信息统一打印到检查报告中。
分散搁置:各自检查对应模块的功能,但是checker之间通信需要特殊连接,得到的信息也比较难统一,checker的使能控制因其分散变得复杂。
集群搁置:各自检查对应模块功能,checker各自相邻,可以共享monitor的输入减少复杂的关系,可以按照统一的报告形式,记录在文件中,集中管理各个checker。
4、验证结构:
首先初步验证集成环境,然后再是不同模块的验证,完成不同模块的验证之后,进入顶层验证,检查各自的模块是否可以工作。在最后的顶层验证之后,会完成整体验证的任务。
接口
interface可以用在设计也可以用作验证,和module的性质很相似,可以在内部定义端口、双向信号,可以使用initial和always,也可以定义task和function,interface也可以在硬件环境和软件环境中传递,硬件中可以作为module的端口列表,软件中可以作为形式参数。接口信号必须采用非阻塞来驱动
接口的优势:可以将有关信号都封装在一个接口中,方便维护;interface可以在module中使用也可以在class中使用,是SV中硬件和软件的媒介交互。接口可以例化,在例化和使用时会使得代码更加灵活和简洁,易于验证环境的管理和维护。
接口的劣势:对于点对点的连接,接口描述跟使用信号列表的端口一样冗长,除此之外,同时使用信号名和接口名,会使得模块变得更加冗长;使用接口需要做比端口连线更多的工作。
使用简单接口的仲裁器:
module arb (arb_if arbif)
....
always@(posedge arbif.clk or posedge arbif.rst)
begin
if(arbif.rst)
arbif.grant<=2'b0;
else
arbif.grant<=next_grant;
....
end
endmodule
连接接口和端口:
module top;
bit clk;
always #5 clk=~clk;
arbif arbif(clk);
arb_port a1(.grant(arbif.grant),
.request(arbif.request),
.rst(arbif.rst),
.clk(arbif.clk));
test t1(arbif )
endmodule
采用和数据驱动
竞争问题:
为了避免竞争问题,我们建议通过非阻塞或者特定的信号延迟来解决同步问题,默认情况下时钟对于组合电路会添加一个无限小时间的延迟(delta_cycle),该延迟无法用绝对时间单位衡量,它比最小的时间单位精度还小。但是由于各种竟可能性,clk和采样数据之间如果只存在若干个delta_cycle,那么仍然还是可能存在采样问题。如何避免竞争问题?
接口中的clocking块:
硬件和软件世界的连接可以通过灵活的interface来实现,也可以通过modport来限制信号传输的方向。接口中声明clocking和采样信号来做时钟的同步和采样,可以消除信号竞争问题,因为tb不会再苦恼如何准确及时的对信号驱动或者采样。
clocking块不仅可以定义在interface里面,还可以定义在module和program中,clocking在声明完名字后,应该伴随定义默认的采样事件(default input/output event),如果没有定义的话会默认在采样事件的前1step对输入进行采样,在采样时间后的#0对输出进行驱动。
clocking bus @(posedge clk1)
default input #10ns output #2ns
input data,ready,enable;
output negedge ack;
input #1step addr;
endclocking
第一行:定义了一个时钟块bus,在时钟上升沿驱动和采样;第二行:默认情况下会在clocking事件的前10ns进行采样,事件的后2ns进行输出驱动;第三行定义了输入信号;第四行声明了要驱动的ack信号,驱动信号的时间为clock1的下降沿;第五行定义了自身采样事件,在clock1上升沿的1step。
测试的开始和结束:
program隐示结束:
Verilog中会考虑$finish()和$stop()来结束后者暂定仿真 ,SV中推出program把验证和设计有效分隔以后,SV将每一个program作为一个独立的测试,如果tb中只有一个program,那么会在执行完该program后自动结束仿真;如果有多个program,也会等到所有的Program中的最后一个initial完成后才结束仿真。
program显示结束:
在目标program内置一个系统函数$exit()来强行结束某个program,然后等待其他program执行完毕来结束仿真。
断言
立即断言:
断言比if语句更加紧凑,但是断言的逻辑条件跟if语句是相反的,下面的只有正确的 产生grant才能继续执行。
a1:assert (bus.cb.grant ==2'b01);
定制断言行为:
一个断言有可选的then和else分句。SV有四个输出消息的函数,$info $warning $error $fatal仅仅允许在断言内部使用,不允许在代码过程中使用,后续将被允许。
a1:assert (bus.cb.grant ==2'b01)
else $error("Grant not asserted");
并发断言:
可以认为是一个连续运行的模块,它为整个仿真器检查信号的值,需要在断言内部指定一个采样的时钟。并发断言使用关键字property...endproperty描述事件。