Displaying "X" for output results? - verilog

8-Bit CLA Adder:
module cla8(a, b, cin, sum, cout);
input [7:0] a;
input [7:0] b;
input cin;
output [7:0] sum;
output cout;
wire p0, g0, p1, g1, p2, g2, p3, g3, p4, g4, p5, g5, p6, g6, p7, g7;
wire c8, c7, c6, c5, c4, c3, c2, c1;
assign p0 = a[0] ^ b[0];
assign p1 = a[1] ^ b[1];
assign p2 = a[2] ^ b[2];
assign p3 = a[3] ^ b[3];
assign p4 = a[4] ^ b[4];
assign p5 = a[5] ^ b[5];
assign p6 = a[6] ^ b[6];
assign p7 = a[7] ^ b[7];
assign g0 = a[0] & b[0];
assign g1 = a[1] & b[1];
assign g2 = a[2] & b[2];
assign g3 = a[3] & b[3];
assign g4 = a[4] & b[4];
assign g5 = a[5] & b[5];
assign g6 = a[6] & b[6];
assign g7 = a[7] & b[7];
assign c0 = cin;
assign c1 = g0|(p0 & c0);
assign c2 = g1|(p1 & g0)|(p1 & p0 & c0);
assign c3 = g2|(p2 & g1)|(p2 & p1 & g0)|(p2 & p1 & p0 & c0);
assign c4 = g3|(p3 & g2)|(p3 & p2 & g1)|(p3 & p2 & p1 & g0)|(p3 & p2 & p1 & p0 & c0);
assign c5 = g4|(p4 & g3)|(p4 & p3 & g2)|(p4 & p3 & p2 & g1)|(p4 & p3 & p2 & p1 & g0)| (p4 & p3 & p2 & p1 & p0 & c0);
assign c6 = g5|(p5 & g4)|(p5 & p4 & g3)|(p5 & p4 & p3 & g2)|(p5 & p4 & p3 & p2 & g1)| (p5 & p4 & p3 & p2 & p1 & g0)|(p5 & p4 & p3 & p2 & p1 & p0 & c0);
assign c7 = g6|(p6 & g5)|(p6 & p5 & g4)|(p6 & p5 & p4 & g3)|(p6 & p5 & p4 & p3 & g2)| (p6 & p5 & p4 & p3 & p2 & g1)|(p6 & p5 & p4 & p3 & p2 & p1 & g0)| (p6 & p5 & p4 & p3 & p2 & p1 & p0 & c0);
assign c8 = g7|(p7 & g6)|(p7 & p6 & g5)|(p7 & p6 & p5 & g4)|(p7 & p6 & p5 & p4 & g3)| (p7 & p6 & p5 & p4 & p3 & g2)|(p7 & p6 & p5 & p4 & p3 & p2 & g1)| (p7 & p6 & p5 & p4 & p3 & p2 & p1 & g0)|
(p7 & p6 & p5 & p4 & p3 & p2 & p1 & p0 & c0);
assign sum[0] = p0 ^ c0;
assign sum[1] = p1 ^ c1;
assign sum[2] = p2 ^ c2;
assign sum[3] = p3 ^ c3;
assign sum[4] = p4 ^ c4;
assign sum[5] = p5 ^ c5;
assign sum[6] = p6 ^ c6;
assign sum[7] = p7 ^ c7;
assign cout = c8;
endmodule
TestBench
module cla8bit_testbench;
reg[7:0] a;
reg[7:0] b;
reg cin;
wire [7:0] sum;
wire cout;
cla8 uut(.a(a),
.b(b),
.cin(cin),
.sum(sum),
.cout(cout));
initial begin
$dumpfile("dump.vcd");
$dumpvars(1);
//With Carry
a = 8'b11110000;
b = 8'b11001100;
cin = 0;
$display("In the case involving carry, For A = %8b, B = %8b, and Cin = %1d: the Sum will be %8b and Cout will be %1d.", a, b, cin, sum, cout);
#20
$display("In the case without involving carry, For A = %8b, B = %8b, and Cin = %1d: the Sum will be %8b and Cout will be %1d.", a, b, cin, sum, cout);
//Without Carry
a = 8'b11110000;
b = 8'b00001101;
cin = 0;
#100;
end
endmodule
Results showed
# KERNEL: In the case involving carry, For A = xxxxxxxx, B = xxxxxxxx, and Cin = x: the Sum will be xxxxxxxx and Cout will be x.
# KERNEL: In the case without involving carry, For A = 11110000, B = 11001100, and Cin = 0: the Sum will be 10111100 and Cout will be 1.
However, the results are supposed to show:
# KERNEL: In the case involving carry, For A = 11110000, B = 11001100, and Cin = 0: the Sum will be 10111100 and Cout will be 1.
# KERNEL: In the case without involving carry, For A = 11110000, B = 00001101, and Cin = 0: the Sum will be 11111101 and Cout will be 0.

