• 基础项目(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行。

  • 相关阅读:
    Dockerfile
    走进Docker
    liunx 设置定时任务
    《程序员自我修养》读书笔记
    Ubuntu换源
    liunx安装python2.7.12
    预习非数值数据的编码方式
    预习原码补码
    第三章预习
    预习非数值数据的编码方式
  • 原文地址:https://www.cnblogs.com/mengyi1989/p/11521058.html
Copyright © 2020-2023  润新知