Fitzzy
Fitzzy

Reputation: 1

Confused with ripple carry adder output

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

Answers (1)

sharvil111
sharvil111

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

Related Questions