0 丑话说在前边

RHS:运算符(= or <=)右侧的表达式

LHS:运算符(= or <=)左侧的表达式

竞争(Race Condition):在同一仿真时间槽(time-slot)多条语句同时执行顺序不同时可能产生不同的执行结果的情况。

建议规则一:模拟组合逻辑时使用阻塞赋值。

建议规则二:在过程性语句中,模拟时序逻辑时使用非阻塞赋值。

建议规则三:模拟latch时使用非阻塞赋值。

建议规则四:在同一个过程性语句中同时包括时序逻辑和组合逻辑时,该过程性语句中使用非阻塞赋值。

建议规则五:不要在同一个过程性语句中混用阻塞赋值与非阻塞赋值。

建议规则六:不要在多个过程性语句中对同一个变量进行赋值操作。

建议规则七:如果要观测非阻塞赋值的结果,使用$strobe和$monitor进行观测。

建议规则八:不要使用#0。

1 阻塞赋值

阻塞赋值使用的赋值运算符为“=”。阻塞赋值的过程是立刻执行的,即阻塞赋值运算符右侧表达式求值完后立刻会更新至运算符左侧,并且这个执行的过程不受其他语句执行的影响,其后的语句只有当前的赋值操作执行完成后才能顺序执行。

2 非阻塞赋值

非阻塞赋值使用的赋值运算符为“<=”。非阻塞赋值执行过程为:在当前仿真时间槽(time-slot)开始分析计算获得右侧表达式的值,在当前时间槽执行结束时更新左侧表达式的值,在右侧表达式分析计算和左侧表达式被更新之间,任何其他事件都可以执行,同时也有可能修改已经计算完成的右侧表达式的值,即非阻塞赋值的过程不影响其他语句的执行.

根据非阻塞赋值的特点,其赋值运算符左侧操作数只能为寄存器类型,因此非阻塞赋值只能用于过程性语句中(initial和always),不允许在连续赋值语句中使用非阻塞赋值。

3 阻塞赋值与非阻塞赋值区别

阻塞赋值(blocking assignment)

非阻塞赋值(non-blocking assignment)

格式:“LHS” = “RHS”

格式:“LHS” <= “RHS”

阻塞赋值RHS会延迟指定延迟(如果没有指定就是0延迟,如果指定了非零延迟,那么就延迟非零延迟,关于延迟位置不同结果不同可参见topic“阻塞赋值中的延迟”)后立即更新至LHS

非阻塞赋值LHS会在当前仿真时间槽(time-slot)最后被更新,即RHS变化后不会立即反应在LHS上

当多条阻塞赋值语句顺序出现在同一个进程中时,所有的语句按顺序执行,即后续的语句必须在当前赋值操作完成后才能进行

同一个进程中的非阻塞赋值在同一个时间槽中是同时执行的,即不会互相阻塞

建议在组合逻辑的结构中使用

建议在时序逻辑进程中使用

可以在过程性赋值和连续性赋值中使用

建议在时序进程中使用

当阻塞赋值中的变量同时出现在不同的进程中时,可能会出现竞争的情况

非阻塞赋值LHS更新在仿真时间槽的最后,可以在一定程度上避免竞争的出现

【示例】

initial begin

    temp_1 = #5 2'b10;

    temp_2 = #1 2'b01;

end

从仿真0时刻开始,temp_1在时刻5被赋值为2'b10,temp_2在时刻6(5+1)被赋值为2'b01,即temp_2更新发生在temp_1之后,即两次赋值有先后顺序

【示例】

initial begin

    temp_1 <= #5 2'b10;

    temp_2 <= #1 2'b01;

end

从仿真0时刻开始,temp_1在时刻5被赋值为2'b10,temp_2在时刻1被赋值为2'b01,即temp_2更新发生在temp_1之前,即两次赋值从同一时刻同时开始

为了更好的理解阻塞赋值与非阻塞赋值的区别,下面就Verilog中语句执行遵循的规则进行简述。

4 层次化事件队列

软件程序代码都是顺序执行的,即一个时间点只会发生一件事情,但是现实的硬件具体执行是并行执行的,即一个时间点会有多个事件同时发生。面对这样的硬件情况,如果要是用软件程序模拟硬件的工作原理,就需要采用必要特定的处理机制才能实现,于是Verilog中出现了事件队列的概念,即在一个事件队列中的事件是按照特定顺序执行的,然后事件队列在按照一定的顺序执行。这些队列在Verilog中被定义为层次化事件队列(stratified event queue),下图采用离散的方式将一个时间槽中的各事件队列按照执行顺序进行了划分,当当前时间槽中的队列执行完毕后,时间轴才会继续进行,即才会进入下一个时间槽,虽然在仿真上观测起来好像事件是并发执行,但是软件实现该序列时是一个时间点完成一件事。

注意:每个事件队列中事件的执行顺序是不确定的。

