4-bit adder not adding correctly - verilog

I'm creating a 4-bit adder using 1-bit adder in Verilog and facing a problem that my 4-bit is not adding correctly.
This is my code for both:
1bit
module ab_fulladd (A,B,Cin,S,Cout);
output Cout,S;
input A,B,Cin;
wire w1,w2,w3;
xor G1(S,A,B,Cin);
and
G2(w1,A,B),
G3(w2,A,Cin),
G4(w3,B,Cin);
or
G5(Cout,w1,w2,w3);
endmodule
4-bit
module add4bit_parametric (a, b, cin, cout, sum);
parameter size = 4;
input [size-1:0] a, b;
input cin;
output cout;
output [size-1:0] sum;
wire [size-2:0] c;
genvar i;
generate
for (i = 0; i < size; i = i + 1) begin: adder
if (i == 0)
ab_fulladd fa (a[i], b[i], cin, c[i], sum[i]);
else if (i == size-1)
ab_fulladd fa(a[i],b[i],c[i-1],cout,sum[i]);
else
ab_fulladd fa (a[i],b[i],c[i-1],c[i],sum[i]);
end endgenerate
endmodule
My 4-bit is not adding up well in the waveform. Can you help me please?

You have a port connection bug. You mistakenly connected the sum and c signals because you use connection-by-order. To avoid this common type of mistake, use connection-by-name. Change:
ab_fulladd fa (a[i], b[i], cin, c[i], sum[i]);
to:
ab_fulladd fa (.A(a[i]), .B(b[i]), .Cin(cin), .Cout(c[i]), .S(sum[i]));
Repeat this for all instances. Here is the complete module code:
module add4bit_parametric (a, b, cin, cout, sum);
parameter size = 4;
input [size-1:0] a, b;
input cin;
output cout;
output [size-1:0] sum;
wire [size-2:0] c;
genvar i;
generate
for (i = 0; i < size; i = i + 1) begin: adder
if (i == 0)
ab_fulladd fa (.A(a[i]), .B(b[i]), .Cin(cin), .Cout(c[i]), .S(sum[i]));
else if (i == size-1)
ab_fulladd fa(.A(a[i]), .B(b[i]), .Cin(c[i-1]), .Cout(cout), .S(sum[i]));
else
ab_fulladd fa (.A(a[i]), .B(b[i]), .Cin(c[i-1]), .Cout(c[i]), .S(sum[i]));
end endgenerate
endmodule
It compiles on multiple simulators on edaplayground (sign up for a free account).

Related

4-bit adder subtractor Verilog code errors

I am trying to do a 4-bit adder subtractor in Verilog code, but there is some kind of problem in my code that I couldn't figure out. I'm not sure if the testbench or the Verilog is wrong. Can someone please help me with it? Also, when I try to simulate it, it gives Loading Errors.
My Verilog code:
module addsubparameter (A, B, OP, C_out, Sum);
input A,B;
input OP;
output C_out;
output Sum;
wire C_out, Sum;
reg assigning;
always#(OP)
begin
if (OP == 0)
assigning = A + B + OP;
else
assigning = A + (~B + 1) + OP;
end
assign {C_out, Sum} = assigning;
endmodule
module adder (a, b, op, cout, sum);
parameter size = 4 ;
input [3:0] a, b;
output [3:0] sum;
input op;
output cout;
wire [2:0] c;
genvar i;
generate
for (i = 0; i < size; i = i + 1) begin: adder
if (i == 0)
addsubparameter (a[i], b[i], op, sum[i], c[i]);
else if (i == 3)
addsubparameter (a[i], b[i], c[i-1], cout, sum[i]);
else
addsubparameter (a[i], b[i], c[i-1], sum[i], c[i]);
end
endgenerate
endmodule
And this is my testbench:
module addsub_tb();
reg [3:0] a;
reg [3:0] b;
reg op;
wire [3:0] sum;
wire cout;
adder DUT (a,b,op,sum,cout);
initial begin
a = 4'b1010; b = 4'b1100; op = 1'b0; #100;
a = 4'b1111; b = 4'b1011; op = 1'b1; #100;
a = 4'b1010; b = 4'b1010; op = 1'b0; #100;
end
endmodule
Your simulator should generate error and/or warning messages because you have syntax errors. If it does not, sign up for a free account on edaplayground, where you will have access to multiple simulators which will produce helpful messages.
You need to add instance names. For example, I added i0 in the line below:
addsubparameter i0 (a[i], b[i], op, sum[i], c[i]);
You have port connection width mismatches, and these indicate connection errors. This is a common type of error when you use connections by position. You mistakenly connected the sum signal to the cout port, and vice versa. You should use connections by name instead. For example, change:
adder DUT (a,b,op,sum,cout);
to:
adder dut (
.a (a),
.b (b),
.op (op),
.cout (cout),
.sum (sum)
);
Use this coding style for all your instances.
You won't get a simulation warning, but you might get a synthesis warnings about an incomplete sensitivity list. Change:
always#(OP)
to:
always #*

