介绍:
生成块可以动态地生成Verilog代码。
这一声明语句方便了参数化模块的生成。当对矢量中的多个位进行重复操作时,或者当进行多个模块的实例引用的重复操作时,或者在根据参数的定义来确定程序中是否应该包括某段Verilog代码的时候,使用生成块语句能够大大地简化程序的编写过程。
生成块语句能够控制变量的声明、任务或者函数的调用,还能对实例引用进行全面的控制。编写代码时必须在模块中说明生成的实例范围,关键字generate-endgenerate用来指定该范围。
生成实例可以使以下的一个或者多种类型:
(1)模块
(2)用户的定义原语
(3)门级原语
(4)连续赋值语句
(5)initial和always块
生成的声明和生成的实例能够在设计中被有条件地调用(实例引用)。在设计中可以多次调用(实例引用)生成的实例和生成的变量声明。生成的实例唯一的标识名,因此可以用层次命名的规则引用。为了支持结构化的元件与过程块语句的相互连接,Verilog语言允许在生成的范围内声明下列数据类型:
(1)net(线网)、寄存器(reg)
(2)integer(整型数)、real(实型数)、time(时间型)、realtime(实数时间型)
(3)event(事件)
生成的数据类型具有唯一的标识名,可以被层次引用。此外,究竟是使用按照次序或者参数名赋值的参数重新定义,还是defparam声明的参数重新定义,都可以在生成范围中定义。
注意:生成范围中定义的defparam语句能够重新定义的参数必须是在同一个生成范围内,或者是在生成范围的层次化实例当中。
任务和函数也允许出现在生成范围中,但是能不能出现在循环生成当中。生成任务和函数具有唯一的标识符名称,可以被层次引用。
不允许出现在生成范围之内的模块项声明包括:
(1)参数、局部参数;
(2)输入、输出和输入/输出声明;
(3)指定块
生成块实例的连接方法与常规模块实例相同。
3中创建生成语句的方法,他们是:
(1)循环生成
(2)条件生成
(3)case生成
举例:
(1)循环生成:
对两个n位总线变量进行按位异或
module bitwise_xor(out,i1,i2);
parameter N = 32;
input [N-1:0] i1;
input [N-1:0] i2;
output[N-1:0] out;
genvar j;//声明的此变量只用于生成块的循环计算,在电路里面并不存在
generate
for(j=0;j
上述代码需要注意以下几个方面:
(1)在仿真开始之前,仿真器会对生成块中的代码进行确立(展平),将生成块转换为展开的代码,然后对展开的代码进行仿 真。因此,生成快的本质是使用循环内的一条语句来代替多条重复的verilog语句,以简化用户的编程。
(2)关键词genvar用于声明生成变量,生成变量只能用在生成快之中;在确立后的代码中,生成变量并不存在,也即是说综合 完之后,它不会真正的映射到实际的(电路)FPGA中。
(3)一个生成变量的值只能由循环生成语句来改变(也即是上述的for语句)
(4)循环生成语句可以嵌套使用,不过同一个生成变量作为索引的循环生成语句不能够相互嵌套。
(5)上述代码中的xor_loop是赋予生成语句的名字,目的在于通过它对循环语句中的变量进行层次化引用。因此,循环生成语句中各个异或门的相对层次为xor_loop[0].g1,xor_loop[1].g1,。。。xor_loop[31].g1,
(2)条件生成语句:
条件生成语句类似于if..else..if的生成构造,该结构可以在设计模块中有条件调用(调用又叫做实例引用)以下verilog结构:
(1)模块;
(2)用户定义原语,门级原语
(3)连续赋值语句
(4)initial或always块
举例说明:
使用条件生成语句实现参数化乘法器
module multiplier(product,a0,a1);
//参数声明,该参数可以重新定义
parameter a0_width = 8;
parameter a1_width = 8;
//本地参数声明
//本地参数不能用参数重新定义(defparam)
//也不能在实例引用时通过传递参数语句,即#(参数1,参数2,.....)的方法修改
localparam product_width = a0_width + a1_width;
input [a0_width-1:0] a0;
input [a1_width-1:0] a1;
ouput [product_width-1:0] prduct;
//条件生成语句如下所示:
//有条件地调用(实例引用)不同类型的乘法器
//根据参数a0_width和a1_width的值,在调用时引用相应的乘法器实例
generate
if(a0_width<8)||(a1_width<8)
cal_multiplier #(a0_width,a1_width)m0(product,a0,a1);
else
tre_multiplier #(a0_width,a1_width)m0(product,a0,a1);
endgenerate
endmodule
(3)case生成语句
case生成语句可以在设计模块中有条件调用(调用又叫做实例引用)以下verilog结构:
(1)模块;
(2)用户定义原语,门级原语
(3)连续赋值语句
(4)initial或always块
举例说明:
//case生成语句实现位加法器
module addr(co,sum,a0,a1,ci);
//参数定义,本参数可以重新定哟
parameter N = 4 //默认总线位宽为4
input [N-1:0]a0,a1;
input ci;
output[N-1:0]sum;
output co;
//根据总线位宽,有条件地调用(实例引用)不同类型的加法器
//参数N在调用(实例引用)时可以重新定义,
//不同类型(位宽)的加法器根据不同的N来决定
generate
case(N)
//当N=1或N=2时分别选用位宽为1或者位宽为2的加法器
1:adder_1bit adder1(co,sum,a0,a1,ci);//实例1位加法器模块
2:adder_1bit adder1(co,sum,a0,a1,ci);//实例2位加法器模块
default:adder_cla #(N) adder3(co,sum,a0,a1,ci);//实例N位加法器模块
endcase
endgenerate
endmodule
生成语句真的很有用,可以减少大规模的重复工作。