Cuando aleatorizamos, deseamos que esos valores obtenidos fruto de la aleatorización se conviertan en estímulos que conduzcan señales a nuestros diseños objeto de verificación. Veamos cómo lo hacemos en varios ejemplos desarrollados en nuestros laboratorios virtuales de ejemplo del radicador.
Paso 1: Tenemos la instanciación del objeto RCSG dentro del mismo módulo donde se declara la señal que se conecta al puerto de entrada del DUV. Tenemos por tanto una visibilidad completa y podemos hacerla cómo se resalta en el siguiente ejemplo, en el que queremos introducir un valor aleatorizado a la entrada X del radicador.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
while ( veamos.get_coverage()<90) begin busInst.impares.constraint_mode(0); busInst.pares.constraint_mode(1); $display("pruebo con pares"); assert (busInst.randomize()) else $fatal("randomization failed"); X = busInst.valor; veamos.sample(); @(posedge CLK); START <= 1'b1; @(posedge CLK); START <= 1'b0; @(posedge FIN); -> comprobar; @(negedge FIN); end |
Paso 2: La situación es bastante parecida. Solo que ahora el módulo en donde conviven el objeto RCSG y la señal a recibir el valor es substituido por un program. La señal X no es directamente la que se conecta a la entrada del DUV, sino una salida del program que se conectará a la entrada del DUV
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
sed i1 ( // port map - connection between master ports and signals/registers .CLK(CLK), .COUNT(COUNT), .FIN(FIN), .RESET(RESET), .START(START), .X(X) ); //instanciacion del program estimulos #(.size(4)) estim1 (.*, .X(X)); |
La gran diferencia de comportamiento la tendremos por generar la asociación de la entrada X a través de un program (ver página relativa al Program); garantizando que el estímulo X sea percibido sin carreras.
Paso 3: De nuevo tenemos un estímulo procedente de un program, pero en este caso hemos cogido el valor aleatorio que nos interesa y lo asignamos a un elemento de un clocking block que tiene un skew de 1 ns. Vemos en el siguiente ejemplo como conducimos sobre sd.X el valor obtenido en la aleatorización. LLama la atención que toda acción de asignación driver a través de un clocking block debe realizarse con asignaciones de tipo non-blocking
1 2 3 4 5 6 7 8 9 10 11 12 13 |
while ( veamos.get_coverage()<40) begin busInst.pares.constraint_mode(0); $display("pruebo con impares"); assert (busInst.randomize()) else $fatal("randomization failed"); sd.X <= busInst.valor; veamos.sample(); ##1 sd.START <= 1'b1; ##1 sd.START <= 1'b0; @(negedge sd.FIN); end |
Podemos ver el cronograma del comportamiento del estímulo sd.X, de cómo es percibida esta entrada por el DUV . Aprovechamos también para observar cómo este estímulo es monitorizado (md.X) para llevarlo al modelo de referencia. hacemos uso de otro clocking block engargado de todas las tareas de monitorización de salidas y entradas.
En cualquier caso en este paso 3 la visibilidad de todas las variables es completa y no es necesario ningún mecanismos especial para garantizarla.
Paso 4 : Estamos en una situación muy parecida a la anterior. Estoy dentro del program y tengo visibilidad de los datos aleatorizados obtenidos en el objeto de la clase RCSG y tengo acceso a las señales del interfaz en sus modport correspondientes (controlados por los clocking-block). Destacamos la línea donde realizamos la acción de driver.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
while ( veamos.get_coverage()<40) begin busInst.pares.constraint_mode(0); $display("pruebo con impares"); assert (busInst.randomize()) else $fatal("randomization failed"); testar.sd.data_in<= busInst.valor; veamos.sample(); @(testar.sd); testar.sd.empieza <= 1'b1; @(testar.sd); testar.sd.empieza <= 1'b0; @(negedge testar.sd.termina); end |
En cuanto al comportamiento tenemos el mismo que teníamos en el paso 3 controlado por la acción de sincronismo de los clocking blocks, ahora situados en el interfaz en lugar de directamente en el program
Paso 5: Este caso el driver se realiza en una task que se encuentra dentro de una clase denominada enviroment.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
task prueba_random_impares; while ( valores_X_trigger.mon_entradas_impares.get_coverage()<80) begin busInst.pares.constraint_mode(0); $display("pruebo con impares"); assert (busInst.randomize()) else $fatal("randomization failed"); testar_ports.sd.data_in<= busInst.valor; valores_X.sample(); @(testar_ports.sd); testar_ports.sd.empieza <= 1'b1; @(testar_ports.sd); testar_ports.sd.empieza <= 1'b0; @(negedge testar_ports.sd.termina); end endtask |
La visibilidad de valor randomizado no es un problema, puesto que proviene de un objeto de tipo RCSG que hemos construido dentro de la clase «enviroment». Más complejo es hacerse luego acceso al interfaz del diseño para asignar ese valor aleatorizado al estímulo «sd.data_in», puesto que se trata de un interfaz físico que no es accesible desde una clase salvo que se utilice un interfaz virtual asociado al mismo.
1 2 |
virtual test_if.test testar_ports; virtual test_if.monitor monitorizar_ports; |