How can I check if my 4-bit adder/sub is working properly

How can I check if my 4-bit adder is working properly. If it is then it should display "OK" or if it's not then "NOT". I wrote the code and the bench test which will calculate all possible 4-bit combinations, but i don't know whether the output values are correct and I want to check it. My test bench is already displaying overflow. Here is my code :
module ripple_carry_adder_subtractor(S, C, V, A, B, Op);
output [3:0] S; // The 4-bit sum/difference.
output C; // The 1-bit carry/borrow status.
output V; // The 1-bit overflow status.
input [3:0] A; // The 4-bit augend/minuend.
input [3:0] B; // The 4-bit addend/subtrahend.
input Op; // The operation: 0 => Add, 1=>Subtract.
wire C0; // The carry out bit of fa0, the carry in bit of fa1.
wire C1; // The carry out bit of fa1, the carry in bit of fa2.
wire C2; // The carry out bit of fa2, the carry in bit of fa3.
wire C3; // The carry out bit of fa2, used to generate final carry/borrrow.
wire B0; // The xor'd result of B[0] and Op
wire B1; // The xor'd result of B[1] and Op
wire B2; // The xor'd result of B[2] and Op
wire B3; // The xor'd result of B[3] and Op
xor(B0, B[0], Op);
xor(B1, B[1], Op);
xor(B2, B[2], Op);
xor(B3, B[3], Op);
xor(C, C3, Op); // Carry = C3 for addition, Carry = not(C3) for subtraction.
xor(V, C3, C2); // If the two most significant carry output bits differ, then we have an overflow.
full_adder fa0(S[0], C0, A[0], B0, Op); // Least significant bit.
full_adder fa1(S[1], C1, A[1], B1, C0);
full_adder fa2(S[2], C2, A[2], B2, C1);
full_adder fa3(S[3], C3, A[3], B3, C2); // Most significant bit.
endmodule // ripple_carry_adder_subtractor
module full_adder(S, Cout, A, B, Cin);
output S;
output Cout;
input A;
input B;
input Cin;
wire w1;
wire w2;
wire w3;
wire w4;
xor(w1, A, B);
xor(S, Cin, w1);
and(w2, A, B);
and(w3, A, Cin);
and(w4, B, Cin);
or(Cout, w2, w3, w4);
endmodule // full_adder
module tb_U2_add_sub;
reg [3:0] A;
reg [3:0] B;
wire [3:0] S;
reg Op;
wire V;
integer i, j;
ripple_carry_adder_subtractor U2AS(.A(A), .B(B), .S(S), .Op(Op), .V(V));
always #* if (V == 1) $display($time, " overflow");
initial begin
Op = 0; // Op = 0 ->adder; Op = 1 ->subtractor
for (i=0; i<16; i=i+1) begin
for (j=0; j<16; j=j+1) begin
A = i;
B = j;
#10;
end
end
end
endmodule
You can calculate expected values at testbench and compare them with calculated results from your module. If they are not same, you will now there is an error. In your case,
module tb_U2_add_sub;
reg [3:0] A;
reg [3:0] B;
wire [3:0] S;
reg Op;
wire V;
integer i, j;
ripple_carry_adder_subtractor U2AS(.A(A), .B(B), .S(S), .Op(Op), .V(V));
reg [3:0] S_exp; // expected S value
reg V_exp; // expected V value
initial begin
Op = 0; // Op = 0 ->adder; Op = 1 ->subtractor
for (i=0; i<16; i=i+1) begin
for (j=0; j<16; j=j+1) begin
A = i;
B = j;
// Calculate expected values
S_exp = i+j;
V_exp = (A[3]&B[3]&(~S_exp[3])) | ((~A[3])&(~B[3])&S_exp[3]);
#10;
// Compare expected values with calculated values
if ((S_exp[3:0] !== S) || (V_exp !== V)) begin
// if there is an error, display it and stop simulation
$display("Failed for A=%d,B=%d.\n",A,B);
$stop();
end
end
end
// if there is no error, you will see "Passed"
$display("Passed");
end
endmodule

