generate语法在verilog中用于控制部分代码的生成,下面以1位全加器级联生成多位加法器的案例,介绍generate for的用法。
模块full_adder_1bit描述了1位全加器:
module full_adder_1bit(
input ai,
input bi,
input ci,
output so,
output co
);
assign so = ai ^ bi ^ ci;
assign co = ((ai ^ bi) & ci) | (ai & bi);
endmodule
模块full_adder描述了多位加法器,通过参数控制加法器的位数:
module full_adder #(
parameter WIDTH= 8
)
(
input [WIDTH-1:0] a,
input [WIDTH-1:0] b,
output [WIDTH:0]s
);
wire [WIDTH-1:0] ci;
wire [WIDTH-1:0] co;
genvar i;
generate
for(i=0;i<WIDTH;i=i+1) begin :gen_adder
full_adder_1bit full_adder_1bit_inst(
.ai(a[i]),
.bi(b[i]),
.ci(ci[i]),
.so(s[i]),
.co(co[i])
);
end
endgenerate
genvar j;
generate
for(j=1;j<WIDTH;j=j+1) begin : co2ci
assign ci[j] = co[j-1];
end
endgenerate
assign ci[0] = 1'd0;
assign s[WIDTH] = co[WIDTH-1];
endmodule
上述例子中,有两个generate语句块,第一个语句块用于批量生成一位全加器,第二个语句块用于将前级的进位值连接至后级的输入,从而级联出多位加法器。
generate生成代码块时,请注意以下几点:
1、循环变量必须由genvar生成;
2、此例中“full_adder_1bit”是模块名,“gen_adder”是循环的名字,在modelsim仿真中此名字生成实例名,见下图,关于“full_adder_1bit_inst”,笔者目前尚不明确该名字的含义,欢迎读者评论区指出。“: gen_adder”可以省略,省略后仍然可以综合出相同的电路,但系统会自动起实例名。建议还是不省略,方便在软件报错时定位问题。
3、对于“co2ci”,此名同样是循环名字,同样可以省略,注意,省略时前方的“:”也要去掉。
仿真测试代码如下:
`timescale 1ns/1ns
module test_sim ;
reg [7:0] a;
reg [7:0] b;
wire [8:0] s;
initial begin
a = 8'd0;
b = 8'd0;
repeat(2**8) begin
repeat(2**8) begin
#10 a = a + 8'd1;
end
b = b + 8'd1;
end
$stop;
end
full_adder #(
.WIDTH(8)
)
full_adder_inst
(
.a(a),
.b(b),
.s(s)
);
endmodule
波形图:
本文参考了以下文章:
【Verilog编程】generate for、generate if、generate case的用法 - 知乎 (zhihu.com)
generate if 和generate case,其作用与预编译命令`ifdef-`endif相似,这里不再赘述。关于混合使用的例子,这里给出generate for与generate if的案例:
以下模块中,参数MODE=0时为加法器;MODE=1时,data_out[WIDTH-1:0]=a&b,data_out[WIDTH]恒为0:
module logic_demo #(
parameter WIDTH = 8,
parameter MODE = 0
)
(
input [WIDTH-1:0] a,
input [WIDTH-1:0] b,
output [WIDTH:0] data_out
);
wire [WIDTH-1:0] ci;
wire [WIDTH-1:0] s;
wire [WIDTH-1:0] co;
wire [WIDTH-1:0] dout;
genvar i;
generate
if(MODE == 0) begin
for(i=0;i<WIDTH;i=i+1) begin :gen_adder
full_adder_1bit full_adder_1bit_inst(
.ai(a[i]),
.bi(b[i]),
.ci(ci[i]),
.so(s[i]),
.co(co[i])
);
end
end
else begin
for(i=0;i<WIDTH;i=i+1) begin :gen_and_gate
and_gate and_gate_inst(
.a(a[i]),
.b(b[i]),
.dout(dout[i])
);
end
end
endgenerate
genvar j;
generate
if(MODE == 0) begin
for(j=1;j<WIDTH;j=j+1) begin : co2ci
assign ci[j] = co[j-1];
end
assign ci[0] = 1'd0;
assign data_out = {co[WIDTH-1],s};
end
else begin
assign data_out = {1'd0,dout};
end
endgenerate
endmodule
与门模块:
module and_gate
(
input a,
input b,
output dout
);
assign dout = a & b;
endmodule
测试代码:
`timescale 1ns/1ns
module test_sim ;
reg [7:0] a;
reg [7:0] b;
wire [8:0] data_out;
initial begin
a = 8'd0;
b = 8'd0;
repeat(2**8) begin
repeat(2**8) begin
#10 a = a + 8'd1;
end
b = b + 8'd1;
end
$stop;
end
logic_demo #(
.WIDTH(8),
.MODE(1)
)
logic_demo_inst
(
.a(a),
.b(b),
.data_out(data_out)
);
endmodule
波形图:
1、MODE=0时,加法器:
2、MODE=1时,8输入与门: