生成语句可以动态地生成Verilog代码。当对矢量中的多个位进行重复操作时,或者当进行多个模块的实例引用的重复操作时,或者在根据参数的定义来确定程序中是否应该包括某段Verilog代码的时候,生成语句的使用方便了参数化模块的生成。
生成语句能够控制变量的声明、任务或函数的调用,还能对实例引用进行全面的控制。关键字generate-endgenerate来指定生成的实例范围。生成实例可以是以下的一个或多个类型:
(1)模块;
(2)用户定义原语;
(3)门级原语;
(4)连续赋值语句;
(5)initial和always块。
1、代码设计中可以多次有条件地调用(实例引用)生成的实例和生成的变量声明,而且生成的实例具有唯一的标识名,可以用层次命名规则引用。
2、为了支持结构化的元件和过程块语句的相互连接,Verilog语言允许在生成范围内声明下列数据类型:
(1)net(线网)、reg(寄存器);
(2)integer(整型数)、real(实型数)、time(时间型)、realtime(实数时间型);
(3)event(事件)。
而且,生成的数据类型具有唯一的标识名,也可以被层次引用。生成范围中可以定义使用按照秩序或者参数名赋值的参数重新定义,或者使用defparam声明的参数(需在同一个生成范围内或者生成范围的层次化实例中)重新定义。
3、任务和函数的声明也允许出现在生成范围之中,但是不允许出现在循环生成中。生成任务和函数同样具有唯一的标识符名称,可以被层次引用。
4、不允许出现在生成范围之中的模块项声明包括:
(1)参数、局部参数;
(2)输入、输出和输入/输出声明;
(3)指定块。
5、在Verilog中有3中创建生成语句的方法:
(1)循环生成;
(2)条件生成;
(3)case生成。
生成块的主要作用:
(1)实例引用(有条件地调用,即只引用需要用到的实例),可以理解为一种静态展开行为,在仿真开始前,编译器就将代码展开,把行为预先确定下来,不会例化不需要的逻辑分支而生成电路;
(2)利用标识后唯一的标识名,可以对生成语句中的变量进行层次化引用。
(1)关键字:generate-for;
(2)关键字genvar用于声明生成变量(定义for的索引变量),生成变量只能用在生成块中,在确立后的仿真代码中,生成变量是不存在的;
(3)for循环体的begin后的标识名是赋予循环生成语句的名字,目的在于通过它对循环生成语句中的变量进行层次化引用。
//8bit width buffer
module buffer_8(
input[7:0] din,
output[7:0] dout
);
// Generate block
//声明一个临时循环生成变量,只用于生成块的循环计算
//Verilog仿真时该变量在设计中并不存在
genvar i;
//用一个单循环生成按位取反
generate
for(i=0; i<8; i=i+1)
begin:buffer_1_loop //循环生成语句的标识名
buffer_1 g1( //实例引用buffer_1
.in(din[i]),
.out(dout[i])
);
end //在生成块内部结束循环
endgenerate //结束生成块
//根据上面的循环生成,Verilog编译器会自动生成以下相对层次实例名
//buffer_1: buffer_1_loop[0].g1, buffer_1_loop[1].g1,
// buffer_1_loop[2].g1, buffer_1_loop[3].g1,
// buffer_1_loop[4].g1, buffer_1_loop[5].g1,
// buffer_1_loop[6].g1, buffer_1_loop[7].g1。
endmodule
//1bit width buffer_1
module buffer_1(
input in,
output out
);
assign out = ~in;
endmodule
(1)关键字:generate-if;
(2) if的条件都为常量条件,根据不同的条件引用不同的实例(这里与普通的if不同,普通的if会例化所有的分支结构生成电路)
module ex_generate_if(
input a, b, c,
output y
);
//本地参数声明,不能用参数重新定义(defparam)修改
//也不能在实例引用时通过传递参数语句,即#(参数1, 参数2,...)的方法修改
localparam size = 12;
//有条件地调用(实例引用)不同类型的组合逻辑
//根据参数size的值,在调用时引用相对应的组合逻辑实例
generate
if(size < 8)
assign y = a & b & c;
else if(size == 8)
assign y = a & b | c;
else
assign y = a | b | c; //The generated instance
endgenerate
endmodule
(1)关键字:generate-case;
(2)只会选择case的一路分支进行实例例化。
//N位加法器(顶层.v)
module adder(a0,a1,ci,co,sum);
parameter N = 4;
input[N-1:0] a0, a1;
input ci;
output co;
output[N-1:0] sum;
//根据总线的位宽N,调用(实例引用)相应的加法器
//参数N在调用时可以重新定义,调用
generate
case(N)
1: adder_1bit adder1(a0,a1,ci,co,sum);
2: adder_2bit adder2(a0,a1,ci,co,sum);
default: adder_cla #(N) adder3(a0,a1,ci,co,sum);
endcase
endgenerate
endmodule