8 bit carry lookahead adder error with SystemVerilog in Questasim using two 4 CLA's

I keep getting an error when I simulate the CLA4Top, CLA8Top and the test.
The testbench was given and the entire project compiles. For the CLA4Top I thought it looked like "cout" is coming out to be correct but "sum" is not matching the expected outputs. I changed that and this is the updated code:
Here is the CLA4Top.sv
//4 bit carry lookahead adder
module CLA4Top(ain, bin, cin, sum, cout);
//parameter nBITS = 4;
//logic [nBITS - 1 : 0] ain, bin, sum;
//logic cin, cout;
input [3:0] ain, bin;
input cin;
output logic [3:0] sum;
output logic cout;
CLA4Bit C1(.*);
test #(4) TB(.*);
endmodule
module CLA4Bit (ain, bin, cin, sum, cout);
timeunit 1ns/1ns;
input [3:0] ain, bin;
input cin;
output logic [3:0] sum;
output logic cout;
wire p0,p1,p2,p3,g0,g1,g2,g3,c1,c2,c3,c4,c0;
assign p0=(ain[0]^bin[0]),
p1=(ain[1]^bin[1]),
p2=(ain[2]^bin[2]),
p3=(ain[3]^bin[3]);
assign g0=(ain[0]&bin[0]),
g1=(ain[1]&bin[1]),
g2=(ain[2]&bin[2]),
g3=(ain[3]&bin[3]);
assign c0=cin,
c1=g0|(p0&cin),
c2=g1|(p1&g0)|(p1&p0&cin),
c3=g2|(p2&g1)|(p2&p1&g0)|(p1&p1&p0&cin),
c4=g3|(p3&g2)|(p3&p2&g1)|(p3&p2&p1&g0)|(p3&p2&p1&p0&cin);
assign sum[0] = ain[0] ^ bin[0] ^ cin,
sum[1] = ain[1] ^ bin[1] ^ c1,
sum[2] = ain[2] ^ bin[2] ^ c2,
sum[3] = ain[3] ^ bin[3] ^ c3;
assign cout=c4;
endmodule
Here is the CLA8Top.sv
// module with 8 bit adder using 4 bit CLA instances
module CLA8Top(ain, bin, cin, sum, cout);
//parameter nBITS = 8;
input [7:0] ain, bin;
input cin;
output logic [7:0] sum;
output logic cout;
wire c1;
// CLA4Bit c11(ain[3:0],bin[3:0],1'b0,sum[3:0],c1);
CLA4Bit c11(ain[3:0],bin[3:0],cin,sum[3:0],c1);
CLA4Bit c22(ain[7:4],bin[7:4],c1,sum[7:4],cout);
test #(8) TB(.*);
endmodule
And this is the testbench.sv
// Test bench for Generic N-Bits Adder design module
module test(ain, bin, cin, sum, cout);
timeunit 1ns/1ns;
parameter nBITS = 4;
parameter DELAY = 100;
input [nBITS - 1 : 0] sum;
input cout;
output [nBITS - 1 : 0] ain, bin;
output cin;
logic [nBITS - 1 : 0] ain, bin, sum;
logic cin, cout;
// test variables
logic [nBITS : 0] exp_value;
int i, j, test_count;
bit error;
initial begin
error = 0;
test_count = 0;
cin = 0;
repeat(2) begin
for(i = 0; i < (1 << nBITS); i++) begin
ain = i;
for(j = 0; j < (1 << nBITS); j++) begin
test_count++;
bin = j;
exp_value = ain + bin + cin;
#DELAY;
if({cout, sum} !== exp_value) begin
$display("For inputs: ain = %b, bin = %b, cin = %b :: Actual outputs: cout = %1b, sum = %b :: Expected outputs: cout = %1b, sum = %b", ain, bin, cin, cout, sum, exp_value[nBITS], exp_value[nBITS-1:0]);
error = 1;
end // end for if block
end // end for j for loop
end // end for i for loop
cin = ~cin;
end // end for repeat block
if(error === 0)
$display("***Congratulations, No errors found after %d tests***", test_count);
else
$display("***Sorry, errors found in your code ***");
end // end for initial block
endmodule
Is there any changes that I can make that would give me the $display("***Congratulations, No errors found after %d tests***", test_count); that you can see? What problems am I having and why? I will include the transcript from running the CLA4Top.sv.
The log file shows that sum[3] mismatches the expected value. There is a typo in the equation for c3. Change:
c3=g2|(p2&g1)|(p2&p1&g0)|(p1&p1&p0&cin),
//
to:
c3=g2|(p2&g1)|(p2&p1&g0)|(p2&p1&p0&cin),
//

