问题描述
练习:通过实例化100个全加器来创建一个 100 位二进制波纹进位加法器。加法器将两个 100 位数字和一个进位相加,产生一个 100 位和并执行。为了鼓励您实际实例化全加器,还要输出纹波进位加法器中每个全加器的进位。cout[99] 是最后一个全加器的最终进位,也是您通常看到的进位。
提示:有许多全加器要实例化。实例数组或生成语句将在这里有所帮助
相关知识:
等波纹进位加法器:最低的比特位先进行简单的全加器计算(A0+B0),生产的和作为最终sum的最低位sum0,然后其进位cout0参与下一位的全加器计算(A1+B1+cout0),其和为sum1,进位为cout1。依次推列,后面是(A2+B2+cout1)、(A3+B3+cout2)……这样的加法器有个很明显的缺陷,即每位的计算都要等低位计算完后才能开始计算(每次全加器计算都要等低一位的进位),会严重的浪费时间。
代码:
module top_module(
input [99:0] a, b,
input cin,
output [99:0] cout,
output [99:0] sum );
genvar i;
generate
for(i=0;i<100;i=i+1) begin:adder
if(i==0)
assign{cout[0],sum[0]} = a[0]+b[0]+cin;
else
assign{cout[i],sum[i]} = a[i]+b[i]+cout[i-1];
end
endgenerate
endmodule
generate语句介绍
generate语句可以动态地生成verilog代码
1、多个模块需要进行重复例化,或者多条赋值语句需要重复执行时(generate-for)
2、多个模块需要进行选择例化,或者多条赋值语句需要选择执行时(generate-if generate-case)
有些抽象,没关系,我们来看例子
1.generate-for
注意事项
①必须使用genvar定义循环索引变量,用作for循环判断
②需要复制的语句必须写到begin_end语句中,即使只有一句话
③begin后面需要有一个类似模块名的名字代码
//以任意位宽数据高位到低位倒序
genvar i; //生成循环索引变量
generate
for(i=0;i<data_width;i=i+1) begin:datashift
assign out_data[data_width-1-i] = in_data[i];
end
endgenerate
再举一个重复例化的例子
// 四个一位半加法器构成一个四位半加法器
// 半加法器module
module half_addr(
input a ,
input b ,
output cout ,
output sum
);
assign sum = a^b;
assign cout = a&b;
endmodule
// 四位半加法器module
module half_adder4(
input [3:0] add_a,
input [3:0] add_b,
output [3:0] cout,
output [3:0] sum
);
genvar i;
generate
// 重复例化
for(i=0;i<4;i=i+1) begin:half_addr_f
half_addr u_half_addr(
.a (add_a[i] ),
.b (add_b[i] ),
.cout (cout[i] ),
.sum (sum[i] )
);
end
endgenerate
endmodule
// testbench
module half_adder4_tb;
reg [3:0] add_a ;
reg [3:0] add_b ;
wire [3:0] cout ;
wire [3:0] sum ;
initial begin
add_a = 4'b0010;
add_b = 4'b1001;
#100;
add_a = 4'b1011;
add_b = 4'b0010;
end
half_adder4 u_half_adder4(
.add_a (add_a ),
.add_b (add_b ),
.cout (cout ),
.sum (sum )
);
endmodule
2.generate-if
注意事项:
①模块的参数(必须是常量parameter型或lacalparam型)作为条件判断,来产生满足条件的电路
②每一个条件分支,在begin后最好命一个名字,如果不写这个名字,有的编译器会报警告
③当begin-end中只需要一句话时,begin-end可以省略(如下面的例子)
语法:
generate
if(condition1)begin:name_one
分支1代码;
end
else if(condition2)begin:name_two
分支2代码;
end
...
else begin:name_n
其他分支代码;
end
endgenerate
例子:
generate
if(a<b)
assign d = a&b;
else
assign d = a|b;
endgenerate
3.generate-case
注意事项:
①模块的参数(必须是常量parameter型或lacalparam型)作为条件判断,来产生满足条件的电路
②每一个条件分支,在begin后最好命一个名字,如果不写这个名字,有的编译器会报警告
③当begin-end中只需要一句话时,begin-end可以省略(如下面的例子)
语法:
generate
case(condition)
case1条件:begin : name_one
分支1代码;
end
case2条件:begin : name_two
分支2代码;
end
case3条件:begin:name_three
分支3代码;
end
default:begin:name_n
分支n代码;
end
endcase
endgenerate
例子:
generate
case(condition)
1'b0: assign d = a&b;
1'b1: assign d = a|b;
default: assign d = 1'b0;
endcase
endgenerate