从事件调度理解阻塞和非阻塞

事件调度3-事件队列入队和出队 Verilog事件调度机制解析:从入队到执行的完整流程 Verilog仿真器通过精细的事件队列系统控制代码执行顺序,分为五大关键阶段:1)活跃事件(阻塞赋值、$display等随机执行);2)非活跃事件(#0延时语句);3)非阻塞赋值更新(<=左式更新);4)监控事件($strobe等);5)将来事件(延时操作)。其中非阻塞赋值的"右式计算-左式更新"两阶段机制完美模拟硬件寄存器特性,而$strobe在监控阶段执行可确保观察最终值。理解这种调度机制可避免常见的竞争条件问题,指导开发 阅读详情

0 为什么要有事件调度

我们知道Verilog是一种并行编程语言,然而Verilog是通过计算机执行的,那么必然要遵循计算机顺序执行的逻辑

当多条语句都被触发时,我们如何确定语句的执行顺序就需要一种规则来做出限定

1 几个关键信息

仿真的代码是由一个个离散事件组成,运行Verilog也就是执行一个个时间和线程

进程包括UDP、module、initial块、always块、连续赋值语句、异步任务和过程赋值语句

在进行仿真时,所有线网、变量和命名块发生变化时,都被认为是更新事件,而进程对更新事件是敏感的,更新事件执行时,所有对该实践敏感的进程都会按照任意顺序进行评估

仿真时间用来模拟被仿真电路所需的实际时间

2 事件队列

Verilog事件队列被分为五个区域:活跃事件、非活跃事件、非阻塞赋值更新时间、监视事件和将来事件

下面是大佬总结的图

在执行顺序上:活跃事件 -> 非活跃事件 -> 非阻塞赋值更新事件 -> 监控事件 -> 将来事件

不过这五个事件内包含的操作,它们的执行顺序是随机的

我对当前仿真时间的理解是当T,将来仿真时间是次T

3 确定性和不确定性

3.1 确定性
  1. begin…end中的语句都是按顺序执行的
  2. 非阻塞赋值的执行顺序也是按照语句出现的顺序执行
initial begin
   a <= 0;
   a <= 1;
end

以上面这个例子来说,根据确定性可知,两条语句的执行按顺序执行的,在进入非阻塞赋值更新时,变量a的值先被更新为0,后被更新为1

3.2 不确定性

在确定性中指出,在一个block中,所有语句的执行都是顺序执行的,那如果语句不在同一个block中呢?

对于不同的block,具体是哪个block先执行,这个行为是不确定的,比如下面这个例子

assign q = a;

always @(*) begin
    q = b;
end

两条语句在不同的block中,而这两个block我们没办法预知到底是哪个block先执行,因此最终变量q是a的值还是b的值是不确定的,这也是为什么在学习Verilog时一直在强调,同一个变量不能在多个block中进行赋值

4 阻塞和非阻塞

从上面的调度表可以看出,阻塞赋值在活跃事件中;非阻塞的右式计算在活跃事件中,而更在非阻塞赋值更新事件中

由于事件队列的执行是顺序执行的,当仿真进入当前仿真时间时,先执行活跃事件,对于阻塞和非阻塞来说,当进入活跃事件时,阻塞赋值进行右式计算,并将计算的结果赋值给左式,而对于非阻塞赋值,此时只进行右式的计算,但不会立即将结果更新到左式,直到事件队列进入非阻塞赋值更新事件时,才更新非阻塞赋值的左式

说的可能不好理解,我们用例子来做说明

module test;
    reg [1:0] a,b;

    initial begin
         a = 2'b11;
    end

    initial begin
        b <= 2'b1;
    end

    initial begin
        $display($time, ,"\$display: a-> %b", a);
        $display($time, ,"\$display: b-> %b", b);
        #10;
        $finish;
    end

endmodule

从上面的事件调度表中可以知道,在这个例子中,阻塞赋值、非阻塞赋值的右式计算和$display都属于活跃事件

那么对于这个例子可以做出提前预测结果,变量a成功赋值,变量b没有完成赋值,来看看运行结果

可以看到运行结果与我们的猜测一致

同样的,如果我们加入监控事件,那么在监控事件中可以看到变量b的成功赋值

module test;
    reg [1:0] a,b;

    initial begin
         a = 2'b11;
    end

    initial begin
        b <= 2'b1;
    end

    initial begin
        $display($time, ,"\$display: a-> %b", a);
        $display($time, ,"\$display: b-> %b", b);
        #10;
        $finish;
    end

    initial begin
        $strobe($time, ,"\$strobe: a-> %b", a);
        $strobe($time, ,"\$strobe: b-> %b", b);
    end
endmodule

可以看到,在$strobe中,变量b成功赋值

回观调度表,有一个显示零延迟(#0),而#0延迟是处于非活跃事件的,那么我们再做一个小更改

module test;
    reg [1:0] a,b;

    initial begin
         #0 a = 2'b11;
    end

    initial begin
        b <= 2'b1;
    end

    initial begin
        $display($time, ,"\$display: a-> %b", a);
        $display($time, ,"\$display: b-> %b", b);
        #10;
        $finish;
    end

    initial begin
        $strobe($time, ,"\$strobe: a-> %b", a);
        $strobe($time, ,"\$strobe: b-> %b", b);
    end
endmodule

可以看到,当我们给阻塞赋值加上#0延迟后,$display不在显示变量a的赋值,因为加上#0延迟后,阻塞赋值进入非活跃事件队列,而处于活跃事件队列的$display自然无法打印变量a的值

同时监控事件$strobe能够打印变量a的值,说明加上#0延迟后,阻塞赋值还是属于当前仿真时间中,并未进入将来仿真事件,而如果我们给阻塞赋值加入一个非0延迟

module test;
    reg [1:0] a,b;

    initial begin
         #1 a = 2'b11;
    end

    initial begin
        b <= 2'b1;
    end

    initial begin
        $display($time, ,"\$display: a-> %b", a);
        $display($time, ,"\$display: b-> %b", b);
        #10;
        $finish;
    end

    initial begin
        $strobe($time, ,"\$strobe: a-> %b", a);
        $strobe($time, ,"\$strobe: b-> %b", b);
    end
endmodule

当加入非0延迟,$strobe便无法获取变量a的赋值

参考资料

( Verilog HDL分层事件队列_formerman的博客-优快云博客

verilog-std-1364-2005

事件调度0-UVM事件调度引起的竞争(附源码) 摘要:本文分析了UVM验证环境中同一仿真时间点出现信号值不一致的现象。通过一个具体案例,揭示了该现象源于SystemVerilog事件调度机制:在T=18000ns时钟上升沿,Active Region先读取非阻塞赋值前的ready=1值并打印;随后NBA Region更新cnt和ready值至0;最后Active Region再次执行时读取新值ready=0。这种分区域执行机制导致同一时间步内信号值"变化"的假象,属于正常行为而非错误。建议修改driver代码,在时钟沿后判断信号状态以 阅读详情

相关推荐

事件调度1-Verilog仿真器到底是怎么工作的?

Verilog仿真模型的核心是基于事件队列的调度机制,采用分层处理策略。仿真器按时间顺序处理任务,同一时刻的事件分为四个优先级:活动事件、#0延迟任务、非阻塞赋值更新和监控任务。非阻塞赋值采用"先计算后统一更新"的方式,有效避免了竞争问题,模拟了硬件寄存器同步更新的特性。通过阻塞与非阻塞赋值的对比示例,展示了后者在变量交换中的正确性优势。理解这一事件调度模型有助于编写正确的时序/组合逻辑代码,并解释仿真过程中的时序行为。

qq_36143127的博客 685

阻塞、非阻塞、同步、异步

异步机制,在实际工作中,往往是用户向异步实现模块注册回调,线程发送请求并注册回调之后,就交给底层的异步模块来负责,线程就不用关心了,有事件到来之后,异步调度模块会自动调用用户注册的回调。领导给你下发任务之后,并不是只盯着你的工作,其它什么工作都不做了。而是给你安排任务之后,就去做其它工作了,但是领导过一会就来问你,工作完成了没有,直到你工作完成,就不来问你了。领导给你下发了任务,下发之后,领导什么事都不做了,而是坐在你的工位旁边,一直监督着你来工作,直到你完成工作,领导才回去做其它的工作,这就是阻塞模式。

weixin_38184628的博客 764

[SystemVerilog语法拾遗] 一文讲清楚SystemVerilog中的阻塞赋值与非阻塞赋值

一文讲清楚SystemVerilog中的阻塞赋值与非阻塞赋值

sunstat的博客 2713

【软考笔记】2. 操作系统基本原理

微内核操作系统只实现基本功能,把图形系统,文件系统,设备驱动和通信功能放在内核之外。技巧:在每个箭头的出发点加一个 V 操作,在每个箭头的终点加一个 P 操作。给每个进程分配它需要的资源数 -1 个,然后再来一个资源,一定不会发生死锁。核心思想:评估该进程是否能及时归还资源,如果不能,就不将此资源放出去。先把资源分给 A 进程,再分给 B 进程,再分给 C 进程。互斥的反义词是共享,同步(需要等待)的反义词是异步。将活跃转为静止是挂起,将静止转为活跃是激活。,则是以进程为单位,按逻辑结构划分。

Ranye的博客 373

从Testbench仿真失效案例,解析FPGA中阻塞与非阻塞赋值的核心差异

本文通过Testbench仿真失效案例,深入解析FPGA中阻塞赋值与非阻塞赋值的核心差异。文章详细对比了两种赋值方式的执行机制和硬件映射关系,揭示了仿真与综合的时空观差异,并提供了Testbench中的正确建模准则和调试技巧,帮助开发者避免常见的赋值陷阱,提升FPGA设计的可靠性和仿真准确性。

weixin_30823001的博客 432

【SV】从仿真器调度机制看非阻塞赋值与延迟控制的协同设计。理解NBA区域与Active事件的交互

本文深入解析SystemVerilog仿真器调度机制中非阻塞赋值(NBA)与延迟控制的协同设计。通过剖析Active事件区与NBA区域的交互关系,揭示阻塞赋值与非阻塞赋值的核心差异及其在时序逻辑、组合逻辑中的应用场景,帮助开发者避免竞争冒险,写出更可靠的硬件模型。

weixin_42549496的博客 353

(Verilog) 阻塞型和非阻塞型的assign语句

在组合型always块中使用阻塞式赋值,在时钟型always块中使用非阻塞式赋值。不遵循此规则会导致非确定性且在仿真和合成的硬件之间不同的极难发现的错误。时钟型always块创建了一个与组合型always块类似的组合逻辑块,但还在组合逻辑块的输出处创建了一组触发器(或“寄存器”)。与组合逻辑块的输出立即可见不同,输出只在下一个(posedge clk)之后立即可见。仅在不在过程("always block")中使用时可用。过程非阻塞式赋值:(x

烧烤团子 1564

基于事件调度的Actor模型

概念 事件在这里可以理解为消息到达事件,事件到来时才为Actor分配线程并执行消息的处理。这样便可以使用少量的线程来执行大量Actor产生的任务,Actor有消息要处理的时候才占用CPU,没有的时候就挂起,保证了每个线程都在高效执行任务。 Actor模型组成 cpu 用于执行线程,目前单机上为多核。 workthread 工作线程,保证线程数目&amp;lt;=cpu核数,否则只会把cpu时间浪费在线...

lewiskyo的专栏 1187

Verilog 阻塞赋值与非阻塞赋值

说明了阻塞赋值和非阻塞赋值的差异,并依据实例详述错误使用阻塞赋值的影响

Richard_D的博客 1492

#systemverilog# 之 event region 和 timeslot 仿真调度(三)概念

SystemVerilog是HDVL语言,相较与,除了面向HW design应用,也为了提高verif的效率。所以其仿真调度算法在向下兼容Verilog的同时,增加了不少新的‘Time region’,以便更好的支持program块等针对验证需求的新特性。SV不同于C/C++等软件语言,为了对硬件进行仿真建模,所以有很多并行的process,而仿真器作为运行在CPU上的软件,只是按照SV LRM的仿真调度算法,开始仿真后,将仿真时间串行的一步步的向前推进。

那么菜的博客 1591

ACR 磁共振安全手册 2024 更新版:全面保障 MRI 安全实践

MR 环境:MR 系统周围的三维空间,包含法拉第屏蔽体积和 9 高斯线,医疗设备在此区域可能因暴露于 MR 设备产生的电磁场而构成危险,需进行访问控制以降低风险MR 受控访问区域:MR 系统周围的局部定义区域,包含 MR 环境(包括其静磁场),访问仅限于授权人员MR 抛射物区域:围绕 MRI 系统的 IV 区区域,铁磁物体在此有成为抛射物的风险图一 磁共振环境:场地规划与区域划分。

楚山之石的博客 2603

Verilog HDL**阻塞赋值和非阻塞赋值

阻塞赋值 符号“=”用于阻塞的赋值,凡是在组合逻辑(如在assign语句中)赋值的需要使用用阻塞赋值。阻塞赋值“=”在begin和end之间的语句是顺序执行,属于串行语句。always语句的敏感变量如果不含有时钟,即always(*)这样描述,那么也属于组合逻辑,需要使用阻塞赋值。 一个组合逻辑的例子: always @(*) begin case (led_ctrl_cnt) 2'd0...

EDA自学笔记 1520

Windows 11 下 WSL 离线安装 Ubuntu 22.04 保姆级教程(国内镜像加速版)

本文提供了一份针对中国地区用户的Windows 11下WSL离线安装Ubuntu 22.04的详细教程。通过使用国内镜像源加速下载安装包,并配合PowerShell命令完成部署,有效解决了官方商店下载缓慢的问题。教程涵盖环境准备、离线包获取、安装初始化及安装后的关键优化配置,帮助用户快速搭建高效的Linux开发环境。

weixin_28452161的博客 1378

SYSTEMVERILOG LRM 学习笔记 -- SV SCHEDULER仿真调度

1. 为什么要理解scheduler? SystemVerilog是HDVL语言,相较与Verilog,除了面向HW design应用,也为了提高verif的效率。所以其仿真调度算法在向下兼容Verilog的同时,增加了不少新的‘Time region’,以便更好的支持program块等针对验证需求的新特性。 SV不同于C/C++等软件语言,为了对硬件进行仿真建模...

luxinwylive的博客 1304

别再只跑memtester了!嵌入式Linux内存压力测试,这5个参数和场景你试过吗?

本文深入探讨了嵌入式Linux内存压力测试的高级技巧,重点解析了memtester工具的5个关键参数和实战场景。通过物理地址测试、迭代控制、内存分配策略等调优方法,帮助开发者有效检测内存稳定性问题,适用于长期运行设备、特定故障重现等复杂场景,提升嵌入式系统可靠性。

weixin_30838873的博客 425

glibc: GLIBC_2.28‘ not found

这个时候,应该怎么解决,因为当前运行的机器是低版本,而程序是高版本,解决方法,或者是将程序降级,或者将当前系统升级。在一个glibc的接口版本是GLIBC_2.25的lab上,运行不了在2.28上编译的程序。看哪一个方便,但是不能通过 临时复制libc.so 文件来解决,因为会遇到下面的错误。所以如果是简单解决就是按照低版本的应用程序,来适配当前系统的glibc版本。比如下面的程序运行提示。

mzhan017的博客 2407

Verilog基础:避免混合使用阻塞和非阻塞赋值

Verilog设计中应避免在同一个always块中混用阻塞和非阻塞赋值。虽然这种写法在某些情况下能正常工作,但会带来仿真行为与硬件不一致、代码可读性差、调试困难等问题。规范做法是将组合逻辑和时序逻辑分开描述:组合逻辑使用assign或单独的always块实现阻塞赋值,时序逻辑使用非阻塞赋值。这种分离式写法能更清晰地映射实际电路结构,减少仿真歧义,提高代码可维护性,是大型工程中的推荐编码风格。

保持终身学习的能力,温故而知新 2577

雷达参数的设置

采样率又可以叫做采样速率或者,顾名思义就是每秒采集的次数。该值越高,单位时间内对信号的采集越多,采样率的单位可以用Hz或者sps表示(sps是采样率,是每秒采样点的数量,sp表示采样点数),一般1sps=1Hz。采样时间是采样点数和采样周期的乘积得到的结果。假设实际采样率为4560ksps,采样点数为256,那么采样周期为1/4560(ms),那么ADC的采样时间就为256*(1/4560)(ms)=0.056ms=56微秒。

qq_50974341的博客 1912

Verilog基础:时序调度中的竞争(四)(描述时序逻辑时使用非阻塞赋值)

作为一个硬件描述语言,Verilog HDL常常需要使用语句描述并行执行的电路,但其实在仿真器的底层,这些并行执行的语句是有先后顺序的,然而Verilog标准并没有将这些事件调度的顺序定死,而是给予了仿真器厂商一定的自由去实现自己的产品,这就导致了设计者如果不遵循一定的编程习惯,会导致意想不到的仿真结果,下面是一些相关的规则。

保持终身学习的能力,温故而知新 2265

基于Simulink的永磁同步电机容错控制(缺相容错)

本文基于Simulink平台,详细介绍了永磁同步电机(PMSM)缺相容错控制的仿真实现方法。针对逆变器开路故障导致的缺相问题,提出"检测-重构-补偿"三阶段控制策略:采用电流阈值法快速检测故障(<5ms),重构αβ坐标系实现两相矢量控制,并通过谐波电流注入抑制转矩脉动(<8%)。仿真结果表明,该方法能有效维持故障后电机运行,转速波动<3%,满足电动汽车等关键应用的可靠性需求。文章包含完整的Simulink建模步骤、MATLAB函数代码及参数设置,为工程实践提供了可复现的

xiaoheshang_123的博客 147

9、工业数据管理:Historian、ERP、MES与资产模型解析

本文深入解析了工业数据管理中的核心概念与技术,包括Historian数据库、ERP和MES系统以及资产模型。文章详细介绍了Historian数据库的特性、架构分类、数据采集方式及时间序列处理能力,同时探讨了ERP和MES系统的功能与优势,特别是MES在生产执行中的重要作用。资产模型部分结合ISA-95和ISA-88标准,阐述了工业资产的层次化建模方法。此外,文章还分析了各系统之间的协同关系、面临的挑战及应对策略,并展望了未来工业数据管理的发展趋势,如云原生技术、人工智能融合和工业物联网的应用。

pz89012345的博客 144

OpenResty/Nginx 事件驱动和lua协程非阻塞I/O 原理

OpenResty通过Nginx事件驱动模型和Lua协程实现高性能非阻塞I/O处理。其核心机制是:当协程遇到I/O操作时,注册事件后立即挂起,由Nginx处理其他请求,待事件就绪后恢复执行。这种设计使得单线程Worker能高效处理大量并发连接,如WebSocket长连接,通过非阻塞I/O和协程调度实现高并发。关键点包括:1)协程轻量级且非抢占式调度;2)所有I/O操作设置超时避免阻塞;3)事件驱动模型高效轮询就绪事件。4个Worker进程可支撑数千连接,突破了传统阻塞模型的限制。

yaotianhao1005的博客 800

SolidWorks 小车底盘 装配体

通过制作小车底盘了解solidworks装配体的部分知识

及时总结 2229

非阻塞与多路复用的关系与区别

非阻塞I/O是打破传统阻塞模型的基础,它赋予单个I/O操作“不阻塞进程”的能力;而多路复用则是协调多个非阻塞I/O的“调度器”,通过内核的高效管理实现“一对多”的事件驱动。非阻塞是多路复用的必要条件:没有非阻塞I/O,多路复用无法实现多流并发处理;多路复用是规模化非阻塞的最优解:当非阻塞I/O的数量超过一定阈值,唯有借助内核级的多路复用机制,才能避免用户态轮询的性能灾难。从select到epoll。

岁月静好 987

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Verilog阻塞赋值 vs 非阻塞赋值:事件队列深解与黄金法则(不再踩坑)

Verilog阻塞与非阻塞赋值核心解析 摘要 Verilog中阻塞赋值(=)与非阻塞赋值(<=)的区别是硬件设计的关键概念。阻塞赋值立即执行并更新变量,适合组合逻辑;非阻塞赋值在时间步结束时更新,模拟寄存器并行特性,适用于时序逻辑。必须遵循黄金法则: 组合逻辑使用阻塞赋值 时序逻辑使用非阻塞赋值 禁止混用两种赋值方式 典型错误案例显示,在移位寄存器中使用阻塞赋值会导致功能错误。深入理解Verilog事件队列的分层执行机制(Active/NBA区域)是掌握赋值语义的基础。SystemVerilog通过语

weixin_44413306的博客 2119

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

从面试题解析poll实现双重非阻塞:高并发网络编程核心模型

I/O多路复用是网络编程中的关键技术,它允许单个线程同时监控多个文件描述符的状态变化,从而高效处理大量并发连接。其核心原理在于操作系统提供select、poll、epoll等系统调用,将多个I/O事件的等待合并为一次系统调用,避免为每个连接创建独立线程带来的资源消耗。这一机制的技术价值在于显著提升服务器的并发处理能力和资源利用率,是实现高性能网络服务(如游戏服务器、实时通信中间件)的基础架构。在实际应用中,结合非阻塞I/O模式,可以构建出“双重非阻塞”的健壮系统:第一层通过fcntl设置O_NONBLOCK

weixin_33508411的博客 340

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

上一篇: 赋值时‘1和‘b1有什么区别
下一篇: 学习记录-Python的局部变量和全局变量
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值