活跃事件队列(Active Event Queue):其中保罗了阻塞赋值、连续赋值、$display等,这些语句之间的执行是没有特定顺序规定的,因此在使用$display显示一些信号的变化时需要格外注意,极易因为竞争导致观测到的信号与期望不一致。

非活跃事件队列(Inactive Event Queue):#0赋值操作被安排在此阶段进行,他会迫使阻塞赋值略晚于正常的阻塞赋值语句执行。这里需要注意的是,#0并不是在一个时间槽的最后执行,其执行阶段先于非阻塞赋值更新队列。

非阻塞赋值事件队列(Non-blocking Event Queue):非阻塞赋值表达式LHS在此事件队列中被更新,因此如果使用$display观测非阻塞赋值表达式的LHS,那么观测到的数据实际上是上一个时间槽LHS的数据。所以观测非阻塞赋值LHS数据变化应该使用其后的Monitor事件队列,该队列中的系统函数可以监测到当前时间槽中所有已经被修改的变量的最后状态。

这里需要注意的是当前仿真时间槽中每一个事件将会排列到对应的事件队列中,各个事件在具体队列中的执行顺序可能不一样,因此如果对于信号变量的赋值更新没有很好理解的情况下极易造成同一队列中不同事件执行顺序不一样导致的竞争情况出现。

PLI事件队列(Other PLI):Verilog PLI允许调用使用C语言编写的一些函数,例如$fsdbDumpfile,$fsdbDumpvars等,这些函数具体执行阶段位于PLI事件队列阶段,这时搭建在编写测试平台就需要注意该函数显示的结果可能会与$display显示的不一样,因为$display在active event queue中已经执行了。

5 常见问题

5.1 阻塞赋值用于时序逻辑

【示例一】

仿真结果如下:

通过上述仿真结果可以观测到,P1对应的always过程性语句中使用阻塞赋值,该赋值操作是立即进行的,其中的data_in赋值给q1后,q1立即更新至data_out。P2对应的always过程性语句中使用非阻塞赋值,第一个赋值语句在当前时间槽最后将data_in更新至q1,第二个非阻塞赋值语句中的RHS为当前进行触发时获得q1的数值,即前一个时间槽最后更新至q1中的值,在当前时间槽结束前,该值才被更新至LHS的data_out中,即造成data_out与q1在仿真波形上相差一个时钟周期。

【示例二】

P1在上时的仿真结果如下:

P2在上时的仿真结果如下:

当P1和P2对应的always块在代码中编写的顺序不一样时,仿真结果是有差异的。当P1先执行时,那么p1和p2复位后都为1'b0,当P2先执行时,p1和p2复位后都为1'b1。造成这种现象的原因是阻塞复制发生在当前时间槽的开始,且多条阻塞赋值在活跃事件队列中执行的顺序是不确定的,所以出现上述仿真结果,为了避免此种不确定情况的出现,建议采用如下方法:

1>在时序逻辑电路中使用非阻塞赋值;

2>确实需要组合逻辑参与时序逻辑时,进程中所有的赋值均采用非阻塞赋值;

5.2 $display和$monitor与$strobe观测到不同的数值

【示例】

仿真结果如下:

从上述仿真结果中可以观测到其中$monitor和$strobe监测到的data值均为2'b01,而$display监测到的数值为2'b10,因为$monitor和$strobe在时间槽中发生非阻塞赋值更新队列之后,所以$monitor和$strobe监测到的是最终的结果,即非阻塞赋值更新后的LHS的值。而$display和阻塞赋值都发生在活跃事件队列中,但是发生在非阻塞赋值更新队列之前,所以观测不到非阻塞赋值后LHS的值。这里需要注意以下几点:

1>使用$monitor和$strobe观测非阻塞赋值LHS变化;

2>$monitor在一个时间点只能使用出现一次;

5.3 #0延迟

【示例】

仿真结果如下:

s1~s4同时启动,按照层次化事件队列对代码中各语句执行队列的划分,s1和s3将会放入Active Event Queue队列中,s2放在Inactive Event Queue,s4放在Monitor Event Queue队列,按照层次化事件队列执行的顺序运行程序,$display将输出Active Event Queue队列中阻塞赋值(s1)执行时赋给sig的值,即1'b0。s2因为属于Inactive Event Queue,发生在Active Event Queue队列之后,所以$display观测不到延迟"#0"后对sig的修改,而s4行的$strobe发生在Monitor Event Queue,该队列发生在Inactive Event Queue之后,所以可以观测到sig延迟后被修改的值1'b1,但是已经看不到Active Event Queue中赋给sig的1'b0。

