Verilog 블록 문장 마스터: 순차(begin-end) vs 병렬(fork-join) 실행
여러 문장을 하나로 그룹화하는 블록 문장은 begin-end (순차)와 fork-join (병렬) 두 가지가 있습니다. 시뮬레이션 시간 제어와 실행 흐름 이해에 필수적입니다.
순차 블록 (Sequential Block: begin-end)
문장이 순서대로 실행. 지연(#)은 이전 문장 실행 시점 기준 상대적.
module design0;
reg [31:0] data;
initial begin
#10 data = 8'hfe; // 시간 10에 실행
$display("[Time=%0t] data=0x%0h", $time, data);
#20 data = 8'h11; // 이전 문장(시간 10) + 20 = 시간 30에 실행
$display("[Time=%0t] data=0x%0h", $time, data);
end
endmodule
출력: Time=10, Time=30.
병렬 블록 (Parallel Block: fork-join)
문장이 동시에 시작 (fork 시점 기준). 지연은 fork 시점부터 절대적.
initial begin
#10 data = 8'hfe; // 시간 10: data=fe
fork
#20 data = 8'h11; // fork 시점(시간 10) + 20 = 시간 30
#10 data = 8'h00; // fork 시점(시간 10) + 10 = 시간 20 ← 먼저 실행!
join
end
실행 순서: 시간 10(fe) → 시간 20(00) → 시간 30(11). 최종값 0x11.
중첩 블록: 순차 블록을 병렬로 실행
initial begin
#10 data = 8'hfe;
fork
#10 data = 8'h11; // 시간 20
begin // 이 begin-end 블록 전체가 병렬로 포크됨
#20 data = 8'h00; // 포크 기준 +20 = 시간 30
#30 data = 8'haa; // 이전 문장(시간 30) +30 = 시간 60
end
join
end
실행: 시간 10(fe) → 시간 20(11) → 시간 30(00) → 시간 60(aa).
블록 명명 (Named Blocks)
begin : name, fork : name으로 명명 후 disable name;으로 강제 종료 가능.
begin : seq_block
#10 a = 1;
#20 b = 1;
end
fork : par_block
#10 c = 1;
#20 d = 1;
join
// 다른 곳에서 강제 종료
disable seq_block;
disable par_block;
- 명명된 블록은
disable 문으로 계층 경로 지정해 비활성화 가능
- 테스트벤치에서 타임아웃 처리, 강제 종료 등에 유용
합성 관점
중요: fork-join, 명시적 지연(#), disable 블록은 합성 불가합니다. 순수 시뮬레이션/테스트벤치용입니다. RTL 설계에서는 always 블록과 상태 머신으로 동기식 구현해야 합니다.
요약 비교표
| 특성 | begin-end (순차) | fork-join (병렬) |
| 실행 순서 | 순차적 | 동시 시작 |
| 지연 기준 | 이전 문장 종료 시점 (상대) | fork 진입 시점 (절대) |
| 합성 가능 | 예 (always 내부에서) | 아니오 |
| 주 용도 | RTL 순차/조합 로직, 테스트벤치 시퀀스 | 테스트벤치 병렬 자극, 타임아웃 감시 |
| 명명/비활성화 | 가능 | 가능 |