How to output a 5 bit number from a ripple-carry adder/subtractor into a 5 bit decoder to account for overflow in Verilog?

128 Views Asked by At

I am working on a project that will take two 4-bit numbers between 0-9 and add/subtract them to be displayed in a seven segment display. Here is a big picture idea of what I am trying to create

My ripple carry adder/subtractor code:

module full_adder(
    input A, B, C,
    output F, G
    );

    assign F = A^B^C; // boolean algebra for sum
    assign G = (A&B)|(B&C)|(A&C); // boolean algebra for carry
endmodule

module ripple_carry_adder(
    input [3:0] A, B,
    input C,
    output [4:0] S
    );

    wire W3, W2, W1, W0;

    full_adder U0(.A(A[0]), .B(B[0]^C), .C(C), .F(S[0]), .G(W0));
    full_adder U1(.A(A[1]), .B(B[1]^C), .C(W0), .F(S[1]), .G(W1));
    full_adder U2(.A(A[2]), .B(B[2]^C), .C(W1), .F(S[2]), .G(W2));
    full_adder U3(.A(A[3]), .B(B[3]^C), .C(W2), .F(S[3]), .G(W3));
endmodule

My 5-bit Decoder code:

module decoder_5bits(
    input [4:0] sum,
    output reg [3:0] tens, ones
    );

    always @(sum)
    begin
        case(sum)
            5'b10111: // -9
            begin
                tens = 4'b1011;
                ones = 4'b1001;
            end

            5'b11000: // -8
            begin
                tens = 4'b1011;
                ones = 4'b1000;
            end

            5'b11001: // -7
            begin
                tens = 4'b1011;
                ones = 4'b0111;
            end

            5'b11010: // -6
            begin
                tens = 4'b1011;
                ones = 4'b0110;
            end

            5'b11011: // -5
            begin
                tens = 4'b1011;
                ones = 4'b0101;
            end

            5'b11100: // -4
            begin
                tens = 4'b1011;
                ones = 4'b0100;
            end

            5'b11101: // -3
            begin
                tens = 4'b1011;
                ones = 4'b0011;
            end

            5'b11110: // -2
            begin
                tens = 4'b1011;
                ones = 4'b0010;
            end

            5'b11111: // -1
            begin
                tens = 4'b1011;
                ones = 4'b0001;
            end

            5'b00000: // 0
            begin
                tens = 4'b0000;
                ones = 4'b0000;
            end

            5'b00001: // 1
            begin
                tens = 4'b0000;
                ones = 4'b0001;
            end

            5'b00010: // 2
            begin
                tens = 4'b0000;
                ones = 4'b0010;
            end

            5'b00011: // 3
            begin
                tens = 4'b0000;
                ones = 4'b0011;
            end

            5'b00100: // 4
            begin
                tens = 4'b0000;
                ones = 4'b0100;
            end

            5'b00101: // 5
            begin
                tens = 4'b0000;
                ones = 4'b0101;
            end

            5'b00110: // 6
            begin
                tens = 4'b0000;
                ones = 4'b0110;
            end

            5'b00111: // 7
            begin
                tens = 4'b0000;
                ones = 4'b0111;
            end

            5'b01000: // 8
            begin
                tens = 4'b0000;
                ones = 4'b1000;
            end

            5'b01001: // 9
            begin
                tens = 4'b0000;
                ones = 4'b1001;
            end

            5'b01010: // 10
            begin
                tens = 4'b1010;
                ones = 4'b0000;
            end

            5'b01011: // 11
            begin
                tens = 4'b1010;
                ones = 4'b0001;
            end

            5'b01100: // 12
            begin
                tens = 4'b1010;
                ones = 4'b0010;
            end
            
            5'b01101: // 13
            begin
                tens = 4'b1010;
                ones = 4'b0011;
            end

            5'b01110: // 14
            begin
                tens = 4'b1010;
                ones = 4'b0100;
            end

            5'b01111: // 15
            begin
                tens = 4'b1010;
                ones = 4'b0101;
            end

            5'b10000: // 16
            begin
                tens = 4'b1010;
                ones = 4'b0110;
            end

            5'b10001: // 17
            begin
                tens = 4'b1010;
                ones = 4'b0111;
            end

            5'b10010: // 18
            begin
                tens = 4'b1010;
                ones = 4'b1000;
            end

            default:
            begin
                tens = 4'b1111;
                ones = 4'b1111;
            end
        endcase
    end
