基础项目(7)generate语句块的讲解

写在前面的话

在设计中很多情况下我们需要编写很多结构相同参数不同的赋值语句或逻辑语句块当参数量很大的情况下原始的列举就会变得很笨拙甚至是不可行的C语言处理这种问题通常情况下会使用如for循环语句来完成多次的相同操作。而verilog 语言呢?同样的为我们提供了generate语句块来帮助我们完成这些过程。接下来,梦翼师兄将和大家一起开始generate语句的学习

基本概念

generate的主要功能就是对modulenetregparameterassignalwaystaskfunction进行复制,genvargenerate语句中的一种变量类型,用以在 generate-for 语句中声明一个正整数的索引变量 (如果将“X”或“Z”或者“负值”赋给genvar 变量将会出错)。genvar 变量可以声明在 generate 语句内,也可以声明在 generate 语句外。

generate 语句有 generate-forgenerate-if generate-case 三种语句,下面梦翼师兄和大家一起来学习这三种语句。

 genrate-for

使用generate_for的时候,必须要注意以下几点要求:

a) 必须使用genvar申明一个正整数变量,用作for的判断变量;

b) for里面的内嵌语句,必须写在begin_end里面,哪怕只有一句

c) begin_end需要一个名字。

1:利用generate_for来复制assign语句

/****************************************************          

 *   Engineer      :   梦翼师兄

 *   QQ             :   761664056

 *   E_mail        :   zxopenwjf@126.com

 *   The module function : generate_for_assign模块

*****************************************************/

01  module for_test(indata, t0, t1, t2, t3);

02

03  input [7:0] indata;            //输入8位位宽indata

04  output [1:0] t0, t1, t2, t3; //输出2位位宽t0,t1,t2,t3;

05                               

06  wire [1:0] temp [3:0];        //定义位宽为2,深度为4temp

07  genvar i;                  

08                               

09  generate for(i=0; i<4; i=i+) //generate for模块复制

10      begin : gfor_block    

11          assign temp[i] = indata[2*i+1:2*i];

12      end                      

13  endgenerate                 

14                                

15  assign t0 = temp[0];            //t0等于temp[0]

16  assign t1 = temp[1];            //t1等于temp[1]   

17  assign t2 = temp[2];            //t2等于temp[2]

18  assign t3 = temp[3];            //t3等于temp[3]

19

20  endmodule

 编写的测试代码如下:

/****************************************************          

 *   Engineer      :   梦翼师兄

 *   QQ            :   761664056

 *   The module function :for_test的测试模块

*****************************************************/

01  `timescale 1ns/1ps

02  module tb;

03

04  reg [7:0] indata;          //输入8位位宽indata

05  wire [1:0] t0, t1, t2, t3; //输出2位位宽t0,t1,t2,t3;

06  

07//----------写入2组数据------------

08  initial

09      begin

10          indata = 8'b1011_1011;

11          #100 indata = 8'b0101_1010;

12      end

13      

14 //---------模块例化--------------

15  for_test for_test(

16   .indata(indata),

17   .t0(t0),

18   .t1(t1),

19   .t2(t2),

20   .t3(t3)

21   );

22

23  endmodule 

仿真波形如下:

观察波形可以得到:

temp[0] = indata[1:0];

temp[1] = indata[3:2];

temp[2] = indata[5:4];

temp[3] = indata[7:6];

由此得出for_test模块9~13行可以这样展开:

assign temp[0] = indata[1:0];

assign temp[1] = indata[3:2];

assign temp[2] = indata[5:4];

assign temp[3] = indata[7:6];

我们发现,这段代码是通过i增加来重复执行temp[i] = indata[2*i+1:2*i] 这条语句的所以generate_for可以复制assign语句。

 2:利用generate_for来复制always语句

/****************************************************          

 *   Engineer      :   梦翼师兄

 *   QQ             :   761664056

 *   The module function : generate_for_always模块

*****************************************************/

01  module for_test1(indata, t0, t1, t2, t3);

02

03  input [7:0] indata;          //输入8位位宽indata

04  output [1:0] t0, t1, t2, t3; //输出2位位宽t0,t1,t2,t3;

05                               

06  reg [1:0] temp [3:0];        //定义位宽为2,深度为4temp

07  genvar i;                    

08                               

09  generate for(i=0; i<4; i=i+)//generate for模块复制

10      begin : gfor_block       

11          always @ (*)         

12              temp[i] = indata [2*i+1:2*i]

13      end                      

14  endgenerate                  

15                               

16  assign t0 = temp[0];            //t0等于temp[0]

17  assign t1 = temp[1];            //t1等于temp[1]   

18  assign t2 = temp[2];            //t2等于temp[2]

19  assign t3 = temp[3];            //t3等于temp[3]

20

21  endmodule

 编写的测试代码如下:

/****************************************************          

 *   Engineer      :   梦翼师兄

 *   QQ             :   761664056 *   The module function :for_test1的测试模块

*****************************************************/

01  `timescale 1ns/1ps

