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

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)的实例名称,用于标识和命名循环生成的硬件结构。
它是必需的语法元素,主要有以下两个作用:

  1. 唯一标识生成的硬件实例

    1. 所有硬件结构(如模块实例、连线等)必须有唯一的名称。
    2. 当使用 for 循环生成多个相同结构时,每个迭代需要有不同的名称来区分。
    3. 每个迭代会被扩展为 adder_loop[i] 的形式(如 adder_loop[1]adder_loop[2] 等),确保每个实例名称唯一。
  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