Trouble with 8-bit Carry Lookahead Adder in Verilog - verilog

I'm new to Verilog programming. I'm trying to put together an 8-bit Carry Lookahead Adder as a step toward building a 64-bit CLA. Basically, the way I implemented it is I use 2 4-bit CLA "blocks" to create the 8-bit CLA. I'll provide my code, then an explanation of the problem I'm having.
Code below:
// 4-BIT CLA CODE
module CLA4Bit(A, B, carryIn, carryOut, PG, GG, Sum);
input[3:0] A, B;
input carryIn;
output carryOut;
output PG;
output GG;
output[3:0] Sum;
wire[3:0] G, P, C;
assign G = A & B;
assign P = A ^ B;
assign Sum = P ^ C;
assign C[0] = carryIn;
assign C[1] = G[0] | (P[0] & C[0]);
assign C[2] = G[1] | (P[1] & G[0]) | (P[1] & P[0] & C[0]);
assign C[3] = G[2] | (P[2] & G[1]) | (P[2] & P[1] & G[0]) | (P[2] & P[1] & P[0] & C[0]);
assign PG = P[3] & P[2] & P[1] & P[0];
assign GG = G[3] | (P[3] & G[2]) | (P[3] & P[2] & G[1]) | (P[3] & P[2] & P[1] & G[0]);
endmodule
// 8-BIT CLA CODE BELOW
module CLA8Bit(A, B, carryIn, carryOut, Sum);
// 8-bit wire for the inputs A and B
input[7:0] A, B;
// Wire for the ORIGINAL carry-in
input carryIn;
// Wire for the carryOut
output carryOut;
// Wire that carries the Sum of this CLA
output[7:0] Sum;
// Wires for the propagate of the first 4-bit block (p3)
// and the second (p7)
wire p3, p7;
// Wires for the generate of the first 4-bit block (g3)
// and the second (g7)
wire g3, g7;
// Wires for the carry of the first block (c3) and the
// second (c7)
wire c3, c7;
// The two 4-bit CLA blocks that make up the 8-bit CLA
CLA4Bit block1(A[3:0], B[3:0], carryIn, c3, p3, g3, Sum[3:0]);
CLA4Bit block2(A[7:4], B[7:4], c3, c7, p7, g7, Sum[7:4]);
endmodule
I wrote a basic testbench to test my code:
module CLA_TB();
// TEST THE 8-BIT CLA
// Inputs
reg[7:0] A;
reg[7:0] B;
reg carryIn;
// Outputs
wire carryOut;
wire[7:0] Sum;
wire PG;
wire GG;
// Instantiate the 8-bit CLA
CLA8Bit CLA8BitDUT (
.A(A),
.B(B),
.carryIn(carryIn),
.carryOut(carryOut),
.Sum(Sum)
);
// Initialize the testbench signals
initial
begin
// Start with the carryIn set to 0
assign carryIn = 0;
// The standard first test. Set
// A = b0000 0001 and B = b0000 0001
// Answer should be Sum = b0000 0010
assign A = 8'b00000001;
assign B = 8'b00000001;
#20
// Next, set A = b0001 1011 and
// B = b1101 0111. Answer should
// be Sum = b1111 0010 = hF2.
assign A = 8'b00011011;
assign B = 8'b11010111;
#20
// Finally, try setting the carryIn
// to 1 and then test A = b0111 1011
// and B = b1101 0011. Answer should be
// Sum = 0100 1111 w/ overflow carry
assign carryIn = 1'b1;
assign A = 8'b01111011;
assign B = 8'b11010011;
#20
$finish;
end
endmodule
So the problem is, in my simulations of the testbench (I use ModelSim), the first 4 bits of the Sum (which correspond to the first 4-bit CLA instance in the 8-bit CLA module) are given as X in the Wave page. The second 4 bits add just fine, though.
After doing some research, I found out that X's are displayed in Verilog when a wire has more than one driver (source of the signal?). However, I don't see any place where I send more than one signal to my first 4-Bit CLA instance in the 8-Bit CLA module. Also, if something like that were the cause, then I don't know why it wouldn't happen to the second set of 4 bits as well, since both the 4-bit CLAs are set up very similarly.
Why is this happening?

