在Verilog中有两种类型的赋值语句:阻塞赋值语句(“=”)和非阻塞赋值语句(“<=”)。正确地使用这两种赋值语句对于Verilog的设计和仿真非常重要。

Verilog语言中讲的阻塞赋值与非阻塞赋值,但从字面意思来看,阻塞就是执行的时候在某个地方卡住了,等这个操作执行完在继续执行下面的语句,而非阻塞就是不管执行完没有,我不管执行的结果是什么,反正我继续下面的事情。而Verilog中的阻塞赋值与非阻塞赋值正好也是这个意思,通过执行一个例子,就可以简单地明白了:
1、阻塞赋值可以理解为语句的顺序执行,因此语句的执行顺序很重要
2、非阻塞赋值可以理解为语句的并行执行,所以语句的执行不考虑顺序
3、在assign的结构中,必须使用的是阻塞赋值

也就是说:

阻塞:在本语句中“右式计算”和“左式更新”完全完成之后,才开始执行下一条语句;
非阻塞:当前语句的执行不会阻塞下一语句的执行。

下面给出实例来说明:

给出相应的案例来帮助理解:

module prj1(in,b,c,d,clk,rst_n);input in;
input clk;
input rst_n;
output b,c,d;
reg b,c,d;always @(posedge clk or negedge rst_n) beginif(!rst_n) beginb <=0;c <=0;d <=0;endelse beginb <=in;c <=b;d <=c;endend
endmodule

这个目的是为了展示非阻塞赋值过程中的时序变化,对应的RTL电路图和仿真波形如下图:

从仿真图可以看书,b,c,d是在每个时钟后依次传递的,如果采用阻塞赋值,如果in改变,那么b,c,d立刻改变,这个就在这里不给出仿真。

阻塞赋值和非阻塞赋值的另外一个区别在于综合的时候,如果输出只有d,bc作为中间变量,阻塞赋值在综合的过程中会自动省略掉中间过程。给出如下仿真,理解更为清楚

module prj1(in,b,c,clk,rst_n);input in;
input clk;
input rst_n;
output b,c;
reg b,c, e,f, m,n;
/* <= */
always @(posedge clk or negedge rst_n) beginif(!rst_n) b <=0;else begine <=in;f <=e;b <=f;endend
/* = */
always @(posedge clk or negedge rst_n) beginif(!rst_n) c=0;else beginm = in;n = m;c = n;endend
endmodule

综合后结果如图,可以看出,采用阻塞赋值,综合后的逻辑单元只有一个,中间变量m,n直接省去了。

下面我们来看看两者代码之间到底是怎么运行的。

(1)对于阻塞赋值的情况:

always @(posedge clk or negedge rst_n) beginif(!rst_n) c=0;else beginm = in;n = m;c = n;endend    

 always语句块对Clk的上升沿敏感,当发生Clk 0~1的跳变时,执行该always语句。

 在begin...end语句块中所有语句是顺序执行的,而且最关键的是,阻塞赋值是在本语句中“右式计算”和“左式更新”完全完成之后,才开始执行下一条语句的。

 在本例中,in的值赋给m以后,再执行n = m;同样在n的值更新以后,才执行c = n。这样,最终的计算结果就是in = c。也就是说时钟上升沿到来的时候,整个语句块执行完后,in,m,n,c的值都是一样的,这也就是我们前面说的,in变化之后,m,n,c都跟着变化。所有的语句执行完以后,该always语句等待Clk的上升沿,从而再一次触发begin...end语句。

总结

完成阻塞赋值的过程为:首先计算等号右边表达式的结果;接着这个结果存入仿真系统的内部临时寄存器中,这个寄存器也称为赋值事件队列和调度的临时寄存器。如果赋值时没有延迟信息,则这个事件立即被调度执行。

(2)对于非阻塞赋值的情况

always @(posedge clk or negedge rst_n) beginif(!rst_n) b <=0;else begine <=in;f <=e;b <=f;endend

首先执行e <= in,产生一个更新事件,将in的当前值赋给e,但是这个赋值过程并没有立刻执行,而是在事件队列中处于等待状态。

然后执行f <= e,同样产生一个更新事件,将e的当前值(注意上一语句中将in值赋给e的过程并没有完成,e还是旧值)赋给f,这个赋值事件也将在事件队列中处于等待状态。

再执行b <= f,产生一个更新事件,将f的当前值赋给b,这个赋值事件也将在事件队列中等待执行。

这时always语句块执行完成,开始对下一个Clk上升沿敏感。也就是说,使用非阻塞赋值方式进行赋值时,各个赋值语句同步执行;因此,通常在一个时钟沿对临时变量进行赋值,而在另一个时钟沿对其进行采样。

那么什么时候才执行那3个在事件队列中等待的事件呢?只有当当前仿真时间内的所有活跃事件和非活跃事件都执行完成后,才开始执行这些非阻塞赋值的更新事件。这样就相当于将in、e和f的值同时赋给了e、f和b。

注:

    *仿真器首先按照仿真时间对事件进行排序,然后再在当前仿真时间里按照事件的优先级顺序进行排序。

    *活跃事件是优先级最高的事件。在活跃事件之间,它们的执行顺序是随机的。阻塞赋值(=)、连续赋值(assign)以及非阻塞赋值的右式计算等都属于活跃事件。

总结 :

