差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

阻塞赋值_非阻塞赋值 [2018/08/20 09:41]
group001 创建
阻塞赋值_非阻塞赋值 [2018/09/11 09:18]
group001
行 1: 行 1:
 ====阻塞赋值语句==== ====阻塞赋值语句====
 串行块语句中的阻塞赋值语句按顺序执行,它不会阻塞其后并行块中语句的执行。阻塞赋值语句使用“=”作为赋值符。\\ ​ 串行块语句中的阻塞赋值语句按顺序执行,它不会阻塞其后并行块中语句的执行。阻塞赋值语句使用“=”作为赋值符。\\ ​
 +<code verilog>
 +
   例子 阻塞赋值语句   例子 阻塞赋值语句
   reg x, y, z;   reg x, y, z;
行 18: 行 20:
           count = count + 1; // 给整形变量赋值(递增)           count = count + 1; // 给整形变量赋值(递增)
    end    end
 + 
 +</​code>​
 在例子中,只有在语句x=0执行完成后,才会执行y=1,而语句count=count+1按顺序在最后执行。由于阻塞赋值语句是按顺序执行的,因此如果在一个begin-end块中使用了阻塞赋值语句,那么这个块语句表现的是串行行为。例子中,begin-end块中各条语句执行的仿真时间为:\\ ​ 在例子中,只有在语句x=0执行完成后,才会执行y=1,而语句count=count+1按顺序在最后执行。由于阻塞赋值语句是按顺序执行的,因此如果在一个begin-end块中使用了阻塞赋值语句,那么这个块语句表现的是串行行为。例子中,begin-end块中各条语句执行的仿真时间为:\\ ​
   * x=0到reg_b = reg_a之间的语句在仿真0时刻执行;   * x=0到reg_b = reg_a之间的语句在仿真0时刻执行;
行 31: 行 35:
 ====非阻塞赋值语句==== ====非阻塞赋值语句====
 非阻塞赋值语句允许赋值调度,但它不会阻塞位于同一个顺序块中其后语句的执行。非阻塞赋值使用“<​=”作为赋值符。读者会注意到,它与“小于等于”关系操作符是同一个符号,但在表达式中它被解释为关系操作符,而在非阻塞赋值的环境下被解释成非阻塞赋值。为了说明非阻塞赋值的意义以及阻塞赋值的区别,让我们来考虑将阻塞赋值例子中的部分阻塞赋值改为非阻塞赋值后的结果,修改后语句如下: 非阻塞赋值语句允许赋值调度,但它不会阻塞位于同一个顺序块中其后语句的执行。非阻塞赋值使用“<​=”作为赋值符。读者会注意到,它与“小于等于”关系操作符是同一个符号,但在表达式中它被解释为关系操作符,而在非阻塞赋值的环境下被解释成非阻塞赋值。为了说明非阻塞赋值的意义以及阻塞赋值的区别,让我们来考虑将阻塞赋值例子中的部分阻塞赋值改为非阻塞赋值后的结果,修改后语句如下:
 +<code verilog>
 +
   例 非阻塞赋值语句   例 非阻塞赋值语句
   reg x, y, z;   reg x, y, z;
行 48: 行 54:
           count <= count + 1; // 给整形变量赋值(递增)           count <= count + 1; // 给整形变量赋值(递增)
    end    end
 +   
 +</​code>​
 在这个例子中,从x=0到reg_b=reg_a之间的语句是在仿真0时刻顺序执行的,之后的三条非阻塞赋值语句在reg_b=reg_a执行完成后并发执行。 在这个例子中,从x=0到reg_b=reg_a之间的语句是在仿真0时刻顺序执行的,之后的三条非阻塞赋值语句在reg_b=reg_a执行完成后并发执行。
   * reg_a[2]=0被调度到15个时间单位之后执行,即仿真时刻为15;   * reg_a[2]=0被调度到15个时间单位之后执行,即仿真时刻为15;
行 58: 行 66:
 ==非阻塞赋值语句的应用== ==非阻塞赋值语句的应用==
 描述了非阻塞赋值的行为之后,理解究竟为什么要在硬件设计中使用非阻塞赋值是很重要的。非阻塞赋值可以被用来为常见的硬件电路行为建立模型,例如当某一事件发生后,多个数据并发传输的行为。在下面的例子中,当时钟信号的上升沿到来之后,执行三个数据的并发传输: 描述了非阻塞赋值的行为之后,理解究竟为什么要在硬件设计中使用非阻塞赋值是很重要的。非阻塞赋值可以被用来为常见的硬件电路行为建立模型,例如当某一事件发生后,多个数据并发传输的行为。在下面的例子中,当时钟信号的上升沿到来之后,执行三个数据的并发传输:
 +<code verilog>
 +
   always @(posedge clock)   always @(posedge clock)
   begin    begin 
