自学内容网 自学内容网

sv标准研读第十四章-clocking block

书接上回:

sv标准研读第十三章-task和function

第14章 clocking block

14.1 总览

-clocking block声明

-input skew和output skew

-clocking block的信号事件

-cycle delay

-同步事件

-同步驱动

14.2概述

Clocking block的作用:识别时钟信号并实现同步。

14.3 clocking block声明

声明格式:

解释说明:

delay_control:可以是具体数值,也可以是常量表达式

clocking_identifier:clocking block的名字,只有默认的clocking block可以没有名字,但是没有名字的clocking block里的声明是不能被引用的。

Signal_identifier:clocking block里声明的一个信号

Clocking_event:clocking block里扮演时钟角色的事件,用于驱动和采样

当clocking block里的变量方向是input时,不能做写操作;当clocking block里的变量方向是output时,不能做读操作。

Clocking_skew:指定驱动和采样信号距离时钟事件的时间,input skew是采样时间,在时钟事件之前,ouput skew是驱动时间,在时钟事件之后。

举例:

上面这个例子中,第一个ck1表示clk上升沿的前#1step会做数据采用,clk上升沿之后的下降沿会做数据驱动。第二个ck2表示如果clk在上升沿,那么采样在上升沿前#1step,驱动在该上升沿后面的下降沿;如果clk在下降沿,那么采样在下降沿前#1step,驱动在该下降沿。

注意:clocking block里声明的变量可以和rtl里面的某个hierarchical信号关联。举例:

注意:上面这个例子第四行的意思是ack这个output信号驱动时会override掉默认的#2ns skew,而选择在clock1的下降沿进行驱动。第五行的作用类似,也是override掉默认的#10ns,而换成#1step。

默认情况下,default input skew是#1step,default output skew是0。#1step指的就是一个时间单位。

14.4 input skew和output skew

input skew和output skew分别控制着采样数据和驱动数据的时间。如下图:

Skew可以是常量表达式,也可以是参数。

当input skew是#0时,会在当前time step的observed域进行采样,当output skew是#0时,会在当前time step的re-NBA域进行采样。

14.5 hierarchical表达式

前面已经有例子说明了clocking block里声明的信号可以和hierarchical信号关联,不仅如此,还可以和hierarchical信号的slice或者通过{}连接符将多个信号拼接起来和clocking block里声明的信号关联上。

需要注意的是关联信号时要注意信号的方向:input/output/inout。

14.6 在多个clocking block里使用的同一个信号

需要注意的是,多个clocking block可以使用同一个信号,比如时钟信号,那么就表示同一个时钟实现了多个同步。

14.7 clocking block的作用范围和生命周期

注意:clocking block和always一样声明就是例化,在调用里面的信号时直接clocking_block_name.signal_name即可。

Clocking block不能在function\task\package里面声明,也不能在编译单元之外声明,只能在module、interface、checker、program里声明,它有着静态生命周期,和module、interface、program一样。

14.8 多个clocking block使用举例

14.9 interface和clocking block联合使用

Clocking block经常和interface搭配使用,这是因为interface封装了一系列信号,能够帮助减少测试平台的代码量。对于testbench而言,信号的方向和rtl是不相同的,那么在使用clocking block时,可以带上modport关键字来声明信号的方向。因此使用modport声明的信号方向是站在clocking block的角度而言的,也即interface的角度,也是testbench的角度。和dut的角度是完全相反的。举例:

14.10 clocking block事件

我们可以直接使用clocking block的名字来当做一个事件,它的作用就相当于使用它的同步时钟事件。举例,定义了这样的一个clocking block:

当我们这样等待一个事件时:

它的作用就相当于:

14.11 ## cycle delay

作用:延迟指定数量个default clocking event。Default Clocking event的概念见下一小节。

语法:##后面跟一个正整数

使用##的前提是当前scope下有定义default clocking event,没有定义就使用##会报错。

##0比较特殊:如果当前time step有default clocking event发生,那么不做任何delay;如果当前time step没有default clocking event发生,那么会一直delay到下一个default clocking event发生。

##不能用在intra-assignment里。

14.12 default clocking event

定义:直接在clocking block定义的关键字前面加上default关键字即可,如下:

一个scope下只能定义一个default clocking event,多于一个会报错,并且只对当前scope起作用。举例:

14.13 Input sampling

当input skew非0时,会在当前clocking event之前的某个time step的postponed region进行采样;当input skew为0时,会在当前clocking event的observed region进行采样。

当表达式中有clocking event时,该event是在observed region触发。举例:

虽然@(cb)和@(negedge clk)等效,但两者触发的region不一样,前者在observed region触发,后者在active region触发,因此前者能避免很多竞争冒险。

14.14 global clocking

作用:当指定了global clocking时,可以调用系统函数$global_clock。

语法:在clocking block关键字前面加上global关键字即可,如下:

可以出现的位置:module、interface、program、checker

不能出现的位置:generate block

一个scope里最多只能声明一个global clocking。

当调用$global_clock系统函数时,有一套搜寻global clock的规则如下:

  1. 首先在当前scope下搜寻,找到了就退出搜寻,找不到且当前scope是top level时,报error,找不到但是当前scope不是top level时,执行第(2)步;
  2. 在parent level scope下继续搜寻,找到了就退出搜寻,找不到则继续在parent level scope下搜寻,直到top level还找不到就报error。

举三个经典的例子:

例子一:

这个例子中,sub1.common里调用的$global_clock是sub1.sub_sys1;sub2.common里调用的$global_clock是sub2.sub_sys2。

例子二:

这个例子中,sub1.checks里的断言p的$global_clock调用的是sub1.sub_sys1;sub2.checks里的断言p的$global_clock调用的是sub2.sub_sys2

注意这里property里的global clock引用比较特殊,引用的不是property声明时scope下的global clock,而是property被引用的assert所在的scope下的global clock。

例子三:

这个例子中,无论是sub1还是sub2,里面的another_module.t里的$global block引用的都是another_clocking。

14.15 synchronous events

完成同步操作需要一个关键符号:@。同步事件语句有下面几种形式:

14.16 synchronous drives

同步驱动发生在re-NBA region。

可以有intra-delay。


原文地址:https://blog.csdn.net/yunduor909/article/details/143080542

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!