当前位置: 首页 > news >正文

记录几个SystemVerilog的语法——时钟块和进程通信

1. 时钟块(clocking block)

时钟块的声明和例化是一体化,也就是在声明的时候,其实就实例化了,不需要再例化了。时钟块不能嵌套,且只能声明再module、interface、checker或program里。时钟块有三大用法:

  • Synchronous events:同步事件
  • Input sampling:输入采样
  • Synchronous drives:同步驱动

时钟块中指定为input方向的信号只能被read,不能被write;指定为output方向的信号只能被write,不能被read;指定为inout方向的信号既能被read,也能被write,因为inout拥有input和output两种属性,它在本质上会同时定义两个相同名字的input和output信号。

2. 时钟偏离(Clocking skew)

Clocking skew决定了一根信号在距离时钟事件多远时被采样或驱动的。Input skew隐含为负数的,也就是总是在时钟事件之前发生的,output skew总是在时钟事件之后发生的。同一个时钟块中不同信号可以采用不同的input/output skew,也可以采用default将一个clocking skew应用到同一个时钟块中。除非有特定指定,不然默认的input skew 是1step和默认的output skew是0。对于不带input skew或者input skew为1step的,输入采样值会在时钟事件之前的postponed region或当前时钟事件的preponed region采样的。

如果input指定#0 skew,按道理应该在对应的时钟事件发生时马上采样,但是SystemVerilog为了避免冲突,把它们放在Observed region采样。类似的,如果output带有#0 skew或没有skew,那re-NBA region驱动。

有个注意点是:如果时钟事件是在program里的执行程序触发的,那么时钟事件和采样值之间存在竞争关系,只有时钟事件是在module里更新的才不会出现竞争关系的。

3. 时钟块同步驱动(synchronous drive)

时钟块中信号的写(赋值)只能使用synchronous drive语法(<=),用其它方式赋值会报错。对于时钟块中信号的赋值可能在非时钟事件时被执行到,这样的驱动语句暂时不会阻塞执行,但驱动的值应该是在下一个时钟事件到来时才生效的。也就是说右边的值在执行到时马上计算评估出来,但是驱动的处理是被延迟了,直到下一个时钟事件到来时。例如:

default clocking cb @(posedge clk);   // Assume clk has a period of #10 unitsoutput v;
endclockinginitial begin#3 cb.v <= expr1;   // Matures in cycle 1; equivalent to ##1 cb.v <= expr1
end

时钟块synchronous drive给inout信号时不改变时钟块中该信号的input值,这是因为input值是刚被采样更新的,而不是在驱动时重新更新的。例子如下:

clocking cb @(posedge clk);inout a;output b;
endclockinginitial begincb.a <= c;  // The value of a will change in the Re-NBA regioncb.b <= cb.a;  // b is assigned the value of a before the change
end

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

4. 进程间同步和通信

SystemVerilog给进程间同步和通信提供了三种方式:

  • named event type(->, @):命名事件类型;
  • semaphore:旗语;
  • mailbox:邮箱;

其中旗语和邮箱是SV内建的class类型,而且可以被作为基类拓展为更高层级的子类。这些内建类都是放在std package里,可以在任何范围内使用。

旗语就像是一把锁,只有获取到这把锁的钥匙(key)的进程才能继续执行,因此它常用语互斥锁、对共享资源的访问控制或基本的同步。

邮箱是一种通讯机制,可以用于进程间进行消息的交换,数据可以通过邮箱从一个进程送到另一个进程。邮箱有有界和无界两种。对于有界的邮箱,如果邮箱满了,那么put()方法会被阻塞住。无界邮箱不会满,因此put()方法不可能会被阻塞住,任何时候数据都可以放进邮箱中。

邮箱有一个要提的是,它分为通用邮箱和参数化邮箱,这两种有什么区别呢?通用邮箱就是它里面可以放各种类型的数据,因此在运行时需要做类型检查,如果put()和get()两测的类型不匹配,那么会报错。参数化邮箱只能放特定类型的数据,仿真器可以在编译时就进行检查。

命名事件提供了同步对象的句柄。当一个进程在等待事件触发时,该进程会被放在事件同步对象维护的队列中。进程可以通过@操作符或检查触发状态的wait()方法来等待命名事件。另外,wait_order还可以用于检测几个event发生的顺序。事件可以通过赋值为null来释放掉的,如:

event E1 = null;
@ E1;  // undefined: might block forever or not at all
wait( E1.triggered );  // undefined
-> E1;  // no effect

还有就是事件变量的句柄可以用logically equality(==, !=)和case equality(===, !==)来进行比较的,如果比较相同,返回1,反之返回0。例子如下:

event E1, E2;
if ( E1 )E1 = E2;    // same as if ( E1 != null )
if ( E1 == E2 )$display( "E1 and E2 are the same event" );

http://www.dtcms.com/a/301320.html

相关文章:

  • maven聚合工程(多个mudule只编译、打包指定module)
  • JVM类加载机制全流程详解
  • 通过硬编码函数地址并转换为函数指针来调用函数
  • Java#包管理器来时的路
  • Leetcode-3427变长子数组求和
  • Mitk教程案例项目编译
  • 嵌入式——单片机的独立按键
  • 【3DsMax+Zbrush+SP】风格化低多边形模型制作教程——以制作杯子为例——03在Substance Painter中制作材质
  • PyTorch深度学习入门记录3
  • 两数之和 II - 输入有序数组-leetcode
  • 【深度学习系列82】joyagent上手体验
  • 五、搭建springCloudAlibaba2021.1版本分布式微服务-gateway网关
  • 基于大模型的预训练、量化、微调等完整流程解析
  • 【思维链(CoT)技术深度解析】从理论到实践的革命性推理方法
  • pytest中的参数化
  • Python-初学openCV——图像预处理(三)
  • 相对路径遍历(CWE-22)
  • 【杂谈】-被引用即被看见:生成式AI如何改写内容规则
  • vscode找不到python解释器的解决方案
  • 8. 若依框架的AjaxResult
  • Baumer工业相机堡盟工业相机如何通过YoloV8深度学习模型实现PCB上二维码检测识别(C#代码UI界面版)
  • 欢乐的周末 - 华为OD统一考试(JavaScript 题解)
  • RAG(检索增强生成)
  • Vue 四个map的使用方法
  • MySQL读写分离部署
  • 【YOLO系列】YOLOv1详解:模型结构、损失函数、训练方法及代码实现
  • 前端面试专栏-前沿技术:31.Serverless与云原生开发
  • Spring AI 项目实战(二十一):Spring Boot + AI +DeepSeek驱动的智能题库系统(附完整源码)
  • Linux-文件与文本管理
  • 【语义分割】记录2:yolo系列