0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

阻塞赋值和非阻塞赋值的用法一篇文章就够了

汽车玩家 来源:FPGA技术联盟 作者:Jarvis 2020-01-30 17:41 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

对于VerilogHDL语言中,经常在always模块中,面临两种赋值方式:阻塞赋值和非阻塞赋值。对于初学者,往往非常迷惑这两种赋值方式的用法,本章节主要介绍这两种文章的用法。其实,有时候概念稍微不清楚,Bug就会找到我们,下面一文扫清阻塞赋值和非阻塞赋值所有的障碍。

基本概念

阻塞赋值(Blocking Assignment)

阻塞赋值的基本描述格式为:

[变量] = [逻辑表达式];

阻塞赋值在执行的时候,右端表达式执行并赋值到左边变量,不会受任何情况打断。所以在本次赋值结束之前他“阻塞”了当前其他的赋值任务,阻塞赋值的操作和C语言中的变量赋值非常相似。

非阻塞赋值(Nonblocking assignment)

非阻塞赋值的基本描述格式为:

[变量] 《= [逻辑表达式];

非阻塞赋值行为有些细微之处比较难以理解。我们最好从硬件角度来理解,always模块可以被认为是纯硬件模块,当always模块被激活时,非阻塞赋值的右侧表达式就开始执行;当always模块所有表达式执行结束之后,所有执行结果才赋值到左侧变量当中。之所以称为“非阻塞”就是在本条赋值语句执行的过程中,其他赋值语句也可以执行。

金规

1. 在组合逻辑电路描述中采用阻塞赋值

阻塞赋值和非阻塞赋值虽然都可以用来描述同一电路,以1位比较器举例来解释这种差别。

阻塞赋值实现1bit比较器

module eq1_block

input wire i0, i1,

output reg eq

);

reg p0, p1;

always @(i0,i1) // i0 和i1 在敏感量列表当中

// 语句描述的顺序非常关键

begin

p0 = ~i0 & ~i1;

p1 = i0 & i1;

eq = p0 | p1;

end

endmodule

分析:程序中,敏感量列表中包含i0和i1,只要这两个变量有一个发生改变,都会激活always语句,那么p0、p1和eq就会顺序赋值,最终eq赋值就会被更新,所以这三条语句的描述顺序非常关键,假如将最后一条语句提前:

always @(i0,i1)

begin

eq = p0 | p1;

p0 = ~i0 & ~i1;

p1 = i0 & i1;

end

在第一条描述中,由于p0和p1还没有被赋予新值,所以p0和p1依然保持原来的赋值,这样得到的最终结果显然是错误的。

非阻塞赋值实现1bit比较器

module eq1_non_block

input wire i0, i1,

output reg eq

);

reg p0, p1;

always @(i0,i1,p0,p1) // p0, p1依然在敏感量列表中

// 描述顺序无关紧要

begin

p0 《= ~i0 & ~i1;

p1 《= i0 & i1;

eq 《= p0 | p1;

end

endmodule

分析:p0和p1包含在敏感量列表当中,当i0 或者 i1有所变化,always模块被激活,p0和p1在第一个时钟节拍结束时赋值,由于eq值为基于p0和p1原来保持值的赋值,所以eq不变,当前赋值结束时,always模块重新被激活,由于p0和p1被改变(这就是p0和p1放在敏感量列表中的原因),eq变量在第二个时钟节拍赋予了新值。从以上分析,即使将以上语句的顺序发生改变,也不会影响最终结果,因为eq的赋值以及always模块的激活与这些语句的顺序并没关系。

总结:虽然两种描述方法都可以描述同一电路,但是两个电路的结果是有区别的,采用非阻塞赋值法描述仿真的时候花的时间更长一些,电路输出结果在时序上也有微弱差别,鉴于此,我们有这么一条原则“在组合逻辑电路描述中采用阻塞赋值”。

2. 时序逻辑描述,采用非阻塞赋值方式赋值

就单独一个寄存器来说,阻塞赋值和非阻塞赋值都可以描述存储单元,如DFF可以描述为

always@(posedge clk)

q 《= d;

也可以描述为

always@(posedge clk)

q = d;

但是当设计中存在多个寄存器描述单元的时候,就会有细微的查别,假设有两个寄存器在每个时钟的上升沿进行数据交换,采用阻塞赋值描述如下:

always@(posedge clk)

a = b;

always@(posedge clk)

b = a;

在时钟的上升沿,两个always语句同时被激活并且并行执行,一个时钟节拍后两条语句执行结束,按照verilog语法标准,两个always语句执行结果时间顺序上谁都有可能在前面,这样一来,如果第一个always语句执行在前面,由于阻塞赋值,所以变量a立即得到b的赋值,那么当第二个always块执行之后,变量b得到a的赋值,由于刚才第一个always执行的时候b值赋予了a,所以现在b的值会维持不变,还是原来的值。

同样的道理,如果第二个always模块先执行了,那么a就会保持自身值不变,从Verilog语法角度来看,两种结果都是有效的。但是从数字电路的角度来说,明显引起了竞争。

下面我们将阻塞赋值修改为非阻塞赋值,以上代码修改为:

always@(posedge clk)

a 《= b;

always@(posedge clk)

b 《= a;

采用非阻塞赋值,由于原始信号在赋值语句中使用,所以a和b都会得到正确的值,而与顺序没有关系。所以在时序逻辑描述中,阻塞赋值往往会引起条件竞争,所以要采用非阻塞赋值方式赋值。

总结一下

① 在组合逻辑电路描述中采用阻塞赋值

