串行进位加法器
半加器
module half_adder (
input in1,
input in2,
output sum,
output cout
);
assign sum = in1^in2;
assign cout = in1&in2;
endmodule
全加器
module full_adder (
input in1,
input in2,
input cin,
output sum,
output cout
);
wire xor2;
assign xor2 = in1^ in2; // reuse
assign sum = xor2^ cin;
// assign cout = in1&in2| in1&cin| in2&cin; // 3and 2or
// assign cout = in1&in2| cin&(in1|in2); // one less and, 2and 2or
assign cout = (xor2&cin)| (in1&in2); // resuse in1^in2, 2and 1or
endmodule
module full_adder_comb (
input in1,
input in2,
input cin,
output sum,
output cout
);
wire sum1;
wire sum2;
wire cout1;
wire cout2;
half_adder u1(
.in1 (in1),
.in2 (in2),
.sum (sum1),
.cout (cout1)
);
half_adder u2(
.in1 (sum1),
.in2 (cin),
.sum (sum2),
.cout (cout2)
);
assign sum = sum2;
assign cout = cout1| cout2;
endmodule
任意位数串行进位加法器
module serial_adder#(
parameter WIDTH = 8
)(
input [WIDTH-1:0] in1,
input [WIDTH-1:0] in2,
input cin,
output [WIDTH:0] sum
);
wire [WIDTH:0]cout;
assign cout[0] = cin;
genvar i;
generate
for(i=0; i<WIDTH; i=i+1)
begin :gf
full_adder_comb ufa(
.in1 (in1[i]),
.in2 (in2[i]),
.cin (cout[i]),
.sum (sum[i]),
.cout (cout[i+1])
);
end
endgenerate
assign sum[WIDTH] = cout[WIDTH];
endmodule
tb
`timescale 1ns / 1ps
module tb_serial_adder;
// serial_adder Parameters
parameter PERIOD = 10;
parameter WIDTH = 2;
// serial_adder Inputs
reg [WIDTH-1:0] in1 = 0 ;
reg [WIDTH-1:0] in2 = 0 ;
reg cin = 0 ;
// serial_adder Outputs
wire [WIDTH:0] sum ;
// initial
// begin
// forever #(PERIOD/2) clk=~clk;
// end
// initial
// begin
// #(PERIOD*2) rst_n = 1;
// end
serial_adder #(
.WIDTH ( WIDTH ))
u_serial_adder (
.in1 ( in1 [WIDTH-1:0] ),
.in2 ( in2 [WIDTH-1:0] ),
.cin ( cin ),
.sum ( sum [WIDTH:0] )
);
initial
begin
in1 = 8'b1111_0000;
in2 = 8'b1111_0101;
#10;
in1 = 8'b1111_1111;
in2 = 8'b1111_1111;
cin = 1;
#10;
in1 = 8'b1111_1111;
in2 = 8'b1001_1111;
cin = 1;
#10;
in1 = 8'b1111_1111;
in2 = 8'b1;
cin = 1;
#10;
in1 = 8'b1111_1111;
in2 = 8'b0;
cin = 1;
#10;
in1 = 8'b1111_1111;
in2 = 8'b1;
cin = 0;
$finish;
end
endmodule
在vivado中被优化的不成样子,且vivado似乎不支持通过WIDTH的方式进行传参,但Modelsim支持的非常完美
4bit超前进位加法器
虽然超前进位加法器不支持任意位数,但是可以通过嵌套实现高位超前进位加法器
嵌套方法有串行超前进位加法器与超前超前进位加法器
// s = in1^in2^cin
// = (in1|in2)^(in1&in2)^cin
// cout = in1&in2 | cin(in1|in2)
module lookahead_carry_adder #(
parameter WIDTH = 4
)(
input [WIDTH-1:0] in1,
input [WIDTH-1:0] in2,
input cin,
output [WIDTH:0] sum
);
wire [WIDTH-1:0] G;
wire [WIDTH-1:0] P;
wire [WIDTH:0] C; // input carry
assign G = in1&in2;
assign P = in1|in2;
assign C[0] = cin; // lsb carry equals to cin
assign C[1] = G[0] | (C[0]&P[0]);
// assign C[2] = G[1] | C[1]&P[1];
assign C[2] = G[1] | (G[0]&P[1]) | (C[0]&P[0]&P[1]);
assign C[3] = G[2] | (G[1]&P[2]) | (G[0]&P[1]&P[2]) | (C[0]&P[0]&P[1]&P[2]);
assign C[4] = G[3] | (G[2]&P[3]) | (G[1]&P[2]&P[3]) | (G[0]&P[1]&P[2]&P[3]) | (C[0]&P[0]&P[1]&P[2]&P[3]);
assign sum[3:0] = P^G^C;
assign sum[4] = C[4];
endmodule
Reference
https://blog.csdn.net/qq_45861449/article/details/109460294
https://wenku.baidu.com/view/3b1b326dcc84b9d528ea81c758f5f61fb736287b.html
https://www.jianshu.com/p/6ce9cad8b467