Testbench can't pass decimal value through wire and reg variables - verilog

I have two files named: summation.v and summationtest.v
Code for summation.v::
module summation(a, b, c);
input [3:0] a;
input [3:0] b;
output reg[7:0] c;
reg[3:0] anum;
reg[3:0] bnum;
always #(a) begin
anum <=a;
bnum <=b;
c = anum + bnum;
end
endmodule
The purpose of summation.v is to take two decimal input from summationtest.v, process the decimal values and send the result c back to the output (summationtest.v) again.
Code for summationtest.v:
module summationtest;
reg[3:0] a;
reg[3:0] b;
wire[7:0] c;
summation a1(a, b, c);
initial begin
a = 3;
b = 4;
$display("%d", c);
end
endmodule
When the program runs, no value of a and b passes from summationtest.v to summation.v; as a result, no value is assigned to c.

That is not the proper way to model combinational logic. You have an incomplete sensitivity list and you should not use nonblocking assignments (<=). You should use $monitor instead of display to view all signal changes.
Here is a much simpler way to code your adder:
module summation(a, b, c);
input [3:0] a;
input [3:0] b;
output [7:0] c;
assign c = a + b;
endmodule
module summationtest;
reg[3:0] a;
reg[3:0] b;
wire[7:0] c;
summation a1(a, b, c);
initial begin
$monitor("%d", c);
a = 3;
b = 4;
end
endmodule

Related

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

Absolute value module in Verilog returning only unknown values

I am trying to implement a simple 16-bit absolute value module; however, I am only getting unknown values as output.
Below is the code that I've written:
module refabs(b, a);
input wire [15:0] a;
output reg signed [15:0] b;
always #* begin
b = ((a < 0) ? -a : a);
end
endmodule
module testbench;
reg [15:0] a;
wire [15:0] b;
refabs abs(b, a);
initial begin
a = -30000;
begin
$display("refabs(%x) = %x", a, b);
end
end
endmodule
The output I get is:
refabs(8ad0) = xxxx
In your example, the initial block executes with 0 delay without giving the always #* a chance to execute.
Either change your $display to $strobe, or add a delay before the $display statement.

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

Verilog Always statement for 4 Demux

This is my Verilog code for the procedural modeling of the 4 Demux:
//4 Bit demux in Gate level
module HW3_PM(input [3:0] I, input Sel, output [3:0] A, output [3:0] B);
always#(*)
begin
case(Sel)
1'b0: begin
A = ~Sel&I;
end
1'b1: begin
B = Sel&I;
end
default: begin
end
endcase
end
endmodule
And I input to receive this error:
eos$ ncverilog +access+r HW3_PM.v HW2_Demux4_tb.v +gui
ncverilog: 09.20-s019: (c) Copyright 1995-2010 Cadence Design Systems, Inc.
file: HW3_PM.v
A = ~Sel&I;
|
ncvlog: *E,WANOTL (HW3_PM.v,8|6): A net is not a legal lvalue in this context [9.3.1(IEEE)].
B = Sel&I;
|
ncvlog: *E,WANOTL (HW3_PM.v,11|6): A net is not a legal lvalue in this context [9.3.1(IEEE)].
module worklib.HW3_PM:v
errors: 2, warnings: 0
file: HW2_Demux4_tb.v
ncverilog: *E,VLGERR: An error occurred during parsing.
Review the log file for errors with the code *E and fix
those identified problems to proceed. Exiting with code (status 1).
I've tried changing and adding A and B as both reg and wire but it causes higher errors. I tried changing to posedge of the clock and get a different error. Your help is appreciated.
NEW:
Changed code:
//4 Bit demux in Gate level
module HW3_PM(input [3:0] I, input Sel, output [3:0] A, output [3:0] B);
reg A, B;
always#(*)
begin
case(Sel)
1'b0: begin
A = ~Sel&I;
end
1'b1: begin
B = Sel&I;
end
default: begin
end
endcase
end
endmodule
Received error:
file: HW3_PM.v
module HW3_PM(input [3:0] I, input Sel, output [3:0] A, output [3:0] B);
|
ncvlog: *E,BADIOO (HW3_PM.v,2|53): input/output/inout 'A' declared as vector, then redeclared as scalar [3.3(IEEE)].
reg A, B;
|
ncvlog: *W,ILLPDX (HW3_PM.v,4|5): Multiple declarations for a port not allowed in module with ANSI list of port declarations (port 'A') [12.3.4(IEEE-2001)].
module HW3_PM(input [3:0] I, input Sel, output [3:0] A, output [3:0] B);
|
ncvlog: *E,BADIOO (HW3_PM.v,2|69): input/output/inout 'B' declared as vector, then redeclared as scalar [3.3(IEEE)].
reg A, B;
|
ncvlog: *W,ILLPDX (HW3_PM.v,4|8): Multiple declarations for a port not allowed in module with ANSI list of port declarations (port 'B') [12.3.4(IEEE-2001)].
module worklib.HW3_PM:v
errors: 2, warnings: 2
file: HW2_Demux4_tb.v
ncverilog: *E,VLGERR: An error occurred during parsing.
Review the log file for errors with the code *E and fix
those identified problems to proceed. Exiting with code (status 1)
module HW3_PM(
input [3:0] I,
input Sel,
output reg [3:0] A,
output reg [3:0] B
);
always#(*)
begin
if(~Sel) begin
A = I;
B = 0;
end else begin
A = 0;
B = I;
end
end
endmodule
or
module HW3_PM(
input [3:0] I,
input Sel,
output wire [3:0] A,
output wire [3:0] B
);
assign A = ~sel&I;
assign B = sel&I;
endmodule
or
module HW3_PM(
input [3:0] I,
input Sel,
output reg [3:0] A,
output reg [3:0] B
);
always#(*)
begin
case(Sel)
0: begin
A = I;
B = 0;
end
1: begin
A = 0;
B = I;
end
endcase
end
endmodule
or
module HW3_PM(input [3:0] I,input Sel,output wire [3:0] A, output wire [3:0] B);
and selA[3:0] (A, ~sel, I);
and selB[3:0] (B, sel, I);
endmodule

