Search code examples
veriloghardwareicarus

Verilog Full Adder Unexpected Behavior


I am trying to do a very basic hardware module/test bench to get the hang of Verilog. I have tried to implement a full adder.

If I am not mistaken, you have three input, immediate addends a and b and a carry in from the 2^n-1 place.

The outputs are sum and carry out (which might serve as a carry in to another module in a basic adder or whatever the not carry-lookahead is called.)

If I am not mistaken the output logic is

sum = (a&b) | (a&cin) | (b&cin) //or all three, which is covered by any of these

cout = a ^ b ^ cin

Here is the full adder module

module FullAdder(
a,
b,
cin,
sum,
co
);

input a;
input b;
input cin;
output sum;
output co;

//wire a;
//wire b;
//wire ci;
wire sum;
wire co;


//At least two
assign co = (a & b) | (a & cin) | (b & cin);

//one or three 
assign sum = a ^ b ^ cin; //(a & ~b & ~cin) | (~a & b & ~cin) | (~a & ~b & cin) | (a & b & cin);


endmodule

And here is the test bench

module HalfAdderTB();
reg a_in;
reg b_in;
reg cin_in;
wire s_out;
wire cout_out;

FullAdder DUT(
        a_in,
        b_in,
        cin_in,
        s_out,
        cout_out
        );

initial begin
        a_in = 1'b0;
        b_in = 1'b0;
        cin_in = 1'b0;
        #20

        a_in = 1'b0;
        b_in = 1'b0;
        cin_in = 1'b0;
        $display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
        $display("s: %b, cout: %b", s_out, cout_out);
        #20

        a_in = 1'b0;
        b_in = 1'b0;
        cin_in = 1'b1;
        $display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
        $display("s: %b, cout: %b", s_out, cout_out);
        #20

        a_in = 1'b0;
        b_in = 1'b1;
        cin_in = 1'b0;
        $display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
        $display("s: %b, cout: %b", s_out, cout_out);
        #20

        a_in = 1'b0;
        b_in = 1'b1;
        cin_in = 1'b1;
        $display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
        $display("s: %b, cout: %b", s_out, cout_out);
        #20

        a_in = 1'b1;
        b_in = 1'b0;
        cin_in = 1'b0;
        $display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
        $display("s: %b, cout: %b", s_out, cout_out);
        #20

        a_in = 1'b1;
        b_in = 1'b0;
        cin_in = 1'b1;
        $display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
                                                                                   2,1            4%
 a_in = 1'b1;
        b_in = 1'b1;
        cin_in = 1'b0;
        $display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
        $display("s: %b, cout: %b", s_out, cout_out);
        #20

        assign a_in = 1'b1;
        assign b_in = 1'b1;
        assign cin_in = 1'b1;
        $display("a: %d, b: %d, cin: %d", a_in, b_in, cin_in);
        $display("s: %b, cout: %b", s_out, cout_out);
        #20
        $finish;
end
endmodule

My output looks like this

a: 0, b: 0, cin: 0

s: 0, cout: 0

a: 0, b: 0, cin: 1

s: 0, cout: 0

a: 0, b: 1, cin: 0

s: 1, cout: 0

a: 0, b: 1, cin: 1

s: 1, cout: 0

a: 1, b: 0, cin: 0

s: 0, cout: 1

a: 1, b: 0, cin: 1

s: 1, cout: 0

a: 1, b: 1, cin: 0

s: 0, cout: 1

a: 1, b: 1, cin: 1

s: 0, cout: 1

I believe the logic statements in my code match those of the boolean equations I wrote up top. I am confident in my logic. I cannot seem to figure out what is wrong with the Verilog. Have I missed something with the timing and input of the test bench to the Full Adder?


Solution

  • Your code is fine, but you are getting this strange result due to $display statement. Your code will work fine, if you use $strobe instead of $display. You could also use $monitor to display the results. The reson is that display statement executes immediately so that your outputs will not yet be updated with the new values, whereas strobe will execute only at the end of a time instant, so that your outputs would have been updated by then. monitor is used to automatically display values, whenever the values see a change.

    Since you are just starting on verilog, I would suggest you to go through this link to understand how various display statements work in verilog and also to go through this link to understand the order of execution of statements in a particular time instant, so that you can plan your code better