문득 Blocking과 Non-blocking의 차이를 직접 파형을 통해 확인해보고 싶었다.
Blocking Assignment는 해당 라인이 실행 완료될 때까지 뒤에 있는 Blocking Assignment들을 잠시 블로킹하는 특성을 가지고 있다.
아래의 예제를 보자.
b=a 부분이 실행되는 동안 뒤에 있는 c=b, d=c, e=d 라인이 실행되지 않는다. b=a가 끝나고서야 뒤에 있는 문장이 실행된다. c=b, d=c 등도 마찬가지다.
(사실 '실행' 된다고 하면 틀린 표현이고, 그렇게 되도록 회로가 '합성' 된다고 보는게 맞다. Schematic을 그려서 설명하고 싶지만 생략..)
`ifndef __BLOCKING_V__
`define __BLOCKING_V__
module blocking(
input a,
output reg b, c, d, e
);
always @ (a) begin
b = a; // blocking
c = b;
d = c;
e = d;
end
endmodule
`endif /*__BLOCKING_V__*/
b에 a가 들어가고 난 후 c에 b가 들어가는 구조이기 때문에, 결과적으로 a의 값이 e에까지 전달된다. 즉 a가 변함에 따라 b, c, d, e가 동시에 같이 변한다.
`timescale 1ms/1ms
`include "blocking.v"
module tb_blocking();
reg a;
wire b, c, d, e;
blocking _blocking(
.a(a),
.b(b),
.c(c),
.d(d),
.e(e)
);
initial begin
// for simulation
$dumpfile("test.vcd");
$dumpvars(-1, _blocking);
// initialize
a <= 1'b0;
// start
#1 a = 1'b1;
#1 a = 1'b0;
#1 a = 1'b1;
#1 a = 1'b0;
#1 a = 1'b1;
#1 a = 1'b0;
#1 a = 1'b1;
#1 a = 1'b0;
#1 a = 1'b1;
#1 a = 1'b0;
// end
#1 $finish;
end
endmodule
> iverilog -o test.vvp blocking.v tb_blocking.v
> vvp test.vvp
> gtkwave test.vcd
위에서 말한 대로 b, c, d, e의 값이 동시에 같이 바뀌는 것을 볼 수 있다.
Non-blocking Assignment는 event 발생 시 block 내의 모든 Non-blocking Assignment들이 동시에 동작한다.
아래의 예제를 보자.
b<=a 부분이 수행됨과 동시에 뒤에 있는 c<=b, d<=c, e<=d 라인도 같이 수행되도록 합성된다.
`ifndef __NONBLOCKING_V__
`define __NONBLOCKING_V__
module nonblocking(
input a,
output reg b, c, d, e
);
always @ (a) begin
b <= a; // non-blocking
c <= b;
d <= c;
e <= d;
end
endmodule
`endif /*__NONBLOCKING_V__*/
b에 a의 값이 들어감과 동시에 b에 있던 값이 c로 들어가기 때문에, c에는 b에 a가 들어오기 전 값이 들어간다. d, e도 마찬가지이므로, 처음에 a가 변하면 같이 변하는 것은 b 뿐이다.
`timescale 1ms/1ms
`include "nonblocking.v"
module tb_nonblocking();
reg a;
wire b, c, d, e;
nonblocking _nonblocking(
.a(a),
.b(b),
.c(c),
.d(d),
.e(e)
);
initial begin
// for simulation
$dumpfile("test.vcd");
$dumpvars(-1, _nonblocking);
// initialize
a <= 1'b0;
// start
#1 a = 1'b1;
#1 a = 1'b0;
#1 a = 1'b1;
#1 a = 1'b0;
#1 a = 1'b1;
#1 a = 1'b0;
#1 a = 1'b1;
#1 a = 1'b0;
#1 a = 1'b1;
#1 a = 1'b0;
// end
#1 $finish;
end
endmodule
> iverilog -o test.vvp nonblocking.v tb_nonblocking.v
> vvp test.vvp
> gtkwave test.vcd
c, d, e에 각각 b, c, d의 이전 값이 들어가기 때문에, 지그재그 모양의 파형이 나오는 것을 볼 수 있다.
Verilog에서는 한 event block 내에서 Blocking Assignment와 Non-blocking Assignment의 혼용을 지양하고 있다.
둘의 차이를 알고 용도에 따라 적절히 사용하면 될 것 같다.