endmodule

When I create a waveform of my whole project, I seem to be caught up at the ripple carry adder and 5-bit decoder. The 5-bit output does not seem to account for the overflow like it should. I am assuming this is where I am going wrong.

Here is the waveform output if that helps.

Here is a minimal reproducible example with a testbench:

module full_adder(
    input A, B, C,
    output F, G
    );

    assign F = A^B^C; // boolean algebra for sum
    assign G = (A&B)|(B&C)|(A&C); // boolean algebra for carry
endmodule

module ripple_carry_adder(
    input [3:0] A, B,
    input C,
    output [4:0] S
    );

    wire W3, W2, W1, W0;

    full_adder U0(.A(A[0]), .B(B[0]^C), .C(C), .F(S[0]), .G(W0));
    full_adder U1(.A(A[1]), .B(B[1]^C), .C(W0), .F(S[1]), .G(W1));
    full_adder U2(.A(A[2]), .B(B[2]^C), .C(W1), .F(S[2]), .G(W2));
    full_adder U3(.A(A[3]), .B(B[3]^C), .C(W2), .F(S[3]), .G(W3));
endmodule

module decoder_5bits(
    input [4:0] sum,
    output reg [3:0] tens, ones
    );

    always @(sum)
    begin
        case(sum)

            5'b11111: // -1
            begin
                tens = 4'b1011;
                ones = 4'b0001;
            end

            5'b00000: // 0
            begin
                tens = 4'b0000;
                ones = 4'b0000;
            end

            5'b00001: // 1
            begin
                tens = 4'b0000;
                ones = 4'b0001;
            end

            5'b10010: // 18
            begin
                tens = 4'b1010;
                ones = 4'b1000;
            end

            default:
            begin
                tens = 4'b1111;
                ones = 4'b1111;
            end
        endcase
    end
endmodule

module top(
    input [3:0] A, B,
    input C,
    output [3:0] tens, ones
    );

    wire [4:0] SUM;

    ripple_carry_adder U1(
        .A          (A),
        .B          (B),
        .C          (C),
        .S          (SUM)
    );

    decoder_5bits U2(
        .sum        (SUM),
        .tens       (tens),
        .ones       (ones)
    );
endmodule

module testbench;
    reg C;
    reg [3:0] A, B;
    wire [3:0] tens, ones;

    top UUT(A, B, C, tens, ones);

    initial begin
        $dumpfile("MRE.vcd");
        $dumpvars(0, testbench);

        A = 4'b1001; B = 4'b1001; C = 0; #10
        A = 4'b0001; B = 4'b0010; C = 1; #10
        A = 4'b0000; B = 4'b1001; C = 1; #10
        $finish;
    end
endmodule

As seen in the waveform output, any time I add up to a double digit number or subtract to a negative number, I run into issues with the 5-bit output from the ripple-carry adder/subtractor.

Here is my waveform output

1

There are 1 best solutions below

0
toolic On

As you can see in your waveforms, bit SUM[4] is z, which means it is undriven. You can trace that back to ripple_carry_adder, where S[4] is also undriven because you did not connect to it.

There is never a reason to use anything more complicated than a single line of code for an adder in Verilog:

module ripple_carry_adder(
    input [3:0] A, B,
    input C,
    output [4:0] S
    );
    assign S = A + B + C;
endmodule

This gets rid of the undriven z value.