硅芯思见:阻塞赋值与非阻塞赋值相关推荐

  1. 硅芯思见:SystemVerilog中的类型转换有哪些

    硅芯思见 更多内容↑↑↑↑↑↑↑↑↑↑,其中更新更多内容! 本文纯属学习之用,欢迎指正文中不足,封面图片若有侵权,请及时沟通! 在SystemVerilog中,经常会用到$cast对数据类型进行转换, ...

  2. 硅芯思见:“软约束”到底有多“软”

    更多内容请关注下面公众号! 硅芯思见 本文纯属学习之用,欢迎指正文中不足,封面图片若有侵权,请及时沟通! 在SystemVerilog中,约束一般分为两种:一种称之为"硬约束hard con ...

  3. 硅芯思见:Timing Borrow深入浅出

    硅芯思见 更多内容↑↑↑↑↑↑↑↑↑↑,其中更新更多内容! 本文纯属学习之用,欢迎指正文中不足,封面图片若有侵权,请及时沟通! Timing Borrow技术又称为cycle stealing技术,其 ...

  4. 硅芯思见:SystemVerilog中的packedarray和unpacked array

    [注]因为在很多书籍资料中关于packed array和unpacked array有不同的翻译,有的称之为压缩数组和非压缩数组,有的称之为合并数组和非合并数组,为了避免混淆,本文不采用任何翻译名称, ...

  5. 硅芯思见:SystemVerilog中unpacked数组的assignment pattern

    在SystemVerilog中根据数组中元素的存储方式,将数组细分为了packed数组和unpacked数组,packed数组一般使用拼接({})操作实现初始化赋值,unpacked数组则使用数值列表 ...

  6. 硅芯思见:IC验证应读书推荐

    本文主要是跟大家分享一些在IC验证学习过程中的一些性价比极高的不错的书籍,通过这些书的学习,你的IC验证学习之路一定会很丰富!当然如果你时间充裕并且口袋比较富裕,觉得自己存数量比较少的话,你也可以买很 ...

  7. 07-阻塞赋值与非阻塞赋值原理分析——小梅哥FPGA设计思想与验证方法视频教程配套文档...

    芯航线--普利斯队长精心奉献 实验目的:掌握阻塞赋值与非阻塞赋值的区别 实验平台:无 实验原理: 阻塞赋值,操作符为"=","阻塞"是指在进程语句(initia ...

  8. 通过举例谈谈阻塞赋值与非阻塞赋值的区别

    这篇博客,通过举例说明:非阻塞赋值和阻塞赋值的区别? 一般非阻塞赋值用于时序逻辑,而阻塞赋值用于组合逻辑: 非阻塞赋值语句是并行执行的,等到一个时钟完成后才完成赋值,而阻塞赋值是顺序执行的,下一条赋值 ...

  9. 查询框赋值后不可编辑_【技巧分享】阻塞赋值与非阻塞赋值

    原创 小黑同学 明德扬FPGA科教 关于阻塞赋值和非阻塞赋值的问题,明德扬的学员提得比较多,今天小黑老师专门给大家普及一下阻塞赋值和非阻塞赋值的相关知识. 一.概述 1.阻塞赋值对应的电路往往与触发沿 ...

最新文章

  1. 如何使用Java获取当前日期/时间
  2. 更新KB915597补丁后导致“您的windows副本不是正版”的解决方案
  3. 【Spring学习】使用Spring的jdbcTemplate简化JDBC操作
  4. jsoncpp去掉多余字符_Python超详细的字符串用法大全
  5. python笔记全_Python笔记
  6. lock_sh 示例_带有示例的Python date __str __()方法
  7. linux pinctl 分析,Linux驱动架构之pinctrl子系统分析(一)
  8. 吴恩达|机器学习作业3.1前馈神经网络
  9. Mac上Gtk-WARNING **: cannot open display解决
  10. python 文件的打开与读取
  11. iOS开发之TableView去掉单个cell的间隔线和去掉全部间隔线和去掉tableView多余的间隔线
  12. CenterOs操作
  13. 什么是CANFD Light
  14. Python3抓取猫眼电影排行
  15. 如何设置二级域名解析(新手小白必看)
  16. 怎么学编程?学编程黄金4步,太多人卡在了第二步!
  17. jsapi设计_Sketch插件如何架构
  18. 全民农场服务器维护上不去,全民农场签到页面空白解决方法
  19. 手机动态:摩托罗拉edge s pro搭载骁龙870处理器
  20. Python超级详细的上台阶楼梯问题,算法运行速度极快,内含计算排列的方法。问题:有n级台阶,每步可以走一级或两级,问有多少种不同的走法。k为传入的参数,默认值为3

热门文章

  1. 2018年的智能手机
  2. An Introduction to Shiro (formerly JSecurity) – A Beginner’s Tutorial Part 3
  3. 浅谈Mybatis之mybatis是什么?
  4. Mybatis 传入数组参数
  5. 微信小程序报错:[渲染层错误] TypeError: Cannot read property ‘$$‘ of undefined
  6. python入门很简单_Python入门很简单
  7. 爱了!Intellij IDEA 自带的 Vim 插件真心不错。。。
  8. 基于vgg19的梵高图像风格迁移
  9. python代码对齐快捷键_PyCharm 格式化代码 常用快捷键
  10. 收藏一些最全的最权威的域名后缀列表留以备用