Verilog code adding two integers generated by a for loop

How about this? I'm looking for an output i+j=1+2, 2+3... 4+5.
module add(i,j,b);
input [31:0] i, j; //32 bit unsigned
output [31:0] y;
task ADD(i, j, y);
begin
for (i= 1; i <= 4; i++)
begin
for(j=2; j <= 5; j++)
assign y = i + j;
end
end
$display("y ", y);
endtask
endmodule
Is this intended for synthesis? If so you should probably avoid using tasks until you have learnt when they can be used. I never use them in synthesisable code.
functions on the other hand are often used for synthesis but can not contain timing information. Ie a function can only represent combinatorial logic, that all happens in an instant.
1) That is not how you use assign. The correct use would be:
wire [9:0] a;
assign a = 10'b0;
//or
//a,b both 10 bits driven from other logic
wire [9:0] sum;
assign sum = a + b;
Note how you assign to a wire, this is combinatorial.
2) Your display is outside of the for loop it will only display once at the end.
I would have done this some thing like:
module add(
input [31:0] a,
input [31:0] b,
output [31:0] sum
);
assign sum = a + b ;
endmodule
module testharness();
reg [31:0] a;
reg [31:0] b;
wire [31:0] sum;
reg clock;
// Make clock toggle every 10ns (20ns clock period)
initial begin
clock = 0;
forever begin
#10ns clock= ~clock;
end
end
//DUT (Device Under Test)
add add_0 (
.a ( a ),
.b ( b ),
.sum ( sum )
);
// Test program
initial begin
a=0;
b=0;
#(posedge clock);
$display( "a (%2d) + b (%2d) = sum (%2d)", a, b, sum );
a=1;
b=2;
#(posedge clock);
$display( "a (%2d) + b (%2d) = sum (%2d)", a, b, sum );
a=3;
b=4;
#(posedge clock);
$display( "a (%2d) + b (%2d) = sum (%2d)", a, b, sum );
$finish;
end
endmodule
Note how we have used time to separate the results, for more complicated designs you may use flip-flops which means you only get a new result per clock. Or per rising and falling edge if using DDR techniques.
You can now try to modify the test program section to stimulate the DUT as per your requirements.

Resources