Verificación funcional pre-silicio del UART 16550 de OpenCores

Anuncio
Universidad de Costa Rica
Facultad de Ingenierı́a
Escuela de Ingenierı́a Eléctrica
Verificación funcional pre-silicio del UART
16550 de OpenCores mediante la
metodologı́a UVM
Por:
José Andrés Pacheco Castro
Ciudad Universitaria “Rodrigo Facio”, Costa Rica
Diciembre 2013
Verificación funcional pre-silicio del UART
16550 de OpenCores mediante la
metodologı́a UVM
Por:
José Andrés Pacheco Castro
IE-0499 Proyecto eléctrico
Aprobado por el Tribunal:
Ing. Enrique Coen Alfaro
Profesor guı́a
PhD Randolph Steinvorth Fernández
Profesor lector
PhD Lucky Lochi Yu
Profesor lector
Resumen
El presente trabajo detalla los pasos generales que requiere un esfuerzo de
verificación. Este comprende del estudio de la especificación del dispositivo, el
plan de verificación, el desarrollo del ambiente de verificación y el análisis de
los resultados.
Para esta verificación se decidió utilizar la metodologı́a uvm, un estándar
en la industria que tiene un gran nivel de penetración.
Se concluye con este trabajo que sı́ se pudo verificar que el envı́o y recepción
de paquetes en el uart funciona correctamente. La metodologı́a uvm provee
un marco de referencia que permite el desarrollo de ambientes de verificación
de manera rápida y efectiva, que pueden ser reutilizados.
Se recomienda buscar herramientas de software libre para impulsar un
laboratorio de verificación en la ucr. Como candidato principal está SystemC,
un lenguaje que se puede usar para verificación desarrollado a partir de C++.
v
Se agradece a:
Enrique Coen, por la idea y su guı́a,
Hewlett-Packard, por la colaboración,
mis padres, por su apoyo.
vi
Índice general
Índice de figuras
viii
Índice de cuadros
viii
Nomenclatura
1 Introducción
1.1 Alcance del proyecto
1.2 Objetivos . . . . . .
1.3 Metodologı́a . . . . .
1.4 Contenido . . . . . .
ix
.
.
.
.
1
1
1
1
2
2 Antecedentes
2.1 El proceso de diseño de circuitos integrados . . . . . . . . . . .
2.2 Conceptos generales de verificación . . . . . . . . . . . . . . . .
2.3 La metodologı́a UVM . . . . . . . . . . . . . . . . . . . . . . .
3
3
4
8
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
3 Desarrollo
3.1 Especificación del UART 16550 . . . . .
3.2 Plan de verificación . . . . . . . . . . . .
3.3 El ambiente de verificación . . . . . . .
3.4 Implementación del plan de verificación
3.5 Análisis de resultados . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
11
11
14
15
18
27
4 Conclusiones y recomendaciones
43
Bibliografı́a
45
vii
Índice de figuras
2.1
2.2
El modelo de reconvergencia (Bergeron, 2003) . . . . . . . . . . . .
Diagrama de un uvc genérico . . . . . . . . . . . . . . . . . . . . .
3.1
3.2
3.3
3.4
3.5
3.6
3.7
3.8
3.9
3.10
3.11
3.12
3.13
3.14
Diagrama de bloques del uart 16550 (Gorban, 2002) . .
Diagrama del ambiente de verificación (Cadence, 2012) .
Cobertura funcional register test . . . . . . . . . . . . .
Cobertura de código register test . . . . . . . . . . . .
Cobertura funcional send frame . . . . . . . . . . . . .
Cobertura de código send frame . . . . . . . . . . . . .
Cobertura funcional receive frame y receive frame err .
Cobertura de código receive frame y receive frame err .
Cobertura funcional loopback . . . . . . . . . . . . . . .
Cobertura de código loopback . . . . . . . . . . . . . .
Cobertura funcional uart<->SoC . . . . . . . . . . . .
Cobertura funcional out<->uart . . . . . . . . . . . .
Cobertura de código por módulo . . . . . . . . . . . . .
Cobertura de código por instancia . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5
9
.
.
.
.
.
.
.
.
.
.
.
.
.
.
13
16
29
30
31
32
33
34
35
36
37
38
39
40
Casos de prueba . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Puntos de cobertura . . . . . . . . . . . . . . . . . . . . . . . . . .
14
15
Índice de cuadros
3.1
3.2
viii
Nomenclatura
ASIC
Application-specific integrated circuit (Circuito integrado
para aplicación especı́fica).
CI
Circuito Integrado.
DU T
Device Under Testing (Dispositivo bajo pruebas).
EDA
Electronic Design Automation (Diseño electrónico automático).
F P GA
Arreglo de compuertas reprogramable por sus siglas en
inglés.
F SM
Máquina de estados finita por sus siglan en inglés.
Overf low
En un arreglo, escribir más datos que el espacio disponible
para mantenerlos.
Riesgo
En verificación, probabilidad de que existan defectos sin
detectar en un diseño.
RT L
Lenguaje de descripción de hardware al nivel de registros.
También se refiere al modelo que lo utiliza.
Secuencia
Método que aplica un estı́mulo al dut.
SoC
System-on-Chip. Se refiere a la combinación de múltiples
bloques funcionales en un diseño final.
Startbit
En una trama, bit que indica el inicio de la misma.
Stopbit
En una trama, bit que indica el final de la misma.
T estbench
Banco de pruebas.
T rama
Unidad de envı́o de datos.
ix
1
Introducción
1.1
Alcance del proyecto
En la escuela de ingenierı́a eléctrica de la Universidad de Costa Rica no se
imparte un curso de verificación. Esto a pesar del creciente papel que esta
disciplina juega en el ciclo de desarrollo de circuitos integrados. Este proyecto
pretende introducir el tema mediante la implementación de un plan de verificación para un diseño de código abierto.
Se realizará una verificación pre-silicio de la versión 0.6 del uart 16550 de
OpenCores, con un banco de verificación basado en un ejemplo publicado por
la fundación Accellera y Cadence. Mediante este se configurará al dispositivo
de diferentes maneras y se enviarán y recibirán paquetes.
1.2
Objetivos
Objetivo general
Verificar la implementación del uart 16550 de OpenCores, de acuerdo con su
especificación técnica.
Objetivos especı́ficos
Para el desarrollo de este proyecto se establecieron los siguientes objetivos:
• Estudiar el proceso de diseño de un circuito integrado, y el rol de la
verificación en éste.
• Desarrollar un plan de verificación para el uart 16550.
• Implementar un ambiente de verificación uvm que permita aplicar el
plan, basado en los modelos de referencia publicados por Accellera.
• Verificar la funcionalidad de la implementación del uart 16550 utilizando el ambiente desarrollado y las herramientas eda de Cadence.
1.3
Metodologı́a
1. Desarrollo de un plan de verificación basado en la especificación del uart
16550.
1
2
1 Introducción
2. Implementación de un ambiente de verificación para aplicar el plan.
3. Aplicar las pruebas repetidamente sobre el dut.
4. Analizar los resultados de cobertura y funcionamiento correcto.
5. Evaluar el desempeño el dut y el ambiente de verificación basado en los
resultados obtenidos.
1.4
Contenido
Antecedentes Se provee un resumen de las ideas básicas sobre las que se
fundamenta la metodologı́a uvm para realizar su trabajo. Se incluye además
una explicación de la estructura que toma un banco de pruebas bajo ésta.
Desarrollo En el desarrollo se estudia la especificación del uart 16550, se
desarrolla un plan de verificación para revisar las caracterı́sticas de interés,
se explica la implementación del ambiente de verificación y se analizan los
resultados obtenidos al ejecutar el plan.
Conclusiones y recomendaciones En este trabajo sı́ se pudo verificar
que el envı́o y recepción de paquetes en el uart funciona correctamente. La
metodologı́a uvm provee un marco de referencia que permite el desarrollo de
ambientes de verificación de manera rápida y efectiva, que pueden ser reutilizados. Adicionalmente de recomienda buscar herramientas de software libre para
impulsar un laboratorio de verificación en la ucr. Como candidato principal
está SystemC.
2
Antecedentes
La disciplina de la verificación ha evolucionado de manera tan vertiginosa
como lo ha hecho la tecnologı́a de CI en sı́. Con la creciente complejidad en
los diseños, la tarea de verificar que estos se ajustan a la especificación llega a
consumir un 70 % del esfuerzo total (Bergeron, 2003). Es por esto que hoy en
dı́a existen decenas de metodologı́as y procesos que intentan facilitar la tarea
de verificación
2.1
El proceso de diseño de circuitos integrados
Todo circuito integrado empieza como una idea innovadora. Esta se pasa a un
equipo de mercadeo que estudia las necesidades del mercado y genera una lista
de caracterı́sticas que debe tener el producto. Esta lista llega a un equipo de
diseñadores de alto nivel (conocidos como arquitectos) que determinan cuáles
caracterı́sticas son posibles de implementar, y planean la estructura general
del circuito. Estos tres actores se ponen de acuerdo y finalmente producen la
especificación del producto.
Esta especificación incluye detalles de funcionamiento, interfaces y caracterı́sticas, más no de implementación.
Los diseñadores se encargan de implementar los requisitos de la especificación en un lenguaje de descripción a nivel de registros (rtl por sus siglas
en inglés).
Este modelo lo reciben los diseñadores fı́sicos, que crean lo que se conoce
como un mapa de nodos. En esencia, se describe al circuito al nivel de transistores y conexiones entre éstos. La tecnologı́a actual automatiza gran parte
de esta conversión de rtl a mapa de nodos, y ya se está logrando incluso
automatizar la generación de rtl.
Finalmente, este mapa de nodos es enviado a una fábrica en donde se imprime el producto en silicio. Los avances en miniaturización de transistores, y
las complejas tecnologı́as que esto implica, ha provocado que el costo de producir un prototipo sea extremadamente alto, superior a un millón de dólares.
Esto hace que reducir el peligro de que este prototipo tenga un defecto sea
una tarea muy importante. Es aquı́ donde entra la verificación.
Paralelo al proceso descrito anterirormente, trabajan los verificadores. Éstos indican alternativas arquitecturales que pueden facilitar la verificación del
diseño; verifican que la funcionalidad implementada en el rtl corresponda con
3
4
2 Antecedentes
lo que define la especificación, y finalmente comprueban que el mapa de nodos
sea equivalente al rtl. Esto se conoce como verificación pre-silicio.
Para repartir el trabajo de manera efectiva, la verificación pre-silicio se
realiza a nivel de bloque y a nivel de sistema. La especificación original se
subdivide en bloques que contienen un sólo aspecto de la funcionalidad del
todo. Éstos se revisan individualmente en la verificación de bloque. En la
verificación de sistema todos son conectados y se ejecutan pruebas de más
alto nivel.
Una vez que se tiene el prototipo, se debe verificar que esté libre de defectos.
Esto se realiza en la verificación post-silicio, que vuelve a aplicar muchas de
las pruebas pre-silico. Finalmente, se crea una baterı́a de pruebas a las que
se somete la lı́nea de producción para evitar la distribución de errores de
impresión.
2.2
Conceptos generales de verificación
Modelo de reconvergencia y el factor humano
En el proceso de diseño de un asic, se parte de una especificación para crear
un producto. Dicha implementación es exitosa en la medida en que su comportamiento sea correcto. Hoy en dı́a esta tarea no es automatizable, requiriendo
la imaginación y habilidad de un diseñador para realizar la conversión.
Esta intervención introduce un riesgo, la falibilidad humana. Esta puede
darse de dos maneras principales: una equivocación, donde el diseñador introduce un error en el diseño que causa que se comporte de manera diferente a la
que él espera. La segunda manera es un error, donde el diseñador se equivoca
al interpretar la especificación y su diseño produce el resultado que él espera,
pero que no es correcto. De estos dos problemas el segundo resulta ser más
serio y difı́cil de detectar y corregir.
Para mitigar el riesgo del factor humano, se ha desarrollado el modelo de
reconvergencia. En éste se separan los roles de diseño y verificación. A partir
de una misma especificación, se crea el rtl y el ambiente de verificación de
manera independiente.
Esto permite que diferentes interpretaciones de la especificación se revisen
unas contra otras, mejorando la detección de errores.
2.2. Conceptos generales de verificación
5
Figura 2.1: El modelo de reconvergencia (Bergeron, 2003)
Tipos de verificación
Una vez establecido el modelo de reconvergencia, la verificación en sı́ se puede
realizar de muchas maneras diferentes. Éstas varı́an en la minuciosidad con la
que se analiza el rtl y el esfuerzo requerido para implementarlos.
Algunas de las opciones que existen son:
• Verificación formal: En este se utilizan algoritmos para probar matemáticamente que el código cumple con ciertos requisitos, como transiciones
de estado especı́ficas. En general sólo es aplicable a módulos pequeños,
que se reutilizan frecuentemente en todo un diseño. Esto debido a que
con diseños más grandes la complejidad crece exponencialmente, impidiendo que se obtengan resultados en un marco de tiempo práctico.
• Emulación: El circuito es sintetizado en un fpga o dispositivo similar.
Esto permite ejercitar el código mucho más rápido que una simulación
de rtl. La mejora en velocidad es gracias a que la simulación está restringida por la naturaleza secuencial de el procesador.
• Chequeo de equivalencia: Es una verificación de más bajo nivel, verifica
que el mapa de nodos se comporte igual al rtl del que se derivó.
• Modelado: Se crea un modelo funcional del diseño en un lenguaje de más
alto nivel que rtl. Luego ambos son sometidos al mismo estı́mulo y se
verifica que produzcan el mismo resultado.
Para este proyecto se utilizó verificación mediante simulación. El rtl es
estimulado mediante un programa que captura sus reacciones, y éstas son
evaluadas para determinar si son aceptables. Esta captura y creación de estı́mulo se realiza mediante una banca de pruebas (testbench), que se desarrolló
mediante la metodologı́a uvm.
6
2 Antecedentes
Verificación de caja negra, blanca o gris
Este concepto, prestado de la disciplina de análisis de sistemas, se usa de forma
muy similar. La aplicación de estı́mulo y recolección de respuesta puede darse
a diferentes niveles en el rtl: En el caso de caja negra, éstos sólo se dan en
la interfaz especificada. En los otros dos, se «abre la caja» y se observa el
comportamiento interno del código en mayor o menor medida.
Estos tres métodos tienen diferentes ventajas y desventajas. El modelo de
caja negra respeta totalmente el modelo de reconvergencia, evitando que cualquier detalle de la implementación se incluya en la verificación, maximizando
el beneficio de tener a varios ingenieros trabajando en un mismo problema. La
ventaja del modelo de caja blanca es que puede llegar a crear escenarios en el
rtl que resultan extremadamente difı́ciles de alcanzar mediante uso solamente
de la interfaz externa.
Banco de pruebas auto-verificado (self-checking testbench)
En el pasado, las pruebas que se aplicaban para realizar verificación tenı́an
una envergadura muy grande. Por sı́ solas definı́an el estı́mulo que se aplicaba
al dut, observaban la respuesta, y determinaban si esta era correcta.
Esta y la siguiente sección separan la tradicional «prueba» que se aplica al
rtl en dos componentes separados: el estı́mulo y la verificación de la respuesta
del dut.
En una banca de pruebas auto-verificada se incluyen componentes que
comparan el estado del dut a un modelo definido por el verificador. Éstos
componentes se encuentran habilitados durante todas las pruebas, y constantemente revisan que el comportamiento se ajuste a la especificación. Esto se
realiza mediante monitores y tablas de verifiación, que se verán en la siguiente
sección.
Es importante notar que debido a esto una prueba que verifica un sumador
en un alu puede encontrar una defecto aparentemente no relacionado en los
registros de control, por ejemplo.
Pruebas aleatorias restringidas (constrained random testing)
Debido a que la verificación de comportamiento es realizado automáticamente
por el testbench, las pruebas que se desarrollan se limitan a generar suficiente
estı́mulo para que el dut atraviese todo su espacio de estados. En el pasado
esto se lograba mediante una gran cantidad de pruebas dirigidas, que aplicaban un estı́mulo especı́fico para activar una caracterı́stica determinada de la
especificación.
Este método se ve limitado por la imaginación del verificador, y resulta
insuficiente para cubrir grandes diseños. Esto se resuelve mediante verifica-
2.2. Conceptos generales de verificación
7
ción limitada aleatoria (constrained random testing). Con este método cada
prueba define aspectos generales de la caracterı́stica que se va a verificar, y
los detalles se rellenan de manera aleatoria. Luego cada prueba se corre de
manera repetida, con una semilla diferente, generando cientos de escenarios
de prueba que consiguen una cobertura más efectiva, en lo que se conoce como
una regresión.
Modelado a nivel de transacciones
El modelado a nivel de transacciones (tlm por sus siglas en ingles) es el
lenguaje con el que se comunican todos los componentes de una banca de
pruebas. Este abstrae los datos funcionales de los detalles de la implementación
y la capa en que se generaron, permitiendo que estos pasen de una abstracción
a otra y de un estándar a otro de manera compatible.
¿Cuándo se completa la verificación de un modelo?
El proceso para determinar que un diseño ha sido verificado es impreciso en
el mejor de los casos. Esto se debe a que el ideal, probar todas las posibles
combinaciones de entradas con todos los estados posibles de dut, requiere de
una cantidad de ciclos de procesador astronómica para todos excepto los más
simples diseños. Para solucionar este problema se han desarrollado una serie
de métricas que aproximan el nivel de verificación alcanzado para un diseño
particular (Vasudevan, 2006).
Los dos métodos que se utilizaron en este trabajo son:
• Cobertura de lı́nea o código: Evalúa la cantidad de lı́neas de código que
han sido ejecutadas en el rtl. Cuando se alcanza un 100 % en esta métrica se puede decir que la implementación está completamente ejercitada.
Esta cobertura comprende más que la ejecución individual de cada lı́nea: cuenta los caminos posibles que se pueden dar debido a expresiones
condicionales, y además cuenta las formas en que dichas expresiones
condicionales pueden activarse.
La cantidad de posibilidades que estos factores generan causa que alcanzar una cobertura del 100 % sea imposible en la práctica. Además, que
todo el código haya sido ejercitado no garantiza que se haya comportado
de manera correcta. Esto depende de los chequeadores, que analizan la
respuesta del dut.
• Cobertura funcional: es definida de manera manual por el verificador.
Éste se da a la tarea de marcar estados interesantes en los que puede
entrar el dut, y se recolecta información de la simulación cuando se
8
2 Antecedentes
dan. Esto es más limitado que la cobertura de lı́nea, pero reduce la
información que se graba a niveles más manejables. Ésta cobertura sı́
puede alcanzar el 100 % en un esfuerzo de verificación real.
2.3
La metodologı́a UVM
La metodologı́a de verificación universal (uvm por sus siglas en inglés) fue
desarrollada por Accellera Systems Initiative. Esta es una organización sin fines de lucro creada para avanzar los estándares de diseño de sistemas, modelado y verificación en la industria electrónica. Entre sus miembros se encuentran
amd, arm, Cadence, Synopsys, Mentor Graphics, Intel, entre otros.
uvm fue creado con la idea de establecer un estándar de verificación en la
industria. Este modulariza muchos de los componentes usados en verificación,
permitiendo un gran alto grado de reúso, y la integración del código de muchos
proveedores en una sola banca de pruebas. Esto se logra mediante tres conceptos clave que dan gran flexibilidad a un banco de pruebas que se aprovecha
de éstos.
Estructura del ambiente de verificación
Un testbench uvm se compone de una serie de componentes de verificación
universal (uvc pos sus siglas en inglés) interactuando entre sı́. Cada uvc
encapsula la información relacionada con un bloque especı́fico (conocido como
componente de verificación de módulo (module uvc)) o con una interfaz o
protocolo (componente de verificación de interfaz (interface uvc))(Robinson,
2007).
Además de estos elementos, el testbench cuenta con un manipulador de
secuencias que controlan los componentes para generar el estı́mulo, un mapa
de señales que permite que los componentes se conecten con el rtl, y otras
utilidades que refinan el comportamiento del ambiente.
Componentes de verificación universal
Los componentes de verificación universal son la unidad más pequeña reutilizable en uvm. Éstos incluyen una serie de bloques que permiten enviar estı́mulo
al dut, monitorear su respuesta y realizar la verificación al nivel de capa del
componente.
Estos bloques son (Rosenberg y Meade, 2010):
Agente El agente instancia y configura todos los demás elementos del componente. Puede ser pasivo, en cuyo caso sólo realiza labores de monitoreo,
2.3. La metodologı́a UVM
9
Figura 2.2: Diagrama de un uvc genérico
o activo, generando estı́mulo que se pasa al dut u otro componente. Un sólo
uvc pude tener varios agentes, por ejemplo para soportar interfaces múltiples.
Manipulador de secuencias (sequence driver) El manipulador de secuencias es utilizado por los agentes activos para estimular al dut. Aquı́ se
generan transacciones tlm que son pasadas de un módulo a otro hasta que
llegan a un modelo funcional de bus.
Modelo funcional de bus El modelo funcional de bus (bfm por sus siglas
en inglés) se encarga de estimular directamente al dut, mediante el mapa de
señales que le provee el ambiente.
Monitor El monitor puede recibir el estı́mulo directamente del dut o de
monitores subalternos en la forma de transacciones tlm. Éste se encarga de
la auto verificación mediante una tabla de verificación y recopila los datos de
cobertura funcional.
Tabla de verificación Este es el elemento clave para realizar la verificación.
Cada vez que se genera una transacción de estı́mulo tlm, esta viaja a través
de los monitores instanciados y es añadida a la tabla apropiada, dependiendo de las caracterı́sticas de la transacción: contenido de datos, dirección ip,
dirección de memoria, paridad, codificación, etc. Como puede observarse, las
transacciones codifican cualquier tipo de paquete o trama que puede usarse
en un diseño.
10
2 Antecedentes
Luego de que la transacción es generada, se pasa al bfm donde es convertida en estı́mulo. Si el dut está funcionando correctamente, este responde de
cierta manera que un monitor capta y usa para generar una transacción de
repuesta, que llega a ser emparejada con la primera transacción en la tabla.
Si al final de la prueba todas las transacciones están emparajedas, el dut
funciona correctamente.
Estos componentes cambian dependiendo de si el uvc que los contiene es
de módulo o de interfaz.
En el caso del module uvc, el monitor recibe las transacciones de monitores
subalternos en los interface uvc. Este es el componente que contiene a la tabla
de verificación principal donde se verifica la funcionalidad de bloque. Dado
que no interactúa directamente con el dut, no tiene un bfm. En su lugar, el
manejador de secuencias se conecta directamente con uvcs subordinados.
En los interface uvc, el monitor genera transacciones directamente de las
respuestas que observa en el dut. También es el punto final donde las transacciones se convierten en estı́mulo que se envı́a mediante el bfm. Las tablas de
verificación en este punto no son comunes, y se limitan a verificar el protocolo
relacionado con la interfaz que le concierne.
3
Desarrollo
3.1
Especificación del UART 16550
El transmisor-receptor ası́ncrono universal (uart por sus siglas en inglés) es
un bloque que se encarga de traducir datos de forma paralela (como se utilizan
dentro del SoC) a forma serial, para ser transmitidos a un dispositivo externo.
Éste es a su vez configurable para diferentes formatos y velocidades de tramas.
Un uart se puede utilizar para comunicarse con estándares seriales como el
rs-232, comunes en una gran variedad de aparatos.
El dut que se verificó en este proyecto es un diseño de código abierto que
pertenece a la fundación OpenCores.org. Pretende ser funcionalmente equivalente al dispositivo 16550A de National Semiconductors. Además, se comunica con el resto del SoC a través de la interface WISHBONE System-on-Chip
(SoC) Interconnect Architecture for Portable ip Cores, una interfaz estándar
para conectar los bloques de rtl de OpenCores.
Este uart funciona mediante 2 registros fifo principales. Uno contiene la
información que se está enviando y otro la información que se está recibiendo.
Otros registros controlan la comunicación con el SoC (interrupciones, nivel
en los fifos, etc) y la comunicación con otros dispositivos (disponibilidad del
SoC, etc).
Finalmente, el uart puede ponerse en modo loopback, donde se conectan
de manera interna los fifos de entrada y salida.
Interfaces (ver figura 3.1):
• wishbone: Estas señales implementan la interfaz para integrar el chip
con el resto del SoC. Consisten de:
– clk: Señal de reloj.
– wb rst i: Reset ası́ncrono.
– wb addr i: Dirección del registro (3 bits).
– wb sel i: Selección del bloque (4 bits).
– wb dat i: Salida de datos (8 bits).
– wb dat o: Entrada de datos (8 bits).
– wb we i: Selección de lectura o escritura.
11
12
3 Desarrollo
– wb stb i: Ciclo de transferencia.
– wb cyc i: Ciclo de bus en progreso.
– wb ack o: ack de transferencia.
• Información: int o Salida de interrupción.
• Salida: Son la señales que salen del chip, implementan una interfaz serial
de entrada y salida.
– stx pad o: Salida serial.
– srx pad i: Entrada serial.
– rts pad o: Petición de envı́o.
– dtr pad o: Terminal de datos disponible.
– cts pad i: Permiso de envı́o.
– dsr pad i: Datos disponibles.
– ri pad i: Indicador de anillo.
– dcd pad i: Detección de portador de datos.
Registros:
• Búfer receptor (Receiver buffer): Registro fifo que almacena hasta 16
bytes recibidos.
• Registro de cola de transmisión (Transmitter holding register): Registro
fifo que almacena hasta 16 bytes por enviar.
• Habilitación de interrupción (Interrupt enable): Máscara para las interrupciones: Datos recibidos, cola de envı́o vacı́a, estado de lı́nea de
recepción, y estado de modem.
• Identificación de interrupción (Interrupt identification): Identifica la fuente de interrupción: Esta de lı́nea de recepción, datos recibidos, timeout,
cola de envı́o vacı́a y estado de modem.
• Control de fifo (fifo control): Escribir a este registro puede resetear el
fifo de entrada o salida, y define el nivel al que se dispara la interrupción
por nivel en el fifo de recepción.
• Control de lı́nea (Line control): Controla la codificación de las tramas:
paridad, stopbits, startbits, largo de trama. Además puede forzar la salida serial a 0.
3.1. Especificación del UART 16550
13
• Control de módem (Modem control): controla las señalesde salida rts pad o,
dtr pad o y pone al uart en modo loopback.
• Estado de lı́nea (Line status): Indica al SoC el estado de la lı́nea: datos disponibles, error de overflow, paridad, stopbit, o trama, transmisor
vacı́o.
• Estado de módem (Modem status): Contiene las entradas de control al
uart: cts pad i, dsr pad i, ri pad i, dcd pad i.
• Registro de división (Divisor latches): Controla el divisor de reloj para la
Reloj del sistema
velocidad en baudios de transmisión. (Divisor del reloj = 16·Velocidad
en baudios )
Figura 3.1: Diagrama de bloques del uart 16550 (Gorban, 2002)
14
3 Desarrollo
3.2
Plan de verificación
El plan de verificación desarrollado con la metodologı́a UVM consta de dos
partes: casos de prueba y puntos de cobertura funcional.
Los casos de prueba consisten de una serie de secuencias que definen el
estı́mulo que le será introducido al dut. Éstos buscan lograr que el dispositivo atraviese su espacio de estados completamente de manera eficiente (es
decir, minimizando los recursos de simulación requeridos). Debido al uso de
aleatorización restringida, la cantidad de casos de prueba que se deben definir
es pequeña en comparación con las que se utilizarı́an en un enfoque de pruebas dirigidas. Sin embargo, esta misma aleatoriedad hace necesaria la segunda
parte del plan de verificación, la cobertura funcional.
Cuadro 3.1: Casos de prueba
Nombre de la prueba
Descripción
register test.e
send frame.e
receive frame.e
receive frame err.e
loopback.e
Escribir y leer todos los registros del dut
Mandar tramas con todos los parámetros posibles aleatorizados.
Recibir tramas con todos los parámetros posibles aleatorizados
Recibir tramas con errores de paridad, stopbit, startbit.
Habilitar modo loopback y enviar tramas. Comprobar que regresan.
Parámetros que se aleatorizan en las pruebas de transmisión:
• Número de tramas (Hasta que el fifo este vacı́o, medio y lleno)
• Número de bits por trama (5,6,7 u 8)
• Número de bits de parada (1 o 2)
• Paridad (Par o impar)
Estos casos de prueba en teorı́a bastan para verificar toda la funcionalidad
del dut. En la práctica el limitante más importante es la cantidad de regresiones que se pueden correr: Pueden requerirse muchos cientos de semillas para
que se dé alguna configuración especı́fica. Si en un punto avanzado del proceso
de verificación hay algún estado interesante que no se ha probado, se crea una
nueva prueba con más restricciones para verificar esa funcionalidad.
La segunda parte del plan de verificación consiste de los puntos de cobertura. La idea es medir el porcentaje de estados que el dut ha recorrido. Esto
permite determinar el progreso que se ha hecho en el esfuerzo de verificación
y la necesidad de crear nuevas pruebas.
Los puntos de cobertura se definieron en 2 grupos: La interfaz de uart
con el SoC y las tramas que atraviesan al uart.
3.3. El ambiente de verificación
15
• Interfaz uart<->SoC cubre los registros de información del dut. Además cubre la señal de salida de interrupciones.
• Interfaz out<->uart cubre las posible tramas que el dut puede enviar
o recibir. Los puntos que cubren tramas ilegales sólo se evalúan con
paquetes entrantes: Si el uart genera una trama errónea el test falla y
se ha encontrado un defecto en el dispositivo.
UART<->SoC
Cuadro 3.2: Puntos de cobertura
Grupo de cobertura
Nombre del punto
Descripción
Buckets
cov tx fifo level e
cov rx fifo level e
cov int register e
tx fifo level
rx fifo level
intr type
rx data avai
tx fifo empty
rx line status
modem status
uart int
uart loobpack
Uso del tx fifo
Uso del rx fifo
Interrupciones generadas
Intr. «Datos recibidos»
Intr. «Nada que transmitir»
Intr. «Estado de lı́nea»
Intr. «Estado de módem»
Salida de intr. «int o»
Modo loopback habilitado
Vacı́o, 1 a 31, Lleno
Vacı́o, 1 a 31, Lleno
0,1,2,3
0,1
0,1
0,1
0,1
0,1
1
parity type
with parity
stopbit type
databit type
delay to next frame
legal frame
has startbit err
has parity err
has stopbit err
payload lsb
payload msb
payload msb payload lsb
databit type stopbit type parity type
cross parity type has parity err
Paridad en trama de salida
Trama incluye bit de paridad
Cantidad de bits de parada
Cantidad de bits en trama
Retraso entre tramas
Trama legal
Error en bit de inicio
Error en bit de paridad
Error en bit final
Bit menos significativo
Bit más significativo
Punto de cruce
Punto de cruce
Punto de cruce
Par, Impar
Si, no
1,2
5,6,7,8
0 a 255 en grupos de 64
Si, no
Si, no
Si, no
Si, no
Si, no
Si, no
cov int mask register e
OUT<->UART
cov uart int e
cov uart loopback
mon frame done
Por último, además de la cobertura funcional definida manualmente, en la
regresión se recopilará cobertura de código, para disponer de una métrica con
la cual evaluar el esfuerzo de verificación.
3.3
El ambiente de verificación
El ambiente de verificación utilizado en este proyecto se basa en un ejemplo
desarrollado por Cadence para demostrar la implementación de uvm en el
lenguaje Specman e. Este se compone de 3 uvcs. Se instancian bajo el ambiente principal, son interconectados y configurados para trabajar en conjunto.
La funcionalidad se divide en la interfaz con el SoC, la interfaz uart, y las
caracterı́sticas particulares del uart 16550.
Para implementar las pruebas requeridas por el plan de verificación se
expandió la capacidad de generación de estı́mulo y recolección de cobertura.
16
3 Desarrollo
Figura 3.2: Diagrama del ambiente de verificación (Cadence, 2012)
APB Interface UVC
El APB Interface UVC modela el resto del SoC al que está conectado el uart.
Éste se conecta directamente con la interfaz wishbone del rtl y se utiliza
para realizar operaciones de escritura y lectura a los registros del DUT. Las
secuencias que provee son del más bajo nivel, es decir, escribir o leer a una
dirección del espacio de memoria. Estas secuencias son utilizadas por el uart
Module UVC para crear secuencias de más alto nivel, como «configurar uart
para recibir tramas de 6 bytes a 9600 baudios por segundo».
La interfaz wishbone usa un esquema maestro-esclavo para manejar transacciones. En un SoC el uart funciona como un esclavo, por lo que se instancia
un agente maestro del APB. Éste agente maestro usa un bfm para estimular
al dut. Además de esto, se instancia un agente esclavo, que monitorea el bus
para detectar las repuestas del uart.
Además de generar estı́mulo, esta interfaz implementa un evaluador de
señales. De esta manera se verifica que el wishbone esté implementado correctamente en el dut.
3.3. El ambiente de verificación
17
UART Interface UVC
El uart Interface uvc es un análogo del componente anterior. En este caso
modela un dispositivo con interfaz serial que es conectado al dut. Se instancian
dos agentes: uno funciona como emisor y el otro como receptor.
El emisor puede ser configurado para enviar tramas con errores, como el
bit de paridad, de parada o de inicio. Esto permite observar el comportamiento
del uart cuando se le conecta un dispositivo errático. El receptor se limita a
detectar errores en las tramas, y levantar un error cuando el dut se comporta
de manera inesperada.
En este nivel, como en en APB Interface UVC, se realiza verificación al
nivel de señales solamente.
UART Module UVC
Este módulo es el director de orquesta en la verificación a nivel de bloque.
Cumple una gran cantidad de tareas bastante diversas, cada una vital para la
ejecución efectiva de la pruebas del plan de verificación.
En primer lugar, instancia y configura a los interface uvcs, de manera
que éstos funcionen de manera compatible con el dut. Cuando las diferentes
partes del ambiente son instanciadas, reciben un paquete de datos llamado
config. Éste indica el nombre de las señales a monitorear en el rtl (utilizado
por los bfm), el scoreboard al que los monitores deben pasar las transacciones
generadas, y el estado del dut: Velocidad en baudios de la interfaz, paridad,
cantidad de stopbits, cantidad de startbits, etcétera.
En segundo lugar, define un número de secuencias estándar que las pruebas
del plan pueden usar para generar el estı́mulo apropiado. Estas van desde una
secuencia que configura los registros del uart, a escribir al registro fifo de
salida para enviar una serie de paquetes, a leer del fifo de llegada, a añadir
una trama a la cola de envı́o del agente emisor uart.
En tercer lugar, ejecuta la verificación a nivel de transacciones. Esto se hace
a través de una tabla de verificación que recibe transacciones del apb y del
uart, y verifica que todos los paquetes enviados y recibidos del dut lleguen
a su destino final. Tres elementos claves estan operando en este proceso:
Cuando el apb Interface uvc escribe al fifo de salida, o lee del fifo
de llegada, genera una transacción apb que se pasa al module uvc. El uart
Interface uvc genera transacciones uart que también se pasan al module uvc
cuando recibe o envı́a una trama. Por último, el module uvc define una serie
de reglas para emparejar las transacciones apb con las transacciones uart y
verificar que el paquete haya sido transmitido de manera correcta.
En cuarto y último lugar, el uart module uvc define los puntos de cobertura con los que se evaluará el desempeño de las pruebas del plan de verificación.
18
3 Desarrollo
Esto se hace definiendo una serie de puntos claves en las secuencias; cada vez
que son tocados indican al simulador que recopile la información indicada del
ambiente.
3.4
Implementación del plan de verificación
Para implementar las pruebas requeridas por el plan de verificación se expandió la capacidad del ejemplo de Cadence en 3 áreas diferentes: En verificación, se expandió la tabla de verificación implementada para que identificara
transacciones de loopback. En cobertura, se modificó la implementación del
uart module e interface uvc para que incorporara los puntos indicados por el
plan de verificación. Por último, se crearon las pruebas para generar el estı́mulo
que requerı́a el plan.
Verificación del DUT
La verificación de transacción de paquetes se realiza en el uart module uvc
mediante una tabla de verificación. Esta recibe transacciones de tipo uart y
de tipo apb. Estas se emparejan dependiendo de la prueba que está siendo
aplicada:
Cuando se envı́a una trama, se genera una transacción apb al escribir al
fifo de salida del uart. Esta es añadida a la tabla. Cierto tiempo después,
el monitor del uart interface uvc detecta actividad en el dut y genera una
transacción uart. La tabla recibe la segunda transacción e intenta emparejarla con las transacciones que ya ha recibido. Si coinciden la transmisión fue
exitosa.
En las pruebas de receive frame, se crea una transacción uart que se
añade a la tabla. Al leer el fifo de entrada del dut, el monitor de la interfaz
apb genera una transacción apropiada que la tabla de verificación empareja.
Si coinciden la recepción fue exitosa.
Por último, en la prueba loopback se emparejan dos transacciones del tipo
apb.
//uart_ctrl_scoreboard.e
unit uart_ctrl_scoreboard like uvm_scoreboard {
//Un port es el punto donde las transacciones son recibidas por la tabla de verificación
//receive_frame y receive_frame_err
scbd_port uart_frame_add : add uart_frame_s;
scbd_port apb_trans_match : match apb_trans_s;
//send_frame
scbd_port apb_trans_add
: add apb_trans_s;
scbd_port uart_frame_match : match uart_frame_s;
//Se a~
nade un UART frame al scoreboard: receive_frame y receive_frame_err
uart_frame_add_predict(item : uart_frame_s) is only {
add_to_scbd(item);
set_match_port(item, apb_trans_match);
3.4. Implementación del plan de verificación
19
message(LOW,"Adding the UART Frame into the scoreboard ") {
print item using hex;
};
};
//Se a~
nade un APB frame al scoreboard: loopback y send_frame
apb_trans_add_predict(item : apb_trans_s) is only {
//Se descartan escrituras que no sean al FIFO de salida del UART
if(item.addr == base_addr + UART_TX_FIFO and
item.direction == WRITE) {
//Si la transacción es loopback, se empareja con una transacción APB, si no, UART
if (item.loopback_transaction) {
add_to_scbd(item);
set_match_port(item, apb_trans_match);
message(LOW,"Adding the APB Frame into the scoreboard ") {
print item using hex;
};
} else {
add_to_scbd(item);
set_match_port(item, uart_frame_match);
message(LOW,"Adding the APB Frame into the scoreboard ") {
print item using hex;
};
};
};
}; // apb_trans_add_predict()
//Método para emparejar transacciones APB: loopback y receive_frame
apb_trans_match_reconstruct( item : apb_trans_s) is only {
if(item.addr == base_addr + UART_RX_FIFO and
item.direction == READ) {
match_in_scbd(item);
message(LOW,"Looking for APB Frame match into the scoreboard ") {
print item using hex;
};
};
};
//Método para emparejar transacciones UART: send_frame
uart_frame_match_reconstruct( item : uart_frame_s) is first {;
message(LOW,"Looking for UART Frame match into the scoreboard ") {
print item using hex;
};
};
//Por último, este método se llama para determinar si 2 transacciones coinciden: en este caso
//se utilizan los datos transmitidos para comparar.
compute_key(item : any_struct ): uint is only {
var data_list: list of bit;
if item is a apb_trans_s then {
data_list = pack(NULL, item.as_a(apb_trans_s).data);
};
if item is a uart_frame_s then {
data_list = pack(NULL, item.as_a(uart_frame_s).payload);
};
data_list.resize(data_len, TRUE, 0, TRUE);
data_list.resize(8, TRUE, 0, TRUE);
return data_list.crc_32(0, 1);
};
};
20
3 Desarrollo
Recolección de cobertura
La recolección de cobertura se da en dos de los módulos: el interface y module
uart uvcs.
El interface UVC procesa las tramas que son enviadas y recibidas por el
uart. En este módulo se implementó el punto de cobertura mon frame done,
en dos versiones diferentes.
La primera recoge información de tramas que son enviadas al dut, por lo
que recopila información de errores inyectados con los ı́tems has startbit err,
has stopbit err, has parity err.
La segunda versión los omite, ya que cubre las tramas emitidas por el dut:
un error en éstas muestra un defecto en el rtl. Además no cubre el retardo
entre tramas, que es constante en el caso del dut.
//uart_coverage.e
extend TX_AGENT uart_monitor_u {
cover mon_frame_done_tx using per_unit_instance is { //Aquı́ se declara el punto de cobertura
// Protocolo
item stopbit_type:uart_frame_stopbit_t=current_frame.stopbit_type; //Aquı́ se declaran los ı́tems asociados.
item parity_type:uart_frame_parity_t=current_frame.parity_type using ignore= parity_type==SPACE;
item databit_type:uart_frame_databit_t=current_frame.databit_type;
item with_parity:bool=current_frame.with_parity;
// Retardo de trama
item delay_to_next_frame: uint(bits :8)=current_frame.delay_to_next_frame
ranges = {range ([0 .. 255],"",64) },at_least = 10;
using
// Inyección de errores
item legal_frame:bool=current_frame.legal_frame;
item has_startbit_err:bool=current_frame.has_startbit_err;
item has_parity_err:bool=current_frame.has_parity_err;
item has_stopbit_err:bool=current_frame.has_stopbit_err;
// Datos enviados
item payload_lsb: bit = current_frame.payload[0];
item payload_msb: bit = current_frame.payload[current_frame.p_len-1];
// Puntos de cruce
cross payload_msb, payload_lsb;
cross databit_type, stopbit_type, parity_type;
cross parity_type, has_parity_err using ignore = parity_type==NONE;
};
};
extend RX_AGENT uart_monitor_u {
cover mon_frame_done_rx using per_unit_instance is {
// Protocolo
item parity_type:uart_frame_parity_t=current_frame.parity_type using ignore= parity_type==SPACE;
item stopbit_type:uart_frame_stopbit_t=current_frame.stopbit_type;
item databit_type:uart_frame_databit_t=current_frame.databit_type;
item with_parity:bool=current_frame.with_parity;
// Datos enviados
item payload_lsb: bit = current_frame.payload[0];
item payload_msb: bit = current_frame.payload[current_frame.p_len-1];
// Puntos de cruce
cross payload_msb, payload_lsb;
cross databit_type, stopbit_type, parity_type;
};
};
3.4. Implementación del plan de verificación
21
Se observa que la distinción entre trama saliente o entrante depende del
agente en que el monitor ha sido instanciado: RX AGENT observa los paquetes emitidos por el dut, y TX AGENT los que emite el testbench. Sin
importar el agente, el monitor detecta de manera automática actividad en los
puertos y determina cuando una trama se ha completado para recolectar la
cobertura:
//uart_monitor_h.e
unit uart_monitor_u like uvm_monitor {
//Eventos de cobertura
event mon_frame_done_tx;
event mon_frame_done_rx;
//Cuando el monitor detecta el final de una trama, emite el evento mon_frame_ended.
//Este a su vez emite el evento que realiza la cobertura
on mon_frame_ended {
frame_done(current_frame);
emit current_frame.frame_done;
emit mon_frame_done_tx;
emit mon_frame_done_rx;
};
};
El module UVC se encarga de la cobertura de los registros y algunas
señales del uart 16550. Esta cobertura no se realiza mediante un monitor; se
accesan de manera directa las señales internas de rtl. Esto permite recolectar
información de cobertura más precisa y de una manera más simple.
Al no limitarse a usar la interfaz externa del bloque, se rompe con el
modelo de caja negra, reduciendo la portabilidad del código. También queda
atado el ambiente a algunos detalles de la implementación. En esta situación,
se decidió que la reducción en el tiempo de implementación ameritaba el uso
de esta técnica.
//uart_ctrl_cover.e
unit uart_ctrl_env_cover_u {
// Tx FIFO level
//Primero se declara un puerto que se conecta al RTL specificado por hdl_path()
tx_fifo_level_p: in simple_port of uint(bits:5) is instance;
keep bind(tx_fifo_level_p, external);
keep soft tx_fifo_level_p.hdl_path() == "regs.transmitter.tf_count";
//Luego se asocia el evento de cobertura al puerto creado
event cov_tx_fifo_level_e is change(tx_fifo_level_p$) @sim;
//Finalmente se indican los ı́temes a cubrir
cover cov_tx_fifo_level_e using per_unit_instance is {
item tx_fifo_level : uint(bits:7) = tx_fifo_level_p$ using
ranges = {
range([0],
"Empty");
range([1..14],
"1 to 14");
range([15],
"FIFO full");
};
};
// Rx FIFO level
rx_fifo_level_p: in simple_port of uint(bits:5) is instance;
keep bind(rx_fifo_level_p, external);
keep soft rx_fifo_level_p.hdl_path() == "regs.receiver.rf_count";
event cov_rx_fifo_level_e is change(rx_fifo_level_p$) @sim;
cover cov_rx_fifo_level_e using per_unit_instance is {
22
item rx_fifo_level
ranges = {
range([0],
range([1..14],
range([15],
};
};
3 Desarrollo
: uint(bits:7) = rx_fifo_level_p$ using
"Empty");
"1 to 14");
"FIFO full");
// Interrupt Channel Status Reg
int_register_p: in simple_port of uint(bits:4) is instance;
keep bind(int_register_p, external);
keep soft int_register_p.hdl_path() == "regs.iir";
event cov_int_register_e is change(int_register_p$) @sim;
cover cov_int_register_e using per_unit_instance is {
item intr_1 : uint(bits : 1) = int_mask_register_p$[0:0];
item intr_2 : uint(bits : 1) = int_mask_register_p$[1:1];
item intr_3 : uint(bits : 1) = int_mask_register_p$[2:2];
item intr_4 : uint(bits : 1) = int_mask_register_p$[3:3];
};
// Interrupt Mask Reg
int_mask_register_p: in simple_port of uint(bits:4) is instance;
keep bind(int_mask_register_p, external);
keep soft int_mask_register_p.hdl_path() == "regs.ier";
event cov_int_mask_register_e
cover cov_int_mask_register_e
item rx_data_avai
: bit =
item tx_fifo_empty : bit =
item rx_line_status : bit =
item modem_status
: bit =
};
is change(int_mask_register_p$) @sim;
using per_unit_instance is {
int_mask_register_p$[0:0];
int_mask_register_p$[1:1];
int_mask_register_p$[2:2];
int_mask_register_p$[3:3];
// Top level interrupt signal
uart_int_p: in simple_port of bit is instance;
keep bind(uart_int_p, external);
keep soft uart_int_p.hdl_path() == "int_o";
event cov_uart_int_e is change(uart_int_p$) @sim; \\$
cover cov_uart_int_e using per_unit_instance is {
item uart_int: bit = uart_int_p$; \\$
};
// Loopback Mode enabled
//En este caso, en lugar de declarar un puerto, se conecta el evento
//de manera directa al RTL
event cov_uart_loopback is change(’~/top.uart_dut.regs.loopback’) @sim;
cover cov_uart_loopback using per_unit_instance is {
item uart_loopback: bit = ’~/top.uart_dut.regs.loopback’ using ignore = uart_loopback == 0;
};
};
La cobertura se recolecta cada vez que cambia el estado de una de las
señales observadas.
Implementación de las pruebas
Las pruebas del plan de verificación se implementan mediante un archivo de
prueba. En uvm, este tiene la capacidad de cambiar la configuración de los
diferentes módulos, generar secuencias, y crear estı́mulo de manera directa.
Las primeras etapas de ejecución son comunes a todas las pruebas.
3.4. Implementación del plan de verificación
23
En primer lugar, se saca al dut de reset. Esto lo realiza de manera automática el apb interface uvc:
\\apb_master_bfm.e
tf_reset() @tf_phase_clock is also {
message(LOW, "Starting RESET phase ");
p_smp.sig_penable$ = 0; \\$
};
tf_hard_reset() @tf_phase_clock is also {
message(LOW, "Starting HARD_RESET phase ");
p_smp.sig_presetn$ = 0; \\$
};
tf_init_dut() @tf_phase_clock is also {
p_smp.sig_presetn$ = 1; \\$
};
Los métodos tf reset, tf hard reset y tf init dut son llamados de manera
automática por el simulador. Esto permite que todos los interface uvcs salgan
de reset simultáneamente. En el caso de este proyecto, sólo el apb interface
uvc controla el reset del dut.
Una vez afuera del reset, se inicia la prueba. Ésta procede a configurar el
ambiente:
\\<nombre del test>.e
extend sys {
// Eventos de sincronización
event VR_SB_uart_config_done;
event VR_SB_uart_data_done;
event VR_SB_uart_read_done;
event VR_SB_uart_div_config_done;
event reset_done is @uart_ctrl_sve.uart_sync.reset_ended;
// Duración máxima del test
setup() is also {
set_config(run, tick_max,MAX_INT);
};
};
«sys» es el ambiente global. Los eventos declarados en él se usan para
señalizar el progreso de la prueba entre métodos. No todas las pruebas usan
todos los eventos. Además de eventos, se configura la duración máxima de la
prueba, para prevenir ciclos infinitos.
\\<nombre del test>.e
extend uart_env_config {
keep parity_type in [ODD, EVEN, NONE];
keep stopbit_type in [ONE,TWO];
keep databit_type in [FIVE,SIX,SEVEN,EIGHT];
keep parity_type == NONE => with_parity == FALSE;
//Restricciones interesantes
keep databit_type == FIVE => stopbit_type == ONE;
keep with_parity == TRUE;
};
«uart env config» guarda la configuración del dut. Éste se pasa a los diferentes monitores y bfms para que generen las tramas apropiadas. Se pueden
observar 2 restricciones interesantes cuyo propósito no resulta obvio:
24
3 Desarrollo
• «with parity == TRUE»: Esta restricción sólo se añade en el caso de la
prueba receive frame err.e, ya que para insertar un error de paridad se
necesita que haya un bit de paridad en primer lugar.
• «databit type == FIVE =>stopbit type == ONE»: El dut presenta
un caso esquina: cuando las tramas son de cinco bits, configurar dos
bits de parada hace se generen 1.5 bits de parada. Esto causa que los
monitores se desincronizen y generen errores de manera esporádica.
Una vez configurado el ambiente, es necesario configurar al dut de la
misma manera. La prueba usa al apb interface uvc para escribir a los registros
del uart y configurarlo.
extend MAIN
!div_lsb
!div_msb
!lcr
!mdm
MAIN_TEST apb_master_sequence {
: WRITE apb::apb_master_transaction;
: WRITE apb::apb_master_transaction;
: WRITE apb::apb_master_transaction;
: WRITE apb::apb_master_transaction;
config : uart_env_config;
keep config == get_enclosing_unit(uart_ctrl_sve_u).uart_if.config;
!parity_sel
!parity_val
!stopbit_val
!datalen_val
!data_value
:
:
:
:
:
uint(bits:1);
uint(bits:1);
uint(bits:1);
uint(bits:2);
uint(bits:32);
body() @driver.clock is only {
wait [400] * cycle;
driver.wait_for_grant(me);
//Se escribe la máscara de interrupciones al registro de control de interrupciones
gen trans keeping {
it.addr == UART_INTR_EN_REG;
it.data == intr_mask;
it.direction == WRITE;
};
driver.deliver_item(trans);
driver.wait_for_item_done(me);
//Se escribe al line_control_register para poder escribir al divisor de reloj.
gen trans keeping {
it.addr == UART_LINE_CNTRL_REG;
it.data == 32’h83000000;
it.direction == WRITE;
};
driver.wait_for_grant(me);
driver.deliver_item(trans);
driver.wait_for_item_done(me);
//Se escribe al divisor de reloj.
do div_msb keeping {
it.addr == UART_DIVISOR_MSB_REG;
it.data == 0;
};
do div_lsb keeping {
it.addr == UART_DIVISOR_LSB_REG;
it.data == 1;
};
3.4. Implementación del plan de verificación
25
//Se escribe al registro de control de modem. Esto habilita la prueba de loopback
do mdm keeping {
it.addr == UART_MODEM_CNTRL_REG;
it.data == 32’h10; \\ ó 32’h00;
};
//Por último se lee la configuración del ambiente para generar el valor a escribir al line_control_register
var stop_bits := config.stopbit_type;
var parity
:= config.parity_type;
var data_len := config.databit_type;
case (parity) {
EVEN : { parity_sel
ODD : { parity_sel
SPACE: { parity_sel
NONE : { parity_sel
};
=
=
=
=
1’b1;
1’b1;
1’b0;
1’b0;
parity_val
parity_val
parity_val
parity_val
=
=
=
=
1;};
0;};
0;dut_error("UNSUPPORTED PARITY");};
0;};
case (stop_bits) {
ONE
: { stopbit_val = 0};
TWO
: { stopbit_val = 1};
default : { };
};
case (data_len) {
SIX
: { datalen_val = 1};
SEVEN : { datalen_val = 2};
EIGHT : { datalen_val = 3};
};
data_value = pack(packing.high, 3’b0, parity_val , parity_sel, stopbit_val, datalen_val , 24’b0);
do lcr keeping {
it.addr == UART_LINE_CNTRL_REG;
it.data == data_value ;
};
wait [100] * cycle;
//Se emite este evento para indicar que el DUT está configurado y la prueba puede proceder.
emit sys.VR_SB_uart_config_done;
};
};
Esta última secuencia varı́a entre pruebas, ya que cada una necesita configurar al dut de manera distinta. La estructura sin embargo se conserva. Para
el caso de register test, la prueba termina en este punto. Ésta escribe a todos
los registros con valores seleccionados al azar.
Las demás pruebas divergen lo suficiente para que se estudien por separado.
Loopback
La prueba de loopback no utiliza uart interface uvc. Esta se limita a escribir
al fifo de salida del uart, esperar un perı́odo de tiempo, y leer el fifo de
entrada.
//Esta es la secuencia principal de la prueba. Se limita a esperar a que la
//secuencia maestra del APB termine para terminar la prueba.
extend MAIN uart::uart_sequence {
body() @driver.clock is only {
driver.raise_objection(TEST_DONE);
26
3 Desarrollo
wait @sys.VR_SB_uart_config_done;
wait @sys.VR_SB_uart_read_done;
driver.drop_objection(TEST_DONE);
};
};
//Esta es la secuencia maestra del APB. Cuando termina la prueba, emite sys.VR_SB_uart_read_done
extend MAIN MAIN_TEST apb_master_sequence {
!fifowr: WRITE apb::apb_master_sequence;
!fiford: READ apb::apb_master_sequence;
body() @driver.clock is also {
wait @sys.VR_SB_uart_config_done;
do fifowr keeping {
it.addr == 0;
it.loopback_transaction == TRUE;
};
wait [10000];
for i from 0 to tx_count {
do fiford keeping {
it.addr == 0;
};
};
emit sys.VR_SB_uart_read_done;
};
};
fifowr es una secuencia que escribe una serie de paquetes al fifo de salida
del uart. El campo loop indica que la transacción es loopback, por lo que la
tabla de verificación del module uvc la emparejará con otra transacción apb
en lugar de una transacción uart.
fiford lee del fifo de entrada del dut. Las transacciones generadas se
emparejarán con las de fifowr. Si todas se correponden apropiadamente, la
prueba pasa de manera exitosa.
Send frame
Send frame verifica que las tramas viajen correctamente del SoC a un dispositivo externo.
extend MAIN uart::uart_sequence {
body() @driver.clock is only {
driver.raise_objection(TEST_DONE);
wait @sys.VR_SB_uart_config_done;
wait @sys.VR_SB_uart_data_done
wait [10000];
driver.drop_objection(TEST_DONE);
};
};
extend MAIN MAIN_TEST apb_master_sequence {
!fifowr: WRITE apb::apb_master_sequence;
body() @driver.clock is also {
wait @sys.VR_SB_uart_config_done;
for i from 0 to tx_count {
do fifowr keeping {
it.addr == 0;
};
};
emit @sys.VR_SB_uart_data_done;
};
};
3.5. Análisis de resultados
27
Esta prueba usa al apb interface uvc para escribir al fifo de salida del
uart. Como éste no esta configurado en modo loopback, empezará a transmitir las tramas por el puerto de salida. Éstas son captadas por el monitor del
uart interface uvc.
El monitor genera transacciones uart que son emparejadas con las transacciones apb que se crearon al escribir al fifo. Se verifica que estas coincidan
para que la prueba pase.
Receive frame y receive frame err
Por último, estos tests configuran al uart interface uvc para emitir tramas.
extend MAIN uart::uart_sequence {
body() @driver.clock is only {
driver.raise_objection(TEST_DONE);
wait @sys.VR_SB_uart_config_done;
for i from 0 to tx_count {
do frame keeping {
it.legal_frame == FALSE;
it.has_startbit_err == FALSE;
it.has_parity_err == FALSE; //Este campo es TRUE para recieve_frame_err
it.has_stopbit_err == FALSE;
};
};
emit sys.VR_SB_uart_data_done;
wait @sys.VR_SB_uart_read_done;
driver.drop_objection(TEST_DONE);
};
};
extend MAIN MAIN_TEST apb_master_sequence {
!fiford: READ apb::apb_master_sequence;
body() @driver.clock is also {
wait @sys.VR_SB_uart_data_done;
for i from 0 to tx_count {
do fiford keeping {
it.addr == 0;
};
};
emit sys.VR_SB_uart_read_done;
};
};
El comando «do frame» genera una trama uart con las propiedades especificadas. Ésta es añadida a la cola de emisión del bfm y finalmente emitida.
El monitor uart detecta esta transmisión, genera una transacción uart y la
añade a la tabla de verificación.
Luego se ejecuta la secuencia fiford, que lee el fifo de entrada del dut.
El monitor apb genera transacciones apb que son emparejadas con las transacciones añadidas previamente. Si los datos difieren, se genera un error.
3.5
Análisis de resultados
Para la evaluación final del dut, se corrió cada prueba 500 veces, con una
semilla diferente cada vez. Esto da un total de 2500 escenarios posibles usados
28
3 Desarrollo
para evaluar el uart. Para un producto comercial, estas pruebas se corren
durante muchos meses, con miles de semillas diferentes, para reducir el riesgo
de defectos no detectados en el rtl a la hora de fabricar el SoC.
La regresión realizada se vio limitada principalmente por el espacio en disco
que ocupan los datos de cobertura. Cada ejecución de una prueba genera 10
MiB de datos, para un total de 23 GiB. Por último, esta regresión tomó 41
horas para completarse.
En cada corrida se recopiló información de la cobertura funcional obtenida, ası́ como de la cobertura de código. Ninguna prueba detectó un error en
el dut, como es de esperarse en un rtl que ha estado en circulación desde el
año 2002. Sin embargo, los datos de cobertura obtenidos permitirán evaluar el
nivel de éxito obtenido en la implementación del plan de verificación: Una alta
cobertura funcional indica que las pruebas desarrolladas ejercitan apropiadamente los estados interesantes del dut. Una alta cobertura de código indica
que el plan de verificación en sı́ es minucioso.
La verificación es una disciplina que intenta reducir el riesgo al máximo
con la mı́nima cantidad de recursos. La información de cobertura recopilada
permite identificar pruebas con alto desempeño, que proveen alta cobertura
con tiempos de ejecución bajos.
Desempeño por prueba
register test
Esta prueba es la más rápida de las pruebas implementadas. Al no tener que
simularse el intercambio de datos con un dispositivo, este tipo de pruebas se
desarrollan temprano en el ciclo de verificación de rtl.
En promedio cada corrida de esta prueba toma 45 segundos. En un ambiente de producción, con varios diseñadores y verificadores produciendo código
para el ambiente de verificación, esto resulta muy útil. Sirve como una prueba
de sanidad para el testbench y el dut, permite determinar rápidamente si un
cambio introducido ha quebrado el ambiente de verificación.
La cobertura funcional obtenida con las 500 corridas se puede observar en
la figura 3.3. Se logró una cobertura del 88 % en la interfaz uart<->SoC, que
corresponde a los registros en los que se enfoca la prueba. No se llegó a cubrir
un 100 % debido a la cantidad limitada de pruebas que se ejecutaron. En la
interfaz out<->uart se dio una cobertura del 0 % para tramas entrantes y
salientes como se esperaba.
La cobertura de código (3.4) obtenida revela una de las limitaciones de
este enfoque. Sólamente sacar al dut de reset ejercita una gran parte del rtl,
por lo que rápidamente se obtiene valores «altos» como el 72 % en este caso.
3.5. Análisis de resultados
29
Figura 3.3: Cobertura funcional register test
Estimular 30 % restante resulta mucho más trabajoso que lo que indican los
primeros esfuerzos.
A pesar de las limitaciones mencionadas en los antecedentes de la cobertura de código, esta métrica resulta útil para comparar el desempeño de una
prueba contra otra, y el progreso que ha tenido la regresión. Se analizarán los
resultados acumulados por prueba, y los resultados acumulados totales.
30
3 Desarrollo
Figura 3.4: Cobertura de código register test
send frame
Esta prueba configura al dut para enviar una cantidad de tramas, variando
la información enviada, ası́ como la paridad, startbit y stopbit. El uart se
configura solamente una vez por prueba, por lo que estos últimos tres rubros
no varı́an durante la ejecución de una misma prueba.
La prueba utiliza dos secuencias separadas. En la primera se configura
el dut, en la segundo se escriben las tramas a enviar al fifo de salida del
uart mediante el apb interface uvc. Paralelo a esto, el uart interface uvc
está monitoreando la salida del dut. La escritura genera una transacción que
el module uvc añade al scoreboard, y el interface uvc en la salida genera la
segunda transacción que es emparejada. Si los datos difieren, se ha encontrado
un error en el rtl.
Esta prueba dura un promedio de 56 segundos ejecutándose. La carga
de las herramientas de simulación consume 40 segundos del tiempo total de
simulación. Por eso esta prueba tarda simulando veces más que la ejecución
de register test. Los datos de cobertura funcional obtenidos son:
Se puede observar inmediatamente que esta prueba se desempeña mejor
que register test. Los mismos registros son ejercitados, y ahora se cubren los
puntos relacionados a la emisión de tramas. El punto que no se cubre com-
3.5. Análisis de resultados
31
Figura 3.5: Cobertura funcional send frame
pletamente es el cruce de tramas de cinco bits con dos bits de parada. Esto
se debe al caso esquina mencionado previamente: Estas dos opciones causan
que el dut use 1.5 bits de parada en lugar de dos. El monitor uart genera
transacciones incorrectas, por lo que el ambiente da un falso positivo.
La mejora en la cobertura de código es menos drámatica. Salta a la vista
como uart transmitter sube de un 25 % en register test a un 92 %. Se puede
decir que la prueba es muy efectiva en el área que se querı́a probar.
32
3 Desarrollo
Figura 3.6: Cobertura de código send frame
receive frame y receive frame err
Esta prueba envı́a una cantidad de tramas al uart, variando la información
enviada, ası́ como la paridad, startbit y stopbit. El uart se configura solamente una vez por prueba, por lo estos últimos 3 rubros no varı́an durante la
ejecución de una misma prueba.
La prueba utiliza tres secuencias separadas. En la primera se configura el
dut, en la segunda se envı́an las tramas al uart mediante su interface uvc,
y en la tercera se lee el fifo de llegada con el apb interface uvc. El envı́o de
la trama genera una transacción que el module uvc añade al scoreboard, y la
lectura del fifo genera la segunda transacción que es emparejada. Si los datos
difieren, se ha encontrado un error en el rtl. En el caso de tramas con errores,
el uart genera una interrupción. El scoreboard sólo compara el contenido de
la trama.
Esta prueba dura un promedio de 58 segundos ejecutándose. Los datos de
cobertura funcional obtenidos son:
3.5. Análisis de resultados
33
Figura 3.7: Cobertura funcional receive frame y receive frame err
La cobertura de estas pruebas es similar a la cobertura que logra send frame,
excepto que para este caso se extiende la cobertura en la recepción de tramas.
Un hueco en la verificación es que solamente se están generando errores de
paridad en el test receive frame err. Esto se debe a una limitación del monitor del uart: si el bit de parada o el bit de inicio son errónos, el monitor se
desincroniza y no genera la transacción con los datos apropiados. Esto llega a
la tabla de verificación y causa un falso positivo.
Esta situación muestra una de las limitaciones del método de tabla de
verificación. La inyección de errores requiere de una implementación mucho
más compleja que otras metodologı́as. Además se sacrifica la modularidad del
monitor, ya que éste debe ser informado de los casos especiales por el ambiente.
Para propósito de este proyecto se consideró que implementar la inyección de
errores de bit de paridad era suficiente para obtener una cobertura aceptable,
es decir, superior al 90 %.
La cobertura de código muestra la mejora en la verificación de uart reciever,
que sube de un 29 % a un 85 %.
34
3 Desarrollo
Figura 3.8: Cobertura de código receive frame y receive frame err
loopback
La prueba de loopback configura al uart para que devuelva al SoC todos los
paquetes transmitidos. Esto se logra mediante el registro de control de módem,
que deshabilita los puertos externos del dut y conecta internamente el emisor
con el receptor.
Esta prueba se implementa con dos secuencias que controlan al apb interface uvc. En primer lugar se escribe al fifo de salida del uart, se espera un
perı́odo de tiempo prudencial, y se lee del fifo de entrada. Para implementar
esta prueba se requirió modificar la tabla de verificación, para que emparajera
transacciones apb unas con otras.
Los datos de cobertura funcional obtenidos son:
3.5. Análisis de resultados
35
Figura 3.9: Cobertura funcional loopback
Se observa que no hay actividad en la interfaz del uart con el exterior.
Además, el punto de cobertura cov uart loopback detectó que sı́ se habilitó
el modo loopback. Sin embargo, es necesario notar que en el análisis para las
pruebas anteriores también este punto de cobertura estaba al 100 %. Esto se
debe a un error en la implementación: la señal interna del dut usada para
determinar esta funcionalidad se activa al azar cuando se saca al dispositivo
de reset, dando falsos positivos.
La cobertura de código muestra una situación interesante: el módulo de
transmisión y el módulo de recepción alcanzaron una cobertura del 96 % y el
85 % respectivamente. Esto parece indicar que la funcionalidad de loopback
implementada se limita a conectarlos internamente, lo que consume poder de
manera innecesaria.
36
3 Desarrollo
Figura 3.10: Cobertura de código loopback
Cobertura general
Por último, se analizó los datos de cobertura combinados, para determinar
la eficacia general del ambiente. En resumen, la cobertura funcional del dut
llegó a un 91 %, y la cobertura de código a un 86 %.
Cobertura funcional
En lo que respecta a la interfaz uart<->SoC, se logró un 100 % de cobertura.
Un resultado tan alto con una regresión tan pequeña indiqua que la cobertura
puede ser expandida para obtener información más detallada de los estados
del dut. Esta idea se refuerza con los resultados de cobertura de código que
se verán más adelante.
Un ejemplo para expandir la cobertura es incluir los registros de configuración del uart. Esto puede parecer redundante, ya que en la cobertura de
la interfaz out<->uart se recorren todos los tipos de tramas posibles. Sin
3.5. Análisis de resultados
37
embargo, queda como recomendación el realizar este cambio.
Figura 3.11: Cobertura funcional uart<->SoC
En el segundo rubro, out<->uart, se logró una cobertura del 95 % en
general, con 92 % para paquetes entrantes y 98 % para paquetes salientes.
Los huecos que quedaron en la cobertura de paquetes entrantes se deben a
que no se generaron errores de bit de inicio o bit de parada. Como se mencionó
previamente, el monitor del uart no puede distinguir el tipo de error que
se genera, creando transacciones incorrectas que terminan la ejecución de la
prueba. Es posible corregir esto cambiando la implementación del monitor y
la forma en la que éste interactúa con el ambiente.
El hueco en paquetes salientes se debe que no se generaron tramas de cinco
bits con dos bits de parada. Como se mencionó previamente, esto se debe al
comportamiento particular del dut que sólo genera 1.5 bits de parada.
38
3 Desarrollo
Figura 3.12: Cobertura funcional out<->uart
Cobertura de código
La herramienta de cobertura de código utilizada recopiló información de 5
categorı́as distintas:
• Ejecución de bloque: Número de lı́neas en el módulo que se han ejecutado.
• Ejecución de expresión: Número de valores booleanos que a tomado cada
expresión.
• Cambio de bit: Cantidad de bits en el rtl que han cambiado su estado.
• Máquina de estados finita (estados): Evalúa la cantidad de estados posibles en los que han estados las fsm internas.
• Máquina de estados finita (transiciónes): Evalúa las transiciones entre
estados que se han dado en las fsm internas.
La cobertura de código es una herramienta usada principalmente por el
diseñador. Con ésta se puede ver directamente qué partes de la implementación
han sido evaluadas, desde un punto de vista meramente programático y no
funcional. Gracias a esto, el diseñador puede ver que partes del diseño no
están recibiendo la suficiente atención e indicarle al verificador qué nuevas
3.5. Análisis de resultados
39
pruebas deben aplicarse. Como el verificador en principio no deberı́a conocer
los detalles de la implementación, la cobertura de código le resulta una métrica
menos útil.
La cobertura de código tiene dos categorı́as. En cobertura de módulo, se
agrupa la información por cada definición de módulo, sin importar cuantas
veces este fue instanciado en el diseño. Esto permite analizar el desempeño de
cada bloque separado de su contexto.
Figura 3.13: Cobertura de código por módulo
40
3 Desarrollo
En este rubro se observa que solo tres módulos utilizan máquinas de estado:
el transmisor, el receptor y la interfaz wishbone. En el transmisor la cobertura
llega al 100 %, en el receptor llega al 93 %, y en el wisbone llega al 78 %.
En el último caso, hubo un estado al que nunca se entró. El diseñador serı́a
capaz de determinar la funcionalidad de este estado y sugerir una prueba para
verificarlo. En el caso del receptor, no se dieron tres transiciones de estado: del
estado sr push a sı́ mismo, de sr push a sr rec start, y se sr rec start a sr idle.
Este nivel de detalle requiere un conocimiento detallado de cómo funciona la
máquina de estado. Es posible que con una regresión mayor se puedan llegar
a cubrir estos puntos.
El punto de cobertura más bajo está en el fifo de salida, que llega a sólo
un 72 %. Esto se debe a que no se llegó a causar una condición de sobrellenado
en él, porque la prueba falla en esos casos. Es responsabilidad del SoC no
intentar enviar más datos de los que el uart es capaz de manejar.
La cobertura de bloque y expresión se analiza con la segunda categorı́a de
cobertura de código:
Figura 3.14: Cobertura de código por instancia
3.5. Análisis de resultados
41
En la cobertura de código por instancia, se recopila información por cada
módulo declarado dentro del rtl. Para ciertos módulos que se reutilizan varias
veces en un diseño, como registros, sumadores, muxes, la cobertura por instancia permite observar cuánto se ha ejercitado el código en un punto especı́fico.
Para el caso de este uart, la reutilización de módulos se limita principalmente
a los registros.
En general la cobertura por instancia alcanzó un 89 %, con una baja varianza. No hay módulos que tengan una cobertura particularmente baja, lo
que indica que mejorar esta cobertura es cuestión de prolongar la regresión.
Un diseñador podrı́a sugerir algunas pruebas especı́ficas para estimular casos
esquina.
La cobertura de bloque más baja se da para la interfaz wishbone, con
un 84 %. Esto se debe a que, siendo el único bloque en bus apb, la señal de
selección no varı́a, omitiendo la lógica que maneja esta situación. Este tipo de
situaciones se verifican en un ambiente de verificación sistema, no un ambiente
de bloque. La cobertura de expresión más baja se da en uart dut.regs (85 %),
donde más ejecuciones de register test puede cubrir esta deficiencia.
En un escenario de producción real, donde la fabricación de un asic puede
costar varios cientos de miles de dólares, una cobertura de código aceptable
debe ser superior al 95 %. Esta cobertura mı́nima es una función del tiempo de
fabricación, importancia de la tarea que realizará el chip, nivel del madurez del
rtl en general, etcétera. Otra consideración es la urgencia de poner el dispositivo en el mercado, caracterı́sticas no crı́ticas que resultan defectuosas pueden
deshabilitarse con tal de no desaprovechar una oportunidad importante.
4
Conclusiones y recomendaciones
• El plan de pruebas y el ambiente desarrollado permitieron alcanzar una
cobertura funcional del 98 % y una cobertura de código del 87 %. De
acuerdo a estos resultados se concluye que se pudo verificar que el envı́o
y recepción de paquetes en el uart funciona correctamente.
• La metodologı́a uvm provee un marco de referencia que permite el desarrollo de ambientes de verificación de manera rápida y efectiva, que pueden ser reutilizados. Esto se aprecia en la integración exitosa de los dos
interface uvc usados con el module uvc desarrollado.
• La cobertura de código es una herramienta que el diseñador puede utilizar para evaluar el progreso de la verificación. La cobertura funcional
es usada por el verificador para comprobar la efectivad de las pruebas
aleatorias restringidas.
• Los huecos que quedaron luego del esfuerzo de verificación se relacionan
a la inyección de errores de bit de inicio y bit de parada. Tampoco se
verificó la generación de tramas de cinco bits con dos bits de parada.
• Se recomienda reestructurar el monitor del uart interface uvc para que
interprete de manera adecuada tramas con errores de bit de inicio y bit
de parada. Adicionalmente, que detecte de manera correcta las tramas
de cinco bits con 1.5 bits de parada.
• Se recomienda el uso de otros métodos de verificación, como verificación
formal. Además existen herramientas para chequeo de ambientes de verificación, que introducen errores en el rtl y verifican que el ambiente
los detecte. Esto se conoce como análisis de mutación.
• Se recomienda buscar herramientas de software libre para impulsar un
laboratorio en la ucr. Actualmente las herramientas más populares,
Specman e y SystemVerilog no cuentan con compiladores o interpretadores de código libre. Hay una tercera opción más desarrollada, SystemC,
que puede resultar apropiada para este propósito.
43
Bibliografı́a
Bergeron, J. (2003). Writing testbenches: functional verification of hdl models, 2nd edition. Kluwer Academic Publishers.
Cadence (2012). uvm e reference flow user guide, version 1.1. Disponible en:
http://forums.accellera.org/files/file/70-uvm-reference-flow-version-11/.
Gorban, J. (2002). uart ip core specification revision 0.6. Disponible en:
http://opencores.org/project,uart16550.
Robinson, D. (2007). Aspect-oriented programming with the e verification language: a pragmatic guide for testbench developers. Morgan Kaufmann Publishers.
Rosenberg, S. y Meade, K. A. (2010). A practical guide to adopting the Universal Verification Methodology ( uvm). Cadence Design Systems.
Vasudevan, S. (2006). Effective functional verification: Principles and processes. Springer.
45
Descargar