Reputation: 1
I am working on a ripple carry adder using structural verilog, which is supposed to take in two random inputs and calculate accordingly.
The general rca I created calculated correctly, but for some reason I get weird outputs when I add a for loop and use the $random
to generate.
Could someone kindly explain where I'm going wrong? Below is my code:
module full_adder(x,y,z,v,cout);
parameter delay = 1;
input x,y,z; //input a, b and c
output v,cout; //sum and carry out
xor #delay x1(w1,x,y);
xor #delay x2(v,w1,z);
and #delay a1(w2,z,y);
and #delay a2(w3,z,x);
and #delay a3(w4,x,y);
or #delay o1(cout, w2,w3,w4);
endmodule
module four_bit_adder(a,b,s,cout,cin);//four_bit_adder
input [15:0] a,b; //input a, b
input cin; //carry in
output [15:0] s; //output s
output cout; //carry out
wire [15:0] c;
full_adder fa1(a[0],b[0],cin,s[0],c0);
full_adder fa2(a[1],b[1],c0,s[1],c1);
.
.
.
full_adder fa16(a[15],b[15],c14,s[15],cout);
endmodule
module testAdder(a,b,s,cout,cin);
input [15:0] s;
input cout;
output [15:0] a,b;
output cin;
reg [15:0] a,b;
reg cin;
integer i;
integer seed1=4;
integer seed2=5;
initial begin
for(i=0; i<5000; i=i+1) begin
a = $random(seed1);
b = $random(seed2);
$monitor("a=%d, b=%d, cin=%d, s=%d, cout=%d",a,b,cin,s,cout);
$display("a=%d, b=%d, cin=%d, s=%d, cout=%d",a,b,cin,s,cout);
end
end
endmodule
Here are two lines from the output that I get:
a=38893, b=58591, cin=x, s= z, cout=z
a=55136, b=58098, cin=x, s= z, cout=z
Upvotes: 0
Views: 1038
Reputation: 4381
This is a combinational circuit, so the output changes instantaneously as the input changes. But, here you are apply all the inputs at same timestamp which should not be done since the full_adder
module provides 1-timestamp delay. This may not cause problems in this module, but may cause issues while modelling sequential logic. Add a minimum of #10
delay between inputs.
Also, $monitor
executes on each change in the signal list, so no need to use it in for
loop. Just initialize $monitor
in initial
condition.
cin
is also not driven from the testbench. Default value of reg
is 'x
and that of wire
is 'z
. Here, cin
is reg
, so the default value is displayed, that is 'x
One more thing, you must instantiate the design in your testbench. And connect respective ports. The outputs from testbench act as inputs to your design and vice-versa. This is just like you instantiate full_adder
module in four_bit_adder
module in design.
Consider testadder
as top level module and instantiate design in it. No need of declaring ports as input and output in this module. Declare the design input ports as reg
or wire
(example: reg [15:0] a
when a
is design input port) and output ports as wire
(example: wire [15:0] sum
when sum
is design input port).
Referring to your question:
The general rca I created calculated correctly, but for some reason I get weird outputs when I add a for loop and use the $random to generate.
Instead of using $random
, use $urandom_range()
to generate random numbers in some range. Using SystemVerilog constraints constructs can also help. Refer this link.
Using $urandom_range
shall eliminate use of seed1
and seed2
, it shall generate random values with some random machine seed.
Following is the module testadder with some of the changes required:
module testAdder();
wire [15:0] s;
wire cout;
// output [15:0] a,b;
// output cin;
reg [15:0] a,b;
reg cin;
integer i;
integer seed1=4;
integer seed2=5;
// Instantiate design here
four_bit_adder fa(a,b,s,cout,cin);
initial begin
// Monitor here, only single time
$monitor("a=%d, b=%d, cin=%d, s=%d, cout=%d",a,b,cin,s,cout);
for(i=0; i<5000; i=i+1) begin
// Drive inputs with some delays.
#10;
// URANDOM_RANGE for input generation in a range
a = $urandom_range(0,15);
b = $urandom_range(0,15);
// a = $random(seed1);
// b = $random(seed2);
// Drive cin randomly.
cin = $random;
$display("a=%d, b=%d, cin=%d, s=%d, cout=%d",a,b,cin,s,cout);
end
end
endmodule
For more information, have a look at sample testbench at this link.
Upvotes: 2