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?
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