【学习笔记】SystemVerilog 常见组合逻辑电路

2 常见组合逻辑电路

2.1 32 位补码加法器

2.1.1一位全加器

一位全加器设计如下:

// 一位全加器
module FullAdder(
	input logic a,
    input logic b,
    input logic cin,
    output logic s,
    output logic cout
	);
    assign s = ((~a) & (~b) & cin) | ((~a) & b & (~cin)) | (a & (~b) & (~cin)) | (a & b & cin);
    assign cout = (b & cin) | (a & b) | (a & cin);
endmodule
    

2.1.2 32位补码加法器

利用一位全加器设计32位补码加法器:

// 32 位补码全加器
module Adder_32bit(
    input logic [31:0] A,
    input logic [31:0] B,
    input logic m,
    output logic [31:0] sum, // 各位输出
    output logic v, // 溢出判断
    output logic cout // 最后一位进位
    );
    // 初始化
    logic [32:0] c;
    logic s32;
    logic [31:0] a;
    logic [31:0] b;
    
    assign a = A;
    assign b = (m) ? (~B) : B; // m = 1 时对B求反
    
    // 加法
    FullAdder ADD0(a[0], b[0], m, sum[0], c[0]);
    for( genvar i = 1; i < 32; i++)begin
        FullAdder ADD(a[i], b[i], c[i-1], sum[i], c[i]);
    end
     FullAdder AD32(a[31], b[31], c[31], s32, c[32]);
     
     // 进位与溢出判断赋值
     assign cout = c[32];
     assign v = sum[31] ^ s32;
endmodule

电路图如下(有点可怕)

2.1.3 测试与验证

编写 testbench 激励文件.

这里用AI生成了一些测试用例用作32位全加器的测试.

Test Case 1: A = 00000000, B = 00000000, m = 0

Test Case 2: A = 00000001, B = 00000002, m = 0

Test Case 3: A = FFFFFFFF, B = 00000001, m = 0

Test Case 4: A = 7FFFFFFF, B = 00000001, m = 0

Test Case 5: A = 80000000, B = 00000001, m = 0

Test Case 6: A = FFFFFFFF, B = FFFFFFFF, m = 0

Test Case 7: A = 00000001, B = 00000001, m = 1

Test Case 8: A = FFFFFFFF, B = FFFFFFFF, m = 1

将测试样例输入testbench文件.