② 时序逻辑描述,采用非阻塞赋值方式赋值

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 阻塞赋值
    +关注

    关注

    0

    文章

    10

    浏览量

    9321
  • VerilogHDL
    +关注

    关注

    2

    文章

    39

    浏览量

    19796
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    飞凌嵌入式ElfBoard-文件I/O的深入学习之阻塞I/O与阻塞I/O

    可能会使程序阻塞等待,直到有数据可读时才会被唤醒返回。 普通文件的读写操作是不会阻塞的,不管读写多少个字节数据,read或 write定会在有限的时间内返回,所以普通文件定是以
    发表于 12-01 13:07

    Siumulink模型测试典型问题分享——模型层级设计不合理

    典型测试问题分享-模型层级设计不合理 问题描述: 重点功能与重点功能混合,导致测试层级选择困难。 模型未体现层级划分,结构平铺导致层级圈复杂度异常。 部分计算/判断/赋值等结构位于测试层级之外,存在未覆盖风险。
    的头像 发表于 09-20 12:31 2779次阅读
    Siumulink模型测试典型问题分享——模型层级设计不合理

    CH32V307 串口发送阻塞的原因?怎么解决?

    */ modbus_set_rx_mode(master); modbus发送,不知为何阻塞在rt_device_write,初始化 find open 正常
    发表于 09-18 06:06

    【HZ-RK3568开发板免费体验】基于 Select Poll的TCP发服务器

    般分为网络IO(本质就是socket读写)和磁盘IO。 IO模型大致可以分为:同步阻塞、同步阻塞、异步、信号驱动。 可细分为5种I/O模型: 1)
    发表于 08-19 22:01

    matlab appdesigner 表格组件赋值问题,求助

    如上图所示,我在用matlab2021Ra APP模块进行编程的时候,想在表格中调入自己编写的结构数组,我从网上AI了个程序语句,看着没问题,但是就是给表格赋值不了,还请各位大神帮忙看下这个是怎么回事,我是初学者,请各位帮
    发表于 07-12 11:45

    CH32V307串口发送阻塞的原因?如何解决?

    */ modbus_set_rx_mode(master); modbus发送,不知为何阻塞在rt_device_write,初始化 find open 正常
    发表于 06-11 08:05

    harmony OS NEXT-Navagation基本用法

    # Navagation基本用法 > Navigation组件是路由导航的根视图容器,般作为Page页面的根容器使用,其内部默认包含了标题栏,内容栏和公工具栏,其中内容区默认首页显示导航内容
    的头像 发表于 04-27 17:39 702次阅读

    《电子发烧友电子设计周报》聚焦硬科技领域核心价值 第8期:2025.04.14--2025.04.18

    输出。 7、在testbench中如何使用阻塞赋值阻塞赋值 https://www.elecfans.com/d/6535823.htm
    发表于 04-18 20:03

    在testbench中如何使用阻塞赋值阻塞赋值

    本文详细阐述了在个testbench中,应该如何使用阻塞赋值阻塞赋值。首先说结论,建议在t
    的头像 发表于 04-15 09:34 1005次阅读
    在testbench中如何使用<b class='flag-5'>阻塞</b><b class='flag-5'>赋值</b>和<b class='flag-5'>非</b><b class='flag-5'>阻塞</b><b class='flag-5'>赋值</b>

    在S32DS上使用JLINK调试S32K341,被阻塞了,怎么处理?

    我正在尝试使用 S32K341 在新板上刷写程序,但在 S32K3X4EVB 上运行并为 S32K341配置的相同代码出现错误。具体来说,当我使用 S32DS 的 J-Link 探针运行调试时,它在此地址被阻塞,并且不会将其闪存到内存中。有人遇到同样的问题或可以帮助我吗?
    发表于 04-03 08:13

    FreeRTOS进阶使用之流缓冲区:高效处理字节流的秘密武器

    开销 基于连续内存存储,相比队列(每个数据项独立存储)更节省RAM。 触发通知机制 当缓冲区数据量达到预设的触发阈值**时,自动唤醒等待的任务,避免轮询开销。 阻塞阻塞模式 阻塞
    发表于 03-24 11:37

    给uint32_t数组填充整型值,除使用循环赋值外有没有c库函数可以实现?

    给uint32_t数组填充整型值,除使用循环赋值外有没有c库函数可以实现
    发表于 03-07 17:05

    “串口阻塞”你真的会用吗?

    很久才会发出来,下子出来很多数据”。经过帮客户检查应用程序源码,发现应用程序在串口阻塞方面没有做正确的处理,修改后解决。阻塞打开串口open("/dev/tty
    的头像 发表于 02-13 11:42 1199次阅读
    “串口<b class='flag-5'>阻塞</b>”你真的会用吗?

    使用TLV5625在主函数里面的FOR循环中对两通道赋值个通道不能更新数据是怎么回事?

    问题:我在使用TLV5625时出现如下问题,在主函数里面的FOR循环中对两通道赋值,2通道DA可以正常更新输出,但是同样的语句放到定时器中断中,只有个通道正常,另个通道不能更新数据,请指教
    发表于 01-08 08:23

    写了个ADS1118的AD转换程序,不知道是不是SPI的写入函数出问题了,返回的值和理论值不同且无法给变量赋值,为什么?

    写了个ADS1118的AD转换程序,不知道是不是SPI的写入函数出问题了,返回的值和理论值不同,且无法给变量赋值,程序如下: unsigned int Write_SIP(unsigned
    发表于 12-09 06:24