Verilog语法之generate for、generate if、generate case

本文转载自:孤独的单刀的CSDN博客

0、前言

        Verilog-2005中有3个generate 语句可以用来很方便地实现重复赋值和例化(generate for)或根据条件选择性地进行编译(generate if和generate case)等功能。接下来就一起看下这3个语句的应用场景和应用方法吧。

1、generate for

假设我希望把2个输入a[4:0]和b[4:0]做一个异或操作,但是顺序要颠倒,也就是这样:

module xor_test(
	input	[4:0]	a,
	input	[4:0]	b,
	output	[4:0]	out
);
	
assign	out[4] = a[4] ^ b[0];
assign	out[3] = a[3] ^ b[1];
assign	out[2] = a[2] ^ b[2];
assign	out[1] = a[1] ^ b[3];
assign	out[0] = a[0] ^ b[4];
			
endmodule

 在vivado中分析出来是这样的:很简单就是两个输出的不同为做一个异或运算。

1.png

 vivado综合出来是这样的:用了几个LUT来实现异或功能。

2.png

1.1、应用场景

        上面的例子限于篇幅我只假设了输入为5bit的位宽,所以这样写并不会让人觉得有多麻烦,但是假想一下如果位宽变成10、20、100呢?那我手不写断去?

        当你需要进行一些重复性的工作时,比如多次例化同一模块、同一语句等,可以使用generate for语句来解放双手,节省工作量。当然你用脚本语言来生成或者直接用某些编辑器也能很快地实现这个功能,不过在这里我们就不提了。     

        上面的例子用generate for语句写是这样的:

module xor_test(
	input	[4:0]	a,
	input	[4:0]	b,
	output	[4:0]	out
);
 
genvar i;										//定义常量作为重复判断条件
 
generate
	for (i = 0; i < 8; i = i + 1)				//重复条件
		begin: XOR_INST							//begin要起个名字
			assign	out[i] = a[i] ^ b[4-i];		//需要重复的语句
		end
endgenerate
				
			
endmodule

在vivado中分析出来是这样的:(与上面的方式一致)

3.png

vivado综合出来是这样的: (仍然与上面的方式一致)

4.png

  这样看, generate for是个不错的提高效率的方案。当然,该语句不光可以对assign进行重复赋值,还适用以下场景:

(1)模块module;(2)用户定义原语UDP;(3)门级语句;(4)连续赋值语句assign;(5)initial和always块。

1.2、格式

 generate for语句的一般用法:

// Declare the loop variable
 
genvar <name>;
 
 
// Code for the
 
generate
 
  for (<initial_condition>; <stop_condition>; <increment>) begin
 
    // Code to execute
 
  end
 
endgenerate

如果你是一个基于xilinx的开发者,可以使用vivado自带的语法模板:

(1)打开语法模板:

5.png

(2)搜索generate:

6.png

(3)把上图右侧的语句复制到你自己的代码里边。

关于generate for语句的使用需要注意:

generate for 语句必须使用genvar关键字定义for循环变量

generate for 循环必须加 begin…end, 哪怕只有一句

不要使用 i++这种C语言式的自增语句(Verilog没有i++这个语法),而是使用 i = i + 1

generate后不加begin,里面的语法:for循环、if…else…、case语句 后面的begin后面一定要加名字,且名字唯一,否则会导致无法比对通过的问题

过多的generate会导致收集覆盖率缓慢,要注意使用

2、generate if

        generate if的使用场景和条件编译语句类似,比如你的代码中包含了一个加法模块和一个减法模块,对于2个输入a和b,希望使用POL来进行控制:如POL=1则进行加法,反之亦然----POL=1----out = a + b;POL=0----out = a - b。

代码是这样写的:

module xor_test(
	input	[4:0]	a,
	input	[4:0]	b,
	output	[4:0]	out
);
 
localparam	integer	POL = 1;		//根据POL的值来生成对应的电路
 
generate
	if (POL == 1) begin: POL1
		assign	out = a + b;
	end else begin: POL0
		assign	out = a - b;
	end
endgenerate
							
endmodule

定义成POL = 1时会由vivado综合成一个加法器:

7.png

定义成POL = 0时则会由vivado综合成一个减法器:

8.png 

假如不使用generate if语法,则代码是这样的:

module xor_test(
	input		[4:0]	a,
	input		[4:0]	b,
	input				POL,
	output	reg	[4:0]	out
);
 
always@(*)begin
	if(POL == 1)
		out = a + b;
	else
		out = a - b;
end
							
endmodule

  这样综合出来的就是加法电路和减法电路一起:

9.png

 使用generate if可以根据需要来灵活地生成对应电路,不会浪费资源,适用于某些根据特定需求来实现电路的场景。而不使用该语句则会把所有潜在的电路均综合出来,会使电路面积增大,但是灵活性却较高。

        这是vivado自带的语法模板:

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

3、generate case

        generate case和generate if作用上是差不多的,都是用于选择性综合电路,区别就是if语句和case语句的区别,如果你会用其中一个,那另一个也很简单,模板如下:

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

 上面的例子照着改就是这样了:

module xor_test(
	input	[4:0]	a,
	input	[4:0]	b,
	output	[4:0]	out
);
 
localparam	integer	POL = 1;		//根据POL的值来生成对应的电路
 
generate
	case(POL)
		1'b1: begin: POL1
				assign	out = a + b;
			end
		1'b0: begin: POL0
				assign	out = a - b;
			end
		default:begin:	DEFAULT end	
	endcase
endgenerate
							
endmodule


最新文章

最新文章