Error using for loop [procedural assignment to a non-register i is not permitted]

I'm not really experienced with Verilog. I'm trying to make an RCA using a for loop but I'm getting an error when trying to synthesize the modules.
The error I'm getting is
procedural assignment to a non-register i is not permitted
//1-bit full adder
module fadder (s, cout, a, b, cin);
input a, b, cin;
output s, cout;
assign s = (a ^ b) ^ cin;
assign cout = ((a & b) | ((a | b) & cin));
endmodule
//RCA Logic
module part1(s, cout, a, b, cin, clk);
parameter BIT_WIDTH = 128;
input [BIT_WIDTH-1:0] a, b;
input cin;
input clk;
output cout;
output [BIT_WIDTH-1:0] s;
wire [BIT_WIDTH:0] cin_wire;
assign cin_wire[0] = cin;
genvar i;
generate
always#(posedge clk)
begin
for(i = 0; i <= BIT_WIDTH-1; i = i + 1) //error is on this line
begin:
fadder fadder_inst (.s(s[i]), .cout(cin_wire[i+1]), .a(a[i]), .b(b[i]), .cin(cin_wire[i]));
end
end
endgenerate
assign cout = cin_wire[BIT_WIDTH];
endmodule
Any help is appreciated. Thanks
generate
for(i = 0; i <= BIT_WIDTH-1; i = i + 1)
begin
fadder fadder_inst (.s(s[i]), .cout(cin_wire[i+1]), .a(a[i]), .b(b[i]), .cin(cin_wire[i]));
end
endgenerate
You can not generate the modules inside always block.
You have to seperately manipulate input inside always block before connecting to fadder_inst.
What I guess is, RCA is not clock dependent. Its purly asynchronous circuit.
You cannot instantiate a module inside a procedural block (initial,
always, always_comb, always_ff, always_latch, final, task, function).
You can do like following to serve your purpose.
module fadder (clk, s, cout, a, b, cin);
input a, b, cin, clk;
output reg s, cout;
always # (posedge clk)
begin
s = (a ^ b) ^ cin;
cout = ((a & b) | ((a | b) & cin));
end
endmodule
//RCA Logic
module part1(s, cout, a, b, cin, clk);
parameter BIT_WIDTH = 128;
input [BIT_WIDTH-1:0] a, b;
input cin;
input clk;
output cout;
output [BIT_WIDTH-1:0] s;
wire [BIT_WIDTH:0] cin_wire;
assign cin_wire[0] = cin;
genvar i;
generate
begin
for(i = 0; i <= BIT_WIDTH-1; i = i + 1) //error is on this line
begin:
fadder fadder_inst (.clk(clk), .s(s[i]), .cout(cin_wire[i+1]), .a(a[i]), .b(b[i]), .cin(cin_wire[i]));
end
end
endgenerate
assign cout = cin_wire[BIT_WIDTH];
endmodule
As others have pointed out, you cannot instantiate modules inside an always block. The need to be separated and a new wire needs to be created to connect the two.
In the below example cout and s are reg type outputs. There is an added wire s_wire (following your naming convention based cin_wire) which is connected to the s output of the fadder_inst instances. part1's s and cout output is synchronously assigned to s_wire and cin[BIT_WIDTH] respectivly. Note that they are assigned with non-blocking assignments (<=).
// ...
output reg cout;
output reg [BIT_WIDTH-1:0] s;
wire [BIT_WIDTH-1:0] s_wire;
wire [BIT_WIDTH:0] cin_wire;
assign cin_wire[0] = cin;
genvar i;
generate
for(i = 0; i <= BIT_WIDTH-1; i = i + 1)
begin
fadder fadder_inst (.s(s_wire[i]), .cout(cin_wire[i+1]), .a(a[i]), .b(b[i]), .cin(cin_wire[i]));
end
endgenerate
always#(posedge clk)
begin
s <= s_wire;
cout <= cin_wire[BIT_WIDTH];
end
// ...

