Ripple Carry Adder

Solving Approach

How do you plan to solve it?

 

Code

// Top module: 4-bit ripple-carry adder built from 1-bit full adders
module rca4_chain (
    input  wire [3:0] a,
    input  wire [3:0] b,
    input  wire       cin,
    output wire [3:0] sum,
    output wire       cout
);

    // Internal carry wires (c0 is cin, c4 is cout)
    wire c1, c2, c3;

    // Bit 0
    full_adder_1bit fa0 (
        .a    (a[0]),
        .b    (b[0]),
        .cin  (cin),   // c0
        .sum  (sum[0]),
        .cout (c1)
    );

    // Bit 1
    full_adder_1bit fa1 (
        .a    (a[1]),
        .b    (b[1]),
        .cin  (c1),
        .sum  (sum[1]),
        .cout (c2)
    );

    // Bit 2
    full_adder_1bit fa2 (
        .a    (a[2]),
        .b    (b[2]),
        .cin  (c2),
        .sum  (sum[2]),
        .cout (c3)
    );

    // Bit 3
    full_adder_1bit fa3 (
        .a    (a[3]),
        .b    (b[3]),
        .cin  (c3),
        .sum  (sum[3]),
        .cout (cout)   // c4
    );

endmodule


// 1-bit full adder (fully combinational)
module full_adder_1bit (
    input  wire a,
    input  wire b,
    input  wire cin,
    output wire sum,
    output wire cout
);

    assign sum  = a ^ b ^ cin;
    assign cout = (a & b) | (a & cin) | (b & cin);

    // Equivalent behavioral form (also synthesizable)
    // assign {cout, sum} = a + b + cin;

endmodule

 

Upvote
Downvote

Testbench Code

`timescale 1ns/1ps

module tb_rca4_chain;
    // 1) Inputs
    reg  [3:0] a, b;
    reg        cin;

    // 2) DUT outputs
    wire [3:0] sum;
    wire       cout;

    // 3) Golden/expected (purely combinational from inputs)
    wire [4:0] golden        = a + b + cin;
    wire [3:0] expected_sum  = golden[3:0];
    wire       expected_cout = golden[4];

    // 4) Single mismatch flag (pure combinational)
    // Use case-inequality so X/Z differences are treated as mismatches.
    wire mismatch = ({cout, sum} !== {expected_cout, expected_sum});

    // Accounting
    integer TOTAL_TEST_CASES        = 0;
    integer TOTAL_PASSED_TEST_CASES = 0;
    integer TOTAL_FAILED_TEST_CASES = 0;

    // Limits
    integer VCD_MAX_CASES   = 32; // normal rows printed (and optional VCD cap below)
    integer ERROR_MAX_CASES = 32; // error rows printed
    integer printed_rows    = 0;
    integer printed_errors  = 0;

    // DUT
    // NOTE: ensure rca4_chain and full_adder_1bit are compiled with this TB.
    rca4_chain dut(.a(a), .b(b), .cin(cin), .sum(sum), .cout(cout));

    // VCD dump (Inputs -> Outputs -> Expected -> Mismatch)
    initial begin
        $dumpfile("tb_rca4_chain.vcd");
        $dumpvars(0,
            tb_rca4_chain.a,
            tb_rca4_chain.b,
            tb_rca4_chain.cin,
            tb_rca4_chain.sum,
            tb_rca4_chain.cout,
            tb_rca4_chain.expected_sum,
            tb_rca4_chain.expected_cout,
            tb_rca4_chain.mismatch
        );
        $dumpon;
    end

    // Header + init
    initial begin
        a = 0; b = 0; cin = 0;
        $display("  a   b  cin | sum cout | expected_sum expected_cout | mismatch");
        $display("---------------------------------------------------------------");
    end

    // Apply + check (drive -> wait -> read combinational mismatch)
    task apply_and_check;
        input [3:0] ta, tb;
        input       tcin;
        begin
            a   = ta;
            b   = tb;
            cin = tcin;

            // Let DUT and expected settle, then read mismatch (still a wire)
            #1;

            TOTAL_TEST_CASES = TOTAL_TEST_CASES + 1;
            if (!mismatch) begin
                TOTAL_PASSED_TEST_CASES = TOTAL_PASSED_TEST_CASES + 1;
                if (printed_rows < VCD_MAX_CASES) begin
                    $display("0x%1h 0x%1h  %0d  | 0x%1h   %0d   |     0x%1h          %0d        |    %0d",
                             a, b, cin, sum, cout, expected_sum, expected_cout, mismatch);
                    printed_rows = printed_rows + 1;
                end
            end else begin
                TOTAL_FAILED_TEST_CASES = TOTAL_FAILED_TEST_CASES + 1;
                if (printed_errors < ERROR_MAX_CASES) begin
                    $display("ERR: a=0x%1h b=0x%1h cin=%0d => sum=0x%1h cout=%0d (exp sum=0x%1h cout=%0d)",
                             a, b, cin, sum, cout, expected_sum, expected_cout);
                    printed_errors = printed_errors + 1;
                end
            end

            // Optional: stop VCD after VCD_MAX_CASES total vectors
            if (TOTAL_TEST_CASES == VCD_MAX_CASES) $dumpoff;
        end
    endtask

    integer ia, ib;
    initial begin
        // Directed sanity
        apply_and_check(4'h0, 4'h0, 1'b0);
        apply_and_check(4'hF, 4'h0, 1'b0);
        apply_and_check(4'h0, 4'hF, 1'b1);
        apply_and_check(4'hA, 4'h5, 1'b0);
        apply_and_check(4'h7, 4'h9, 1'b1);

        // Full sweep
        for (ia = 0; ia < 16; ia = ia + 1) begin
            for (ib = 15; ib >= 0; ib = ib - 1) begin
                apply_and_check(ia[3:0], ib[3:0], 1'b0);
                apply_and_check(ia[3:0], ib[3:0], 1'b1);
            end
        end

        // Summary
        $display("---------------------------------------------------------------");
        $display("TOTAL_TEST_CASES=%0d", TOTAL_TEST_CASES);
        $display("TOTAL_PASSED_TEST_CASES=%0d", TOTAL_PASSED_TEST_CASES);
        $display("TOTAL_FAILED_TEST_CASES=%0d", TOTAL_FAILED_TEST_CASES);
        $display("ALL_TEST_CASES_PASSED=%s", (TOTAL_FAILED_TEST_CASES==0) ? "true" : "false");

        #2 $finish;
    end
endmodule