之前一直在排斥对generate的使用,认为这种类似于c语言中for的循环语法并不适用于FPGA设计,因为FPGA实际上还是硬件,循环N次,就会映射N个同样的模块到FPGA,也就是多消耗的N倍的资源,为了节约资源多都会选择复用的方式来处理类循环数据。
但是殊不知在处理循环数据的时候还是会消耗一定的资源以及逻辑调试的时间成本(同时也可能买下bug),最终可能也节约不了多少资源,而且相比于处理逻辑,循环语句要简洁明了,便于代码的阅读和维护。
随着工艺水平的提升,资源貌似也并不是项目考虑的首要因素了,大家都会留出充足的余量,所以开始正视这种generate“非主流”verilog语法。
Verilog-2001中新增了语句generate,通过generate循环,可以产生一个对象(比如一个元件或者是一个模块)的多次例化,为可变尺度的设计提供了方便,generate语句一般在循环和条件语句中使用,为此,Verilog-2001增加了四个关键字generate,endgenerate,
genvar, localparam,genvar是一个新增的数据类型,用在generate的循环中的标尺变量必须定义为genvar类型。
generate语句的最主要功能就是对module、reg、assign、always、task等语句或者模块进行复制。
generate语句有generate_for、generate_if、generate_case三种语句。
一、generate for
note:
1、generate for语句必须有genvar关键字定义for的变量,不可以是reg型,integer型
2、for 的内容必须加begin和end
3、一般要给for语段起个名字(BLOCK1)
// Generate block
genvar i;
generate
for(i=0; i<8; i=i+1) begin:BLOCK1
buffer_1 buffer_1_1(.in(din[i]), .out(dout[i]));
end
endgenerate
二、generate if
generate_for用于复制模块,而generate_if则是根据模块的参数(必须是常量)作为条件判断,来产生满足条件的电路。相当于判断语句。
module generate_if(
input t0 ,
input t1 ,
input t2 ,
output d
);
localparam S = 6; //定义模块所需参数,用于判断产生电路
generate
if(S < 7)
assign d = t0 | t1 | t2;
else
assign d = t0 & t1 & t2;
endgenerate
endmodule
三、generate case
generate_case其实跟generate_if一样,都是根据参数(都必须为常量)作为判断条件,来产生满足条件的电路,不同于使用了case语法而已。
module generate_case(
input t0 ,
input t1 ,
input t2 ,
output d
);
localparam S = 8; //定义模块所需参数,用于判断产生电路
generate
case(S)
0:
assign d = t0 | t1 | t2;
1:
assign d = t0 & t1 & t2;
default:
assign d = t0 & t1 | t2;
endcase
endgenerate
endmodule