`timescale 1ns / 1ps

module tb_Adder_32bit();
    logic [31:0] A; 
    logic [31:0] B;
    logic m;
    logic [31:0] sum;
    logic v;
    logic cout;
    
    Adder_32bit tb_Adder_32bit(.A(A),.B(B),.m(m),.sum(sum),.v(v),.cout(cout));
    
    initial begin
        // 初始化输入信号
        A = 32'h00000000;
        B = 32'h00000000;
        m = 1'b0;
        
        // 测试用例1: A = 00000000, B = 00000000, m = 0
        #10;
        $display("Test Case 1: A = 0, B = 0, m = 0");
        $display("sum = %h, v = %b, cout = %b", sum, v, cout);
        
        // 测试用例2: A = 00000001, B = 00000002, m = 0
        A = 32'h00000001;
        B = 32'h00000002;
        #10;
        $display("Test Case 2: A = 1, B = 2, m = 0");
        $display("sum = %h, v = %b, cout = %b", sum, v, cout);
        
        // 测试用例3: A = FFFFFFFF, B = 00000001, m = 0
        A = 32'hFFFFFFFF;
        B = 32'h00000001;
        #10;
        $display("Test Case 3: A = FFFFFFFF, B = 1, m = 0");
        $display("sum = %h, v = %b, cout = %b", sum, v, cout);
        
        // 测试用例4: A = 7FFFFFFF, B = 00000001, m = 0
        A = 32'h7FFFFFFF;
        B = 32'h00000001;
        #10;
        $display("Test Case 4: A = 7FFFFFFF, B = 1, m = 0");
        $display("sum = %h, v = %b, cout = %b", sum, v, cout);
        
        // 测试用例5: A = 80000000, B = 00000001, m = 0
        A = 32'h80000000;
        B = 32'h00000001;
        #10;
        $display("Test Case 5: A = 80000000, B = 1, m = 0");
        $display("sum = %h, v = %b, cout = %b", sum, v, cout);
        
        // 测试用例6: A = FFFFFFFF, B = FFFFFFFF, m = 0
        A = 32'hFFFFFFFF;
        B = 32'hFFFFFFFF;
        #10;
        $display("Test Case 6: A = FFFFFFFF, B = FFFFFFFF, m = 0");
        $display("sum = %h, v = %b, cout = %b", sum, v, cout);
        
        // 测试用例7: A = 00000001, B = 00000001, m = 1
        A = 32'h00000001;
        B = 32'h00000001;
        m = 1'b1;
        #10;
        $display("Test Case 7: A = 1, B = 1, m = 1");
        $display("sum = %h, v = %b, cout = %b", sum, v, cout);
        
        // 测试用例8: A = FFFFFFFF, B = FFFFFFFF, m = 1
        A = 32'hFFFFFFFF;
        B = 32'hFFFFFFFF;
        m = 1'b1;
        #10;
        $display("Test Case 8: A = FFFFFFFF, B = FFFFFFFF, m = 1");
        $display("sum = %h, v = %b, cout = %b", sum, v, cout);
        
        // 结束仿真
        $finish;
    end
endmodule

测试结果

可以验证结果是正确的.

Test Case 1: A = 0, B = 0, m = 0
输入:A = 0, B = 0
输出:sum = 00000000, v = 0, cout = 0
说明:0 + 0 = 0,无溢出和进位。

Test Case 2: A = 1, B = 2, m = 0
输入:A = 1, B = 2
输出:sum = 00000003, v = 0, cout = 0
说明:1 + 2 = 3,无溢出和进位。

Test Case 3: A = FFFFFFFF, B = 1, m = 0
输入:A = -1 (补码表示为32'hFFFFFFFF), B = 1
输出:sum = 00000000, v = 0, cout = 1
说明:-1 + 1 = 0,进位标志为1,无溢出。

Test Case 4: A = 7FFFFFFF, B = 1, m = 0
输入:A = 2147483647 (最大正数), B = 1
输出:sum = 80000000, v = 1, cout = 0
说明:2147483647 + 1 = -2147483648(溢出),溢出标志为1。

Test Case 5: A = 80000000, B = 1, m = 0
输入:A = -2147483648 (最小负数), B = 1
输出:sum = 80000001, v = 0, cout = 0
说明:-2147483648 + 1 = -2147483647,无溢出。

Test Case 6: A = FFFFFFFF, B = FFFFFFFF, m = 0
输入:A = -1, B = -1
输出:sum = FFFFFFFE, v = 0, cout = 1
说明:-1 + (-1) = -2,进位标志为1,无溢出。

Test Case 7: A = 1, B = 1, m = 1
输入:A = 1, B = 1
输出:sum = 00000000, v = 0, cout = 1
说明:1 - 1 = 0,进位标志为1,无溢出。

Test Case 8: A = FFFFFFFF, B = FFFFFFFF, m = 1
输入:A = -1, B = -1
输出:sum = 00000000, v = 0, cout = 1
说明:-1 - (-1) = 0,进位标志为1,无溢出。

2.2 32 位补码乘法器

2.2.1 32位补码乘法器

利用32位补码加法器设计32位补码乘法器,其中全加器同上:点击跳转

`timescale 1ns / 1ps

module FullAdder(
	input logic a,
    input logic b,
    input logic cin,
    output logic s,
    output logic cout
	);
    assign s = ((~a) & (~b) & cin) | ((~a) & b & (~cin)) | (a & (~b) & (~cin)) | (a & b & cin);
    assign cout = (b & cin) | (a & b) | (a & cin);
endmodule


module Multiplier_32bit(
    input logic [31:0] A,
    input logic [31:0] B,
    output logic [63:0] product
);
    logic [31:0][30:0] sum, c;
    logic [63:0] p;
    logic [31:0] a, b;
    
    assign a = A;
    assign b = B;
    
    assign p[0] = a[0] & b[0];
    
    for(genvar i = 0; i < 31; i++) begin
        FullAdder ADD(a[i+1] & b[0], a[i] & b[1] , 0, sum[0][i], c[0][i]);
    end
    
    for(genvar j = 1; j < 31; j++)begin
        assign p[j] = sum[j-1][0];
        for(genvar i = 0; i < 30; i++)begin
            FullAdder ADD(sum[j-1][i+1], a[i] & b[j+1], c[j-1][i], sum[j][i], c[j][i]);
        end
        FullAdder ADD(a[31] & b[j], a[30] & b[j+1], c[j-1][30], sum[j][30], c[j][30]);
    end
    
    assign p[31] = sum[30][0];
    FullAdder ADD31_0(sum[30][1], c[30][0], 0, sum[31][0], c[31][0]);
    assign p[32] = sum[31][0];
    for(genvar i = 1; i < 30; i++)begin
        FullAdder ADD(sum[30][i+1], c[30][i], c[31][i-1], sum[31][i], c[31][i]);
        assign p[32+i] = sum[31][i];
    end
    
    FullAdder ADD31_30(a[31] & b[31], c[30][30], c[31][29], sum[31][30], c[31][30]);
    
    assign product = p;


endmodule

