Verilog Generate 블록 마스터: 동적 인스턴스화와 조건부 설계
generate 블록은 모듈 인스턴스를 반복 생성하거나 파라미터 기반으로 조건부 인스턴스화를 수행합니다. 정적 엘라보레이션(Elaboration) 단계에서 전개되므로 런타임 오버헤드 제로.
generate 블록 제약
- 포트, 파라미터,
specparam, specify 블록 포함 불가
- 모듈 아이템, 다른 generate 블록, 연속 할당,
always/initial, UDP 허용
generate ~ endgenerate 키워드로 감싸기
생성 구조 3가지
- Generate for loop
- Generate if-else
- Generate case
1. Generate For Loop: 반복 인스턴스화
루프 변수는 genvar 키워드로 선언 (엘라보레이션 타임 변수).
// 하프 가산기
module ha (input a, b, output sum, cout);
assign sum = a ^ b;
assign cout = a & b;
endmodule
// N개 하프 가산기 배열
module my_design #(parameter N = 4) (
input [N-1:0] a, b,
output [N-1:0] sum, cout
);
genvar i;
generate
for (i = 0; i < N; i = i + 1) begin : gen_ha
ha u0 (.a(a[i]), .b(b[i]), .sum(sum[i]), .cout(cout[i]));
end
endgenerate
endmodule
begin : gen_ha로 블록 명명 → 계층 경로에서 gen_ha[0], gen_ha[1]... 접근 가능
- 파라미터
N로 인스턴스 수 제어
테스트벤치
module tb;
parameter N = 2;
reg [N-1:0] a, b;
wire [N-1:0] sum, cout;
my_design #(.N(N)) md (.a(a), .b(b), .sum(sum), .cout(cout));
initial begin
a=0; b=0; $monitor("a=%h b=%h sum=%h cout=%h", a,b,sum,cout);
#10 a=2; b=3; #20 b=4; #10 a=5;
end
endmodule
2. Generate If-Else: 조건부 인스턴스화
파라미터 값에 따라 다른 구현 선택.
// 구현 1: assign 기반 멀티플렉서
module mux_assign (input a, b, sel, output out);
assign out = sel ? a : b;
initial $display("mux_assign instantiated");
endmodule
// 구현 2: case 기반 멀티플렉서
module mux_case (input a, b, sel, output reg out);
always @(a or b or sel) case (sel) 0: out=a; 1: out=b; endcase
initial $display("mux_case instantiated");
endmodule
// 탑레벨: 파라미터로 선택
module my_design (input a, b, sel, output out);
parameter USE_CASE = 0;
generate
if (USE_CASE)
mux_case mc (.a(a), .b(b), .sel(sel), .out(out));
else
mux_assign ma (.a(a), .b(b), .sel(sel), .out(out));
endgenerate
endmodule
시뮬레이션 로그로 어느 구현이 엘라보레이트됐는지 확인 가능.
3. Generate Case: 다중 선택
module ha (input a, b, output reg sum, cout);
always @(a or b) {cout, sum} = a + b;
initial $display("Half adder instantiated");
endmodule
module fa (input a, b, cin, output reg sum, cout);
always @(a or b or cin) {cout, sum} = a + b + cin;
initial $display("Full adder instantiated");
endmodule
module my_adder (input a, b, cin, output sum, cout);
parameter ADDER_TYPE = 1;
generate
case (ADDER_TYPE)
0: ha u0 (.a(a), .b(b), .sum(sum), .cout(cout));
1: fa u1 (.a(a), .b(b), .cin(cin), .sum(sum), .cout(cout));
endcase
endgenerate
endmodule
ADDER_TYPE=0이면 하프 가산기 인스턴스화 → cin 무시됨.
실무 활용 시나리오
- 파이프라인 스테이지 수 파라미터화:
for (i=0; i
- 기능 옵션 선택: ECC 포함/미포함, 압축 모드 등
- 비트 폭별 다른 구현: 좁은 폭은 룩업테이블, 넓은 폭은 DSP 블록
- 공정/전압/온도(PVT) 코너별 다른 타이밍 제약 적용
주의사항
- Generate는 엘라보레이션 타임에 전개 → 시뮬레이션/합성 후 구조 고정
genvar는 일반 변수와 다름: 프로시저럴 블록에서 사용 불가
- 중첩 generate 시 블록 명명(
begin : name) 필수로 계층 경로 충돌 방지