02  module tb;

03

04  reg [7:0] indata;          //输入8位位宽indata

05  wire [1:0] t0, t1, t2, t3; //输出2位位宽t0,t1,t2,t3;

06  

07//----------写入2组数据------------

08  initial

09      begin

10          indata = 8'b1011_1011;

11          #100 indata = 8'b0101_1010;

12      end

13      

14 //---------模块例化---------------

15  for_test1 for_test1(

16   .indata(indata),

17   .t0(t0),

18   .t1(t1),

19   .t2(t2),

20   .t3(t3)

21   );

22

23  endmodule 

仿真波形如下:

 

观察波形可以得到:

temp[0] = indata[1:0];

temp[1] = indata[3:2];

temp[2] = indata[5:4];

temp[3] = indata[7:6];

由此得到for_test1模块第9~14行我们可以这样展开

always @ (*)

temp[0] = indata[1:0];

always @ (*)

temp[1] = indata[3:2];

always @ (*)

temp[2] = indata[5:4];

always @ (*)

temp[3] = indata[7:6];

我们发现,这段代码是通过i增加来重复执行

always @ (*)

temp[i] = indata[2*i+1:2*i]

这条语句的所以generate_for可以复制always语句。

 3:利用多个generate_for来实现模块复制

/****************************************************          

 *   Engineer      :   梦翼师兄

 *   QQ            :   761664056

 *   The module function : generate_for_多个模块

*****************************************************/

01  module for_test2(indata, t0, t1, t2, t3);

02  

03  input [7:0] indata;               //输入8位位宽indata

04  output [1:0] t0, t1, t2, t3;    //输出2位位宽t0,t1,t2,t3;

05  

06  wire [1:0] temp [3:0];          //定义位宽为2,深度为4temp

07  genvar i, j;

08  

09  generate for(i=0; i<4; i=i+1)   //generate for模块复制

10      begin : gfor_block_a        

11          for(j=0; j<2; j=j+1)    

12              begin : gfor_block_b

13                  assign temp[i][j] = indata[2*i+j];

14              end

15      end

16  endgenerate

17  

18  assign t0 = temp[0];            //t0等于temp[0]

19  assign t1 = temp[1];            //t1等于temp[1]   

20  assign t2 = temp[2];            //t2等于temp[2]

21  assign t3 = temp[3];            //t3等于temp[3]

22  endmodule

 编写的测试代码如下:

/****************************************************          

 *   Engineer      :   梦翼师兄

 *   QQ             :   761664056

 *   The module function :for_test2的测试模块

*****************************************************/

