0

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

1 Answer 1

0

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
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for this, it all makes sense to me. Am I right in saying that the binary_adder module that I wrote is only an adder for single bit addition? (A half-adder I think?) And then because I’m trying to add 4 bits, I need what 4 full adders using the ripple-carry implementation?
Not exactly, since a half adder requires S to be A xor B and Cout to be A and B, so S = A ^ B; Cout = A && B would work (since on single bits, logical and boolean operators are the same). A || B isn't enough logic, you'd also need to account for when A and B are set as S would be 0 and Cout would be 1 in that case.
Apologies. I was getting mixed up myself. The Binary Adder example I had seen used the line "assign {C_out, S} = A + B + C_in;". I mistook the '+' in this for boolean notation, and assumed it mean a logical OR. I didn't realise that Verilog supported addition like that, (I am a complete beginner, sorry!) Nevertheless, I managed to use your advice and successfully write a Ripple Carry Adder that I then converted to Binary Coded Decimal. I did all this before realising my mistake, so it was all good practice! Thanks for your help, I understand it all now!
Oh, I see -- yes, the regular mathematic operations are all available (and much more!), just always be cognoscente of what hardware you are creating! Glad you now have a better understanding and best of luck with your continued education.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.