The testbench code has a simulation race condition. The 1st $display statement executes at time 0. Also at time 0 a, b and cin start with their initial value of x because reg types are initialized to x (the unknown value). Again at time 0, you change the values of these 3 signals to known values (a = 8'b11110000, etc.). Since these 3 things occur during the same time step, the result is indeterminate.
One way to get the result you want is to add a delay before the 1st $display statement, such as #1.
A similar reason applies for the 2nd $display statement; to fix that, also add delay. Here is modified code that produces the desired result:
initial begin
$dumpfile("dump.vcd");
$dumpvars(1);
//With Carry
a = 8'b11110000;
b = 8'b11001100;
cin = 0;
#1;
$display("In the case involving carry, For A = %8b, B = %8b, and Cin = %1d: the Sum will be %8b and Cout will be %1d.", a, b, cin, sum, cout);
#20;
//Without Carry
a = 8'b11110000;
b = 8'b00001101;
cin = 0;
#1;
$display("In the case without involving carry, For A = %8b, B = %8b, and Cin = %1d: the Sum will be %8b and Cout will be %1d.", a, b, cin, sum, cout);
#100;
end
Output:
In the case involving carry, For A = 11110000, B = 11001100, and Cin = 0: the Sum will be 10111100 and Cout will be 1.
In the case without involving carry, For A = 11110000, B = 00001101, and Cin = 0: the Sum will be 11111101 and Cout will be 0.
Another approach is to use a single $monitor statement instead of multiple $display statements:
initial begin
$dumpfile("dump.vcd");
$dumpvars(1);
$monitorb(a,, b,, cin,, sum,, cout);
//With Carry
a = 8'b11110000;
b = 8'b11001100;
cin = 0;
#20;
//Without Carry
a = 8'b11110000;
b = 8'b00001101;
cin = 0;
#100;
end
Out:
11110000 11001100 0 10111100 1
11110000 00001101 0 11111101 0
See also $strobe

Related

Verilog Two bit Magnitude comparator

I was trying to write Verilog code of a two bit comparator, but I keep getting errors. Any help?
Error Codes:
10170 Verilog HDL syntax error at two_bitcomparatorVerilog.v(5) near text: ";"; expecting ")"
10170 Verilog HDL syntax error at two_bitcomparatorVerilog.v(7) near text: ";"; expecting ")"
10170 Verilog HDL syntax error at two_bitcomparatorVerilog.v(15) near text: "~"; expecting ")"
Design:
module twobit_comparator(
//assigning inputs
input wire [1:0] A, B;
// assigning outputs
output wire LT, GT, EQ;
// L=Less, G=Greater, E=Equal
);
wire [9:0] s;
//A = B output
assign s0 = (~A[1] & ~A[0] & ~B[1] ~B[0]);
assign s1 = (~A[1] & A[0] & ~B[1] & B[0]);
assign s2 = (A[1] & ~A[0] & B[1] & ~B[0]);
assign s3 = (A[1] & A[0] & b[1] & B[0]);
assign EQ = s0 | s1 | s2 | s3;
//A less than B output
assign s4 = (~A[0]) & (~A[1]) & B[0];
assign s5 = (~A[1]) & B[1];
assign s6 = (~A[0]) & B[1] & B[0];
assign LT = s4 | s5| s6;
// A greater than B output
assign s7 = (~B[0]) & (~B[1]) & A[0];
assign s8 = (~B[1]) & A[1];
assign s9 = (~B[0]) & A[1] & A[0];
assign GT = s7 | s8 | s9;
endmodule
Separate ports with commas, not semicolons, and do not end the port list with a semicolon:
module twobit_comparator(
//assigning inputs
input wire [1:0] A, B,
// assigning outputs
output wire LT, GT, EQ
// L=Less, G=Greater, E=Equal
);
You are missing the & operator; I added it here:
assign s0 = (~A[1] & ~A[0] & ~B[1] & ~B[0]);
// ^
I changed b to B here (Verilog is case-sensitive):
assign s3 = (A[1] & A[0] & B[1] & B[0]);
// ^
I don't get any more compile errors with the changes above. However, you declared signal s, but it is not used. And, you did not declare s0, s1, etc., but you are using them. This works because Verilog allows you to use undeclared wires when they are 1-bit wide. But, you should declare all signals. For example, you could use:
wire [9:0] s;
assign s[0] = (~A[1] & ~A[0] & ~B[1] & ~B[0]);
assign s[1] = (~A[1] & A[0] & ~B[1] & B[0]);

Verilog test bench for 4-bit adder with Carry Lookahead [duplicate]

This question already has answers here:
Can anyone help me to create a Verilog testbench?
(2 answers)
Closed 1 year ago.
I'm still honestly a bit unfamiliar with Verilog especially with test benches, considering I've only created a childishly simple project once. I'm not sure how to make a test bench for a Verilog file I've made and so I can't test if it works. Here's my code:
`timescale 1ns/1ps
module adder_4bit_cla(sum, Cout, A, B, S);
input [3:0] A, B;
input S;
output [3:0] sum;
output Cout;
wire P0, G0, P1, G1, P3, G3;
wire C4, C3, C2, C1;
assign
P0 = A[0] ^ B[0],
P1 = A[1] ^ B[1],
P2 = A[2] ^ B[2],
P3 = A[3] ^ B[3];
assign
G0 = A[0] & B[0],
G1 = A[1] & B[1],
G2 = A[2] & B[2],
G3 = A[3] & B[3];
assign
C1 = G0 | (P0 & S),
C2 = G1 | (P1 & G0) | (P1 & P0 & S),
C3 = G2 | (P2 & G1) | (P2 & P1 & G0) | (P2 & P1 & P0 & S),
C4 = G3 | (P3 & G2) | (P3 & P2 & G1) | (P3 & P2 & P1 & G0) | (P3 & P2 & P1 & P0 & S);
assign
sum[0] = P0 ^ S,
sum[1] = P1 ^ C1,
sum[2] = P2 ^ C2,
sum[3] = P3 ^ C3;
assign Cout = C4;
endmodule
Honestly, what I really need to do is a 4-bit adder-subtractor using carry lookahead, but I have no idea how to implement a carry lookahead to begin with so here I am. If anyone could help me that would be really great :<
Edit: I have calmed down and I can finally pinpoint the exact problem: the values of A and B for the test bench. While I could brute force it, how can I make use of loops to increment A and B so that it would be like this:
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
While also updating M?
Use the following to improve your testbench.
`timescale 1ns / 1ps
module adder_4bit_cla_tb();
// inputs - keep them having reg as the data type
reg [3:0] A, B;
reg S;
// outputs - keep them having wire as the data type
wire [3:0] sum;
wire Cout;
adder_4bit_cla adder_4bit_cla_inst
(
.sum(sum), .Cout(Cout), .A(A), .B(B), .S(S)
);
initial begin
A = 4'd1; B = 4'd2; S = 1'd1;
#10 A = 4'd2; B = 4'd5; S = 1'd0;
#10 A = 4'd5; B = 4'd6; S = 1'd0;
#50 $stop;
end
endmodule
Waveform results
Inputs can be fed using for loops as follows.
`timescale 1ns / 1ps
module adder_4bit_cla_tb();
// inputs - keep them having reg as the data type
reg [3:0] A, B;
reg S;
// outputs - keep them having wire as the data type
wire [3:0] sum;
wire Cout;
reg [3:0] i;
adder_4bit_cla adder_4bit_cla_inst
(
.sum(sum), .Cout(Cout), .A(A), .B(B), .S(S)
);
initial begin
for(i = 4'd0; i < 4'd15; i = i + 4'd1) begin
A = i; B = i; S = 1'b0;
#10;
end
#200 $stop;
end
endmodule
Waveform Results

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 adder from 4-bit Carry Look Ahead (CLA) - Cout from Block Generate and Propagate

I'm new to Verilog. Here's what I have done so far and the 4-bit CLA works. However, the 16-bit (using instances of 4-bit CLA) doesn't. The problem is definitely in setting the Cout_itermed (intermediate carries) values from block propagate (BP) and block generate (BG). I've created a module carries to deal with this.
In Xilinx ISE, the output waveform shows up as this (no wave shown):
module CLA_4bit(
output [3:0] S,
output Cout, PG, GG,
input [3:0] A, B,
input Cin
);
wire [3:0] G,P,C;
assign G = A & B; //Generate
assign P = A ^ B; //Propagate
assign C[0] = Cin;
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 Cout = G[3] | (P[3] & G[2]) | (P[3] & P[2] & G[1]) | (P[3] & P[2] & P[1] & G[0]) |(P[3] & P[2] & P[1] & P[0] & C[0]);
assign S = P ^ C;
assign PG = P[3] & P[2] & P[1] & P[0]; // block generate
assign GG = G[3] | (P[3] & G[2]) | (P[3] & P[2] & G[1]) | (P[3] & P[2] & P[1] & G[0]); // block propagate
endmodule
module CLA_16bit(
output reg [15:0] S,
output reg Cout,
input [15:0] A, B,
input Cin
);
reg [3:0] BP, BG;
reg [3:0] Cout_itermed;
carries my_carries(BP, GP, Cin, Cout_itermed, Cout);
CLA_4bit cla0(S[3:0], Cout_itermed[0], BP[0], BG[0], A[3:0], B[3:0], Cin);
CLA_4bit cla1(S[7:4], Cout_itermed[1], BP[1], BG[1], A[7:4], B[7:4], Cout_itermed[0]);
CLA_4bit cla2(S[11:8], Cout_itermed[2], BP[2], BG[2], A[11:8], B[11:8], Cout_itermed[1]);
CLA_4bit cla3(S[15:12], Cout_itermed[3], BP[3], BG[3], A[15:12], B[15:12], Cout_itermed[2]);
Cout = Cout_itermed[3];
endmodule
module carries (
input [3:0] BP,
input [3:0] BG,
input Cin,
output reg [3:0] Cout_itermed,
output reg Cout
);
assign Cout_itermed[0] = BG[0] | (BP[0] & Cin);
assign Cout_itermed[1] = BG[1] | (BP[1] & Cout_itermed[0]);
assign Cout_itermed[2] = BG[2] | (BP[2] & Cout_itermed[1]);
assign Cout = Cout_itermed[3];
endmodule
The waveform does show up (and correctly) when I run a test bench of the 4 bit CLA. Could anyone explain where the problem lies in the carries or the CLA_16bit module?
Cout_itermed has two drivers - the first being the Cout outputs of a CLA_4bit, and the second being the Cout_itermed output of the carries module.
The same applies to Cout in CLA_16bit (though it's two drivers end up being the same signal, Cout_itermed[3], in CLA_16bit and carries).
Remember that in Verilog you're describing physical circuitry, and you should never have two sources (drivers) connected to the same wire - that's how we get short circuits!
The following is based on https://en.wikipedia.org/wiki/Lookahead_carry_unit#16-bit_adder.
What you'll want to do is define remove the Cout_itermed[x] from the Cout port in the CLA_16bits (you can just leave the port hanging). You should move the logic to determine Cout_itermed[3] (i.e. BG[3] | (BP[3]&Cout_itermed[2])) to the carries module.

Verilog carry look ahead adder propagation confusion

I have just learned about the CLA adder am a little confused about getting the sum. I see there are two versions of p, p = a or b and p = a xor b.
If I simulate this code it will give the correct result:
module CLA_4bit(
output [3:0] S,
output Cout,
input [3:0] A,B,
input Cin
);
wire [3:0] G,P,C;
assign G = A & B;
assign P = A ^ B;
assign C[0] = Cin;
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 Cout = G[3] | (P[3] & G[2]) | (P[3] & P[2] & G[1]) | (P[3] & P[2] & P[1] & G[0]) |(P[3] & P[2] & P[1] & P[0] & C[0]);
assign S = P ^ C;
endmodule
However, if I change P = A ^ B to P = A | B it would give an incorrect sum. What changes to the code would be needed to have it work with P = A | B ?
The formula for S (P^C) is valid for P computed with XOR operation. As you probably know, the only difference in the truth tables between OR and XOR operation is when both bits are 1. That's why the formula for Sshould be slightly different if you use OR operation:
S = (P & (~G)) ^ C

Resources