关键字generate
和endgenerate
作为使用语法的起点,有三种衍生结构:
generate-for
语句结构generate-if
语句结构generate-case
语句结构使用generate的情况主要如下:
generate在综合过程中重复构造相似电路。
使用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
语句进行命名( 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-if
语句核心思想都是进行条件判断,用法基本一致。
和generate-if
语句一样,case判断条件必须是常量。
parameter SEL = 1;
generate
case( SEL )
1: begin
//xxx
end
2: begin
// xxx
end
default: begin
// xxx
end
endcase
endgenerate
循环生成构造提供了一种简单而简洁的方法来创建模块项的多个实例,例如模块实例、分配语句、断言、接口实例等。
本质上,它是一种特殊类型的for循环,其循环索引变量为 datatype genvar。
genvar
它是一个整数数据类型,仅在综合时存在并在运行时消失。
可以嵌套generate-for
循环,只需确保genvar将外部循环和内部循环分开使用,并在嵌套的 for 循环中引用这些变量时要小心。
条件生成构造允许根据在模块实例化期间传递的参数值更改设计结构。
这在为设计创建参数化通用 RTL 模块时非常有用。
通过使用generate而不是简单的多路复用器,可以节省一堆门电路和触发器。
访问位于生成块内的模块项。
生成块有一个名字。
如果不为其命名,编译器将自动分配一个通用名称,例如genblk01、genblk02等,通常必须转储 wave 并用Visualizer工具以查看分配了哪些名称。
要访问生成块中的模块项,必须分层访问
。
i++
的写法,要写成i=i+1
。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