版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、深入理解阻塞和非阻塞赋值的不同概述1、阻塞赋值对应的电路往往与触发沿没有关、阻塞赋值对应的电路往往与触发沿没有关系系,只与输入电平的变化有关系。阻塞赋值符只与输入电平的变化有关系。阻塞赋值符号号: = 2 非阻塞赋值对应的电路结构往往与触发沿有非阻塞赋值对应的电路结构往往与触发沿有关系,只有在触发沿时才有可能发生赋值的关系,只有在触发沿时才有可能发生赋值的情况。非阻塞赋值符号情况。非阻塞赋值符号: =阻塞赋值和非阻塞赋值阻塞赋值和非阻塞赋值阻塞阻塞(Blocking)(Blocking)赋值方式赋值方式 “= ”= ”, 如如 b = a; b = a; 赋值语句执行完后赋值语句执行完后, ,
2、块才结束。块才结束。b b的值在赋值语句执行完后立刻就改变的。的值在赋值语句执行完后立刻就改变的。非阻塞非阻塞(Non_Blocking)(Non_Blocking)赋值方式赋值方式 “ ”,如,如 b = b = a; a; 块结束后才完成赋值操作。块结束后才完成赋值操作。b b的值并不是立刻就改变的。的值并不是立刻就改变的。这是一种比较常用的赋值方法(特别在编写可综这是一种比较常用的赋值方法(特别在编写可综合时序模块时)。合时序模块时)。阻塞赋值阻塞赋值 阻塞赋值操作符用等号(即 = )表示。阻塞赋值时先计算等号右手方向(RHS)部分的值,这时赋值语句不允许任何别的语句的干扰,直到现行的赋
3、值完成时刻,即把RHS赋值给 LHS的时刻,它才允许别的赋值语句的执行。 一般可综合的阻塞赋值操作在RHS不能设定有延迟,(即使是零延迟也不允许)。若在RHS 加上延迟,则在延迟期间会阻止赋值语句的执行, 延迟后才执行赋值,这种赋值语句是不可综合的,在需要综合的模块设计中不可使用这种风格的代码。 阻塞赋值的执行可以认为是只有一个步骤的操作:所谓阻塞的概念是指在同一个always块中,其后面的赋值语句从概念上(即使不设定延迟)是在前一句赋值语句结束后再开始赋值的。非阻塞赋值非阻塞赋值 非阻塞赋值操作符用小于等于号非阻塞赋值操作符用小于等于号 ( (即即 = )= )表示。在赋值操表示。在赋值操作
4、时刻开始时计算非阻塞赋值符的作时刻开始时计算非阻塞赋值符的RHSRHS表达式,赋值操作时刻表达式,赋值操作时刻结束时更新结束时更新LHSLHS。在计算非阻塞赋值的RHS表达式和更新LHS期间,其他的Verilog语句,包括其他的Verilog非阻塞赋值语句都能同时计算RHS表达式和更新LHS。非阻塞赋值允许其他的Verilog语句同时进行操作。非阻塞赋值的操作可以看作为两个步骤的过程: 1)1)在赋值时刻开始时,计算非阻塞赋值在赋值时刻开始时,计算非阻塞赋值RHSRHS表达式。表达式。 2)2)在赋值时刻结束时,更新非阻塞赋值在赋值时刻结束时,更新非阻塞赋值LHSLHS表达式。表达式。非阻塞赋
5、值操作只能用于对寄存器类型变量进行赋值,因此只非阻塞赋值操作只能用于对寄存器类型变量进行赋值,因此只能用在能用在“initial”initial”块和块和“always”always”块等过程块中。非阻塞赋块等过程块中。非阻塞赋值不值不允许用于连续赋值。允许用于连续赋值。难点1 1 何时使用非阻塞赋值,何时使用阻塞赋值才能设计何时使用非阻塞赋值,何时使用阻塞赋值才能设计出符合要求的电路。出符合要求的电路。2 2 在可综合风格的在可综合风格的VerilogVerilog模块的设计中,为什么还要模块的设计中,为什么还要用非阻塞赋值,以及符合用非阻塞赋值,以及符合IEEE IEEE 标准的标准的Ve
6、rilog Verilog 仿真仿真器究竟如何来处理非阻塞赋值的仿真。器究竟如何来处理非阻塞赋值的仿真。本小节明确地提出可综合的本小节明确地提出可综合的VerilogVerilog模块编程在使用赋模块编程在使用赋值操作时应注意的要点,按照这些要点来编写代码就值操作时应注意的要点,按照这些要点来编写代码就可以避免在可以避免在Verilog Verilog 仿真时出现冒险和竞争的现象仿真时出现冒险和竞争的现象 非阻塞赋初值导致错误阻塞赋初值正确综合后波形对比仿真波形对比要 点1 在描述组合逻辑的always块中用阻塞赋值,则综合成组合逻辑的电路结构。2 在描述时序逻辑的always块中用非阻塞赋值
7、,则综合成时序逻辑的电路结构。RHS 方程式右手方向的表达式或变量可分别缩写为: RHS表达式或RHS变量。 LHS 方程式左手方向的表达式或变量可分别缩写为: LHS表达式或LHS变量。 深入理解阻塞的概念 阻塞赋值的执行可以认为是只有一个步骤的操作:阻塞赋值的执行可以认为是只有一个步骤的操作:计算计算RHSRHS并更新并更新LHSLHS,此时不能允许有来自任何其他,此时不能允许有来自任何其他VerilogVerilog语句的干扰。语句的干扰。 所谓阻塞的概念是指在同一个所谓阻塞的概念是指在同一个alwaysalways块中,其后面的赋块中,其后面的赋值语句从概念上(即使不设定延迟)是在前一
8、句赋值语句结值语句从概念上(即使不设定延迟)是在前一句赋值语句结束后再开始赋值的。束后再开始赋值的。如果在一个过程块中阻塞赋值的如果在一个过程块中阻塞赋值的RHSRHS变量正好是另一个过变量正好是另一个过程块中阻塞赋值的程块中阻塞赋值的LHSLHS变量,这两个过程块又用同一个时钟变量,这两个过程块又用同一个时钟沿触发,这时阻塞赋值操作会出现问题,即如果阻塞赋值的沿触发,这时阻塞赋值操作会出现问题,即如果阻塞赋值的次序安排不好,就会出现竞争。若这两个阻塞赋值操作用同次序安排不好,就会出现竞争。若这两个阻塞赋值操作用同一个时钟沿触发,则执行的次序是无法确定的。一个时钟沿触发,则执行的次序是无法确定
9、的。 深入理解非阻塞的概念非阻塞赋值的操作可以看作为两个步骤的过程:非阻塞赋值的操作可以看作为两个步骤的过程:1 1 在赋值时刻开始时,计算非阻塞赋值在赋值时刻开始时,计算非阻塞赋值RHSRHS表达式。表达式。2 2 在赋值时刻结束时,更新非阻塞赋值在赋值时刻结束时,更新非阻塞赋值LHSLHS表达式。表达式。 非阻塞赋值操作只能用于对寄存器类型变量进行非阻塞赋值操作只能用于对寄存器类型变量进行赋值,因此只能用在赋值,因此只能用在“initial”“initial”块和块和“always”“always”块块等过程块中。非阻塞赋值不允许用于连续赋值。等过程块中。非阻塞赋值不允许用于连续赋值。 阻
10、塞赋值项 目例 1 例 2描 述wire ck;reg 7:0 a, b, c, d;always ( posedge ck ) beginc = b;b = a;a = d;end代入前的初始值a = 5;c = 10;b = 3;d = 2;wire ck;reg 7:0 a, b, c, always ( posedge ck ) begina = d;/不同处c = b;b = a;end代入前的初始值a = 5;c = 10;b = 3;d = 2;运算结果 a = 2;c = 3;b = 5;d= 2; a = 2;c = 3;b = 2;d= 2;非阻塞赋值项 目例 1 例 2描
11、 述wire ck;reg 7:0 a, b, c, d;always ( posedge ck ) beginc = b;b = a;a = d;end代入前的初始值a = 5;c = 10;b = 3;d = 2;wire ck;reg 7:0 a, b, c, always ( posedge ck ) begina = d;/不同处c = b;b = a;end代入前的初始值a = 5;c = 10;b = 3;d = 2;运算结果 a = 2;c = 3;b = 5;d= 2; a = 2;c = 3;b = 5;d= 2;阻塞赋值阻塞赋值wire dinreg a, b, c;al
12、ways (posedge ck) begin a= din; b=a; c=b;end非阻塞赋值非阻塞赋值wire dinreg a, b, c;always (posedge ck) begin a= din; b=a; c=b;endwire dinreg a, b, c;always (posedge ck) begin a= din; b=a; c=b;end阻塞赋值阻塞赋值非阻塞赋值非阻塞赋值wire dinreg a, b, c;always (posedge ck) begin a= din; b=a; c=b;endDCKQDINCKCC=DIN;DCKQCKCDCKQDCK
13、QABVerilogVerilog模块编程要点模块编程要点1 时序电路建模时,用非阻塞赋值。2 锁存器电路建模时,用非阻塞赋值。3 用always块建立组合逻辑模型时,用阻塞赋值。4 在同一个always块中建立时序和组合逻辑电路时,用非阻塞赋值。5 在同一个always块中不要既用非阻塞赋值又用阻塞赋值。6 不要在一个以上的always块中为同一个变量赋值。7 用$strobe系统任务来显示用非阻塞赋值的变量值8 在赋值时不要使用 #0 延迟Verilog 的层次化事件队列说明事件是按照一定的规则被加入到事件是按照一定的规则被加入到5 个区域中任意一个区域的,个区域中任意一个区域的,但是只从
14、其中的但是只从其中的“活跃事件活跃事件”区域出队,出队之后该事件将区域出队,出队之后该事件将会立刻执行。会立刻执行。仿真器首先按照仿真时间对事件进行排序,然后再在当前仿真仿真器首先按照仿真时间对事件进行排序,然后再在当前仿真时间里按照事件的优先级顺序进行排序。时间里按照事件的优先级顺序进行排序。活跃事件是优先级最高的事件。在活跃事件之间,它们的执行活跃事件是优先级最高的事件。在活跃事件之间,它们的执行顺序是随机的。阻塞赋值顺序是随机的。阻塞赋值(=)、连续赋值、连续赋值Cassign) 以及非阻以及非阻塞赋值的右式计算等都属于活跃事件。塞赋值的右式计算等都属于活跃事件。将来仿真时间里的所有事件
15、都将暂时存放在将来事件队列中。将来仿真时间里的所有事件都将暂时存放在将来事件队列中。当仿真器前进到某个时刻后,该时刻的所有事件也会被分类当仿真器前进到某个时刻后,该时刻的所有事件也会被分类到当前仿真时间事件队列中,而仿真时刻未到的事件则仍然到当前仿真时间事件队列中,而仿真时刻未到的事件则仍然留在将来事件队列中。留在将来事件队列中。自触发自触发alwaysalways块块 例例3 使用阻塞赋值的非自触发振荡器使用阻塞赋值的非自触发振荡器 module osc1 (clk); output clk; reg clk; initial #10 clk = 0; always (clk) #10 cl
16、k = clk; endmodule例4 采用非阻塞赋值的自触发振荡器module osc2 (clk); output clk; reg clk; initial #10 clk = 0; always (clk) #10 clk = clk;Endmodule 移位寄存器模型移位寄存器模型下图表示是一个简单的移位寄存器方框图。下图表示是一个简单的移位寄存器方框图。例5 不正确地使用的阻塞赋值来描述移位寄存器。(方式 #1) module pipeb1 (q3, d, clk); output 7:0 q3; input 7:0 d; input clk; reg 7:0 q3, q2, q
17、1; always (posedge clk) begin q1 = d; q2 = q1; q3 = q2; end endmoduleD的值赋给Q1以后,再执行Q2 = Q1;同样在Q2的值更新以后,才执行Q3 = Q2。这样,最终的计算结果就是Q3 = D。即在每一个clk边沿,输入值被无延迟地传到q3的输出。这很明显并没有建立一个流水线而只是为一个寄存器建模-例例6 用阻塞赋值来描述移位寄存器也是可行的,但这种风格用阻塞赋值来描述移位寄存器也是可行的,但这种风格并不好。(方式并不好。(方式 #2 )module pipeb2 (q3, d, clk); output 7:0 q3; i
18、nput 7:0 d; input clk; reg 7:0 q3, q2, q1; always (posedge clk) begin q3 = q2; q2 = q1; q1 = d; end endmodule阻塞赋值被仔细地安排了次序以使得行为仿真正确。这种建阻塞赋值被仔细地安排了次序以使得行为仿真正确。这种建模同样也可以得到正确的综合结果模同样也可以得到正确的综合结果 例例7 不好的用阻塞赋值来描述移位时序逻辑的风格不好的用阻塞赋值来描述移位时序逻辑的风格(方式(方式 #3) module pipeb3 (q3, d, clk); output 7:0 q3; input 7:0
19、d; input clk; reg 7:0 q3, q2, q1; always (posedge clk) q1 = d; always (posedge clk) q2 = q1; always (posedge clk) q3 = q2; endmodule阻塞赋值”被安排在不同的always块里面。这样Verilog标准允许以任意的次序来仿真执行3个always块-这也许会使得该流水线仿真结果产生错误,因为这产生了Verilog竞争条件。由不同的always块执行顺序会产生不同的结果。尽管这样,它的综合结果将是正确的! 这就意味着综合前仿真和综合后仿真不匹配 例例8 不好的用阻塞赋值来
20、描述移位时序逻辑的风格不好的用阻塞赋值来描述移位时序逻辑的风格(方式(方式 #4) module pipeb4 (q3, d, clk); output 7:0 q3; input 7:0 d; input clk; reg 7:0 q3, q2, q1; always (posedge clk) q2 = q1; always (posedge clk) q3 = q2; always (posedge clk) q1 = d; endmodule颠倒了一下赋值次序,对实际仿真次序却不产生决定作用 ,综合结果是对的,但是仿真结果也许不正确 例例9 正确的用非阻塞赋值来描述时序逻辑的设计风正确
21、的用非阻塞赋值来描述时序逻辑的设计风格格 #1 module pipen1 (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 endmodule注意* *仿真器首先按照仿真时间对事件进行排序,仿真器首先按照仿真时间对事件进行排序,然后再在当前仿真时间里按照事件的优先级然后再在当前仿真时间里按照事件的优先级顺序进行排序。顺序进行排序。* *活跃事件是优先级最高的事件。在活跃事件活跃事件是优
22、先级最高的事件。在活跃事件之间,它们的执行顺序是随机的。阻塞赋值之间,它们的执行顺序是随机的。阻塞赋值(= =)、连续赋值()、连续赋值(assignassign)以及非阻塞赋值)以及非阻塞赋值的右式计算等都属于活跃事件。的右式计算等都属于活跃事件。例例10 正确的用非阻塞赋值来描述时序逻辑的设计正确的用非阻塞赋值来描述时序逻辑的设计风格风格 #2 module pipen2 (q3, d, clk); output 7:0 q3; input 7:0 d; input clk; reg 7:0 q3, q2, q1; always (posedge clk) begin q3 = q2; q
23、2 = q1; q1 = d; end endmodule例例11 正确的用非阻塞赋值来描述时序逻辑正确的用非阻塞赋值来描述时序逻辑的设计风格的设计风格 #3 module pipen3 (q3, d, clk); output 7:0 q3; input 7:0 d; input clk; reg 7:0 q3, q2, q1; always (posedge clk) q1 = d; always (posedge clk) q2 = q1; always (posedge clk) q3 = q2; endmodule例例12 正确的用非阻塞赋值来描述时序逻辑的设计正确的用非阻塞赋值来描
24、述时序逻辑的设计风格风格 #4module pipen4 (q3, d, clk); output 7:0 q3; input 7:0 d; input clk; reg 7:0 q3, q2, q1; always (posedge clk) q2 = q1; always (posedge clk) q3 = q2; always (posedge clk) q1 = d; endmodule例题总结四种阻塞赋值设计方式中有一种可以保证仿真正确四种阻塞赋值设计方式中有一种可以保证仿真正确四种阻塞赋值设计方式中有三种可以保证综合正确四种阻塞赋值设计方式中有三种可以保证综合正确四种非阻塞赋值设
25、计方式全部可以保证仿真正确四种非阻塞赋值设计方式全部可以保证仿真正确四种非阻塞赋值设计方式全部可以保证综合正确四种非阻塞赋值设计方式全部可以保证综合正确 虽然在一个虽然在一个alwaysalways块中正确的安排赋值顺序,块中正确的安排赋值顺序,用阻塞赋值也可以实现移位寄存器时序流水线逻用阻塞赋值也可以实现移位寄存器时序流水线逻辑。但是,用非阻塞赋值实现同一时序逻辑要相对辑。但是,用非阻塞赋值实现同一时序逻辑要相对简单,而且,非阻塞赋值可以保证仿真和综合的结简单,而且,非阻塞赋值可以保证仿真和综合的结果都是一致和正确的。果都是一致和正确的。因此建议大家在编写因此建议大家在编写VerilogVe
26、rilog时序逻辑时要用非阻塞赋值的方式。时序逻辑时要用非阻塞赋值的方式。 时序反馈移位寄存器建模时序反馈移位寄存器建模 线性反馈移位寄存器(线性反馈移位寄存器(Linear Feedback Shift-Register 简称简称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 negedge pre_n) if (!pre_n)
27、 begin q3 = 1b1; q2 = 1b1; q1 = 1b1; end线性反馈移位寄存器RTL级电路思考思考:真正的:真正的LFSR电路图是什么样子?电路图是什么样子?用阻塞赋值描述的线性反馈移位寄存器,其功能正用阻塞赋值描述的线性反馈移位寄存器,其功能正确,但模型的含义较难理解。确,但模型的含义较难理解。 module lfsrb2 (q3, clk, pre_n); output q3; input clk, pre_n; reg q3, q2, q1; always (posedge clk or negedge pre_n) if (!pre_n) q3,q2,q1 = 3b
28、111; else q3,q2,q1 = q2,(q1q3),q3; endmodule 把所有赋值弄到一个等式的方式(把所有赋值弄到一个等式的方式(one-line equations)来)来避免使用临时变量编码显得更难于理解尤其当涉及的表达避免使用临时变量编码显得更难于理解尤其当涉及的表达式更大更长时,编写代码和调试都变得比较困难,因此不式更大更长时,编写代码和调试都变得比较困难,因此不鼓励使用这种风格鼓励使用这种风格 用非阻塞语句描述的LFSR,可综合,其功能正确。module lfsrb1 (q3, clk, pre_n); output q3; input clk, pre_n; r
29、eg q3, q2, q1; wire n1; assign n1 = q1 q3; always (posedge clk or negedge pre_n) if (!pre_n) begin q3 = 1b1; q2 = 1b1; q1 = 1b1; end else begin q3 = q2; q2 = n1; q1 = q3; endendmoduleRTL级电路 例例 用非阻塞语句描述的用非阻塞语句描述的LFSR,可综合其功,可综合其功能正确。能正确。 module lfsrn2 (q3, clk, pre_n); output q3; input clk, pre_n; reg
30、 q3, q2, q1; always (posedge clk or negedge pre_n) if (!pre_n) q3,q2,q1 = 3b111; else q3,q2,q1 = q2,(q1q3),q3; endmodule移位寄存器设计1 含同步预置功能的移位寄存器设计含同步预置功能的移位寄存器设计REG86:0=REG87:1;工作时序图模式可控的移位寄存器设计2 使用移位操作符设计移位寄存器使用移位操作符设计移位寄存器移位寄存器的RTL图阻塞赋值及一些简单的例子阻塞赋值及一些简单的例子 例例13 module dffb (q, d, clk, rst); output q
31、; input d, clk, rst; reg q; always (posedge clk) if (rst) q = 1b0; else q = d;endmodule虽然可行也很简单,但我们不建议这种用阻塞赋值来描述D触发器模型的风格。如果要把所有的模块写到一个always块里,是可以采用阻塞赋值得到正确的建模、仿真并综合成期望的逻辑。但是,这种想法将导致使用阻塞赋值的习惯,而在较为复杂的多个always块的情况下可能会导致竞争冒险 例例14 使用非阻塞赋值来描述使用非阻塞赋值来描述D触发器是建触发器是建议使用的风格议使用的风格 module dffx (q, d, clk, rst)
32、; output q; input d, clk, rst; reg q; always (posedge clk) if (rst) q = 1b0; else q = d; endmodule小结 从上面介绍的移位寄存器的例子以及LFSR的例子,建议使用非阻塞赋值实现时序逻辑。而用非阻塞赋值语句实现锁存器也是最为安全的 。原则1 :时序电路建模时,用非阻塞赋值。原则2 :锁存器电路建模时,用非阻塞赋值。 组合逻辑组合逻辑 使用阻塞赋值使用阻塞赋值 用用VerilogVerilog可以有很多种方法为组合逻辑建模,但是可以有很多种方法为组合逻辑建模,但是当使用当使用alwaysalways块来
33、为组合逻辑建模时,应该使用阻塞块来为组合逻辑建模时,应该使用阻塞赋值(赋值(blocking assignmentblocking assignment)。)。 如果在某个如果在某个alwaysalways块里面只有一个赋值(表达),块里面只有一个赋值(表达),使用阻塞或者非阻塞赋值都可以正确工作。但是如果使用阻塞或者非阻塞赋值都可以正确工作。但是如果您对养成好的编码习惯有兴趣的话,还是要您对养成好的编码习惯有兴趣的话,还是要“总是用总是用阻塞赋值对组合逻辑建模阻塞赋值对组合逻辑建模”。 对于简单的组合对于简单的组合alwasysalwasys块不仅可以用于时序逻辑,块不仅可以用于时序逻辑,也
34、可以用于组合逻辑,但是当也可以用于组合逻辑,但是当alwaysalways块中有多个赋值块中有多个赋值语句时语句时使用了不含延迟(使用了不含延迟(delaydelay)的非阻塞赋值会造)的非阻塞赋值会造成仿真不正确,或者要使仿真正确您需要另外的添加成仿真不正确,或者要使仿真正确您需要另外的添加敏感事件列表(敏感事件列表(sensitivity list entriessensitivity list entries),和),和“多输入路径多输入路径”(multiple passesmultiple passes)来贯穿)来贯穿always always 块以使得仿真正确。因而从仿真的时间效率角
35、度看也块以使得仿真正确。因而从仿真的时间效率角度看也不合算。不合算。例例module ao4 (y, a, b, c, d); output y; input a, b, c, d; reg y, tmp1, tmp2; always (a or b or c or d) begin tmp1 = a & b; tmp2 = c & d; y = tmp1 | tmp2; end endmodule y y输出建立在输出建立在3 3个依次执行的顺序上。由于非阻塞赋值的个依次执行的顺序上。由于非阻塞赋值的LHSLHS变量值更新是变量值更新是在对在对RHSRHS表达式估值之后,所以
36、表达式估值之后,所以tmp1tmp1和和tmp2tmp2的值仍然是该的值仍然是该alwaysalways块上一个块上一个输入口的值而不是在这一个仿真时间步(输入口的值而不是在这一个仿真时间步(simulation time stepsimulation time step)结束)结束时被更新的值。因此时被更新的值。因此y y的值将受旧的的值将受旧的tmp1tmp1和和tmp2tmp2影响,而不是这次扫描过影响,而不是这次扫描过的的alwaysalways块内被更新的值。块内被更新的值。 例例 module ao5 (y, a, b, c, d); output y; input a, b, c
37、, d; reg y, tmp1, tmp2;5 always (a or b or c or d or tmp1 or tmp2) begin tmp1 = a & b; tmp2 = c & d; y = tmp1 | tmp2; end endmodule 不同之处在于不同之处在于tmp1和和tmp2被添加到事被添加到事件列表中去了,当非阻塞赋值更新件列表中去了,当非阻塞赋值更新LHS变量时,变量时,always块将会块将会“自触发自触发”并使用并使用最新的最新的tmp1和和tmp2来更新来更新y输出。现在输出。现在y输出值正确了因为增加使用了两条输出值正确了因为增加使用
38、了两条“登登入路径入路径”(two passes)贯穿整个)贯穿整个always块。使用更多的块。使用更多的“登入路径登入路径”来贯穿来贯穿always块等于降低仿真器的性能,因此如块等于降低仿真器的性能,因此如果可以有合理的一些代码变化可以取代果可以有合理的一些代码变化可以取代这这 种用法的话,就尽量避免这种用法。种用法的话,就尽量避免这种用法。 例例 使用阻塞赋值实现组合逻辑是推荐使用的编码使用阻塞赋值实现组合逻辑是推荐使用的编码风格。风格。 module ao2 (y, a, b, c, d); output y; input a, b, c, d; reg y, tmp1, tmp2;
39、 always (a or b or c or d) begin tmp1 = a & b; tmp2 = c & d; y= tmp1 | tmp2; end endmodule 小结原则3 :用always块描述组合逻辑时,应采用阻塞赋值语句 时序和组合的混合逻辑时序和组合的混合逻辑使用非阻塞赋值使用非阻塞赋值有时候将简单的组合逻辑和时序逻辑写在一起很方便。当把有时候将简单的组合逻辑和时序逻辑写在一起很方便。当把组合逻辑和时序逻辑写到一个组合逻辑和时序逻辑写到一个always块中时,应遵从时序逻块中时,应遵从时序逻辑建模的原则,使用非阻塞赋值,如例所示。辑建模的原则,使用非
40、阻塞赋值,如例所示。例例2 在一个在一个always块中同时实现组合逻辑和时序逻辑块中同时实现组合逻辑和时序逻辑 module nbex2 (q, a, b, clk, rst_n); output q; input clk, rst_n; input a, b; reg q; always (posedge clk or negedge rst_n) if (!rst_n) q = 1b0; / 时序逻辑时序逻辑 else q = a b;/ 异或,为组合逻辑异或,为组合逻辑 endmodule例例 将组合和时序逻辑分别写在两个将组合和时序逻辑分别写在两个alwaysalways块中,一块中
41、,一个是纯粹的时序逻辑(使用非阻塞赋值),另一个是纯粹的个是纯粹的时序逻辑(使用非阻塞赋值),另一个是纯粹的组合逻辑(使用阻塞赋值)建模组合逻辑(使用阻塞赋值)建模 module nbex1 (q, a, b, clk, rst_n); output q; input clk, rst_n; input a, b; reg q, y; always (a or b) y = a b; always (posedge clk or negedge rst_n) if (!rst_n) q = 1b0; else q = y; endmodule小结 原则4:在同一个always块中描述时序和组合
42、逻辑混合电路时,用非阻塞赋值。 其它混合其它混合“阻塞阻塞”与与“非阻塞非阻塞”赋值建模赋值建模方针方针 Verilog语法并没有禁止将阻塞和非阻塞赋语法并没有禁止将阻塞和非阻塞赋值自由地组合在一个值自由地组合在一个always块里。虽然块里。虽然Verilog语法是允许这种写法的,但我们不建语法是允许这种写法的,但我们不建议在可综合模块的编写中采用这种风格议在可综合模块的编写中采用这种风格 例例24 在在always块中同时使用阻塞和非阻塞赋值的例子。块中同时使用阻塞和非阻塞赋值的例子。 module ba_nba2 (q, a, b, clk, rst_n); output q; inpu
43、t a, b, rst_n; input clk; reg q; always (posedge clk or negedge rst_n) begin: ff reg tmp; if (!rst_n) q = 1b0; else begin tmp = a & b; q = tmp; end end endmodule仿真和综合都将是正确的,因为“阻塞”与“非阻塞”赋值不是针对同一个变量来的。尽管这可以“正常工作”,但是不推荐这种风格。 例例 对同一变量既进行阻塞赋值对同一变量既进行阻塞赋值,又进行非阻塞赋值又进行非阻塞赋值有时会产生综合错误。有时会产生综合错误。 module ba
44、_nba6 (q, a, b, clk, rst_n); output q; input a, b, rst_n; input clk; reg q, tmp; always (posedge clk or negedge rst_n) if (!rst_n) q = 1b0; / 对对 q进行阻塞赋值进行阻塞赋值 else begin tmp = a & b; q = tmp; / 对对 q进行非阻塞赋值进行非阻塞赋值 end endmodule小结原则5:不要在同一个always块中同时使用阻塞和非阻塞赋值 对同一变量进行多次赋值对同一变量进行多次赋值 在一个以上在一个以上alwa
45、ys块中对同一个变量进行多块中对同一个变量进行多次赋值可能会导致竞争冒险,即使使用非阻次赋值可能会导致竞争冒险,即使使用非阻塞赋值也可能产生竞争冒险。在下例中,两塞赋值也可能产生竞争冒险。在下例中,两个个always块都对输出块都对输出q进行赋值。由于两个进行赋值。由于两个always块执行的顺序是随机的,所以仿真时块执行的顺序是随机的,所以仿真时会产生竞争冒险会产生竞争冒险 例例25 使用非阻塞赋值语句,由于两个使用非阻塞赋值语句,由于两个always块对同块对同一变量一变量q赋值产生竞争冒险的程序:赋值产生竞争冒险的程序: module badcode1 (q, d1, d2, clk,
46、rst_n); output q; input d1, d2, clk, rst_n; reg q; always (posedge clk or negedge rst_n) if (!rst_n) q = 1b0; else q = d1; always (posedge clk or negedge rst_n) if (!rst_n) q = 1b0; else q = d2; endmodule在在synplify Pro下综合,产生错误信息下综合,产生错误信息: E: Only one always block may assign a given variable q综合出现的错
47、误小结原则6:严禁在多个always块中对同一个变量赋值 常见的对于非阻塞赋值的误解常见的对于非阻塞赋值的误解 1 非阻塞赋值和非阻塞赋值和$display误解误解1: “使用使用$display命令不能用来显示非阻塞语句命令不能用来显示非阻塞语句的赋值的赋值”事实是:事实是: 非阻塞语句的赋值在所有的非阻塞语句的赋值在所有的$display命令执行命令执行以后才更新数值以后才更新数值2 #0 延时赋值延时赋值 误解误解2: “0延时把赋值强制到仿真时间步的末尾延时把赋值强制到仿真时间步的末尾”事实是:事实是: 0延时将赋值事件强制加入停止运行事件延时将赋值事件强制加入停止运行事件队列中。队列
48、中。例例module display_cmds; reg a; initial $monitor($monitor: a = %b, a); initial begin $strobe ($strobe : a = %b, a); a = 0; a = 1; $display ($display: a = %b, a); #1 $finish; end endmodule下面是上面模块的仿真结果说明下面是上面模块的仿真结果说明$display命令命令的执行是安排在活动事件队列中,但排在非的执行是安排在活动事件队列中,但排在非阻塞赋值数据更新事件之前。阻塞赋值数据更新事件之前。 $display: a = 0 $monitor: a = 1 $strobe : a = 1 例例28 module nb_schedule1; reg a, b; initial begin a = 0; b = 1; a = b; b = a; $monitor (%0dns: $monitor: a=%b b=%b, $stime, a, b); $display (%0dns: $display: a=%b b=%b, $stime, a, b); $strobe (%0dns: $strobe : a=%b b=%bn, $stime, a, b); #0 $di
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 课题申报参考:教育家精神引领民族地区师范院校高质量教师队伍建设的路径研究
- 课题申报参考:家校社协同育人下大学新生积极心理品质的培育研究
- 2025版学生入学校园网络安全与信息保护合同3篇
- 三方出口交易合作合同2024年版版B版
- 二零二五年度金融创新合伙协议书模板3篇
- 基于二零二五年度哺乳期妇女权益保护的离婚赡养协议3篇
- 2025年度个人客户信息保密合作协议4篇
- 二零二五年度仓储仓储设施节能改造合同4篇
- 2025年度乐器租赁与电商平台合作协议3篇
- 二零二五美容院客户投诉处理与反馈机制合同4篇
- 2024年国家工作人员学法用法考试题库及参考答案
- 国家公务员考试(面试)试题及解答参考(2024年)
- 《阻燃材料与技术》课件 第6讲 阻燃纤维及织物
- 同等学力英语申硕考试词汇(第六版大纲)电子版
- 人教版五年级上册递等式计算100道及答案
- 2024年部编版初中语文各年级教师用书七年级(上册)
- 2024年新课标全国Ⅰ卷语文高考真题试卷(含答案)
- 湖南省退休人员节日慰问政策
- QB/T 5998-2024 宠物尿垫(裤)(正式版)
- 4P、4C、4R-营销理论简析
- 《电力信息系统信息安全检查规范》
评论
0/150
提交评论