阻塞赋值和非阻塞赋值
理论学习
阻塞赋值 用 = 表示 ,这种对应的电路结构常常与触发器没有关系,只与输入电平的变化有关系。可以将阻塞赋值的操作看作只有一个步骤的操作,即将计算赋值符号的右边赋值给左边,在未执行完之前,不允许其他verilog语句执行。
非阻塞赋值 用 <= 表示,这种对应的电路结构常常与触发沿有关系,只有在触发沿才能执行。非阻塞逻辑开始时 先计算式子右边的语句,赋值操作结束时才更行式子左边的语句,可以认为需要两个步骤来完成赋值。非阻塞赋值执行的时候,其他verilog语句都能同时计算。
阻塞赋值
module blocking
(
input wire sys_clk ,
input wire sus_rst_n ,
input wire [1:0] in ,
output reg [1:0] out
);
reg [1:0] in_reg ;//给out延迟 1 clk
always(posedge sys_clk or negedge sys_rst_n )
begin
if(sys_rst_n == 1'b0)
begin
in_reg = 2'b0 ;
out = 2'b0 ;
end
else
begin
in_reg = in ;
out = in_reg ;
end
end
endmodule
阻塞赋值对应的tb
`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'b0 ;
sys_rst_n <= 1'b0 ;
int <= 2'b0 ;
#20 ;
sys_rst_n <= 1'b1 ;
end
always #10 sys_clk <= ~sys_clk ;
always #20 in <= {$random}%4 ;
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)
begin
if(sys_rst_n == 1'b0)
begin
in_reg <= 2'b0 ;
out <= 2'b0 ;
end
else
begin
in_reg <= in ;
out <= in_reg ;
end
end
endmodule
非阻塞赋值对应的tb,结果发现,in和in_reg有一个clk延时,in_reg和out有一个延时,也就是in和out有两个延时。
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'b1 ;
in <= 2'b0 ;
#20 ;
sys_rst_n <= 1'b1 ;
end
always #10 sys_clk = ~sys_clk ;
always #20 in <= {$random}%4 ;
non_block non_block_inst
(
.sys_clk (sys_clk) ,
.sys_rst_n (sys_rst_n) ,
.in (in) ,
.out (out)
);
endmodule