Verilog generate

Verilog generate

文章目录

  • Verilog generate
    • generate用法
      • generate-for
      • generate-if
      • generate-case
    • 应用分析
      • 1. 循环生成构造
      • 2. 条件生成构造
      • 3. 分层访问生成块
    • 注意点
    • 例子

generate用法

关键字generateendgenerate作为使用语法的起点,有三种衍生结构:

  • generate-for语句结构
  • generate-if 语句结构
  • generate-case语句结构

使用generate的情况主要如下:

  • 使用for循环对模块进行多次相似实例化
  • 使用参数更改模块的结构或者设计
  • 使用带有断言语句进行功能和形式验证

generate在综合过程中重复构造相似电路。

generate-for

使用generate-for之前,需要先声明一个genvar变量,用于for循环语句进行判断。

genvar i;
generate 
    for( i=0;i<15;i=i+1)
    begin: loop
        always @ (posedge clk or negedge rst_n ) begin
            if( !rst_n ) begin
                dout[i] <= 1'b0;
            end
            else begin
                dout[i] <= din_a[i] ^ din_b[i];
            end
        end
    end
endgenerate

// 如果for结构中没有使用always,注意要使用assign
genvar i;
generate 
    for(i=0;i<15;i=i+1)
    begin : loop
        xor xor_inst(
            .dout (dout[i]) ,
            .din_a(din_a[i]),
            .din_b(din_b[i])
        ); 
    end
endgenerate

第一个例子是对always块进行了循环,第二个则是对实例化时的模块进行了循环。

begin后面的内容为标签名,是generate语句模块名,目的是通过它对循环语句进行层次化引用。第n个模块相对层次名为loop[n].xor_inst

只有当for循环在generate中时,才能将always放在for循环中。

generate-if

generate-if语句结构比较宽松,不需要对generate语句进行命名( generate-for主要是对循环语句进行层次化引用),也不需要genvar变量。

由于generate-if语句结构是通过判断语句执行代码块,也就决定了每次最多执行一个代码块,这种情况下,对各个代码块使用相同命名是合法的,并且有助于保持对代码的层次化引用。

注意点:generate块中的判断条件必须是常量。

parameter DIV = 4;
generate
    if( DIV == 4 ) begin : u1
        div4 div4_inst(xxxx);
    end
    else if( DIV == 8 ) begin: u1 // 命名可以相同
        div8 div8_inst(xxxx);
    end
endgenerate

generate-case

generate-case 语句和generate-if语句核心思想都是进行条件判断,用法基本一致。

generate-if语句一样,case判断条件必须是常量

parameter SEL = 1;
generate
    case( SEL ) 
        1: begin
           //xxx 
        end
        2: begin
           // xxx
        end
        default: begin
           // xxx 
        end
    endcase
endgenerate

应用分析

1. 循环生成构造

循环生成构造提供了一种简单而简洁的方法来创建模块项的多个实例,例如模块实例、分配语句、断言、接口实例等。

本质上,它是一种特殊类型的for循环,其循环索引变量为 datatype genvar。

genvar它是一个整数数据类型,仅在综合时存在并在运行时消失

可以嵌套generate-for循环,只需确保genvar将外部循环和内部循环分开使用,并在嵌套的 for 循环中引用这些变量时要小心

2. 条件生成构造

条件生成构造允许根据在模块实例化期间传递的参数值更改设计结构

这在为设计创建参数化通用 RTL 模块时非常有用。

通过使用generate而不是简单的多路复用器,可以节省一堆门电路和触发器。

3. 分层访问生成块

访问位于生成块内的模块项。

生成块有一个名字。

如果不为其命名,编译器将自动分配一个通用名称,例如genblk01、genblk02等,通常必须转储 wave 并用Visualizer工具以查看分配了哪些名称。

要访问生成块中的模块项,必须分层访问.

注意点

  1. Verilog 中没有i++的写法,要写成i=i+1
  2. generate-for中可以用always块或者assign赋值

例子

hdlbits的练习题:BCD加法

module top_module( 
    input  [399:0] a         ,
    input  [399:0] b         ,
    input          cin       ,
    output         cout      ,
    output [399:0] sum 
);
    
    wire [99:0] cin_reg;
    bcd_fadd bcd_fadd_inst_0(
        .a   (a[3:0]    ),
        .b   (b[3:0]    ),
        .cin (cin       ),
        .cout(cin_reg[0]),
        .sum (sum[3:0]  )
    );
    genvar gv_i;
    generate 
        for(gv_i=1;gv_i<100;gv_i= gv_i+1)begin :loop
            bcd_fadd bcd_fadd_inst(
                .a   (a[(gv_i+1)*4-1:gv_i*4]  ),
                .b   (b[(gv_i+1)*4-1:gv_i*4]  ),
                .cin (cin_reg[gv_i-1]         ),
                .cout(cin_reg[gv_i]           ),
                .sum (sum[(gv_i+1)*4-1:gv_i*4])
            );
        end
    endgenerate
    
    assign cout = cin_reg[99];
endmodule

你可能感兴趣的:(FPGA,fpga开发)