未闻verilog---generate生成块
生成块
生成块语句可以动态的生成Verilog代码。
编写代码时必须在代码中说明生成的实例范围,关键字generate-endgenerate用来指定该范围。
可以允许出现在生成块中的
实例
Verilog允许生成实例,生成实例可以是以下的一个或多个类型:
- 模块
- 用户定义原语
- 门级原语
- 连续赋值语句
- initial 和 always块
生成的实例具有唯一的标识名,因此可以用层次命名规则引用。
数据类型
Verilog语言允许在生成范围内声明下列数据类型:
- net(线网),reg(寄存器)
- integer(整型数),real(实型数),time(时间型),realtime(实数时间型)
- event(事件)
生成的数据类型具有唯一的标识名,可以被层次引用。
任务和函数
任务和函数的声明可以出现在生成范围之中,但是不能出现在循环生成(generate-for)之中。生成的任务和函数同样具有唯一的标识符名称,可以被层次引用。
不能出现在生成块中的:
不允许出现在生成范围之中的模块项声明包括:
- 参数(parameter),局部参数(localparameter) //可以使用,但不能声明
- 输入,输出和输入/输出声明。
- 指定块。
生成块的形式
generate生成块有两种结构
- 循环结构(generate-for)
- 条件结构(generate-if 和generate-case)
generate-for
允许使用者对下面的模块或者模块项进行多次实例引用:
- 变量声明
- 模块
- 用户定义原语,门级原语
- 连续赋值语句
- initial和always块
基本结构:
parameter N =..//声明循环的边界,没必要用paramete去声明,这里只是为了方便
genvar i; //声明一个临时循环变量,该变量只用于生成块的循环计算,仿真时并不存在
generate
for(i=0;i<N;i=i+1)
begin:block_name //注意一定要声明块的名字!!!
...
end
endgenerate
generate循环的语法与for循环语句的语法很相似。但是在使用时必须先在genvar声明中声明循环中使用的索引变量名,然后才能使用它。genvar声明的索引变量被用作整数用来判断generate循环。genvar声明可以是generate结构的内部或外部区域,并且相同的循环索引变量可以在多个generate循环中,只要这些环不嵌套。genvar只有在建模的时候才会出现,在仿真时就已经消失了。
在仿真开始之前,仿真器会对生成快中的代码进行展开,将生成快转换为展开的代码,然后对展开的代码进行仿真。生成快循环结构的本质就是用循环内的一条语句代替多条重复的Verilog代码,简化用户的编程
循环生成语句可以嵌套使用,不过使用同一个生成变量作为索引的循环生成语句不能相互嵌套。
Verilog中generate循环中的generate块可以命名也可以不命名。如果已命名,则会创建一个generate块实例数组。如果未命名,则有些仿真工具会出现警告,因此,最好始终对它们进行命名。从上面的例子里,块的名字声明为block_name
,虽然名字是block_name
,但实际上是一个组,每个循环生成块的名字为block_name
,例如当要层次化引用时可以写成block_name[1]
generate-if
条件生成语句允许有条件的调用(实例引用)以下结构:
- 模块
- 用户定义原语,门级原语
- 连续赋值语句
- initial或者always块
基本结构
generate
if(condition)
...
else
...
endgenerate
条件语句从很多的备选块中选择最多一个generate块,请注意,在这我说的是最多,因为有可能是一个也不选择的。在建模中,条件必须为常量表达式。
条件if-generate不关心是否命名,并且可以不具有begin / end。当然,上述两个条件只能包含一项。它也会创建单独的范围和层次结构级别,这个和generate循环是一样的。由于最多选择一个代码块,因此在单个的if-generate中以相同的名称命名所有的备用代码块是合法的,而且这有助于保持对代码的分层引用。但是,不同的generate构造中必须具有不同的名称。
generate-case
条件生成语句允许有条件的调用(实例引用)以下结构:
- 模块
- 用户定义原语,门级原语
- 连续赋值语句
- initial或者always块
基本结构:
gengerate
case(..)
..
..
endcase //!!!
endgenerate
case-generate也可用于从几个块中有条件地选择一个代码块。它的用法类似于基本case语句,并且if-generate中的所有规则也适用于case-generate块。
生成块的作用
作用
一个是用来构造循环结构,用来多次实例化某个模块。
一个是构造条件generate结构,用来在多个块之间最多选择一个代码块。
generate-for 与 for之间的区别
参数声明for循环使用integer,generate使用genvar
for循环往往用于always内部,但generate for更加自由,内部可以进行循环例化always和assign
generate -if/case 作用
生成逻辑,和generate for 不一样的是他不会复制逻辑。这个更像是C中的#if ... #endif 条件预编译。要知道在verilog里面只有 `ifdef .....`endif这样的条件编译语句。有了generate if 这样的语句之后我们就可以通过参数/宏 ,当然主要是通过参数,来控制哪部分逻辑需要生成。同样这个generate 块里的东西和generate for 相同。
参考引用
(10 封私信 / 80 条消息) Verilog里的generate到底有什么好处? - 知乎 (zhihu.com)
Verilog中generate的使用 - 知乎 (zhihu.com)