ImageVerifierCode 换一换
格式:DOCX , 页数:28 ,大小:36.95KB ,
资源ID:1510027      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bingdoc.com/d-1510027.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(阻塞赋值和非阻塞赋值Word格式.docx)为本站会员(b****2)主动上传,冰点文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰点文库(发送邮件至service@bingdoc.com或直接QQ联系客服),我们立即给予删除!

阻塞赋值和非阻塞赋值Word格式.docx

1、从理论上讲,它与后面的赋值语句只有概念上的先后,而无实质上的延迟。 若在RHS 加上延迟,则在延迟期间会阻止赋值语句的执行, 延迟后才执行赋值,这种赋值语句是不可综合的,在需要综合的模块设计中不可使用这种风格的代码。 阻塞赋值的执行可以认为是只有一个步骤的操作: 计算RHS并更新LHS,此时不能允许有来自任何其他Verilog语句的干扰。 所谓阻塞的概念是指在同一个always块中,其后面的赋值语句从概念上(即使不设定延迟)是在前一句赋值语句结束后再开始赋值的。 如果在一个过程块中阻塞赋值的RHS变量正好是另一个过程块中阻塞赋值的LHS变量,这两个过程块又用同一个时钟沿触发,这时阻塞赋值操作会

2、出现问题,即如果阻塞赋值的次序安排不好,就会出现竞争。若这两个阻塞赋值操作用同一个时钟沿触发,则执行的次序是无法确定的。下面的例子可以说明这个问题:例1. 用阻塞赋值的反馈振荡器 module fbosc1 (y1, y2, clk, rst); output y1, y2; input clk, rst; reg y1, y2; always (posedge clk or posedge rst) if (rst) y1 = 0; / reset else y1 = y2; if (rst) y2 = 1; / preset else y2 = y1; endmodule 按照IEEE V

3、erilog 的标准,上例中两个always块是并行执行的,与前后次序无关。如果前一个always块的复位信号先到0时刻,则y1 和y2都会取1,而如果后一个always块的复位信号先到0时刻,则y1 和y2都会取0。这清楚地说明这个Verilog模块是不稳定的会产生冒险和竞争的情况。非阻塞赋值非阻塞赋值操作符用小于等于号 (即 = )表示。为什么称这种赋值为非阻塞赋值?这是因为在赋值操作时刻开始时计算非阻塞赋值符的RHS表达式,赋值操作时刻结束时更新LHS。在计算非阻塞赋值的RHS表达式和更新LHS期间,其他的Verilog语句,包括其他的Verilog非阻塞赋值语句都能同时计算RHS表达式

4、和更新LHS。非阻塞赋值允许其他的Verilog语句同时进行操作。非阻塞赋值的操作可以看作为两个步骤的过程:在赋值时刻开始时,计算非阻塞赋值RHS表达式。在赋值时刻结束时,更新非阻塞赋值LHS表达式。非阻塞赋值操作只能用于对寄存器类型变量进行赋值,因此只能用在initial块和always块等过程块中。非阻塞赋值不允许用于连续赋值。例2. 用非阻塞赋值的反馈振荡器 module fbosc2 (y1, y2, clk, rst); if (rst) y1 = 0; else y1 = y2; if (rst) y2 = 1; else y2 = y1;同样,按照IEEE Verilog 的标准

5、,上例中两个always块是并行执行的,与前后次序无关。无论哪一个always块的复位信号先到, 两个always块中的非阻塞赋值都在赋值开始时刻计算RHS表达式,而在结束时刻才更新LHS表达式。所以这两个always块在复位信号到来后,在always块结束时 y1为0而y2为1是确定的。从用户的角度看这两个非阻塞赋值正好是并行执行的。Verilog模块编程要点:下面我们还将对阻塞和非阻塞赋值做进一步解释并将举更多的例子来说明这个问题。在此之前,掌握可综合风格的Verilog模块编程的八个原则会有很大的帮助。在编写时牢记这八个要点可以为绝大多数的Verilog用户解决在综合后仿真中出现的90-

