Verilog之blocking(阻塞) & nonblocking(非阻塞) assignments(赋值)

Verilog中的阻塞与非阻塞赋值是一对十分难理解的概念,没有之一!本文展开说明,望解开难理解之谜。

1、阻塞赋值,很明显,具有阻塞之意,即在always块中,它要阻值其他语句的进行(在阻塞赋值语句LHS的赋值完成之前),然后才接着执行其他语句。而阻塞赋值本身,RHS的计算和LHS的赋值是同时完成的。整体是分前后顺序的,但内部是同时进行的。(整体是指每一条阻塞赋值语句本身,内部是指RHS的计算和LHS的赋值)

2、非阻塞赋值,即无阻塞之意,就是说always块内所有的非阻塞赋值语句同时进行,但非阻塞赋值本身,RHS的计算和LHS的赋值是前后完成的。故,同时进行是指:所有非阻塞赋值语句的RHS同时完成计算(timestep的开始),再对其LHS同时完成赋值(timestep的结束)。整体是同时进行的,但具体内部是分前后顺序的。(在timestep开始和结束之间,允许其他语句的进行,故非阻塞之意)

3、阻塞赋值的竞争:指的是两个always块内,其中一个块内某个变量在RHS中,而另一个always块内变量在LHS中,就会产生竞争。如下:

module fbosc1 (y1, y2, clk, rst);

output reg y1, y2;

input clk, rst;

 

always @(posedge clk or negedge rst)

begin

if (!rst) y1 = 0; // reset

else y1 = y2;

end

 

always @(posedge clk or negedge rst)

begin

if (!rst) y2 = 1; // preset

else y2 = y1;

end

endmodule

很明显,开始异步复位y1=1,y2=0,因为根据IEEE Verilog Standard,如果第一个always块中的else先执行,那么最后y1=y2=1,反过来就是y1=y2=0,这就是阻塞赋值带来的竞争。所以强烈不推荐上述这种写法。

4、同样的上述代码采用非阻塞实现:

module fbosc1 (y1, y2, clk, rst);

output reg y1, y2;

input clk, rst;

 

always @(posedge clk or negedge rst)

begin

if (!rst) y1< = 0; // reset

else y1< = y2;

end

 

always @(posedge clk or negedge rst)

begin

if (!rst) y2 <= 1; // preset

else y2 <= y1;

end

endmodule

开始异步复位,y1=0,y2=1,第二步,两个always块内else中的RHS先同时进行,然后LHS同时完成赋值。故最终,y1=1,y2=0,则没有竞争现象。

5、verilog中的分层事件队列

Verilog之blocking(阻塞) & nonblocking(非阻塞) assignments(赋值)

图1 分层事件队列

该图有两个维度,横向维度和纵向维度,横向表示时间间隔(一个仿真周期),纵向表示某个时间间隔内由上往下的执行顺序。具体的说明请看图中。

6、verilog中阻塞和非阻塞赋值的8准则

Guideline #1: When modeling sequential logic, use nonblocking assignments.

Guideline #2: When modeling latches, use nonblocking assignments.

Guideline #3: When modeling combinational logic with an always block, use blocking assignments.

Guideline #4: When modeling both sequential and combinational logic within the same always block, use nonblocking assignments.

Guideline #5: Do not mix blocking and nonblocking assignments in the same always block.

Guideline #6: Do not make assignments to the same variable from more than one always block.

Guideline #7: Use $strobe to display values that have been assigned using nonblocking assignments.

Guideline #8: Do not make assignments using #0 delays.

之所以用英文,是想提示大家,有时间多看看英文资料,因为很多翻译本资料不能反映原作者的最初想法,所以看那些中文资料很容易出现误解的现象,有时只有自己去看英文原著,才能更好地理解本意。

NOTE:上传一个有关阻塞与非阻塞赋值的英文文档,对其理解颇有帮助,特此贴出

链接:https://download.****.net/download/huigeyu/11150360

如有需要,清自行下载!

上述理解如有问题,欢迎指正交流!