Why isn't my test bench working?

I decided to start playing around with Verilog this weekend. I am really new to this and don't entirely understand what I am doing. I copied this adder code out of a PDF tutorial. The issue is that the tutorial does not give any test code to run it with. I tried to write my own but the output I am getting is zzzz. I am thinking that maybe it is trying to produce the output before the addition function has finished executing.
module addbit(a, b, ci, sum, co);
input a, b, ci;
output sum, co;
wire a, b, ci, sum, co;
assign {co, sum} = a + b + ci;
endmodule
module adder(result, carry, r1, r2, ci);
input [3:0] r1;
input [3:0] r2;
input ci;
output [3:0] result;
output carry;
wire [3:0] r1;
wire [3:0] r2;
wire ci;
wire [3:0] result;
wire carry;
wire c1, c2, c3;
addbit u0(r1[0], r2[0], ci, result[0], c1);
addbit u1(r1[1], r2[1], c1, result[0], c2);
addbit u2(r1[2], r2[2], c2, result[0], c3);
addbit u3(r1[3], r2[3], c3, result[0], carry);
endmodule
module test();
wire [3:0] a = 4'b1000;
wire [3:0] b = 4'b0100;
wire [3:0] result;
wire carry = 0;
wire ocarry;
adder x(result, ocarry, a, b, carry);
initial begin
$display("%b", result);
end
endmodule
the output I am getting is zzzz
The reason why you are getting an output zzzz is from your adder circuit (see mcleod_ideafix's comment below).
You might want to change you're input type of a and b as reg type so you can assign them inside a procedural block and assign them with different values.
module test();
reg [3:0] a = 4'b1000;
reg [3:0] b = 4'b0100;
wire [3:0] result;
wire carry = 0;
wire ocarry;
adder x(result, ocarry, a, b, carry);
initial begin
$display("# %0dns a: %0d b: %0d result: %0d", $time, a, b, result);
#1ns;
a = 5;
b = 6;
$display("# %0dns a: %0d b: %0d result: %0d", $time, a, b, result);
end
endmodule
Using the RTL that you posted and the test bench I modified above, it will produce an output:
# 0ns a: 8 b: 4 result: X
# 1ns a: 5 b: 6 result: X
You're adder does not work as expected for an adder circuit.
To help you further, I created an adder circuit for you.
module adder(result, carry, r1, r2, ci);
input [3:0] r1;
input [3:0] r2;
input ci;
output [3:0] result;
output carry;
assign {carry, result} = r1 + r2 + ci;
endmodule
And a working test bench that initializes the input to 0 then loops 10 times. Inside the loop, we create a delay of 1ns and changes the input to a random value from 0 to 15.
module test();
reg [3:0] a;
reg [3:0] b;
wire [3:0] result;
wire carry = 0;
wire ocarry;
adder x(result, ocarry, a, b, carry);
initial begin
$monitor("#%0dns [a: %0d] + [b: %0d] = [result: %0d] [carry = %0d] [ocarry = %0d] ", $time, a, b, result, carry, ocarry);
end
initial begin
a = 0;
b = 0;
repeat (10) begin
#1ns;
a = $random % 'h10;
b = $random % 'h10;
end
end
endmodule
You can run this code in edaplayground and see the output.
For every change of a, b, result, carry, ocarry, this code is executed.
$monitor("#%0dns [a: %0d] + [b: %0d] = [result: %0d] [carry = %0d] [ocarry = %0d] ", $time, a, b, result, carry, ocarry);

Resources