X's are displayed in Verilog when a wire has more than one driver
That is true but it is only part of the story. There are other cases which produce X'es:
If a reg is not given a value it will be X.
If a Z is used in an expression it will produce an X .
Your waveform has some obvious 'Z' (blue) lines one it.
If you following the signals back to where they originate: your 4-bit adder never assigns a value to carryOut.
Then you make the same error in CLA8Bit.
If you see a 'Z' in a simulation: jump on it! 99.9% of the time you have an wire which has not been given a value!

Related

In Verilog, what is the pragma directive to inform a simulator / synthesizer to throw an error for undefined netlists? [duplicate]

I have to make a 64 Bit ALU that takes in A and B 64-bit inputs, a carry_in input and outputs a 64bit result along with a 1-bit carry_out. There is also a 5 bit function-select FS. Where FS[0] controls whether B is inverted or not (using a 2to1 mux.) F[1] does the same for the A. And FS[4:2] determines which operation (Adding, subtracting, logical operations, etc) using an 8to1 Mux. Below is the code for the ALU and Testbench.
I'm pretty sure my testbench is good and so is all the separate components for the ALU. I'm not too confident about my top-level where I instantiate and connect all the inputs/outputs. What is causing the high impedance in the waveform?
module ALU(A, B, FS, cin, cout, result);
input [63:0] A, B;
input [4:0] FS;
input cin;
output cout;
output [63:0] result;
eight_one_mux u7 (firstoutA & secoutB, firstoutA | secoutB, sum, firstoutA ^ secoutB,
left, right, 1'b0, 1'b0, FS[4:2], result);
adder u6 (firstoutA, secoutB, cin, sum, cout);
firstmux u1 (A, !A, FS[1], firstoutA);
secmux u2 (B, !B, FS[0], secoutB);
Alu_shifter u5 (A, left, right);
endmodule
//--------------------------------------------------------------------------------//
//These are the two muxes to split into input and inverted input A,B
module firstmux(a, nota, firstS, firstoutA);
input [63:0] a, nota;
input firstS;
output reg [63:0] firstoutA;
always #(a or nota or firstS)
begin
case(firstS)
0 : firstoutA = a;
1 : firstoutA = nota;
default : firstoutA = 1'bx;
endcase
end
endmodule
//<><><><><><><>//
module secmux(b, notb, secS, secoutB);
input [63:0] b, notb;
input secS;
output reg [63:0] secoutB;
always #(b or notb or secS)
begin
case(secS)
0 : secoutB = b;
1 : secoutB = notb;
default : secoutB = 1'bx;
endcase
end
endmodule
//--------------------------------------------------------------------------------//
//This is the Shifter Blocks
module Alu_shifter (shiftA, right, left); //This shifter block shifts the A input once right or left
input [63:0] shiftA;
output [63:0] right;
output [63:0] left;
shift_right w1 ( //instantiate right shifter block
.a_R(shiftA),
.R(right)
);
shift_left w2 ( //instantiate left shifter block
.a_L(shiftA),
.L(left)
);
endmodule
////////><><><><><><><><><><><><><><><///////
module shift_right (a_R, R); // right shifter block
input [63:0] a_R;
output [63:0] R;
assign R = a_R >> 1; //shift A right once (shift in a 0)
endmodule
module shift_left (a_L, L); //left shifter block
input [63:0] a_L;
output [63:0] L;
assign L = a_L << 1; //shift A left once (shift in a 0)
endmodule
//End shifter blocks (3 total modules)
//----------------------------------------------------//////////////////////
//This is the Adder that Adds A, B and cin
module adder(addA, addB, nic, sum, cout);
input [63:0] addA, addB;
input nic;
output [63:0] sum;
output cout;
assign {cout, sum} = addA + addB + nic;
endmodule
//----------------------------------------------------//////////////////////
//This is the 8to1 Mux that decides which operation is put forward
module eight_one_mux(D0, D1, D2, D3, D4, D5, D6, D7, S, out);
input [63:0] D0, D1, D2, D3, D4, D5, D6, D7;
input [2:0] S;
output reg [63:0] out;
always #(D0 or D1 or D2 or D3 or D4 or D5 or D6 or D7 or S)
begin
case(S)
0 : out = D0; //And
1 : out = D1; //Or
2 : out = D2; //Adder
3 : out = D3; //xor
4 : out = D4; //lefter
5 : out = D5; //righter
6 : out = D6; //GND
7 : out = D7; //GND
default : out = 1'bx;
endcase
end
endmodule
////////////-------------------------------////////////////////////////////
module ALU_tb();
reg [63:0] A, B;
reg [4:0] FS;
reg cin;
wire cout;
wire [63:0] result;
ALU dut (
.A(A),
.B(B),
.FS(FS),
.cin(cin),
.cout(cout),
.result(result)
);
initial begin
A = 8'b11001100;
B = 8'b11001101;
FS = 5'b01101;
cin = 1;
end
always
#5 cin <= ~cin;
always begin
#5
A <= A + 1;
B <= B + 2;
#5;
end
initial begin
#100 $finish;
end
endmodule
```
Unexpected high impedance (z) values are typically the result of undriven signals, and that is the problem with your code.
adder u6 (firstoutA, secoutB, cin, sum, cout);
In the line above, you connect the 1-bit signal firstoutA to the 64-bit addA input port. This connects firstoutA to addA[0], leaving the other 63 bits undriven. Thus, addA[63:1] are all z.
firstoutA is a 1-bit signal because you did not explicitly declare it. Also, undeclared signals are assumed to be of type wire, which default to z.
It is good practice to declare all signals.
To find all undeclared signals, add this to the top of your code:
`default_nettype none
You should get compile errors like:
Error-[IND] Identifier not declared
Identifier 'firstoutA' has not been declared yet. If this error is not
expected, please check if you have set `default_nettype to none.
Error-[IND] Identifier not declared
Identifier 'secoutB' has not been declared yet. If this error is not
expected, please check if you have set `default_nettype to none.
First you need to define signals (wire) for connections between modules. For example, you have left and right as outputs of Alu_shifter module and they are connected to firstmux and secmux modules; however, they are not defined in your top module. You should add following signal definitions to your topmodule:
wire [63:0] left,right;
wire [63:0] firstoutA;
wire [63:0] secoutB;
wire [63:0] sum;
Also, eight_one_mux module takes eight 64-bit inputs. However, you set the last two of them as 1'b0. You should change them to 64'b0 as below.
eight_one_mux u7 (firstoutA & secoutB, firstoutA | secoutB, sum, firstoutA ^ secoutB,
left, right, 64'b0, 64'b0, FS[4:2], result);
Finally, !A does not invert all bits of A (same for B). It applies a reduction operation and generates a 1-bit signal (and firstmux module expects a 64-bit signal in its second input port).