01  `timescale 1ns/1ps

02  module tb;

03

04  reg [7:0] indata;          //输入8位位宽indata

05  wire [1:0] t0, t1, t2, t3; //输出2位位宽t0,t1,t2,t3;

06  

07//----------写入2组数据------------

08  initial

09      begin

10          indata = 8'b1011_1011;

11          #100 indata = 8'b0101_1010;

12      end

13      

14 //---------模块例化---------------

15  for_test2 for_test2(

16   .indata(indata),

17   .t0(t0),

18   .t1(t1),

19   .t2(t2),

20   .t3(t3)

21   );

22

23  endmodule 

仿真波形如下:

 

观察波形可以得到:

temp[0] [0] = indata[0];

temp[0] [1] = indata[1];

temp[1] [0] = indata[2];

temp[1] [0] = indata[3];

temp[2] [0] = indata[4];

temp[2] [1] = indata[5];

temp[3] [0] = indata[6];

temp[3] [1] = indata[7];

由此得到for_test2模块第9~16行可以这样展开

assign temp[0] [0] = indata[0];

assign temp[0] [1] = indata[1];

assign temp[1] [0] = indata[2];

assign temp[1] [0] = indata[3];

assign temp[2] [0] = indata[4];

assign temp[2] [1] = indata[5];

assign temp[3] [0] = indata[6];

assign temp[3] [1] = indata[7];

我们发现,这段代码是通过ij的增加来重复执行

temp[i][j] = indata[2*i+j]

这条语句的所以generate_for可以实现模块的复制

genrate-if

generate_for是用于复制模块,而generate_if则是根据模块的参数(必须是常量)作为条件判断,来产生满足条件的电路。如

/****************************************************          

 *   Engineer      :   梦翼师兄

 *   QQ             :   761664056

 *   The module function : generate_if模块

*****************************************************/

01  module if_test(a,  b,  c,  d);

02

03  input a, b, c;         //输入信号abc

04  output d;               //输出信号d

05

06  localparam WIDE = 8;    //参数模块,用于选择产生的电路

07

08  generate

09      if(WIDE <10)        //WIDE小于10d等于abc相或

10          assign  d   =   a | b | c;

11      else                //WIDE大于等于10d等于abc相与

12          assign  d   =   a & b & c;

13  endgenerate

14

15  endmodule

该代码生成的RTL电路图如下:

 

当把WIDE改成等于12的时候,代码如下:

/****************************************************          

 *   Engineer      :   梦翼师兄

 *   QQ            :   761664056

 *   The module function : generate_if模块

*****************************************************/

01  module if_test(a,  b,  c,  d);

02

03  input a, b, c;         //输入信号abc

04  output d;               //输出信号d

05

06  localparam WIDE = 12;    //参数模块,用于选择生产的电路

07

08  generate

09      if(WIDE <10)        //WIDE小于10d等于abc相或

10          assign  d   =   a | b | c;

11      else                //WIDE大于等于10d等于abc相与

12          assign  d   =   a & b & c;

13  endgenerate

14

15  endmodule

该代码生成的RTL电路图如下:

 

从上面2个不同的WIDE值得出的RTL图可知,generate_if是根据模块的参数来作为判断条件,来产生满足条件的电路,当WIDE等于8时d等于abc相或,对应于我们代码的第9~10行;当WIDE等于12时d等于abc相与,对应于我们代码的第11~12行。

generate-case

generate_case其实跟generate_if一样的,都是根据模块的参数(必须是常量)作为条件判断,来生成满足条件的电路,不同的地方仅仅是改成使用case 的语法而已。如:

/****************************************************          

 *   Engineer      :   梦翼师兄

 *   QQ             :   761664056

 *   The module function : generate_case模块

*****************************************************/

01  module case_test(a,  b, c,  d);

02

03  input a, b, c;             //输入信号abc

04  output d;                   //输出信号d

05  

06  localparam WIDE = 12;    //参数模块,用于选择生产的电路

07  

08  generate

09      case(WIDE)      

10      0   :                       //WIDE等于0d等于abc相或

11              assign  d   =   a | b | c;

12          

13      1   :                       //WIDE等于1d等于abc相与

14              assign  d   =   a & b & c;

15              

16      default :                   //WIDE不等于10d等于abc

17              assign  d   =   a & b | c;

18              

19      endcase

20  endgenerate

21      

22  endmodule

代码生成的RTL电路图如下:

我们将参数WIDE设置位0,生成的RTL电路图如下:

 

参数WIDE设置位1,生成的RTL电路图如下:

从上面3个不同的WIDE值得出的RTL图可知,generate_case也是根据模块的参数来作为条件判断,来产生满足条件的电路,当WIDE等于12时d等于a与b或c,对应于我们代码的第16~17行;当WIDE等于0时d等于abc相或,对应于我们代码的第10~11行;当WIDE等于1时d等于abc相与,对应于我们代码的第13~14行。

原文地址:https://www.cnblogs.com/mengyi1989/p/11521058.html