6、100% 的冒险竞争问题。1) 时序电路建模时,用非阻塞赋值。2) 锁存器电路建模时,用非阻塞赋值。3) 用always块建立组合逻辑模型时,用阻塞赋值。4) 在同一个always块中建立时序和组合逻辑电路时,用非阻塞赋值。5) 在同一个always块中不要既用非阻塞赋值又用阻塞赋值。6) 不要在一个以上的always块中为同一个变量赋值。7) 用$strobe系统任务来显示用非阻塞赋值的变量值8) 在赋值时不要使用 #0 延迟我们在后面还要对为什么要记住这些要点再做进一步的解释。Verilog的新用户在彻底搞明白这两种赋值功能差别之前,一定要牢记这几条要点。照着要点来编写Verilog模块程

7、序,就可省去很多麻烦。Verilog的层次化事件队列 详细地了解Verilog的层次化事件队列有助于我们理解Verilog的阻塞和非阻塞赋值的功能。所谓层次化事件队列指的是用于调度仿真事件的不同的Verilog事件队列。在IEEE Verilog标准中,层次化事件队列被看作是一个概念模型。设计仿真工具的厂商如何来实现事件队列,由于关系到仿真器的效率,被视为技术诀窍,不能公开发表。本节也不作详细介绍。在IEEE 1364-1995 Verilog标准的5.3节中定义了: 层次化事件队列在逻辑上分为用于当前仿真时间的4个不同的队列, 和用于下一段仿真时间的若干个附加队列。1) 动态事件队列(下列事

8、件执行的次序可以随意安排) 阻塞赋值 计算非阻塞赋值语句右边的表达式 连续赋值 执行$display命令 计算原语的输入和输出的变化 2) 停止运行的事件队列 #0 延时阻塞赋值 3) 非阻塞事件队列 更新非阻塞赋值语句LHS(左边变量)的值 4) 监控事件队列 执行$monitor 命令 执行$strobe 命令 5) 其他指定的PLI命令队列 (其他 PLI 命令) 以上五个队列就是Verilog 的“层次化事件队列” 大多数Verilog事件是由动态事件队列调度的,这些事件包括阻塞赋值、连续赋值、$display命令、实例和原语的输入变化以及他们的输出更新、非阻塞赋值语句RHS的计算等。

9、而非阻塞赋值语句LHS的更新却不由动态事件队列调度。 在IEEE标准允许的范围内被加入到这些队列中的事件只能从动态事件队列中清除。而排列在其他队列中的事件要等到被“激活”后,即被排入动态事件队列中后,才能真正开始等待执行。IEEE 1364-1995 Verilog 标准的5.4节介绍了一个描述其他事件队列何时被“激活”的算法。 在当前仿真时间中,另外两个比较常用的队列是非阻塞赋值更新事件队列和监控事件队列。细节见后。 非阻塞赋值LHS变量的更新是按排在非阻塞赋值更新事件队列中。而RHS表达式的计算是在某个仿真时刻随机地开始的,与上述其他动态事件是一样的。 $strobe 和 $monitor

10、显示命令是排列在监控事件队列中。在仿真的每一步结束时刻,当该仿真步骤内所有的赋值都完成以后,$strobe 和 $monitor显示出所有要求显示的变量值的变化。在Verilog标准5.3节中描述的第四个事件队列是停止运行事件队列,所有#0延时的赋值都排列在该队列中。采用#0延时赋值是因为有些对Verilog理解不够深入的设计人员希望在两个不同的程序块中给同一个变量赋值,他们企图在同一个仿真时刻,通过稍加延时的赋值来消除Verilog可能产生的竞争冒险。这样做实际上会产生问题。因为给Verilog模型附加完全不必要的#0延时赋值,使得定时事件的分析变得很复杂。我们认为采用#0延时赋值根本没有必