For instance uut/A1/, width 1 of formal port S is not equal to width 4 of actual signal in1

Can anyone tell why I am getting these warnings?
For instance uut/A1/, width 1 of formal port S is not equal to width 4
of actual signal in1.
For instance uut/A1/, width 1 of formal port Cout is not equal to
width 4 of actual signal in2.
For instance uut/A1/, width 1 of formal port A is not equal to width 4
of actual signal s1.
For instance uut/A2/, width 1 of formal port S is not equal to width 4
of actual signal in3.
For instance uut/A2/, width 1 of formal port Cout is not equal to
width 4 of actual signal in4.
For instance uut/A2/, width 1 of formal port A is not equal to width 4
of actual signal s2.
module binary(A,B,P);
input [2:0]A;
input [3:0]B;
output [6:0]P;
wire c1,c2;
wire [3:0]s1,in1,in2,in3,in4,s2;
assign in1[0] = A[0] & B[1];
assign in1[1] = A[0] & B[2];
assign in1[2] = A[0] & B[3];
assign in2[0] = A[1] & B[0];
assign in2[1] = A[1] & B[1];
assign in2[2] = A[1] & B[2];
assign in2[3] = A[1] & B[3];
assign in3[0] = A[2] & B[0];
assign in3[1] = A[2] & B[1];
assign in3[2] = A[2] & B[2];
assign in3[3] = A[2] & B[3];
FA A1(in1,in2,s1,c1);
assign in4[0] = s1[1];
assign in4[1] = s1[2];
assign in4[2] = s1[3];
assign in4[3] = c1;
FA A2(in3,in4,s2,c2);
assign P[0] = A[0] & B[0];
assign P[1] = s1[0];
assign P[2] = s2[0];
assign P[3] = s2[1];
assign P[4] = s2[2];
assign P[5] = s2[3];
assign P[6] = c2;
endmodule
module FA(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
You declared the S output port of the FA module as a 1-bit signal:
module FA(S, Cout, A, B, Cin);
output S;
Inside module binary, you declared in1 as a 4-bit signal:
wire [3:0]s1,in1,
Then you connected a 4-bit signal (in1) to a 1-bit port (S):
// S
FA A1(in1,in2,s1,c1);
Since this is an unusual thing to do, your tool is doing the correct thing by issuing a warning message.
The width of the signal should match the width of the port. Based on your design requirements, you must decide which bit of in1 to connect to S. For example,
FA A1(in1[0],in2,s1,c1);
The same applies for the other warnings as well.

16 -bit CLA instantiation

DO I need anything else to make a 16bit CLA ??????
so far I instantiated 4 (4 bit CLA to make a 16 bit CLA)
but I think I am missing about the carry I just don't understand how to add it to what I have since the 8 bit CLA was just instantiating 2 (4 bit CLA) I don't understand why can't just instantiate 4 (4 bit CLA together to get 16 bit CLA). Can someone help me figure out how to complete the 16bit CLA?
//CLA16Top.sv
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;
logic [3:0] G,P,C;
// Carry propagate
assign P = ain ^ bin;
//Carry generate
assign G = ain & bin;
// Calculating each stage of the carry out
assign C[0] = cin;
assign #4 C[1] = (G[0] | (C[0] & P[0]));
assign #6 C[2] = (G[1] | (G[0] & P[1]) | (C[0] & P[1] & P[0]));
assign #8 C[3] = (G[2] | (G[1] & P[2]) | (G[0] & P[1] & P[2]) | (C[0] &
P[2] & P[1] & P[0]));
assign sum = P ^ C;
assign #13 cout= (G[3] | (G[2]&P[3]) | (G[1]&P[2]&P[3]) |
(G[0]&P[1]&P[2]&P[3]) | (C[0]&P[0]&P[1]&P[2]&P[3]));
endmodule
/*
module CLA16Top;
timeunit 1ns/1ns;
parameter nBITS = 16;
logic [nBITS - 1 : 0] ain, bin, sum;
logic in;
logic cout;
logic c4, c8, c12, c16;
assign cout = c16;
// instantiating the 16 bit CLA
CLA4Bit uut1(
.ain(ain[3:0]),
.bin(bin[3:0]),
.cin(cin),
.sum(sum[3:0]),
.cout(c4)
);
CLA4Bit uut2(
.ain(ain[7:4]),
.bin(bin[7:4]),
.cin(c4),
.sum(sum[7:4]),
.cout(c8)
);
CLA4Bit uut3(
.ain(ain[11:8]),
.bin(bin[11:8]),
.cin(c8),
.sum(sum[11:8]),
.cout(c12)
);
CLA4Bit uut4(
.ain(ain[15:12]),
.bin(bin[15:12]),
.cin(c12),
.sum(sum[15:12]),
.cout(c16)
);
// SIMULATE (CLA16Top)
//
test #(16) TB(.*);
endmodule: CLA16Top
I get compile errors in your test module. Change:
output in;
to:
output cin;
Also, the double-quoted string must be on one line:
$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,
test_count could be too big to fit into an int variable. Use real and %g:
real test_count;
$display("***Congratulations, No errors found after %g tests***", test_count);
After those changes, the code compiles and runs for me. It took about 2 hours before the nested loops completed, and only the final message displays:
***Congratulations, No errors found after 8.58993e+09 tests***
This indicates that the adder works properly.
If you want to see more intermediate results, add more displays in the loops.
Note: The test module code was removed from the Question after I posted this Answer.

Verilog not displaying the correct results for 8-bit adder

I am having some trouble displaying the result of my 8 bit adder verilog
module Adder(a,b,cin,s,co);
input [7:0]a;
input [7:0]b;
output [7:0]s;
output co;
wire [6:0] u;
input cin;
Carry c1(a[0],b[0],cin,s[0],u[0]);
Carry c2(a[1],b[1],u[0],s[1],u[1]);
Carry c3(a[2],b[2],u[1],s[2],u[2]);
Carry c4(a[3],b[3],u[2],s[3],u[3]);
Carry c5(a[4],b[4],u[3],s[4],u[4]);
Carry c6(a[5],b[5],u[4],s[5],u[5]);
Carry c7(a[6],b[6],u[5],s[6],u[6]);
Carry c8(a[7],b[7],u[6],s[7],co);
endmodule
module Carry(a,b,cin,s,co);
input wire a;
input wire b;
input wire cin;
output wire co;
output wire s;
assign co = (a & b) | (b & cin) | (a & cin);
assign s = (~a & ~b & cin) | (~a & b & ~cin) | (a & ~b & ~cin)| (a & b & cin);
endmodule
module testbench;
reg [7:0]a;
reg [7:0]b;
reg cin;
wire [7:0]s;
wire co;
Adder add(a, b, cin, s, co);
initial begin
$dumpfile("result.vcd");
$dumpvars;
a <= 00000010; b <= 00000010; cin <= 0;
#5
$monitor("time=%4d: %b + %b + %b: sum = %b, carry = %b\n",$time,a,b,cin,s,co);
end
endmodule
although it adds everything correctly, it's not adding the numbers I originally wanted.
time= 5: 00001010 + 00001010 + 0: sum = 00010100, carry = 0
How can i fix it so that instead of adding those numbers, it would add the numbers i'd want.
(a = 00000010; b = 00000010; cin = 0;)
I already tried changing the numbers around and it does not work except when they're 00000001.
By default, Verilog interprets a numerical literal value as decimal. The value 00000010 is decimal 10. The $monitor statement uses %b, and it correctly displays the decimal value 10 as 1010. The sum of 10 + 10 is 20 (decimal), which is correctly displayed as 10100 (binary).
For Verilog to interpret 00000010 as binary, you need to specify the base as 'b00000010:
a <= 'b00000010; b <= 'b00000010; cin <= 0;
Refer to IEEE Std 1800-2012, section 5.7.1 Integer literal constants.
The reason that 1 + 1 works is that 1 is the special case where 00000001 (decimal) is the same value as 'b00000001 (binary).

Using created ALU to make a bigger one

I have a 8-bit ALU unit in verilog that can do addition, invert, etc. This single unit is tested and performs correctly. When I combine 4 of these to make a bigger ALU every output is correct except when I choose the addition operation it comes out as
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx01010101, basically the first alu does the work right then the output from the second is xxxxxxxx as is the third and fourth. This is really frustrating!!
the 8 bit module( it would be nice to point if this model is behavioral or structural model i go for the former!)
module alu_8bit(
output reg [7:0] out,
output reg cout,g,e,
input [7:0] A,B,
input cin,
input [2:0] S
);
//used functions
parameter BUF_A = 3'b000;
parameter NOT_A = 3'b001;
parameter ADD = 3'b010;
parameter OR = 3'b011;
parameter AND = 3'b100;
parameter NOT_B = 3'b101;
parameter BUF_B = 3'b110;
parameter LOW = 3'b111;
always #(A or B or S) begin
//Comparator
g = A>B;
e = A==B;
//Other selective functions
case(S)
BUF_A: out = A;
NOT_A: out = ~A;
ADD: {cout,out} = A+B+cin;
OR: out = A | B;
AND: out = A & B;
NOT_B: out = ~B;
BUF_B: out = B;
LOW: out = {8{1'b0}};
endcase
end
endmodule
Here is the code of the bigger one:
module alu_32bit(
output [31:0] out,
output cout,g,e,
input [31:0] A,B,
input cin,
input [2:0] S
);
wire e1,e2,e3,e4;
wire g1,g2,g3,g4;
alu_8bit ALU1(out[7:0],cin2,g1,e1,A[7:0],B[7:0],cin,S);
alu_8bit ALU2(out[15:8],cin3,g2,e2,A[15:8],B[15:8],cin2,S);
alu_8bit ALU3(out[23:16],cin4,g3,e3,A[23:16],B[23:16],cin3,S);
alu_8bit ALU4(out[31:24],cout,g4,e4,A[31:24],B[31:24],cin4,S);
assign g = g4 | (e4 & g3) |(e4 & e3 & g2) | (e4& e3 & e2 & g1);
assign e = e4 & e3 & e2 & e1;
endmodule
Can any one give some help?! if you need more info just tell me.
Edited:
Waveform pic clearly input comes in correct but output not
The dataflow diagram shows that ALU1 output is just fine
Your sensitivity list for the main part of the ALU doesn't include cin.

Resources