binaryverilogadditiondigital-logicbcd

Verilog Binary Coded Decimal Adder Not Outputting Correctly


I'm new to Verilog and basically trying to teach myself a Digital Logic Design module for university. I am trying to write a BCD Adder in Verilog using two Full Adders with some logic in between for conversion to BCD when needed.

Here is my code:

module      binary_adder (
    output  [3:0]   Sum,
    output          C_out,
    input   [3:0]   A, B,
    input           C_in
);
    assign  {C_out, Sum} = A || B || C_in;
endmodule

module      BCD_Adder (
    output  [3:0]   Sum,
    output          Carry_out,
    input   [3:0]   Addend, Augend,
    input           Carry_in
);

wire [3:0]  Z, correction;
wire adder1C_out, carryInAdder2, adder2C_out;

    binary_adder adder1 (.Sum(Z), .C_out(adder1C_out), .A(Addend), .B(Augend), .C_in(Carry_in));
    
assign Carry_out = (adder1C_out || (Z[3] && Z[1]) || (Z[3] && Z[2]));
assign correction = (Carry_out) ? (4'b0110) : (4'b0000);
assign carryInAdder2 = (1'b0);

    binary_adder adder2 (.Sum(Sum), .C_out(adder2C_out), .A(correction), .B(Z), .C_in(carryInAdder2));

endmodule

For some reason, I keep getting the following outputs:

Submitted: A = 0000, B = 0010, Carry In = 0, Sum = 0001, Carry Out = 0

Expected: A = 0000, B = 0010, Carry In = 0, Sum = 0010, Carry Out = 0

Submitted: A = 0000, B = 0011, Carry In = 0, Sum = 0001, Carry Out = 0

Expected: A = 0000, B = 0011, Carry In = 0, Sum = 0011, Carry Out = 0

Submitted: A = 0000, B = 0100, Carry In = 0, Sum = 0001, Carry Out = 0

Expected: A = 0000, B = 0100, Carry In = 0, Sum = 0100, Carry Out = 0

It basically continues like this for all values. My A, B, Carry In and Carry Out values always match, but for some reason the output sum is always 0001. I'm not sure where I'm going wrong, the logic seems okay to me. I am very new to this and only know the basics, so any help would be greatly appreciated!

Thanks, Wes


Solution

  • The logic in binary_adder does not implement addition; as it is currently written, it will just set Sum to 1 if any of A, B or C_in are non-zero.

    While there are many architectures of multibit addition (see https://en.wikipedia.org/wiki/Adder_(electronics)#Adders_supporting_multiple_bits), the simplest to understand is the Ripple Carry Adder. It implements several full adders and chains them together to implement addition.

    A simple implementation of this architecture looks like this:

    module full_add(input A, B, Cin,
                    output S, Cout);
      // Basic implementation of a Full Adder (see https://en.wikipedia.org/wiki/Adder_(electronics)#Full_adder)
      assign S = A ^ B ^ Cin;
      assign Cout = A & B | ((A ^ B) & Cin); // Note I use bit-wise operators like | and ^ instead of logical ones like ||; its important to know the difference
    endmodule
    
    module add(input [3:0] A, B,
               input Cin,
               output [3:0] S,
               output Cout);
    
      wire [3:0] Carries; // Internal wires for the carries between full adders in Ripple Carry
    
      // This is an array instance which just makes [3:0], ie 4, instances of the full adder.
      // Take note that a single Full Adder modules takes in single bits, but here
      // I can pass bit vectors like A ([3:0]) directly which assign full_add[0].A = A[0], full_add[1].A = A[1], etc
      // Common alternatives to using array instances (which are more rare) include generate statements or just instantiate the module X times
      full_add f[3:0](.A(A), .B(B), .Cin({Carries[2:0], Cin}), .S(S), .Cout(Carries));
    
      assign Cout = Carries[3];
    endmodule