Systemverilog中Clocking blocks的记录

1. clocking block的作用

Clocking block可以将timing和synchronization detail从testbench的structural、functional和procedural elements中分离出来,因此sample timming和clocking block信号的驱动会隐含相对于clocking block的clock了,这就使得对一些key operations的操作很方便,不需要显示使用clocks或指定timing。这些操作如下:

  • Synchronous events
  • Input sampling
  • Synchronous drives

Clocking block拥有declaration和instance一体化,也就说在declaration的时候,就已经实例化了,不需要再做一遍了。多个clocking blocks不能嵌套,且clocking block不能声明在function、task、package或compilation unit的所有声明之外。Clocking block只能声明在module、interface、checker或program里。

2. clocking blocksignal_identifierinput/output

Clocking block中指定为input方向signal只能被read,不能被write;

Clocking block中指定为output方向signal只能被write,不能被read;

Clocking block中指定为inout方向signal既能被read,也能被write;inout拥有input和output两种属性,它在本质上会同时定义两个相同名字的input和output。

3. clocking skew

Clocking skew决定了一根signal在距离clock event有多少time units后被sampled或driven的。Input skews隐含为负数的,也就意味着总是在clock event之前发生的,output skews总是在clock event之后发生的。

Clocking event可以用edge,而不是一个数字来指定的。

可以采用default来将一个clocking skew应用到整个clocking block。

input指定#0 skew应该在corresponding clocking event时采样,但为了避免冲突,它们会在Observed region采样。相似的,对于output带有#0 skew或没有skew,那它们会在re-NBA region时驱动

如果input没有显示指定#0,那么采样值会在clocking event之前的postponed region的sample的。这里有个注意点:如果clocking event是在program里的执行程序触发的,那么clocking eventsample value之间存在竞争关系,只有clocking eventmodule里更新才不会有竞争关系的。

在处理clocking event时,clocking block应先更新自己的sampled values,然后采取trigger与它相关的event事件。event应该在observed region时触发,因此一个正在等clocking block的process可以保证读到updated sampled value。

4. cycle delay: ##

##可以控制delay特定的clocking event或clock cycle的个数之后,才继续执行。例如:

5. Synchronous events

显示的同步可以通过event control operator (@) 来控制的,这样会允许一个process等待一个特别信号值的变化或一个clocking event。例如:

@(negedge dom.sig1 or posedge dom.sig2);

@(posedge ram_bus.enable);

@(edge dom.sig1);

@(ram_bus)   // ram_bus is clocking block

6. Delay control

在赋值语句中有两种delay的控制方法,分别为intra-assigment delayprocedural cycle delay

intra-assignment delay的形式如下:

bus.data <= #4 r;  //等价于:temp = r; #4 bus.data <= temp; 也就是说在#4之前就搞好值了,只不过在#4之后才把赋值的

Procedural cycle delay的形式如下:

#2  bus.data <= 2;  //也就是说在#2之后,才会计算右边的值,并赋值的

在对clocking block里的signals进行赋值时,intra-assignment只能用cycle delay(##)的,不能用常规的delay(#),如下:

Systemverilog中Clocking blocks的记录_第1张图片

对于clocking block中信号的赋值可能在非clocking event时被执行到,这样的drive statements应该没有blocking的执行,但drive的值应该是在下一个clocking event到来时才生效的。也就是说右边的值在执行到时马上计算评估出来,但是drive的处理是被delay了,直到下一个clocking event的事件到来时。例如:

Systemverilog中Clocking blocks的记录_第2张图片

对于clockvar(clocking block中的signal)的写只能用synchronous drive语法,用其他方式会报错。因此,在任何的continuous assignment、force statement、procedural continuous assignment去写clockvar是非法的。

7. Drives and nonblocking assignments

Clocking block里的信号必须用<=这种赋值符号,否则编译会报错,我猜想跟clocking block里drive的值是在re-NBA生效有关的吧。

Systemverilog中Clocking blocks的记录_第3张图片

尽管clocking block的synchronous drives语法operator和nonblocking variable assignment一样,但它们本质上有点区别的:

区别1:clocking block的赋值不支持intra-assignment的delay syntax,它要求delay syntax必须是cycle delay(##)。

区别2(重要):clocking blocksynchronous drivesinout clockvars时不改变clocking blockinput,这是因为input总是在最后才会被sampled更新的,而不是在驱动时更新的。例子如下:

Systemverilog中Clocking blocks的记录_第4张图片

用以上例子来比较下clocking block和regular variable在驱动和采样上的区别:

首先是上述的clocking block,a信号在re-NBA时才会被驱动的,b表达式右边的a在上一time step时已经采样了,在当前step还没有被更新,因此b仍然用的是旧值(看input skew,#0则在observed时,非#0则在更之前采样的(如#1step则是在上一个step的postponed采样))。

然后说下如果是regular variable,a和b没有在clocking block里,因为a和b的驱动是在module里的话,那么a和b会在NBA执行,如果在program里驱动的话,那么a和b会在re-NBA里执行。对于b右边表达式a的值,如果在module里的话,会用active时的值,如果在program,会用reactive的值。

你可能感兴趣的:(SystemVerilog,Systemverilog,Clocking,interface,clockvar,cb)