Verilog Two bit Magnitude comparator - verilog

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]);

Related

Displaying "X" for output results?

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

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.

Compile issues with verilog

Can anyone see any blatant errors as to why this does not compile. I think the logic is correct for most of these operations. Its most likely syntax errors.
the only thing i can think of is the switch statement isn't written correctly as well as the add module. Each of the foury bit statements are connected to one of the modules below it. (bitwise not binary)
module _4bitALU(C , O , A , B , Switch);
input[3:0] A ;
input [3:0] B;
input [3:0] Switch;
output [3:0] O;
output C;
case(Switch)
4'B0000: notop(O , A);
4'B0001: andop(O , A , B);
4'B0010: orop(O , A , B);
4'B0011: xorop(O , A , B);
4'B1000: addop(C , O , A , B);
endcase // case (Switch)
endmodule // _4bitALU
module notop(O , A);
input [3:0] A;
output [3:0] O;
assign O = ~A;
endmodule // notop
module andop(O , A , B);
input [3:0] A;
input [3:0] B;
output [3:0] O;
assign O = (A & B);
endmodule // andop
module orop(O , A , B);
input [3:0] A;
input [3:0] B;
output [3:0] O;
assign O = (A | B);
endmodule // orop
module xorop(O , A , B);
input [3:0] A;
input [3:0] B;
output [3:0] O ;
assign O = (A ^ B);
endmodule // xorop
module addop(C , O , A , B);
input [3:0] A;
input [3:0] B;
output [3:0] O;
output C;
assign C1 = (A[0] & B[0]);
assign C2 = ((A[1] & B[1]) | (A[1] & C1) | (B[1] & C1));
assign C3 = ((A[2] & B[2]) | (A[2] & C2) | (B[2] & C2));
assign C = ((A[3] & B[3]) | (A[3] & C3) | (B[3] & C3));
assign O[0] = (A[0] ^ B[0]);
assign O[1] = ((A[1] ^ B[1] ^ C1) | (A[1] & B[1] & C[1]));
assign O[2] = ((A[2] ^ B[2] ^ C2) | (A[2] & B[2] & C[2]));
assign O[3] = ((A[3] ^ B[3] ^ C3) | (A[3] & B[3] & C[3]));
assign O[4] = ((A[4] ^ B[4] ^ C4) | (A[4] & B[4] & C[4]));
endmodule // addop
There are quite a few problems in the _4bitALU module:
The case statement is not inside an always block.
You can't "call" other modules like you do in the case branches, instead you need to create instances of those modules and assign the wires which connect to those instances within the case branches to the desired output(s).
These issues are rather basic Verilog, therefore I suggest you read up on how it is used (maybe this tutorial might help). Remember that you are (in most cases anyway) trying to describe the structure of hardware, not a software program that just gets executed.

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