一把王者的时间,学会generate语句【Verilog高级教程】

generate

    • 一、写在前面
    • 二、generate的作用
    • 三、generate的分类
    • 四、Generate的用法
      • 4.1 Loop-generate案例
      • 4.2 Conditional-genertate案例
        • 4.2.1 if-generate案例
        • 4.2.2 case-generate案例
    • 五、generate可能出现的错误
      • 5.1 genvar声明变量的重复使用
      • 5.2 generate_instance的名称与其他声明冲突
    • 六、generate练习与参考
    • 七、往期【Verilog】高级教程文章

一、写在前面

本专栏为作者在 【数字IC手撕代码】 【数字IC笔试面经分享】 【数字IC工具解析】 以外开设的第四个独立专栏,旨在学习并提供有关Verilog硬件描述语言中非基础性的高阶语法特性知识,因本身专栏的独特定位,因此作者并不会涉及基础Verilog语言如阻塞式非阻塞赋值,过程块,数据类型等内容;同时受限于作者知识有限,本专栏也不会涉及System Verilog的相关内容,若按照IEEE的相关标准来看,本专栏将会聚焦Verilog-2005,即“IEEE Std 1364™-2005”以及之前的有关内容,提供相关的IC设计领域语法特性。以下为Verilog的进阶框图,有更多学习需求的读者可以检索相关英文标准进行学习。
在这里插入图片描述

二、generate的作用

Verilog中generate的作用是为了有条件的例化或者多重例化,当我们需要例化很多module而例化的规则又有规律的时候,或者我们希望可以根据条件选择性的例化对应的module,我们就可以考虑使用generate来进行,比如说串行加法器中对全加器的例化,就是按照端口递增这一相似的规律去进行的例化,就可以使用generate来进行,这可以减少所需要的代码量。

三、generate的分类

  • loop型
    使用for循环去控制例化
  • conditional型
    conditional型generate语句又可以细分成if-generate型case-generate型

四、Generate的用法

4.1 Loop-generate案例

想要使用loop-generate语句,首先我们需要声明一个genvar变量,注意这个变量默认是整数型的,同时这个变量不能在generate语句之外出现(比如声明的genvar型的i不能再always块里出现),我们可以使用generate和endgenerate语句去包裹住例化部分也可以缺省它,下面的例子就缺省了generate和endgenerate但是VCS并不会报错。

module addergen1 (co, sum, a, b, ci);
parameter SIZE = 4;
output [SIZE-1:0] sum;
output co;
input [SIZE-1:0] a, b;
input ci;
wire [SIZE :0] c;
genvar i;
assign c[0] = ci;
// Hierarchical gate instance names are:
// xor gates: bit[0].g1 bit[1].g1 bit[2].g1 bit[3].g1
// bit[0].g2 bit[1].g2 bit[2].g2 bit[3].g2
// and gates: bit[0].g3 bit[1].g3 bit[2].g3 bit[3].g3
// bit[0].g4 bit[1].g4 bit[2].g4 bit[3].g4
// or gates: bit[0].g5 bit[1].g5 bit[2].g5 bit[3].g5
// Gate instances are connected with nets named:
// bit[0].t1 bit[1].t1 bit[2].t1 bit[3].t1
// bit[0].t2 bit[1].t2 bit[2].t2 bit[3].t2
// bit[0].t3 bit[1].t3 bit[2].t3 bit[3].t3
for(i=0; i<SIZE; i=i+1) 
begin:bit
wire t1, t2, t3;
xor g1 ( t1, a[i], b[i]);
xor g2 ( sum[i], t1, c[i]);
and g3 ( t2, a[i], b[i]);
and g4 ( t3, t1, c[i]);
or g5 ( c[i+1], t2, t3);
end
assign co = c[SIZE];
endmodule

更一般化的loop_generate_construct如下,for括号内的分别为genvar的初始化条件genvar判断的表达式genvar的迭代方式

 loop_generate_construct ::=
     for ( genvar_initialization ; genvar_expression ; genvar_iteration )
     generate_block

4.2 Conditional-genertate案例

