system-verilograndomized-algorithm

How to generate a 'glitchy' signal in the systemverilog class


Quite often I have to simulate a situation, where an input signal entering the FPGA is either heavily glitching, or just has very slow rise/fall times, which in the real design might result in metastability, and signal glitching. To clean the signal, I have designed a 'debouncing' module, which I use whenever such a situation happens, and I simulate my design using ideal behaviour of the signal.

My question here is related to the simulation of such a situation. In particular - how to take any test-bench generated signal (in a driver class), and make it randomly glitching at rising and falling edges. All within a specification I give. For example, I'd like to simulate a 'clean' push-button signal, and make it randomly bounce between low and high whenever any transition happens, for anywhere between 1 and 5 milliseconds, up to 30 times.

Is there a way how to simulate such behaviour effectively in System Verilog?


Solution

  • thank you, for your clear answer. I managed to come with the following solution, it is a bit less elaborate than yours, but works as well:

    Here is the generator class:

        class bouncer #(parameter int max_num_transactions = 30,
            // in nanoseconds:
            parameter int max_collective_time = 10000);
    
    
            rand int               num_transactions;
            // we cannot randomize time as it requires svrnm license,
            // so we do in integer. These are in nanoseconds as it is expected
            // to have triggering max in milliseconds range
            rand int               wait_times[2*max_num_transactions];
            rand int               lastwait;
            // this is somewhat of a guess, having max num transactions
            // and collective time we have to guess on maximum allowable space
            // to be able to generate proper vector:
            parameter int         maxval = integer'(max_collective_time / max_num_transactions * 1.5);
    
    
           constraint m_num_transactions {num_transactions > 6;
              num_transactions < 2*max_num_transactions;};
    
           // 100ns - 5us, all here in nanoseconds
           constraint waits {foreach(wait_times[i]) wait_times[i] > 100 &&
              wait_times[i] < maxval && wait_times.sum() < max_collective_time;};
    
           constraint lw {lastwait > 100; lastwait < 2500;};
    
           function void post_randomize();
               $display("Total delay: %.2f us", (wait_times.sum() * 1e-3));
               $display("Max per tick delay: ", maxval);
           endfunction // post_randomize
    
           // generates 'bouncing' according to randomly generated
           // spoiling of the signal by transactions
           task generate_spoiled_signal(logic final_state,
                        ref logic tospoil);
           // spoiling procedure:
           foreach (wait_times[i]) begin
               #(wait_times[i] * 1ns);
               tospoil = ~tospoil;
           end
           #(lastwait * 1ns);
           tospoil = final_state;
          endtask // generate_spoiled_signal
        endclass // bouncer
    

    And this is how I generate the bouncing in the driver class:

        class motor_driver;
            virtual t_motor motor_x;
            bouncer B;
            ....
            task run();
               ....
               B = new;
               assert(B.randomize());
               B.generate_spoiled_signal('1, motor_x.motor_pg_i);
               #1ms;
               B.generate_spoiled_signal('0, motor_x.motor_pg_i);
            endtask
        endclass
    

    It generated the desired bouncing: enter image description here

    I have to say that I like how you tackled the dynamic array resizing and total sum. I did not know about these methods. What I have posted respects the total time as well, but until I have introduced 'maxval' to constraint a single transaction to a meaningful value it failed occasionally the randomization. Probably it could not find correct values.