verilog 中generate(生成块)的相关知识详解

本文介绍了Verilog生成块,它可动态生成代码,方便参数化模块生成,能控制变量声明、任务或函数调用及实例引用。说明了生成实例类型、可声明的数据类型,介绍了循环生成、条件生成、case生成三种创建方法,并举例说明,强调其能减少大规模重复工作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

介绍:

生成块可以动态地生成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<N;j=j+1)
        begin:xor_loop//xor_loop为块名字,命名块
           xor g1 (out[j],i0[j],i[j]);
        end
endgenerate
//另外一种形式,异或门可以用always代替
//reg[N-1:0] out;
//generate
//    for(j=0;j<N;j=j+1)
//     begin:bit
//       always@(i0[j] or i1[j]) out[j] = i0[j]^i1[j];
//     end
//endgenerate
endmodule

上述代码需要注意以下几个方面:

(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

生成语句真的很有用,可以减少大规模的重复工作。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值