4.2.1 if-generate案例

以下就是一个conditional-generate的例子,这里的例子是希望于通过a_width和b_width的大小判断来例化CLA乘法器或Wallace乘法器,其中例化时通过"#"进行了传参。
Wallace乘法器也是作者曾经写过的一个例子,具体的内容和原理可以参考这里

  • 【MUL】大数乘法器的设计与优化(32位,16位,8位 Dadda Tree与Wallace Tree)
module
multiplier(a,b,product);
parameter a_width = 8, b_width = 8;
localparam product_width = a_width+b_width;
// cannot be modified directly with the defparam
// statement or the module instance statement #
input [a_width-1:0] a;
input [b_width-1:0] b;
output [product_width-1:0] product;
generate
if((a_width < 8) || (b_width < 8))
begin:mult
CLA_multiplier #(a_width,b_width) u1(a, b, product);
// instantiate a CLA multiplier
end
else begin:mult
WALLACE_multiplier #(a_width,b_width) u1(a, b, product);
// instantiate a Wallace-treemultiplier
end
endgenerate
// The hierarchical instance name is mult.u1
endmodule

4.2.2 case-generate案例

对于case-generate来说,这里再给出一个例子,即通过对WIDTH的大小判断调用一位加法器两位加法器CLA加法器

generate
case (WIDTH)
1: begin: adder // 1-bit adder implementation
adder_1bit x1(co, sum, a, b, ci);
end
2: begin: adder // 2-bit adder implementation
adder_2bit x1(co, sum, a, b, ci);
end
default:
begin: adder // others - carry look-ahead adder
adder_cla #(WIDTH) x1(co, sum, a, b, ci);
end
endcase
// The hierarchical instance name is adder.x1
endgenerate

五、generate可能出现的错误

这里对generate语句可能出现的错误进行补充。

5.1 genvar声明变量的重复使用

声明的genvar变量i的值在evaluation的过程中被重复使用
具体深层次的原因和generate执行中默认的loacalparam声明有关,有兴趣的读者可以自行研究,不在这里赘述,以下的例子,重复使用i,会有报错,正确的做法是再声明一个genvar型的m去替换第二个for中的i。

module mod_a;
genvar i;

//"generate","endgenerate" keywords are not required
for begin:a
(i=0; i<5; i=i+1)
for begin:b
(i=0; i<5; i=i+1)
...
// error -- using "i" as loop index for
...
// two nested generate loops
end
end

5.2 generate_instance的名称与其他声明冲突

instance的a的命名与寄存器类型的声明冲突,loop-generate的命名a和reg a冲突导致错误的错误

module mod_b;
genvar i;
reg a;
for (i=1; i<0; i=i+1) begin: a
... // error -- "a" conflicts with name of reg "a"
end
endmodule

六、generate练习与参考

以下的链接提供了generate的一些例子,
其中32-bit低时延高速整数ALU的设计|超前进位加法器中有关行波进位加法器的例化使用了generate语句
HDLBits_loop型generate_Adder100i与HDLBits_loop型generate_BCD_adder提供了两道有关generate的例题

【ALU】32-bit低时延高速整数ALU的设计|超前进位加法器
HDLBits_loop型generate_Adder100i
HDLBits_loop型generate_BCD_adder

七、往期【Verilog】高级教程文章

  • 多维数组:灭霸打个响指的功夫,看懂Verilog多维数组
  • clog2系统函数: 关于Verilog自动计算位宽的系统函数$clog2,这些是你不得不知道的
  • UDP用户原语:玩转UDP用户原语,这篇文章就够了
  • $monitor系统函数:放学前的最后几分钟,看懂Verilog中的monitor系统函数
  • generate语句:一把王者的时间,学会Verilog中的generate语句
  • parameter常量:玩转parameter与localparameter,这篇文章就够了
  • inout双向端口:通俗易懂的带你解读inout双向端口
  • task与function区别:芯片人必会的task与function区别详解

你可能感兴趣的:(Verilog进阶教程,fpga开发,verilog,fpga,芯片,硬件架构)