You are here

System Verilog - Coverage

// Literatur: Vorlesungsunterlagen AMV von Rainer Findenig (FH-Hagenberg)
 
// Coverage ... Grad der Abdeckung
 
// Covergroups & Coverpoints
        bit mysignal2;
        int mysignal3;
 
        covergroup mycg @(myEvent);
            label1: coverpoint mysignal1;
            label2: coverpoint mysignal2 {
                bins enabled  = { 1 };
                bins disabled = { 0 };
            }
            label3: coverpoint mysignal3 {
                bins firstSection =  { 0, 1, 2 };
                bins secondSection = { 10, 20, 30 };
                bins other = default;
            }
            label4: coverpoint mysignal4 {
                // bins die nicht betrachtet werden
                ignore_bins zero = {0};
                ...
                // bins die nicht auftreten sollten/duerfen
                illegal_bins invalid = default;
                ...
                // Transition Coverage:
                //  wie oft wurden bestimmte Uebergaenge ausgefuehrt
                bins posEdge = ( 0 => 1 );
                bins negEdge = ( 1 => 0 );
                bins nothing = ( 0 => 0 ), ( 1 => 1 );
            }
            // Conditional Coverage: Bsp. keine Infos waehrend Reset
            label5: coverpoint mysignal5 iff (!rst);
        endgroup
 
        mycg cg = new;                  // Objekt muss angelegt werden
        mycg = new;
 
 
// Cross Coverage
        covergroup cg_opcodes @(posedge clk);
            val_cmd: coverpoint cmd {
                bins arith  = { ... };
                bins logic_ = { ... };
                ...
            }
            val_reg: coverpoint regaddr;
 
            cmd_with_reg: cross val_cmd, val_reg;
 
            // Illegale Kombinationen markieren
            // Bsp. logische Operationen duerfen Register 0 nicht nuetzen
            cmd_with_reg: cross val_cmd, val_reg {
                illegal_bins log_r0 = binsof(val_cmd.logi_) &&
                                      binsof(val_reg) intersect {0};
            }
        endgroup
 
 
// Bereiche Betrachten
        int regaddr;
        ...
        covergroup somecg @(someevent);
            reg_address: coverpoint regaddr {
                bins zero      = { 0 };        // 1 bin
                bins local_ [] = { [1:7] };    // 7 bins: local_[1]..local_[7]
                bins in        = { [8:15] };   // 1 bin
                bins out []    = { [16:24] };  // 8 bins
 
                bins invalid   = default;
            }
        endgroup
 
 
// zufaellig generierte Werte
        typedef enum { NOP=0, SLEEP=1,
                       LOADI=2, LOAD=3, STORE=4,
                       JUMP=8, JUMPC=10, JUMPZ=11,
                       MOVE=12,
                       AND=16, OR=17, XOR=18, NOT=19,
                       ADD=20, ADDC=21, SUB=22, SUBC=23,
                       COMP=24,
                       INC=26, DEC=27,
                       SHL=28, SHR=29, SHLC=30, SHRC=31 } aProl16Command;
        typedef bit [REGISTER_WIDTH-1 : 0] aData_v;
 
        class clProl16Opcode;
            rand int            ra;
            rand int            rb;
            rand aProl16Command cmd;
            rand aData_v        data;
            // rand  ... zufaellige Werte
            // randc ... zufaellige Werte, wiederholt Werte erst
            //                             wenn bereits alle vorgekommen
 
            constraint no_invalid_model_cmd { 
                cmd != NOP;
                cmd != SLEEP;
                cmd != LOAD;
                cmd != STORE;
            };
 
            constraint only_valid_regA {
                ra >= 0;
                ra <  REGISTER_NR;
            };
 
            constraint only_valid_regB {
                rb >= 0;
                rb <  REGISTER_NR;
            };
 
            function void pre_randomize();
            begin
                $write("pre_randomize: Called for randomizing data.");
            end
            endfunction
 
            function void post_randomize();
            begin
                $write("post_randomize: Called after randomizing data.");
            end
            endfunction
        endclass
 
        ...
        opcode = new ();
        void'(opcode.randomize());
        // void damit keine Warnings ausgegeben werden
 
        opcode.randomize() with {
            cmd == NOP;
        };
 
 
 
// Constraints steuern
        opcode.only_valid_regA::constraint_mode(0);     // Constraint aus
        opcode.only_valid_regA::constraint_mode(1);     // Constraint ein
        opcode::constraint_mode(0);
 
        // Constraint Modus auslesen
        int on = opcode.only_valid_regA::constraint_mode();
 
        opcode.only_valid_regA::rand_mode(0);           // Random-Funkt. aus
        int on = opcode.only_valid_regA::rand_mode();   // auslesen
 
 
// weitere Constraints
        constraint array_size  { data.size() <= 8; };
        constraint id_not_null { id != 0; };
        constraint c {
            // inclusive
            src_port inside { [8'h0:8'hA],8'h14,8'h18 };
            // exclusive
            ! (des_port inside { [8'h4:8'hFF] });
        }
 
        constraint len {
            length dist {
                [64  :  127 ] := 10,    // mindestens 10x im Bereich 64-127
                [128 :  511 ] := 10,    // ...
                [512 :  2048] := 10
            };
        }
        constraint src {
            src_port dist {
                0  := 1,
                1  := 1,
                2  := 5,
                4  := 1
            };
        }
 
        // gewichtete Distribution:
        constraint high_id {
            id dist {
                [0 : 0x400] :/ 25,      // 25% im Bereich 0-0x400
                [0x401 , 0x800] :/ 75   // 75% im Bereich 0x401-0x800
            }
        }
        // bedingte Constraints
        constraint my_const {
            (id == 0)   -> data.size() >= 2;
            (id == 100) -> data.size() == 0;
 
            if (size == RUNT) {
                length >= 0;
                length <= 63;
            } else if (size == OVERSIZE) {
                length >= 1501;
                length <= 5000;
            }
        };
 
        // Iterative Constraints
        constraint frame_sizes {
            data.size inside {[1:10]};  // im Bereich 1-10
            foreach (data[i])           // bekommt jedes Element ein
                data[i] == i;           // eigenes Constraint
        }
 
        // Variable Ordnung der Constraints
        constraint frame_sizes {
            solve zero before data.size;    // zuvor wird zero ausgewertet,
            zero -> data.size == 0;         // danach data.size
            data.size inside {[0:10]};
            foreach (data[i])
                data[i] == i;
        }
 
 
// zufaelliges Abarbeiten eines Zweiges
        task do_randcase();
        begin
            randcase
                20 : begin                          // 20 gibt das Gewicht
                    $write ("first randcase \n");   // dieses Zweiges an
                end                                 // (aus Summe berechnet)
                20 : begin
                    $write ("second randcase \n");
                end
                20 : begin
                    $write ("third randcase\n");
                end
            endcase 
        end
        endtask