我了解Verilog中阻塞和非阻塞语句之间的基本区别。但是,我仍然无法理解&
在何时何地使用阻塞和非阻塞语句正在发生什么。例如,考虑简单的dff代码:
module dff (clk, reset,d, q, qb);
input clk;
input reset;
input d;
output q;
output qb;
reg q;
assign qb = ~q;
always @(posedge clk or posedge reset)
begin
if (reset) begin
// Asynchronous reset when reset goes high
q <= 1'b0;
end else begin
// Assign D to Q on positive clock edge
q <= d;
end
end
endmodule
但是,如果我使用两段编码技术编写完全相同的逻辑:
module dff(input wire d,
clk,
reset,
en,
output wire q);
reg q;
reg r_reg, r_next;
always @(posedge clk, posedge reset)
if(reset)
r_reg<=1'b0;
else
r_reg<=r_next;
always @*
if(en)
r_reg=d;
else
r_reg=r_next;
assign q<=r_reg;
endmodule
现在,在这段代码中,我只是不明白为什么在第一个Always块中使用<=
以及为什么在第二个Always块中使用=
。我也知道,建议在组合逻辑电路=
中按顺序&
使用<=
。但是,我仍然无法找到使用阻塞和非阻塞语句的答案。你能帮我吗??
答案 0 :(得分:1)
阻止/非阻止分配仅是模拟工件。与信念相反,verilog不描述硬件。 Verilog描述了硬件的期望的行为,试图将其适应事件驱动的仿真方案。
这是一个使用2个触发器的移位寄存器的简单示例:
always @(posedge clk)
out1 = in;
always @(posedge clk)
out2 = out1;
现在,out2的输出是什么?由于我们正在处理模拟,因此它取决于这两个语句的执行顺序。要么是out1的旧值,要么是新值(实际上是in的值);。
在硬件中没有这种混乱。它将扑灭摆锤时间存在的值out1的 old 值(嗯,除非时钟出现异常延迟)。
为了匹配此行为,引入了非阻塞分配。 Verilog仿真是在仿真刻度中完成的。只要有可能导致其他区块重新评估的事件,每个刻度都将保持不变。非阻塞分配被调度为在带有当前rhs值的滴答结束时执行(实际上有几个调度区域)。因此,请考虑以下因素:
always @(posedge clk)
out1 <= in;
always @(posedge clk)
out2 <= out1;
在上面的示例中,所有分配都将在刻度线的末尾发生。 “ out2”将被分配一个在<=时存在的值,因此它将是out1的旧值。现在,执行顺序无关紧要。
因此,最高级别的建议是将阻塞分配(=)用于组合逻辑,并将非阻塞分配(<=)用于状态设备,触发器和锁存器的所有输出。请注意,状态设备内部的一些临时变量(仅在内部使用)也应分配有阻塞功能。另外,切勿在时钟树中使用非阻塞分配。