Verilog 블록 간/블록 내 지연 이해: 인터/인트라 할당 지연
Verilog 지연 문장은 할당 연산자의 좌변(LHS) 또는 우변(RHS) 어느 쪽에든 지연을 지정할 수 있습니다.
블록 간 지연 (Inter-assignment Delays)
// 지연이 왼쪽 항에 지정됨
#<delay> <LHS> = <RHS>
블록 간 지연 문장은 할당 연산자의 LHS에 지연 값이 있습니다. 이는 문장 자체가 지연이 만료된 후에 실행됨을 나타내며, 지연 제어의 가장 일반적인 형태입니다.
module tb;
reg a, b, c, q;
initial begin
$monitor("[%0t] a=%0b b=%0b c=%0b q=%0b", $time, a, b, c, q);
// 시간 0에 모든 신호를 0으로 초기화
a <= 0; b <= 0; c <= 0; q <= 0;
// 블록 간 지연: #5 타임 유닛 대기 후 a와 c에 1 할당
// 'a'와 'c'는 현재 타임스텝 끝에 업데이트됨
#5 a <= 1; c <= 1;
// 블록 간 지연: #5 타임 유닛 대기 후 q에 RHS 평가값 할당
#5 q <= a & b | c;
#20;
end
endmodule
q가 10 타임 유닛에 1이 되는 것에 주목하세요. 문장이 10 타임 유닛에 평가되고 RHS(a, b, c의 조합)가 1로 평가되기 때문입니다.
시뮬레이션 로그
xcelium> run
[0] a=0 b=0 c=0 q=0
[5] a=1 b=0 c=1 q=0
[10] a=1 b=0 c=1 q=1
xmsim: *W,RNQUIE: Simulation is complete.
블록 내 지연 (Intra-assignment Delays)
// 지연이 오른쪽 항에 지정됨
<LHS> = #<delay> <RHS>
블록 내 지연은 할당 연산자의 RHS에 지연이 있는 경우입니다. 이는 문장이 먼저 평가되고 RHS의 모든 신호 값이 캡처된 다음, 지연이 만료된 후에 결과 신호에 할당됨을 나타냅니다.
module tb;
reg a, b, c, q;
initial begin
$monitor("[%0t] a=%0b b=%0b c=%0b q=%0b", $time, a, b, c, q);
// 시간 0에 모든 신호를 0으로 초기화
a <= 0; b <= 0; c <= 0; q <= 0;
// 블록 간 지연: #5 타임 유닛 대기 후 a와 c에 1 할당
// 'a'와 'c'는 현재 타임스텝 끝에 업데이트됨
#5 a <= 1; c <= 1;
// 블록 내 지연: 먼저 문장 실행, 5 타임 유닛 대기 후 평가된 값을 q에 할당
q <= #5 a & b | c;
#20;
end
endmodule
로그에서 q에 대한 할당이 누락된 것을 볼 수 있습니다!
시뮬레이션 로그
xcelium> run
[0] a=0 b=0 c=0 q=0
[5] a=1 b=0 c=1 q=0
xmsim: *W,RNQUIE: Simulation is complete.
이유는 5 타임 유닛에 a와 c가 비차단 문으로 할당되기 때문입니다. 비차단 문의 동작은 RHS가 평가되지만 변수에는 그 타임스텝 끝에 할당된다는 것입니다.
따라서 a와 c의 값은 1로 평가되지만 아직 할당되지 않은 상태에서 다음 비차단 문(q의 것)이 실행됩니다. 그래서 q의 RHS가 평가될 때 a와 c는 여전히 0이고, $monitor은 변화를 감지하지 못해 문을 표시하지 않습니다.
변화를 관찰하려면 a와 c에 대한 할당문을 비차단에서 차단으로 변경해 봅시다.
...
// 비차단을 차단으로 변경, 나머지 코드는 동일
#5 a = 1; c = 1;
q <= #5 a & b | c;
...
시뮬레이션 로그
xcelium> run
[0] a=0 b=0 c=0 q=0
[5] a=1 b=0 c=1 q=0
[10] a=1 b=0 c=1 q=1
xmsim: *W,RNQUIE: Simulation is complete.