阻塞赋值与非阻塞赋值
1. 理论学习
阻塞赋值的赋值号用“ = ”表示。
阻塞赋值的操作可以认为是只有一个步骤的操作,即计算赋值号右边的语句并更新赋值号左边的语句,此时不允许有来自任何其他 Verilog 语句的干扰,直到现行的赋值完成时刻,即把当前赋值号右边的值 赋值给左边的时刻完成后,它才允许下一条的赋值语句的执行。
阻塞的概念是指在同一个 always 块中,其后面的赋值语句是在前一句赋值语句结束后再开始下面的赋值。
非阻塞赋值的赋值号用“ <= ”表示。
非阻塞操作开始时计算非阻塞赋值符的赋值号右边的语句,赋值操作结束时刻才更新赋值号左边的语句,可以认为是两个步骤(赋值开始时刻和结束时刻)来完成非阻塞赋值。
在计算非阻塞语句赋值号右边的语句和更新赋值号左边的语句期间,其他的 Verilog 语句包括其他 的 Verilog 非阻塞赋值语句都能同时计算赋值号右边的语句和更新赋值号左边的语句,允许其他的 Verilog 语句同时进行操作。
- 注意:非阻塞操作只能用于对寄存器类型变量进行赋值,因此只能用于“initial”和“always”块 中,不允许用于连续赋值“assign”。
2. 代码部分
阻塞赋值
module blocking
(
input wire sys_clk,
input wire sys_rst_n,
input wire [1:0] in,
output reg [1:0] out
);
reg [1:0] in_reg;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
begin
in_reg = 2'b0;
out = 2'b0;
end
else
begin
in_reg = in; //in_reg被赋值,但是占用20ns“阻塞”
out = in_reg; //而后out被in_reg赋值,所以波形显示“延迟了”20ns
end
endmodule
阻塞赋值仿真代码
`timescale 1ns/1ns
module tb_blocking();
reg sys_clk;
reg sys_rst_n;
reg [1:0] in;
wire [1:0] out;
initial begin
sys_clk = 1'b1;
sys_rst_n <= 1'b0;
in <= 2'b0;
#20;
sys_rst_n <= 1'b1;
end
always #10 sys_clk = ~sys_clk;
always #20 in <= {$random}%4; //取0123,因为单位是2bits
blocking blocking_inst
(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.in (in),
.out (out)
);
endmodule
非阻塞赋值
module non_blocking
(
input wire sys_clk,
input wire sys_rst_n,
input wire [1:0] in,
output reg [1:0] out
);
reg [1:0] in_reg;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
begin
in_reg <= 2'b0;
out <= 2'b0;
end
else
begin
in_reg <= in;
out <= in_reg;
end
endmodule
非阻塞赋值仿真代码
`timescale 1ns/1ns
module tb_non_blocking();
reg sys_clk;
reg sys_rst_n;
reg [1:0] in;
wire [1:0] out;
initial begin
sys_clk = 1'b1;
sys_rst_n <= 1'b0;
in <= 2'b0;
#20;
sys_rst_n <= 1'b1;
end
always #10 sys_clk = ~sys_clk;
always #20 in <= {$random}%4; //取0123,因为单位是2bits
non_blocking non_blocking_inst
(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.in (in),
.out (out)
);
endmodule
3. 仿真图以及解析
阻塞赋值:
与sys_clk无关,只要in_reg改变,out跟着直接变,没有sys_clk的20 ns的等待,但是这样子赋值的话电路就不确定,所以尽量要使用非阻塞赋值
非阻塞赋值:
与sys_clk有关,每一次in -> in_reg, in_reg -> out的过程,都要经过sys_clk的等待,但是这样子赋值是并行进行,电路确定,所以设计FPGA应多使用非阻塞赋值