FPGA之道(74)Verilog生成语句

举报
李锐博恩 发表于 2021/07/15 00:37:43 2021/07/15
【摘要】 文章目录 前言Verilog生成语句循环生成条件生成generate-if语句generate-case语句 前言 为什么要把这一节单独拎出来,因为个人原因,平时觉得用的Verilog生成语句,generate for居多,generate if以及generate case没用过,因此,也没在意过。 但是上次遇到一个实际问题,想到了这个语法,...

前言

为什么要把这一节单独拎出来,因为个人原因,平时觉得用的Verilog生成语句,generate for居多,generate if以及generate case没用过,因此,也没在意过。
但是上次遇到一个实际问题,想到了这个语法,但是用错了,if以及case后面的变量应该是常量,而不应该是变量等,这和我们之前用到的case 以及if有所区别,因此也就没用成。
这里注意一下。
最重要:本文来自于《FPGA之道》对这一知识点的讲解。

Verilog生成语句

Verilog中的生成语句主要使用generate语法关键字,按照形式主要分为循环生成与条件生成,分别介绍如下:

循环生成

循环生成的主要目的是简化我们的代码书写,利用循环生成语句我们可以将之前需要写很多条比较相似的语句才能实现的功能用很简短的循环生成语句来代替。基本语法如下:

genvar ;
generate
for (=0; < ; =+1)
begin:

end
endgenerate
关于以上语法有四点注意:
1、循环生成中for语句使用的变量必须用genvar关键字定义,genvar关键字可以写在generate语句外面,也可以写在generate语句里面,只要先于for语句声明即可;
2、必须给循环段起一个名字。这是一个强制规定,并且也是利用循环生成语句生成多个实例的时候分配名字所必须的;
3、for语句的内容必须加begin-end,即使只有一条语句也不能省略。这也是一个强制规定,而且给循环起名字也离不开begin关键字;
4、可以是实例化语句也可以是连续赋值语句。
关于循环生成,举例如下:

input [3:0] a,b;
output [3:0] c,d;

generate
genvar i;
	for (i=0; i < 4; i=i+1) 
	begin : genExample
		myAnd insAnd (.a(a[i]), .b(b[i]), .c(c[i]));
		assign d[i] = a[i];
	end
endgenerate

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

注意,利用循环生成语句生成的实例名称不能像数组例化那样用方括号表示,否则会报错。那么,你可能会疑惑上例中实例的名字,其实,上述实例化展开来类似:

myAnd genExample(0).insAnd (.a(a[0]), .b(b[0]), .c(c[0]));
myAnd genExample(1).insAnd (.a(a[1]), .b(b[1]), .c(c[1]));
myAnd genExample(2).insAnd (.a(a[2]), .b(b[2]), .c(c[2]));
myAnd genExample(3).insAnd (.a(a[3]), .b(b[3]), .c(c[3]));

  
 
  • 1
  • 2
  • 3
  • 4

这也是为什么循环生成语句必须要有个名字。从上例我们还可以看出,当循环语句用作实例化时,所表述的功能跟数组实例化语句其实是类似的。
最后,循环生成语句是支持嵌套的,例如二重循环生成语法如下:

	genvar <var1>, <var2>;
generate for (<var1>=0; <var1> < <limit>; <var1>=<var1>+1) begin: <label_1> for (<var2>=0; <var2> < <limit>; <var2>=<var2>+1) begin: <label_2> <code> end end
endgenerate	

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

条件生成

条件生成的目的是为了左右编译器的行为,类似于C语言中的条件选择宏定义,根据一些初始参数来决定载入哪部分代码来进行编译。Verilog中共提供了两种条件生成语句,一种是generate-if语句,一种是generate-case语句,两者的功能几乎相同,只是书写形式不一样而已,分别介绍如下:

generate-if语句

该语句的语法如下:

generate
	if (<condition>) begin: <label_1>
		<code>;
	end else if (<condition>) begin: <label_2>
		<code>;
	end else begin: <label_3>
		<code>;
	end
endgenerate

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

关于该语法有三点注意:

1、必须是常量比较,例如一些参数,这样编译器才可以在编译前确定需要使用的代码;
2、if语句的内容中,begin-end只有在 < code > 有多条语句时才是必须的;
3、每一个条件分支的名称是可选的,这点不像循环生成语句那么严格。

关于generate-if语句,举例如下:

wire c, d0, d1, d2;
parameter sel = 1;

generate
	if (sel == 0)
		assign c = d0;
	else if (sel == 1)
		assign c = d1;
	else
		assign c = d2;
endgenerate

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

该例子表示编译器会根据参数sel的值,来确定到底是让d0~d2中哪个变量和c连通。但是注意,一旦连通,那么要想更改必须修改参数后重新编译,如果需要动态选择,可以写成如下这样,但是资源上却都需要一个多路复用器来实现。

assign c = (sel == 0) ? d0 : (sel == 1) ? d1 : d2;

  
 
  • 1

generate-case语句

该语句的语法如下:

	generate
		case (<constant_expression>) <value>: begin: <label_1> <code> end <value>: begin: <label_2>
<code> end …… default: begin: <label_N>
<code>
end endcase endgenerate

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

关于该语法也有三点注意,和generate-if类似:
1、<constant_expression>必须是常量比较,例如一些参数,这样编译器才可以在编译前确定需要使用的代码;
2、case语句的内容中,begin-end只有在< code >有多条语句时才是必须的;
3、每一个条件分支的名称是可选的,这点不像循环生成语句那么严格。

关于generate-case语句,举例如下:

wire c, d0, d1, d2;
parameter sel = 1;

generate
	case (sel)
		0 : assign c = d0;
		1: assign c = d1;
		default: assign c = d2;
	endcase
endgenerate

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

该例所描述的功能和generate-if小节的例子是一模一样的。

文章来源: reborn.blog.csdn.net,作者:李锐博恩,版权归原作者所有,如需转载,请联系作者。

原文链接:reborn.blog.csdn.net/article/details/105068239

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。