天天看点

FPGA的阻塞赋值与非阻塞赋值

答:因为对应的电路结构往往与触发沿没有关系,只与输入电平的变化有关系。阻塞赋值的操作可以认为是只有一个步骤的操作,即计算赋值号右边的语句并更新赋值号左边的语句,此时不允许有来自任何其他 verilog语句的干扰,直到现行的赋值完成时刻,即把当前赋值号右边的值赋值给左边的时刻完成后,它才允许下一条的赋值语句的执行。串行块(begin-end)中的各条阻塞型过程赋值语句将以它们在顺序块后的排列次序依次执行。阻塞型过程赋值语句的执行过程是:首先计算赋值号右边的值,然后立即将计算结果赋值给左边,赋值语句结束,变量值立即发生改变。阻塞的概念是指在同一个 always 块中,其后面的赋值语句从概念上是在前一句赋值语句结束后再开始下面的赋值。

答:这是因为对应的电路结构往往与触发沿有关系,只有在触发沿的时刻才能进行非阻塞赋值。非阻塞操作开始时计算非阻塞赋值符的赋值号右边的语句,赋值操作结束时刻才更新赋值号左边的语句,可以认为是两个步骤(赋值开始时刻和结束时刻)来完成非阻塞赋值。在计算非阻塞语句赋值号右边的语句和更新赋值号左边的语句期间,其他的 verilog语句包括其他的 verilog 非阻塞赋值语句都能同时计算赋值号右边的语句和更新赋值号左边的语句,允许其他的 verilog 语句同时进行操作。非阻塞赋值的操作可以看作为两个步骤的过程:在赋值开始时刻,计算赋值号右边的语句。在赋值结束时刻,更新赋值号左边的语句。注意:非阻塞操作只能用于对寄存器类型变量进行赋值,因此只能用于“initial”和“always”块中,不允许用于连续赋值“assign”。

阻塞赋值(=)”和“非阻塞赋值(<=)”符号其实我们早就见过,大家可能存在疑问,有时候用阻塞赋值而有时候用非阻塞赋值,所以阻塞赋值和非阻塞赋值的概念一直是初学者较为头疼的一件事情,因为大多数人往往因为文字概念的描述理解不透彻,说白了就是看那些文字的解释反而让我们更难理解,更容易被绕进去,产生懵的感觉。甚至有些很有经验的 逻辑设计工程师也不能完全正确地理解何时使用非阻塞赋值何时使用阻塞赋值才能设计出符合要求的电路,不明白在电路结构的设计中,即可综合风格的 verilog模块的设计中,究竟为什么还要用非阻塞赋值,以及符合ieee标准的verilog 仿真器究竟如何来处理非阻塞赋值的仿真。

本章的目的是尽可能地把阻塞和非阻塞赋值的含义和用法详细地解释清楚,并通过实例给出正确的用法,使之能够设计出符合我们意愿的的代码及功能。

一、阻塞赋值

开始 rtl 代码的编写,rtl 代码编写出的模块叫 rtl 模块(后文中也称功能模块、可综合模块)。之所以叫 rtl 代码是因为用 verilog hdl 在 resistances transistors logic(寄存器传输级逻辑)来描述硬件电路,rtl 代码能够综合出真实的电路以实现我们设计的功能,区别于不可综合的仿真代码。

FPGA的阻塞赋值与非阻塞赋值
FPGA的阻塞赋值与非阻塞赋值
FPGA的阻塞赋值与非阻塞赋值

打开 modelsim 执行仿真,仿真出来的波形如图所示,我们让仿真运行了 500ns即可得到较好的观察效果。

我们知道一个寄存器就是“延一拍”,所以该仿真波形和前面的 rtl视图刚好对应,发现<code>输入信号 in</code> 和<code>中间变量 in_reg</code>、<code>输出信号out</code>的关系就是延迟一拍的关系,但是为什么只是延迟一拍呢?

首先中间变量<code>in_reg</code>一定要等待复位被释放后且第一个时钟上升沿来到时才会被赋值为<code>输入信号in</code> 的值,所以会比输入信号<code>in</code>延迟一拍,而<code>中间变量 in_reg</code> 和<code>输出信号 out</code> 却没有延迟一拍的关系了,而是在同一时刻同时变化的,因为我们使用的是阻塞赋值,也就是说只要赋值号右边的表达式的值有变化,赋值号左边的表达式的值也将立刻变化,所以我们最终看到的结果是中间变量in_reg 和输出信号 out是同时变化的。

FPGA的阻塞赋值与非阻塞赋值

二、非阻塞赋值

开始rtl代码的编写,rtl代码编写出的模块叫rtl模块(后文中也称功能模块、可综合模块)。之所以叫rtl代码是因为用verilog hdl在resistances transistors logic(寄存器传输级逻辑)来描述硬件电路,rtl代码能够综合出真实的电路以实现我们设计的功能,区别于不可综合的仿真代码。

FPGA的阻塞赋值与非阻塞赋值
FPGA的阻塞赋值与非阻塞赋值
FPGA的阻塞赋值与非阻塞赋值
FPGA的阻塞赋值与非阻塞赋值

打开modelsim执行仿真,仿真出来的波形如图所示,我们让仿真运行了 500ns即可得到较好的观察效果。

同样该仿真波形和其对应的 rtl视图也是刚好对应的,我们发现<code>输入信号 in</code>和<code>中间变量 in_reg</code> 是延迟一拍的关系,而<code>中间变量 in_reg</code> 和<code>输出信号 out</code>也是延迟一拍的关系,也就是<code>输入信号 in</code> 和<code>输出信号 out</code> 一共是延迟两拍的关系,为什么会这样呢?

首先<code>中间变量 in_reg</code>一定要等待复位被释放后且第一个时钟上升沿来到时才会被赋值为<code>输入信号 in</code>的值,所以会比输入信号 in延迟一拍,这是和阻塞赋值过程相同的,

但是接下来就不一样了,因为我们使用的是非阻塞赋值,也就是说只要赋值号右边的表达式的值有变化,赋值号左边的表达式的值也不会立刻变化,需要等待下一次时钟沿到来时一起变化,所以我们最终看到的结果是<code>输出信号out</code>相对于<code>输入信号</code>是打了两拍的关系。

FPGA的阻塞赋值与非阻塞赋值
FPGA的阻塞赋值与非阻塞赋值