Modules

The code for module mod_a looks like this:

module mod_a ( input in1, input in2, output out );
    // Module body
endmodule

By position:
mod_a instance1 ( wa, wb, wc );

By name:
mod_a instance2 ( .out(wc), .in1(wa), .in2(wb) );

Notice the period immediately preceding the port name in this syntax.

在 top_module 中 按名称实例化子模块

Solution

module top_module ( input a, input b, output out );
    //mod_a 是已知的
   mod_a u1 (.in1(a), .in2(b), .out(out));
endmodule

Connecting ports by position

Solution

module top_module ( 
    input a, 
    input b, 
    input c,
    input d,
    output out1,
    output out2
);

    mod_a u1 (out1,out2,a,b,c,d);
endmodule  

Connecting ports by name

Solution

module top_module ( 
    input a, 
    input b, 
    input c,
    input d,
    output out1,
    output out2
);

    mod_a u1(.out1(out1), .out2(out2), .in1(a), .in2(b), .in3(c), .in4(d));
endmodule

Three modules

Solution

module top_module ( input clk, input d, output q );

    wire q1; //别忘了写“;”
    my_dff u1 (clk,d,q1);
    wire q2;
    my_dff u2 (clk,q1, q2);
    my_dff u3 (clk,q2,q);
endmodule

Modules and vectors

Solution

module top_module ( 
    input clk, 
    input [7:0] d, 
    input [1:0] sel, 
    output [7:0] q 
);

    wire [7:0] q1;
    my_dff8 u1 (clk, d, q1);
    wire [7:0] q2;
    my_dff8 u2 (clk, q1, q2);
    wire [7:0] q3;
    my_dff8 u3 (clk, q2, q3);  
    
    always @(*) begin 
        case (sel)
            2'b00: q = d;
            2'b01: q = q1;
            2'b10: q = q2;
            2'b11: q = q3;
            default: q = d;
        endcase
    end
endmodule

always @(*) 里的 (*) 是一种 隐式敏感列表 语法,用于自动推断组合逻辑的触发条件。
作用:当块内所有被读取的信号发生变化时,自动触发块内代码执行
编写组合逻辑时优先使用 @(*),避免敏感列表遗漏导致的错误。

Adder 1

Solution

module top_module(
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);

    wire cout_low;
    add16 u1 (a[15:0], b[15:0],1'b0, sum[15:0],cout_low);  
    add16 u2 (a[31:16], b[31:16],cout_low, sum[31:16]);  
endmodule

Adder 2

Solution

module top_module (
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);
    wire cout_low;
    
    // 用 add1 链接 add16 是题目已知条件
    add16 u1 (
        .a(a[15:0]), 
        .b(b[15:0]),
        .cin(1'b0),
        .sum(sum[15:0]),
        .cout(cout_low)
    );
    
    add16 u2 (
        .a(a[31:16]),
        .b(b[31:16]),
        .cin(cout_low),
        .sum(sum[31:16]),
        .cout()
    );

endmodule

module add1 ( input a, input b, input cin,   output sum, output cout );

    // Full adder module here
    assign sum = a ^ b ^ cin;
    assign cout = (a & b) | (b & cin) | (a & cin);
    
endmodule

Carry-select adder

进位选择加法器的典型实现:
并行计算 + 多路选择

Solution

module top_module(
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);

    // 1. 低16位加法:计算a[15:0]+b[15:0],cin=0
    wire [15:0] sum_low;  // 低16位和
    wire cout_low;        // 低16位进位输出

    add16 u1 (
        .a(a[15:0]),
        .b(b[15:0]),
        .cin(1'b0),
        .sum(sum_low),
        .cout(cout_low)
    );

    // 2. 高16位并行计算两种进位假设
    wire [15:0] sum_high0; // 假设cin=0时的高16位和
    wire [15:0] sum_high1; // 假设cin=1时的高16位和

    // 高16位,cin=0
    add16 u2 (
        .a(a[31:16]),
        .b(b[31:16]),
        .cin(1'b0),
        .sum(sum_high0),
        .cout()  // 忽略进位输出
    );

    // 高16位,cin=1
    add16 u3 (
        .a(a[31:16]),
        .b(b[31:16]),
        .cin(1'b1),
        .sum(sum_high1),
        .cout()  // 忽略进位输出
    );

    // 3. 多路选择器:根据cout_low选择高16位的和
    assign sum[31:16] = cout_low ? sum_high1 : sum_high0;
    assign sum[15:0]  = sum_low;  // 低16位和直接赋值

endmodule

Adder-subtractor

Adder-subtractor 工作原理:
在二进制运算中,减法 A - B 可通过 “加上 B 的补码” 实现,即: A - B = A + (-B) .
其中,-B 是 B 的 2 的补码(二进制中最常用的补码形式)。而 2 的补码计算规则为:-B = ~B + 1~B 表示对 B 的每一位取反,即 1 的补码,再加 1)。

Solution

module top_module(
    input [31:0] a,
    input [31:0] b,
    input sub,
    output [31:0] sum
);

    wire [31:0] b_xor;      // b与sub异或后的结果(取反控制)
    wire cout_lo;           // 低16位加法器的进位输出,连接高16位的进位输入
    wire [15:0] sum_lo;     // 低16位的和
    wire [15:0] sum_hi;     // 高16位的和

    // 1. 对b进行异或处理:sub=1时b取反,sub=0时保持原码
    assign b_xor = b ^ {32{sub}};  // {32{sub}}将sub扩展为32位,每一位与b异或

    // 2. 实例化低16位加法器(add16_lo)
    add16 add16_lo (
        .a(a[15:0]),        // 低16位输入a
        .b(b_xor[15:0]),    // 低16位输入b(已异或处理)
        .cin(sub),          // 进位输入:sub=1时实现"加1",完成补码转换
        .sum(sum_lo),       // 低16位和输出
        .cout(cout_lo)      // 低16位进位输出,连接高16位的cin
    );

    // 3. 实例化高16位加法器(add16_hi)
    add16 add16_hi (
        .a(a[31:16]),       // 高16位输入a
        .b(b_xor[31:16]),   // 高16位输入b(已异或处理)
        .cin(cout_lo),      // 低16位的进位作为高16位的进位输入
        .sum(sum_hi),       // 高16位和输出
        .cout()             // 高16位进位无需输出(32位结果已包含所有信息)
    );

    // 4. 拼接低16位和高16位的结果
    assign sum = {sum_hi, sum_lo};

endmodule