1.1简单叙述阻塞赋值和非阻塞赋值的区别:
(1)阻塞赋值(=)必须是阻塞赋值完成后,才进行下一条语句的执行;赋值一旦完成,等号左边的变量值立即变化。在同一个块中,非阻塞赋值表达式的书写顺序不影响赋值的结果。硬件没有对应的电路。(要点为串行,立即生效)
(2)非阻塞赋值(<=)在赋值开始时计算表达式右边的值,在本次仿真周期结束时才更新被赋值变量,即赋值不是立即生效的;非阻塞赋值允许块中其他语句同时执行。在同一个块中,非阻塞赋值表达式的书写顺序不影响赋值的结果。硬件有对应的电路。(要点:并行,不是立即生效,同时执行)
夏宇闻老师《Verilog数字系统设计教程》的读书笔记
阻塞赋值对应的电路结构往往与触发沿没有关系,只与输入的电平变化有关系;非阻塞赋值对应的电路结构往往与触发沿有关系,只有在触发沿时才有可能发生赋值的情况。
阻塞赋值操作符是“=”,非阻塞赋值操作符是“<=”。
阻塞的概念是指在同一个always块中,其后面的赋值语句从概念上是前一句赋值语句结束后再开始赋值的。
非阻塞赋值的概念是指在赋值操作开始时刻计算RHS表达式,赋值操作结束时刻更新LHS。关键来了,always块里的其他语句是同时进行计算RHS表达式和更新LHS的。
非阻塞赋值操作只能对寄存器类型变量进行赋值,因此只能用在“initial”块和“always”块等过程块中,非阻塞赋值不能用于连续赋值(assign语句)。
个人理解:阻塞赋值是指过程块中的语句是串行执行的(即一条语句执行完成才能执行下一条语句);非阻塞赋值是指过程块中的语句是并行执行的,即所有的语句都可以在赋值操作开始时刻同时计算RHS,在赋值操作结束时刻同时更新LHS。
8个要点:
(1) 时序电路建模时,用非阻塞赋值(<=)。
(2) 锁存器电路建模时,用非阻塞赋值(<=)。
(3) 用always块建立组合逻辑时,用阻塞赋值(=)。
(4) 在同一个always块中建立时序和组合逻辑电路时,用非阻塞赋值。
(5) 在同一个always块中不要既用非阻塞赋值又用阻塞赋值。
(6) 不要在一个以上的always块中为同一个变量赋值。
(7) 用$strobe系统任务来显示用非阻塞赋值的变量值。
(8) 在赋值时不要使用#0延迟。
举例:移位寄存器
(1)阻塞赋值按照下面的写法生成的并非移位寄存器
module pipe(
input d,
input clk,
output q3
);
reg q1,q2,q3;
always@(posedge clk)
begin
q1=d;
q2=q1;
q3=q2;
end
endmodule
综合效果如下图所示
用阻塞赋值实现移位寄存器的代码:
module pipe(
input d,
input clk,
output q3
);
reg q1,q2,q3;
always@(posedge clk)
begin
q3=q2;
q2=q1;
q1=d;
end
endmodule
综合出来的结果是不同的。
(2)将上面两个换成非阻塞赋值后,综合出来的结果都是移位寄存器且结果相同。
第一种情况的代码及对应电路
module pipe(
input d,
input clk,
output q3
);
reg q1,q2,q3;
always@(posedge clk)
begin
q1<=d;
q2<=q1;
q3<=q2;
end
endmodule
第二种情况的代码和对应的电路
module pipe(
input d,
input clk,
output q3
);
reg q1,q2,q3;
always@(posedge clk)
begin
q3<=q2;
q2<=q1;
q1<=d;
end
endmodule
参考出处传送门