行 64: 行 74:
      reg3 <= #1 reg1; // reg1 的“旧值”      reg3 <= #1 reg1; // reg1 的“旧值”
   end   end
 +  ​
 +</​code>​
 每当一个时钟上升沿到来时,其中的非阻塞赋值语句按下面的顺序执行: 每当一个时钟上升沿到来时,其中的非阻塞赋值语句按下面的顺序执行:
   -在每个时钟上升沿到来时读取操作数变量in1, in2, in3和reg1,计算右侧表达式的值,该值由仿真器临时保存;   -在每个时钟上升沿到来时读取操作数变量in1, in2, in3和reg1,计算右侧表达式的值,该值由仿真器临时保存;
行 70: 行 82:
 由上面的分析可见,reg1,reg2和reg3的最终值与赋值完成的顺序无关,体现了非阻塞赋值并行的特点。\\ ​ 由上面的分析可见,reg1,reg2和reg3的最终值与赋值完成的顺序无关,体现了非阻塞赋值并行的特点。\\ ​
 为了进一步理解阻塞和非阻塞赋值,让我们来看以下例子。这个例子的目的是在每个时钟上升延处交换a和b这两个寄存器变量的值,其中使用了两个always语句。 为了进一步理解阻塞和非阻塞赋值,让我们来看以下例子。这个例子的目的是在每个时钟上升延处交换a和b这两个寄存器变量的值,其中使用了两个always语句。
 +<code verilog>
 +
   例 使用非阻塞赋值来避免竞争   例 使用非阻塞赋值来避免竞争
   // 说明1:使用阻塞语句的两个并行的always块   // 说明1:使用阻塞语句的两个并行的always块
行 84: 行 98:
   always @(posedge clock)   always @(posedge clock)
              b <= a;              b <= a;
 +             
 +</​code>​
 在第一种描述中我们使用了阻塞赋值,这样就产生了竞争的情况:a=b和b=a,具体执行顺序的先后取决于所使用的仿真器。因此这段代码达不到交换a和b值的目的,而是使得两者具有相同的值(在时钟上升沿到来之前a或b的值),具体是哪一个值与使用的仿真器有关。\\ ​ 在第一种描述中我们使用了阻塞赋值,这样就产生了竞争的情况:a=b和b=a,具体执行顺序的先后取决于所使用的仿真器。因此这段代码达不到交换a和b值的目的,而是使得两者具有相同的值(在时钟上升沿到来之前a或b的值),具体是哪一个值与使用的仿真器有关。\\ ​
 在第二种描述中,我们通过使用非阻塞赋值语句来避免竞争:在每个时钟上升沿到来的时候,仿真器读取每个操作数的值,进而计算表达式的值并保存在临时变量中;当赋值的时候,仿真器将保存的值赋予非阻塞赋值语句的左侧变量。这样就将读和写分开来了,达到了交换数据的目的,并且不受语句执行顺序的影响。以下例子介绍了如何使用阻塞赋值实现说明2中使用非阻塞语句才能实现的数值交换。 在第二种描述中,我们通过使用非阻塞赋值语句来避免竞争:在每个时钟上升沿到来的时候,仿真器读取每个操作数的值,进而计算表达式的值并保存在临时变量中;当赋值的时候,仿真器将保存的值赋予非阻塞赋值语句的左侧变量。这样就将读和写分开来了,达到了交换数据的目的,并且不受语句执行顺序的影响。以下例子介绍了如何使用阻塞赋值实现说明2中使用非阻塞语句才能实现的数值交换。
 +<code verilog>
 +
   例 使用阻塞赋值来达到非阻塞赋值的目的   例 使用阻塞赋值来达到非阻塞赋值的目的
   // 使用临时变量和阻塞赋值来模仿非阻塞赋值的行为   // 使用临时变量和阻塞赋值来模仿非阻塞赋值的行为
行 99: 行 117:
       b = temp_a;       b = temp_a;
    end    end
 +   
 +</​code>​
 在数字电路设计中,如果某事件发生后将产生多个数据的并发传输,我们强烈建议读者使用非阻塞赋值来描述这种情形。如果我们使用阻塞赋值来描述这种情形,由于最终结果依赖于语句的具体执行顺序,有可能引起竞争风险;而非阻塞赋值语句的执行结果是与执行顺序无关的,因此它能够准确地描述这种情况。非阻塞赋值的典型应用包括流水线建模和多个互斥(mutually exclusive)数据传输的建模。使用非阻塞赋值所带来的问题是,它会引起仿真速度的下降以及内存使用量的增加。 在数字电路设计中,如果某事件发生后将产生多个数据的并发传输,我们强烈建议读者使用非阻塞赋值来描述这种情形。如果我们使用阻塞赋值来描述这种情形,由于最终结果依赖于语句的具体执行顺序,有可能引起竞争风险;而非阻塞赋值语句的执行结果是与执行顺序无关的,因此它能够准确地描述这种情况。非阻塞赋值的典型应用包括流水线建模和多个互斥(mutually exclusive)数据传输的建模。使用非阻塞赋值所带来的问题是,它会引起仿真速度的下降以及内存使用量的增加。