非阻塞和阻塞赋值???
初学者在学习Verilog的初期,非常喜欢纠结这个问题,当然这个问题总容易搞错和误用,直到.....了解了。
给初学者的建议:在进行时序逻辑电路时,基本采用的是非阻塞赋值。组合逻辑电路设计时,基本采用的是阻塞赋值。下面来简单来看一下,为何在时序电路里面要用非阻塞赋值。
---电路层面来说:当待赋值的寄存器位置不同时,有时可以综合出正确的电路,有时又不能综合出正确电路。
[方式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 endmodule

图1 没有交换位置时的阻塞赋值方式
如图1所示,D的值赋给Q1以后,再执行Q2 = Q1;同样在Q2的值更新以后,才执行Q3 = Q2。这样,最终的计算结果就是Q3 = D。即在每一个clk边沿,输入值被无延迟地传到q3的输出。这很明显并没有建立一个流水线而只是为一个寄存器建模。
[方式2] 用阻塞赋值来描述移位寄存器也是可行的,但这种风格并不好。
module pipeb2 (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; q2 = q1; q1 = d; end endmodule

图2 交换位置后的阻塞赋值方式
如图2所示,阻塞赋值被仔细地安排了次序以使得行为仿真正确,这种建模同样也可以得到正确的综合结果 。
[例] 正确的用非阻塞赋值来描述时序逻辑的设计风格 #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
如图3所示,颠倒了一下赋值次序,对实际仿真次序却不产生决定作用 ,综合结果是对的,仿真结果是正确的。

图3 采用非阻塞赋值
喜欢本文的同学欢迎收藏点赞多多留言,本文原发于【FPGA hdl】
#读书笔记##C/C++#