11、要,完全可用其他的方式来代替,因此不推荐使用。在下面的一些例子中,常常用上面介绍的层次化事件队列来解释Verilog代码的行为。时件队列的概念也常常用来说明为什么要坚持上面提到的8项原则。自触发always块一般而言,Verilog的always块不能触发自己,见下面的例子: 例3 使用阻塞赋值的非自触发振荡器 module osc1 (clk); output clk; reg clk; initial #10 clk = 0; always (clk) #10 clk = clk;上例描述的时钟振荡器使用了阻塞赋值。阻塞赋值时,计算RHS表达式并更新LHS的值,此时不允许其他语句的干扰。阻

12、塞赋值必须在(clk)边沿触发到来时刻之前完成。当触发事件到来时,阻塞赋值已经完成了,因此没有来自always块内部的触发事件来触发(clk),是一个非自触发振荡器。而例4中的振荡器使用的是非阻塞赋值,它是一个自触发振荡器。例4 采用非阻塞赋值的自触发振荡器 module osc2 (clk); always (clk) #10 clk = clk;endmodule(clk)的第一次触发之后,非阻塞赋值的RHS表达式便计算出来,把值赋给LHS的事件被安排在更新事件队列中。在非阻塞赋值更新事件队列被激活之前,又遇到了(clk)触发语句,并且always块再次对clk的值变化产生反应。当非阻塞L

