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 Answers1

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
Unn
  • 4,775
  • 18
  • 30
  • 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? – Wesley Shaw Aug 15 '21 at 12:56
  • 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. – Unn Aug 15 '21 at 19:05
  • 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! – Wesley Shaw Aug 16 '21 at 10:42
  • 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. – Unn Aug 16 '21 at 18:14