电路图如下(有点可怕\(\times 2\)

2.2.2 测试与验证

编写 testbench 激励文件.

同样用AI生成一些测试用例用作32位补码乘法器的测试.

Test Case 1: A = 0, B = 0

Test Case 2: A = 1, B = 2

Test Case 3: A = -1, B = 1

Test Case 4: A = 2, B = -3

Test Case 5: A = -2, B = -3

Test Case 6: A = 0, B = 5

Test Case 7: A = 5, B = 0

Test Case 8: A = 0xFFFFFFFF, B = 0xFFFFFFFF

将测试样例输入testbench文件.

`timescale 1ns / 1ps

module tb_Multiplier_32bit();
    logic [31:0] A;
    logic [31:0] B;
    logic [63:0] product;
    
    logic [31:0] abs_a, abs_b, c;
    
    always_comb begin
        if(A[31] == 1'b1)begin
            abs_a[30:0] = (~A[30:0]) + 1'b1;
            abs_a[31] = 1'b0;
        end
        else begin
            abs_a = A;
        end
    end
    
    always_comb begin
        if(B[31] == 1'b1)begin
            abs_b[30:0] = (~B[30:0]) + 1'b1;
            abs_b[31] = 1'b0;
        end
        else begin
            abs_b = B;
        end
    end
    
    assign c[31] = A[31] ^ B[31];
    
    Multiplier_32bit tb_Multiplier_32bit(
        .A(abs_a),
        .B(abs_b),
        .product(product)
    );
    
    always_comb begin
        if(c[31] == 1'b1)begin
            c[30:0] = (~product[30:0]) + 1'b1;
        end
        else begin
            c[30:0] = product[30:0];
        end
    end
    
    initial begin
        // 初始化输入信号
        A = 32'h00000000;
        B = 32'h00000000;
        
        // 测试用例1: A = 0, B = 0
        #10;
        $display("Test Case 1: A = 0, B = 0");
        $display("c = %h", c);
        
        // 测试用例2: A = 1, B = 2
        A = 32'h00000001;
        B = 32'h00000002;
        #10;
        $display("Test Case 2: A = 1, B = 2");
        $display("c = %h", c);
        
        // 测试用例3: A = -1, B = 1
        A = 32'hFFFFFFFF;
        B = 32'h00000001;
        #10;
        $display("Test Case 3: A = -1, B = 1");
        $display("c = %h", c);
        
        // 测试用例4: A = 2, B = -3
        A = 32'h00000002;
        B = 32'hFFFFFFFD;
        #10;
        $display("Test Case 4: A = 2, B = -3");
        $display("c = %h", c);
        
        // 测试用例5: A = -2, B = -3
        A = 32'hFFFFFFFE;
        B = 32'hFFFFFFFD;
        #10;
        $display("Test Case 5: A = -2, B = -3");
        $display("c = %h", c);
        
        // 测试用例6: A = 0, B = 5
        A = 32'h00000000;
        B = 32'h00000005;
        #10;
        $display("Test Case 6: A = 0, B = 5");
        $display("c = %h", c);
        
        // 测试用例7: A = 5, B = 0
        A = 32'h00000005;
        B = 32'h00000000;
        #10;
        $display("Test Case 7: A = 5, B = 0");
        $display("c = %h", c);
        
        // 测试用例8: A = 0xFFFFFFFF, B = 0xFFFFFFFF
        A = 32'hFFFFFFFF;
        B = 32'hFFFFFFFF;
        #10;
        $display("Test Case 8: A = 0xFFFFFFFF, B = 0xFFFFFFFF");
        $display("c = %h", c);
        
        // 结束仿真
        $finish;
    end
    
endmodule

测试结果:

可以验证结果是正确的.

Test Case 1: A = 0, B = 0
输入:A = 0, B = 0
输出:product = 0
说明:0乘以0等于0,无溢出。

Test Case 2: A = 1, B = 2
输入:A = 1, B = 2
输出:product = 2
说明:1乘以2等于2,无溢出。

Test Case 3: A = -1, B = 1
输入:A = -1, B = 1
输出:product = -1
说明:-1乘以1等于-1,无溢出。

Test Case 4: A = 2, B = -3
输入:A = 2, B = -3
输出:product = -6
说明:2乘以-3等于-6,无溢出。

Test Case 5: A = -2, B = -3
输入:A = -2, B = -3
输出:product = 6
说明:-2乘以-3等于6,无溢出。

Test Case 6: A = 0, B = 5
输入:A = 0, B = 5
输出:product = 0
说明:0乘以5等于0,无溢出。

Test Case 7: A = 5, B = 0
输入:A = 5, B = 0
输出:product = 0
说明:5乘以0等于0,无溢出。

Test Case 8: A = 0xFFFFFFFF, B = 0xFFFFFFFF
输入:A = 0xFFFFFFFF, B = 0xFFFFFFFF
输出:product = 0x0000000100000001
说明:-1乘以-1等于1,无溢出。
posted @ 2025-03-15 13:58  NeoAxiomN  阅读(37)  评论(1)    收藏  举报