13、HS的值在同一时刻被更新时, (clk)再一次触发。该例是自触发式,在编写仿真测试模块时不推荐使用这种写法的时钟信号源。移位寄存器模型下图表示是一个简单的移位寄存器方框图。从例5至例8介绍了四种用阻塞赋值实现图2移位寄存器电路的方式,有些是不正确。例5 不正确地使用的阻塞赋值来描述移位寄存器。(方式 #1) module pipeb1 (q3, d, clk); output 7:0 q3; input 7:0 d; input clk; reg 7:0 q3, q2, q1; always (posedge clk) begin q1 = d; q2 = q1; q3 = q2; end 在

14、上面的模块中,按顺序进行的阻塞赋值将使得在下一个时钟上升沿时刻,所有的寄存器输出值都等于输入值d。在每个时钟上升沿,输入值d将无延时地直接输出到q3。显然,上面的模块实际上被综合成只有一个寄存器的电路(见图3),这并不是当初想要设计的移位寄存器电路。例6 用阻塞赋值来描述移位寄存器也是可行的,但这种风格并不好。(方式 #2 )module pipeb2 (q3, d, clk);在上面例6的模块中,阻塞赋值的次序是经过仔细安排的,以使仿真的结果与移位寄存器相一致。虽然该模块可被综合成图2所示的移位寄存器,但我们不建议使用这种风格的模块来描述时序逻辑。例7 不好的用阻塞赋值来描述移位时序逻辑的风

15、格(方式 #3) module pipeb3 (q3, d, clk); always (posedge clk) q1 = d; always (posedge clk) q2 = q1; always (posedge clk) q3 = q2;在例7中,阻塞赋值分别被放在不同的always块里。仿真时,这些块的先后顺序是随机的,因此可能会出现错误的结果。这是Verilog中的竞争冒险。按不同的顺序执行这些块将导致不同的结果。但是,这些代码的综合结果却是正确的流水线寄存器。也就是说,前仿真和后仿真的结果可能会不一致。例8 不好的用阻塞赋值来描述移位时序逻辑的风格(方式 #4) module

16、 pipeb4 (q3, d, clk);若在例8中仅把always块的次序的作些变动,也可以被综合成正确的移位寄存器逻辑,但仿真结果可能不正确。如果用非阻塞赋值语句改写以上这四个阻塞赋值的例子,每一个例子都可以正确仿真,并且综合为设计者期望的移位寄存器逻辑。例9 正确的用非阻塞赋值来描述时序逻辑的设计风格 #1 module pipen1 (q3, d, clk); always (posedge clk) begin q1 = d; q2 = q1; q3 = q2; 例10 正确的用非阻塞赋值来描述时序逻辑的设计风格 #2 module pipen2 (q3, d, clk);例11 正

17、确的用非阻塞赋值来描述时序逻辑的设计风格 #3 module pipen3 (q3, d, clk); always (posedge clk) q1 always (posedge clk) q2 always (posedge clk) q3 例12 正确的用非阻塞赋值来描述时序逻辑的设计风格 #4module pipen4 (q3, d, clk);以上移位寄存器时序逻辑电路设计的例子表明: 四种阻塞赋值设计方式中有一种可以保证仿真正确 四种阻塞赋值设计方式中有三种可以保证综合正确 四种非阻塞赋值设计方式全部可以保证仿真正确 四种非阻塞赋值设计方式全部可以保证综合正确虽然在一个alway

18、s块中正确的安排赋值顺序,用阻塞赋值也可以实现移位寄存器时序流水线逻辑。但是,用非阻塞赋值实现同一时序逻辑要相对简单,而且,非阻塞赋值可以保证仿真和综合的结果都是一致和正确的。因此我们建议大家在编写Verilog时序逻辑时要用非阻塞赋值的方式。阻塞赋值及一些简单的例子许多关于Verilog和Verilog仿真的书籍都有一些使用阻塞赋值而且成功的简单例子。例13就是一个在许多书上都出现过的关于触发器的例子。例13 module dffb (q, d, clk, rst); output q; input d, clk, rst; reg q; always (posedge clk) if (r

19、st) q = 1b0; else q = d;虽然可行也很简单,但我们不建议这种用阻塞赋值来描述D触发器模型的风格。如果要把所有的模块写到一个always块里,是可以采用阻塞赋值得到正确的建模、仿真并综合成期望的逻辑。但是,这种想法将导致使用阻塞赋值的习惯,而在较为复杂的多个always块的情况下可能会导致竞争冒险。例14 使用非阻塞赋值来描述D触发器是建议使用的风格 module dffx (q, d, clk, rst); if (rst) q = 1 else q 养成在描述时序逻辑的多个always块(甚至在单个always块)中使用非阻塞赋值的习惯比较好,见例14所示。现在来看一个

20、稍复杂的时序逻辑线性反馈移位寄存器或LFSR。时序反馈移位寄存器建模线性反馈移位寄存器(Linear Feedback Shift-Register 简称LFSR)是带反馈回路的时序逻辑。反馈回路给习惯于用顺序阻塞赋值描述时序逻辑的设计人员带来了麻烦。见15所示。例15 用阻塞赋值实现的线性反馈移位寄存器,实际上并不具有LFSR的功能 module lfsrb1 (q3, clk, pre_n); output q3; input clk, pre_n; reg q3, q2, q1; wire n1; assign n1 = q1 q3; always (posedge clk or neg

21、edge pre_n) if (!pre_n) q3 = 1b1; q2 = 1 q1 = 1 else q2 = n1; q1 = q3;除非使用中间暂存变量,否则用例15所示的赋值是不可能实现反馈逻辑的。有的人可能会想到将这些赋值语句组成单行等式(如例16所示),来避免使用中间变量。如果逻辑再复杂一些,单行等式是难以编写和调试的。这种方法不推荐使用。例16 用阻塞赋值描述的线性反馈移位寄存器,其功能正确,但模型的含义较难理解。 module lfsrb2 (q3, clk, pre_n);pre_n) q3,q2,q1 = 3b111; else q3,q2,q1 = q2,(q1q3),q3;如果将例15和例16中的阻塞赋值用非阻塞赋值代替,如例17和例18所示,仿真结果都和LFSR的功能相一致。例17 用非阻塞语句描述的LFSR,可综合其功能正确。 module lfsrn1 (q3, clk, pre_n);pre_n) begin else begin= n1;= q3; 例18 用非阻塞语句描述的LFSR,可综合其功能正确。 module lfsrn2 (q3, clk, pre_n);

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2