1
\$\begingroup\$

I want to implement a 4-bit parallel adder and subtractor using the same circuit while using a control input variable to switch between addition and subtraction. When my ctrl input variable is 0, I want the operation to be addition and subtraction when it is 1. When it is subtraction, I want to ignore the last carry out.

Here is my code,

module p4bitadd_sub( output [4:0]sum,input ctrl,[3:0]a,b);

wire c1,c2,c3;

fadder ad0(a[0],ctrl^b[0],ctrl, sum[0], c1);
fadder ad1(a[1],ctrl^b[1],c1, sum[1], c2);
fadder ad2(a[2],ctrl^b[2],c2, sum[2], c3);
fadder ad3(a[3],ctrl^b[3],c3, sum[3], sum[4]);
assign sum[4] = (~ctrl)&sum[4];

endmodule

module fadder(input a,b,cin,output s,cout);

assign s=a^b^cin;
assign cout = (a&b)|(b&cin)|(cin&a);

endmodule

My testbench,

module p4bitadd_sun_tb();

reg [3:0] a;
reg [3:0] b;
reg ctrl;
wire [4:0] s;

p4bitadd_sub dut(.sum(s),.a(a),.b(b),.ctrl(ctrl));
initial begin

ctrl=0;a=4'b1000;b=4'b0100;
#5
$display("Addition:");
$display("   %b%b%b%b",a[3],a[2],a[1],a[0]);
$display("  +%b%b%b%b",b[3],b[2],b[1],b[0]);
$display("  -----");
$display("  %b%b%b%b%b",s[4],s[3],s[2],s[1],s[0]);
ctrl=0;a=4'b0101;b=4'b0011;
#5
$display("");
$display("   %b%b%b%b",a[3],a[2],a[1],a[0]);
$display("  +%b%b%b%b",b[3],b[2],b[1],b[0]);
$display("  -----");
$display("  %b%b%b%b%b",s[4],s[3],s[2],s[1],s[0]);
ctrl=1;a=4'b1000;b=4'b0100;
#5
$display("Subtraction:");
$display("   %b%b%b%b",a[3],a[2],a[1],a[0]);
$display("  -%b%b%b%b",b[3],b[2],b[1],b[0]);
$display("  -----");
$display("  %b%b%b%b%b",s[4],s[3],s[2],s[1],s[0]);
ctrl=1;a=4'b0101;b=4'b0011;
#5
$display("");
$display("   %b%b%b%b",a[3],a[2],a[1],a[0]);
$display("  -%b%b%b%b",b[3],b[2],b[1],b[0]);
$display("  -----");
$display("  %b%b%b%b%b",s[4],s[3],s[2],s[1],s[0]);

$finish;
end
endmodule

My console output:

addition output

subtraction output

Any help is appreciated

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

The problem is in the p4bitadd_sub module. Your code has multiple drivers for the sum[4] bit.

One driver is the output of the ad3 instance:

fadder ad3(a[3],ctrl^b[3],c3, sum[3], sum[4]);

The other driver is the continuous assignment:

assign sum[4] = (~ctrl)&sum[4];

When you have multiple drivers of a signal, you can have contention, and contention results in an x value in Verilog. x is the unknown value, or "don't care" value.

You need to change the code in the p4bitadd_sub module so that sum[4] is not driven this way. One way is to add a new wire (c4):

module p4bitadd_sub( output [4:0]sum,input ctrl,[3:0]a,b);

wire c1,c2,c3,c4;

fadder ad0(a[0],ctrl^b[0],ctrl, sum[0], c1);
fadder ad1(a[1],ctrl^b[1],c1, sum[1], c2);
fadder ad2(a[2],ctrl^b[2],c2, sum[2], c3);
fadder ad3(a[3],ctrl^b[3],c3, sum[3], c4);
assign sum[4] = (~ctrl)&c4;

endmodule

Output:

Addition:
   1000
  +0100
  -----
  01100

   0101
  +0011
  -----
  01000

Subtraction:
   1000
  -0100
  -----
  00100

   0101
  -0011
  -----
  00010

If you aren't already doing so, you should also dump waveforms for your simulation. Looking at waves can make it much easier to see values of internal signals than just $display statements alone. This is how I quickly narrowed down the problem with your code.

\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.