Dentro de module, program o interface
El elemento esencial en el que se basa la cobertura funcional es la utilización de covergroups. Básicamente se conocen dos tipos de covergroups que son:
- «without event triggering»:
- No disponen de ninguna especificación de cuando son muestreados los coverpoints.
- Por tanto tiene que especificarse en el curso de ejecución el momento exacto donde tiene que hacerse el muestreo.
- Dicho muestreo se realiza con un método asociado denominado «sample»
- «with event triggering»:
- Disponen de especificación de cuando son muestreados los coverpoints.
- Esta especificación puede ser en flancos positivos o en flancos negativos del reloj.
Veamos ejemplos de ambos tipos:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
bit [1:0] b; modulo DUV (.*, .salida(b)) covergroup cg_salidas; //define bcov: coverpoint b; endgroup cg_salidas cg_inst ; //declare initial begin cg_inst = new; //instantiate a cg.group repeat(10) end // do something if (condition) cg_inst.sample(); ##1; end end |
Puede observarse en este ejemplo las tareas acciones que comentábamos en la idea principal:
- ACCION DEFINICIÓN: en las líneas 6, 7 y 8
- ACCION MUESTREO: en la línea 16. Es un muestreo inmediato que debe explicitarse mediante el método «sample»
- ACCIÓN MONITORIZACIÓN: prácticamente el resto de líneas. Se declara e instancia el objeto covergroup en el mismo «module» donde se encuentra la variable salida a muestrear. Con lo cual el intercoexionado es prácticamente directo
Veamos ahora un ejemplo del otro tipo de covergroup:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
bit [1:0] a; modulo DUV (.*, .entrada(a)) covergroup cg_entradas @(negedge clk);//define acov: coverpoint a; endgroup initial begin cg_entradas cg_inst = new; //declare and instantiate ... end |
- Siempre muestree en cada flanco negativo del reloj el valor de b. Se puede habilitar una condición para seleccionar en qué flancos muestrear y así acotar los eventos de reloj. Para ello utilizaríamos la palabra reservad iff seguida de la condición en el coverpoint que nos interesara
- acov: coverpoint a iff (b==2);
- Registre la cobertura en a en cada flanco negativo del reloj, solo si b==2, de lo contrario ignorar (no muestrear).
- Se puede utilizar en covergroups con o sin triggering events
- iff se puede utilizar en cualquier coverpoint, en cualquier covergroup.
- Uso típico: desactivar la cobertura cuando el reset está activo
- Al final de la simulación podemos obtener los resultados en la forma: 125 veces b fue 00, 48 veces b fue 01, 70 veces b fue 10, 113 veces b fue 11.
- Si b nunca fue 01, entonces tenemos un agujero de cobertura (75% de cobertura solamente).
- Es posible especificar una cantidad mínima de cuentas para que un caso se considere como cubierto.
Dentro de clases (embedded covergroups)
Cuando hacemos la definición , declaración e instanciación del objeto covergoup dentro de una clase, la declaración es implícita . Veamos un ejemplo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class fifo_driver; covergroup COV_salidas; //define coverpoint mports.px.data_out; endgroup function new (virtual fifo_if.test ports, virtual fifo_if.monitor mports); begin .... COV_salidas=new; //instantiate .... end ... endclass |
La sintaxis , cómo puede observarse es un tanto extraña por cuanto no existe una declaración explícita de objeto y parece que se construya directamente el covergroup en la instanciación. En cualquier caso, aunque se ha elegido en este ejemplo un «without triggering event covergroup», podría haberse utilizado un «with triggering event covergroup».