Half adder
Solution
module top_module(
input a, b,
output cout, sum );
assign cout = a & b;
assign sum = a ^ b;
endmodule
A half adder adds two bits (with no carry-in) and produces a sum and a carry-out.
Full adder
Solution
module top_module(
input a, b, cin,
output cout, sum );
assign sum = a ^ b ^ cin;
assign cout = (a & b) | (a & cin) | (b & cin);
endmodule
3-bit binary adder
三位加法器需 3 个全加器级联,将低位的进位输出连接到高位的进位输入,形成进位链。
Solution
module top_module(
input [2:0] a, b,
input cin,
output [2:0] cout,
output [2:0] sum );
assign sum[0] = a[0] ^ b[0] ^ cin;
assign cout[0] = (a[0] & b[0]) | (b[0] & cin) | (a[0] & cin);
assign sum[1] = a[1] ^ b[1] ^ cout[0];
assign cout[1] = (a[1] & b[1]) | (b[1] & cout[0]) | (a[1] & cout[0]);
assign sum[2] = a[2] ^ b[2] ^ cout[1];
assign cout[2] = (a[2] & b[2]) | (b[2] & cout[1]) | (a[2] & cout[1]);
endmodule
Adder
Solution
module top_module (
input [3:0] x,
input [3:0] y,
output [4:0] sum);
wire cout0,cout1,cout2;
FullAdder FA1 (x[0],y[0],1'b0,cout0,sum[0]);
FullAdder FA2 (x[1],y[1],cout0,cout1,sum[1]);
FullAdder FA3 (x[2],y[2],cout1,cout2,sum[2]);
FullAdder FA4 (x[3],y[3],cout2,sum[4],sum[3]);
endmodule
//直接用一下全加器
module FullAdder(
input a, b, cin,
output cout, sum );
assign sum = a ^ b ^ cin;
assign cout = (a & b) | (a & cin) | (b & cin);
endmodule
Signed addition overflow
A signed overflow occurs when adding two positive numbers produces a negative result, or adding two negative numbers produces a positive result.
In addition,正数和负数相加时,因和的范围天然被补码覆盖,故无需判断溢出,必然无溢出。
BTW:
// 加法运算
wire [7:0] sum = a + b; // 执行数值相加,考虑进位
// 按位与操作
wire [7:0] and_result = a & b; // 逐位AND,不考虑进位
Solution
module top_module (
input [7:0] a,
input [7:0] b,
output [7:0] s,
output overflow
);
// assign s = ...
// assign overflow = ...
assign s = a + b;
//仅需要考虑最高位(符号位)即可
assign overflow = (a[7] && b[7] && ~s[7] ) || (~a[7] && ~b[7] && s[7]);
endmodule
100-bit binary adder
Solution
module top_module(
input [99:0] a, b,
input cin,
output cout,
output [99:0] sum );
//assign sum = a ^ b ^ cin;
//assign cout = (a & b) | (a & cin) | (b & cin);
wire [99:0] cinm;
assign cinm[0] = (a[0] & b[0]) | ( (a[0] | b[0]) & cin );
assign sum[0] = a[0] ^ b[0] ^ cin;
generate
genvar i;
for (i = 1; i < 100; i = i + 1) begin : adder_loop //生成加法器链
assign sum[i] = a[i] ^ b[i] ^ cinm[i - 1];
assign cinm[i] = (a[i] & b[i]) | (a[i] & cinm[i -1]) | (b[i] & cinm[i -1]);
end
endgenerate
//注意:generate 中是需要写assign的。
assign cout = cinm[99];
endmodule
: adder_loop
是 生成块(generate block)的实例名称,用于标识和命名循环生成的硬件结构。
它是必需的语法元素,主要有以下两个作用:
唯一标识生成的硬件实例
- 所有硬件结构(如模块实例、连线等)必须有唯一的名称。
- 当使用
for
循环生成多个相同结构时,每个迭代需要有不同的名称来区分。 - 每个迭代会被扩展为
adder_loop[i]
的形式(如adder_loop[1]
、adder_loop[2]
等),确保每个实例名称唯一。
- 支持层次化引用。
4-digit BCD adder
Solution
module top_module (
input [15:0] a, b,
input cin,
output cout,
output [15:0] sum );
wire cout1,cout2,cout3;
wire cout4;
bcd_fadd u1 (a[3:0],b[3:0],cin,cout1,sum[3:0]);
bcd_fadd u2 (a[7:4],b[7:4],cout1,cout2,sum[7:4]);
bcd_fadd u3 (a[11:8],b[11:8],cout2,cout3,sum[11:8]);
bcd_fadd u4 (a[15:12],b[15:12],cout3,cout4,sum[15:12]); //把cout4修改为cout就可以直接输出
assign cout = cout4; //其实以下两行完全没必要写
assign sum = {sum[15:12],sum[11:8],sum[7:4],sum[3:0]}; //sum已经通过实例化直接赋值
endmodule