非阻塞语句的执行过程为:首先,它会把非阻塞赋值放入调度队列中;接着,仿真工具开始执行下一条语句而不等待当前这条语句执行完毕。也就是说,先计算出等号右边表达式的结果,再把这个结果的赋值操作保存在事件队列中,等轮到事件被调度的时候,把这个结果赋值给等号左边。如果没有指定等号右边的延迟,赋值的操作会发生在当前时间单位的最后时刻。

知道了阻塞赋值和非阻塞赋值的区别之后,大家肯定就会关心什么时候该用阻塞赋值什么时候该用非阻塞赋值,下面我简单的说几句:

赋值的类型的选择取决于建模的逻辑类型。一般情况是这样的(也有特殊情况):(1)在时序逻辑电路中一般使用非阻塞赋值。    非阻塞赋值在块结束后才完成赋值操作,此赋值方式可以避免在仿真出现冒险和竞争现象。(2)在组合逻辑电路中一般使用阻塞赋值。    使用阻塞方式对一个变量进行赋值时,此变量的值在在赋值语句执行完后就立即改变。(3)在assign语句中必须使用阻塞赋值语句

希望大家在懂得了阻塞和非阻塞语句的区别之后,能够很好的在自己的项目中灵活地运用,这也是大家面试的时候,必须会面对的一个问题,希望大家能够掌握!

转载于:https://www.cnblogs.com/xd-elegant/p/3982274.html

Verilog HDL中阻塞语句和非阻塞语句的区别相关推荐

  1. begin end中阻塞语句与非阻塞语句执行顺序的问题

    1 module fsm_2(clk,A,Y); input clk,A; output reg Y; reg q1; always@(posedge clk) begin Y<=q1& ...

  2. Verilog中阻塞赋值和非阻塞赋值的区别

    Verilog中阻塞赋值(=)和非阻塞赋值(<=)的区别 **阻塞赋值:**前面语句执行完,才可执行下一条语句:即:前面语句的执行(b=a)阻塞了后面语句的执行(c=b).即:always块内, ...

  3. verilog中阻塞赋值与 非阻塞赋值的区别

    非阻塞(Non_Blocking)赋值方式( 如 b <= a; ), 块结束后才完成赋值操作,值并不是立刻就改变的, 这是一种比较常用的赋值方法.(特别在编写可综合模块时). 阻塞(Block ...

  4. verilog reg赋初值_Verilog语法之六:阻塞赋值与非阻塞赋值

    本文首发于微信公众号"花蚂蚁",想要学习FPGA及Verilog的同学可以关注一下. 一.初步理解阻塞赋值与非阻塞赋值 在Verilog HDL语言中,信号有两种赋值方式: (1) ...

  5. 【Verilog 基础】阻塞赋值和非阻塞赋值的区别

    目录 阻塞赋值 非阻塞赋值 实际工程仿真 阻塞赋值仿真 编写Verilog代码 编写测试文件代码 综合看RTL图 进行实际仿真 非阻塞赋值仿真 编写Verilog代码 编写测试文件代码 综合看RTL图 ...

  6. 网络传输中的两个阶段、阻塞IO、非阻塞IO和多路复用

    今天学习了网络传输中的两个阶段.阻塞IO.非阻塞IO和多路复用 一.网络传输中的两个阶段 分别是 waitdata 和 copydata send就是copydata recv是waitdata和co ...

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

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

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

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

  9. 硅芯思见:阻塞赋值与非阻塞赋值

    0 丑话说在前边 RHS:运算符(= or <=)右侧的表达式 LHS:运算符(= or <=)左侧的表达式 竞争(Race Condition):在同一仿真时间槽(time-slot)多 ...

最新文章

  1. linux select使用
  2. Spark is not running in local mode, therefore the checkpoint directory must not be on the local……
  3. Ubuntu 软件包管理详解
  4. Intellij IDEA调试
  5. 【TCP传输数据-键盘录入】
  6. Ruby学习-第二章
  7. 用2468这四个数字c语言,C语言作业及参考答案.doc
  8. 华为云PB级数据库GaussDB(for Redis)解析第二期:Redis消息队列Stream的应用探讨
  9. 100行代码搞定抖音短视频App,终于可以和美女合唱了。
  10. 9.6.1 三维数据可视化之曲面图
  11. linux 挂载raid_linux下做raid
  12. 计算机硬盘分区知识简介、Linux企业级分区方案建议
  13. 小工具-悬浮窗LogViewer在android手机上查看数据日志
  14. 【教程:利用Axure快速原型工具制作电影信息网站】——小白也会,傻瓜式做法,简易快速!!!可应对(毕业)课程设计喔!!
  15. VFB直接使用TCP发送电子邮件源码
  16. 电脑桌面的计算机图标都不见了,如何解决电脑桌面的图标都不见了的问题
  17. ccleaner激活后又要注册_ccleaner如何激活? ccleaner注册激活图文步骤
  18. java 加密与解密算法,简单地加密和解密算法(java实现)
  19. 韶关市教育信息化名教师蓝凌工作室成员简介
  20. 程序员是否合格----看看键盘就知道了

热门文章

  1. leetcode - 1221. 分割平衡字符串
  2. 基于图结构的图合成与差分隐私【LDPGen】
  3. 二分查找原理非递归与递归实现【转载】
  4. Apache CXF入门
  5. 百练 03 复杂的整数划分问题
  6. 群同态基本定理证明_有限群的线性表示 | 表示与群代数
  7. 嵩天python123测试6_神华化工股票
  8. 德州python培训_人工智能在多人桌德州扑克比赛中战胜世界顶尖选手
  9. udp打洞没反应_这8种酒精饮料:1亿人在喝,你还没听过
  10. python中for循环-python中关于for循环的碎碎念