generate是 Verilog/SystemVerilog 中的生成语句,用于在编译时根据参数条件生成重复的硬件结构或选择性地包含代码模块。
主要用途:
1. 生成重复结构 - 类似 for 循环
// 生成 8 个 D 触发器
genvar i;
generate
for (i = 0; i < 8; i = i + 1) begin : gen_dff
d_ff dff_inst (
.clk(clk),
.rst(rst),
.d(data_in[i]),
.q(data_out[i])
);
end
endgenerate
2. 条件生成 - 类似 if-else
parameter WIDTH = 8;
generate
if (WIDTH > 16) begin : wide_bus
// 宽总线逻辑
adder_32bit adder_inst (...);
end
else if (WIDTH > 8) begin : medium_bus
// 中等宽度逻辑
adder_16bit adder_inst (...);
end
else begin : narrow_bus
// 窄总线逻辑
adder_8bit adder_inst (...);
end
endgenerate
3. case 生成
parameter IMPLEMENTATION = "FAST";
generate
case (IMPLEMENTATION)
"FAST" : begin
fast_multiplier mult_inst (...);
end
"SMALL" : begin
small_multiplier mult_inst (...);
end
default : begin
generic_multiplier mult_inst (...);
end
endcase
endgenerate
重要特点:
1. genvar 类型变量
genvar i; // 专门用于 generate 的变量
2. 块标签必须要有
generate
for (i = 0; i < 4; i++) begin : my_block // 这个标签必须有
// 实例化代码
end
endgenerate
3. 编译时确定
generate 语句在编译时展开,不是运行时逻辑。
实用示例:
例1:可配置宽度的移位寄存器
module shift_register #(
parameter WIDTH = 8,
parameter DEPTH = 4
)(
input clk, rst,
input [WIDTH-1:0] data_in,
output [WIDTH-1:0] data_out
);
wire [WIDTH-1:0] stage [0:DEPTH];
assign stage[0] = data_in;
assign data_out = stage[DEPTH];
genvar i;
generate
for (i = 0; i < DEPTH; i = i + 1) begin : gen_stage
d_ff #(WIDTH) dff_inst (
.clk(clk),
.rst(rst),
.d(stage[i]),
.q(stage[i+1])
);
end
endgenerate
endmodule
例2:参数化多路选择器
module param_mux #(
parameter WIDTH = 8,
parameter NUM_INPUTS = 4
)(
input [clog2(NUM_INPUTS)-1:0] sel,
input [WIDTH-1:0] data_in [0:NUM_INPUTS-1],
output [WIDTH-1:0] data_out
);
generate
if (NUM_INPUTS == 1) begin : single_input
assign data_out = data_in[0];
end
else begin : multiple_inputs
assign data_out = data_in[sel];
end
endgenerate
// 计算 log2 的函数
function integer clog2(input integer value);
// ...
endfunction
endmodule
与普通 for 循环的区别:
| 特性 | generate for |
普通 for |
|---|---|---|
| 执行时间 | 编译时 | 运行时 |
| 用途 | 实例化硬件 | 描述行为 |
| 变量类型 | genvar |
integer |
| 可实例化模块 | 可以 | 不可以 |
常见错误:
// 错误:在 generate 中使用 reg/integer
genvar i;
generate
for (i = 0; i < 4; i++) begin
reg temp; // 错误!不能在 generate 中声明 reg
end
endgenerate
// 正确:在 generate 块内实例化模块或 assign
generate
for (i = 0; i < 4; i++) begin
assign out[i] = in[i]; // 正确
end
endgenerate
总结:
generate是一个强大的元编程工具,用于:
-
创建可重用的参数化设计
-
根据配置生成不同的硬件结构
-
减少重复代码
-
提高代码的可维护性和可配置性