阻塞赋值与非阻塞赋值在FPGA开发中非常关键,但新手在刚接触这两个概念时容易搞混,导致仿真结果与预想的时序不一样。其实阻塞赋值和非阻塞赋值理解起来很简单。
一、阻塞赋值(=)
阻塞赋值(blocking assignments)由符号“=”完成。
在描述组合逻辑的always块、assign语句、task、function中用阻塞赋值,则综合成组合逻辑电路,与信号电平触发有关。
阻塞赋值是顺序执行的,只有执行完前一条语句才会执行下一条,执行前一条语句时,下一条语句等待执行,也就是被“阻塞”了
module block(
input clk,
input rst,
input [7:0] in,
output reg [7:0] out1,
output wire [7:0] out2
);
// 参数定义
reg [7:0] in_r;
//阻塞赋值
always @(*) begin
in_r = in;
out1 = in_r;
end
assign out2 = in_r;
endmodule
二、非阻塞赋值(<=)
非阻塞赋值(nonblocking assignments)由符号“<=”完成。
在描述时序逻辑的always块中用阻塞赋值,则综合成时序逻辑电路, 与边沿触发有关。
在时序逻辑电路中,非阻塞赋值语句的执行过程是并行的,即所有的非阻塞赋值语句同时执行,没有先后顺序之分。
注意:非阻塞赋值只能对reg变量进程操作,不能对wire变量进行赋值,只能用在时序逻辑always块中。
module non_block(
input clk,
input rst,
input [7:0] in,
output reg [7:0] out
);
//参数定义
reg [7:0] in_r;
//阻塞赋值
always @(posedge clk or posedge rst) begin
if(rst) begin
in_r <= 'b0;
out <= 'b0;
end else begin
in_r <= in;
out <= in_r;
end
end
endmodule
三、总结
非阻塞赋值和阻塞赋值很好区分,大家只要搞清楚这两点,前期思维转换过来需要点时间,但写代码越多,习惯了,也就越容易理解。
1、逻辑上
非阻塞赋值可以理解成时钟发生边沿变化时,即更新新的计算结果;
阻塞赋值可以理解成计算结果直接依次执行;
2、使用时
大家只需要always@(posedge clk)块中使用非阻塞赋值”<=“和寄存器reg,其余情况使用阻塞赋值”=“即可。